1 ;;- Machine description for ARM for GNU compiler
2 ;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;; 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4 ;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;; and Martin Simmons (@harleqn.co.uk).
6 ;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
8 ;; This file is part of GCC.
10 ;; GCC is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 2, or (at your
13 ;; option) any later version.
15 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
18 ;; License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; see the file COPYING. If not, write to
22 ;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 ;; Boston, MA 02110-1301, USA.
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
28 ;;---------------------------------------------------------------------------
33 [(R0_REGNUM 0) ; First CORE register
34 (IP_REGNUM 12) ; Scratch register
35 (SP_REGNUM 13) ; Stack pointer
36 (LR_REGNUM 14) ; Return address register
37 (PC_REGNUM 15) ; Program counter
38 (CC_REGNUM 24) ; Condition code pseudo register
39 (LAST_ARM_REGNUM 15) ;
40 (FPA_F0_REGNUM 16) ; FIRST_FPA_REGNUM
41 (FPA_F7_REGNUM 23) ; LAST_FPA_REGNUM
44 ;; 3rd operand to select_dominance_cc_mode
53 ;; Note: sin and cos are no-longer used.
56 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
57 ; operand 0 is the result,
58 ; operand 1 the parameter.
59 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
60 ; operand 0 is the result,
61 ; operand 1 the parameter.
62 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
63 ; operand 0 is the first register,
64 ; subsequent registers are in parallel (use ...)
66 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
67 ; usage, that is, we will add the pic_register
68 ; value to it before trying to dereference it.
69 (UNSPEC_PIC_BASE 4) ; Adding the PC value to the offset to the
70 ; GLOBAL_OFFSET_TABLE. The operation is fully
71 ; described by the RTL but must be wrapped to
72 ; prevent combine from trying to rip it apart.
73 (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses
74 ; being scheduled before the stack adjustment insn.
75 (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
76 ; this unspec is used to prevent the deletion of
77 ; instructions setting registers for EH handling
78 ; and stack frame generation. Operand 0 is the
80 (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
81 (UNSPEC_WSHUFH 8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
82 (UNSPEC_WACC 9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
83 (UNSPEC_TMOVMSK 10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
84 (UNSPEC_WSAD 11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
85 (UNSPEC_WSADZ 12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
86 (UNSPEC_WMACS 13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
87 (UNSPEC_WMACU 14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
88 (UNSPEC_WMACSZ 15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
89 (UNSPEC_WMACUZ 16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
90 (UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
91 (UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
92 (UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
93 (UNSPEC_TLS 20) ; A symbol that has been treated properly for TLS usage.
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)))]
3503 (define_insn "*compareqi_eq0"
3504 [(set (reg:CC_Z CC_REGNUM)
3505 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3509 [(set_attr "conds" "set")]
3512 (define_expand "extendhisi2"
3514 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3516 (set (match_operand:SI 0 "s_register_operand" "")
3517 (ashiftrt:SI (match_dup 2)
3522 if (GET_CODE (operands[1]) == MEM)
3526 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3531 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3532 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3537 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3539 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3543 if (!s_register_operand (operands[1], HImode))
3544 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3549 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3551 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3552 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3557 operands[1] = gen_lowpart (SImode, operands[1]);
3558 operands[2] = gen_reg_rtx (SImode);
3562 (define_insn "thumb_extendhisi2"
3563 [(set (match_operand:SI 0 "register_operand" "=l")
3564 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3565 (clobber (match_scratch:SI 2 "=&l"))]
3566 "TARGET_THUMB && !arm_arch6"
3570 rtx mem = XEXP (operands[1], 0);
3572 /* This code used to try to use 'V', and fix the address only if it was
3573 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3574 range of QImode offsets, and offsettable_address_p does a QImode
3577 if (GET_CODE (mem) == CONST)
3578 mem = XEXP (mem, 0);
3580 if (GET_CODE (mem) == LABEL_REF)
3581 return \"ldr\\t%0, %1\";
3583 if (GET_CODE (mem) == PLUS)
3585 rtx a = XEXP (mem, 0);
3586 rtx b = XEXP (mem, 1);
3588 if (GET_CODE (a) == LABEL_REF
3589 && GET_CODE (b) == CONST_INT)
3590 return \"ldr\\t%0, %1\";
3592 if (GET_CODE (b) == REG)
3593 return \"ldrsh\\t%0, %1\";
3601 ops[2] = const0_rtx;
3604 gcc_assert (GET_CODE (ops[1]) == REG);
3606 ops[0] = operands[0];
3607 ops[3] = operands[2];
3608 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3611 [(set_attr "length" "4")
3612 (set_attr "type" "load_byte")
3613 (set_attr "pool_range" "1020")]
3616 ;; We used to have an early-clobber on the scratch register here.
3617 ;; However, there's a bug somewhere in reload which means that this
3618 ;; can be partially ignored during spill allocation if the memory
3619 ;; address also needs reloading; this causes us to die later on when
3620 ;; we try to verify the operands. Fortunately, we don't really need
3621 ;; the early-clobber: we can always use operand 0 if operand 2
3622 ;; overlaps the address.
3623 (define_insn "*thumb_extendhisi2_insn_v6"
3624 [(set (match_operand:SI 0 "register_operand" "=l,l")
3625 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3626 (clobber (match_scratch:SI 2 "=X,l"))]
3627 "TARGET_THUMB && arm_arch6"
3633 if (which_alternative == 0)
3634 return \"sxth\\t%0, %1\";
3636 mem = XEXP (operands[1], 0);
3638 /* This code used to try to use 'V', and fix the address only if it was
3639 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3640 range of QImode offsets, and offsettable_address_p does a QImode
3643 if (GET_CODE (mem) == CONST)
3644 mem = XEXP (mem, 0);
3646 if (GET_CODE (mem) == LABEL_REF)
3647 return \"ldr\\t%0, %1\";
3649 if (GET_CODE (mem) == PLUS)
3651 rtx a = XEXP (mem, 0);
3652 rtx b = XEXP (mem, 1);
3654 if (GET_CODE (a) == LABEL_REF
3655 && GET_CODE (b) == CONST_INT)
3656 return \"ldr\\t%0, %1\";
3658 if (GET_CODE (b) == REG)
3659 return \"ldrsh\\t%0, %1\";
3667 ops[2] = const0_rtx;
3670 gcc_assert (GET_CODE (ops[1]) == REG);
3672 ops[0] = operands[0];
3673 if (reg_mentioned_p (operands[2], ops[1]))
3676 ops[3] = operands[2];
3677 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3680 [(set_attr "length" "2,4")
3681 (set_attr "type" "alu_shift,load_byte")
3682 (set_attr "pool_range" "*,1020")]
3685 (define_expand "extendhisi2_mem"
3686 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3688 (zero_extend:SI (match_dup 7)))
3689 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3690 (set (match_operand:SI 0 "" "")
3691 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3696 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3698 mem1 = change_address (operands[1], QImode, addr);
3699 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
3700 operands[0] = gen_lowpart (SImode, operands[0]);
3702 operands[2] = gen_reg_rtx (SImode);
3703 operands[3] = gen_reg_rtx (SImode);
3704 operands[6] = gen_reg_rtx (SImode);
3707 if (BYTES_BIG_ENDIAN)
3709 operands[4] = operands[2];
3710 operands[5] = operands[3];
3714 operands[4] = operands[3];
3715 operands[5] = operands[2];
3720 (define_insn "*arm_extendhisi2"
3721 [(set (match_operand:SI 0 "s_register_operand" "=r")
3722 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3723 "TARGET_ARM && arm_arch4 && !arm_arch6"
3725 [(set_attr "type" "load_byte")
3726 (set_attr "predicable" "yes")
3727 (set_attr "pool_range" "256")
3728 (set_attr "neg_pool_range" "244")]
3731 (define_insn "*arm_extendhisi2_v6"
3732 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3733 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3734 "TARGET_ARM && arm_arch6"
3738 [(set_attr "type" "alu_shift,load_byte")
3739 (set_attr "predicable" "yes")
3740 (set_attr "pool_range" "*,256")
3741 (set_attr "neg_pool_range" "*,244")]
3744 (define_insn "*arm_extendhisi2addsi"
3745 [(set (match_operand:SI 0 "s_register_operand" "=r")
3746 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3747 (match_operand:SI 2 "s_register_operand" "r")))]
3748 "TARGET_ARM && arm_arch6"
3749 "sxtah%?\\t%0, %2, %1"
3752 (define_expand "extendqihi2"
3754 (ashift:SI (match_operand:QI 1 "general_operand" "")
3756 (set (match_operand:HI 0 "s_register_operand" "")
3757 (ashiftrt:SI (match_dup 2)
3762 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3764 emit_insn (gen_rtx_SET (VOIDmode,
3766 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3769 if (!s_register_operand (operands[1], QImode))
3770 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3771 operands[0] = gen_lowpart (SImode, operands[0]);
3772 operands[1] = gen_lowpart (SImode, operands[1]);
3773 operands[2] = gen_reg_rtx (SImode);
3777 (define_insn "*extendqihi_insn"
3778 [(set (match_operand:HI 0 "s_register_operand" "=r")
3779 (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3780 "TARGET_ARM && arm_arch4"
3782 [(set_attr "type" "load_byte")
3783 (set_attr "predicable" "yes")
3784 (set_attr "pool_range" "256")
3785 (set_attr "neg_pool_range" "244")]
3788 (define_expand "extendqisi2"
3790 (ashift:SI (match_operand:QI 1 "general_operand" "")
3792 (set (match_operand:SI 0 "s_register_operand" "")
3793 (ashiftrt:SI (match_dup 2)
3798 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3800 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3801 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3805 if (!s_register_operand (operands[1], QImode))
3806 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3810 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3811 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3815 operands[1] = gen_lowpart (SImode, operands[1]);
3816 operands[2] = gen_reg_rtx (SImode);
3820 (define_insn "*arm_extendqisi"
3821 [(set (match_operand:SI 0 "s_register_operand" "=r")
3822 (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3823 "TARGET_ARM && arm_arch4 && !arm_arch6"
3825 [(set_attr "type" "load_byte")
3826 (set_attr "predicable" "yes")
3827 (set_attr "pool_range" "256")
3828 (set_attr "neg_pool_range" "244")]
3831 (define_insn "*arm_extendqisi_v6"
3832 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3833 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3834 "TARGET_ARM && arm_arch6"
3838 [(set_attr "type" "alu_shift,load_byte")
3839 (set_attr "predicable" "yes")
3840 (set_attr "pool_range" "*,256")
3841 (set_attr "neg_pool_range" "*,244")]
3844 (define_insn "*arm_extendqisi2addsi"
3845 [(set (match_operand:SI 0 "s_register_operand" "=r")
3846 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3847 (match_operand:SI 2 "s_register_operand" "r")))]
3848 "TARGET_ARM && arm_arch6"
3849 "sxtab%?\\t%0, %2, %1"
3850 [(set_attr "type" "alu_shift")
3851 (set_attr "predicable" "yes")]
3854 (define_insn "*thumb_extendqisi2"
3855 [(set (match_operand:SI 0 "register_operand" "=l,l")
3856 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3857 "TARGET_THUMB && !arm_arch6"
3861 rtx mem = XEXP (operands[1], 0);
3863 if (GET_CODE (mem) == CONST)
3864 mem = XEXP (mem, 0);
3866 if (GET_CODE (mem) == LABEL_REF)
3867 return \"ldr\\t%0, %1\";
3869 if (GET_CODE (mem) == PLUS
3870 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3871 return \"ldr\\t%0, %1\";
3873 if (which_alternative == 0)
3874 return \"ldrsb\\t%0, %1\";
3876 ops[0] = operands[0];
3878 if (GET_CODE (mem) == PLUS)
3880 rtx a = XEXP (mem, 0);
3881 rtx b = XEXP (mem, 1);
3886 if (GET_CODE (a) == REG)
3888 if (GET_CODE (b) == REG)
3889 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3890 else if (REGNO (a) == REGNO (ops[0]))
3892 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3893 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3894 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3897 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3901 gcc_assert (GET_CODE (b) == REG);
3902 if (REGNO (b) == REGNO (ops[0]))
3904 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3905 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3906 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3909 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3912 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3914 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3915 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3916 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3921 ops[2] = const0_rtx;
3923 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3927 [(set_attr "length" "2,6")
3928 (set_attr "type" "load_byte,load_byte")
3929 (set_attr "pool_range" "32,32")]
3932 (define_insn "*thumb_extendqisi2_v6"
3933 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3934 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3935 "TARGET_THUMB && arm_arch6"
3941 if (which_alternative == 0)
3942 return \"sxtb\\t%0, %1\";
3944 mem = XEXP (operands[1], 0);
3946 if (GET_CODE (mem) == CONST)
3947 mem = XEXP (mem, 0);
3949 if (GET_CODE (mem) == LABEL_REF)
3950 return \"ldr\\t%0, %1\";
3952 if (GET_CODE (mem) == PLUS
3953 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3954 return \"ldr\\t%0, %1\";
3956 if (which_alternative == 0)
3957 return \"ldrsb\\t%0, %1\";
3959 ops[0] = operands[0];
3961 if (GET_CODE (mem) == PLUS)
3963 rtx a = XEXP (mem, 0);
3964 rtx b = XEXP (mem, 1);
3969 if (GET_CODE (a) == REG)
3971 if (GET_CODE (b) == REG)
3972 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3973 else if (REGNO (a) == REGNO (ops[0]))
3975 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3976 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3979 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3983 gcc_assert (GET_CODE (b) == REG);
3984 if (REGNO (b) == REGNO (ops[0]))
3986 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3987 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3990 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3993 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3995 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3996 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4001 ops[2] = const0_rtx;
4003 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4007 [(set_attr "length" "2,2,4")
4008 (set_attr "type" "alu_shift,load_byte,load_byte")
4009 (set_attr "pool_range" "*,32,32")]
4012 (define_expand "extendsfdf2"
4013 [(set (match_operand:DF 0 "s_register_operand" "")
4014 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
4015 "TARGET_ARM && TARGET_HARD_FLOAT"
4019 ;; Move insns (including loads and stores)
4021 ;; XXX Just some ideas about movti.
4022 ;; I don't think these are a good idea on the arm, there just aren't enough
4024 ;;(define_expand "loadti"
4025 ;; [(set (match_operand:TI 0 "s_register_operand" "")
4026 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4029 ;;(define_expand "storeti"
4030 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4031 ;; (match_operand:TI 1 "s_register_operand" ""))]
4034 ;;(define_expand "movti"
4035 ;; [(set (match_operand:TI 0 "general_operand" "")
4036 ;; (match_operand:TI 1 "general_operand" ""))]
4042 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4043 ;; operands[1] = copy_to_reg (operands[1]);
4044 ;; if (GET_CODE (operands[0]) == MEM)
4045 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4046 ;; else if (GET_CODE (operands[1]) == MEM)
4047 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4051 ;; emit_insn (insn);
4055 ;; Recognize garbage generated above.
4058 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4059 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4063 ;; register mem = (which_alternative < 3);
4064 ;; register const char *template;
4066 ;; operands[mem] = XEXP (operands[mem], 0);
4067 ;; switch (which_alternative)
4069 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4070 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4071 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4072 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4073 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4074 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
4076 ;; output_asm_insn (template, operands);
4080 (define_expand "movdi"
4081 [(set (match_operand:DI 0 "general_operand" "")
4082 (match_operand:DI 1 "general_operand" ""))]
4087 if (!no_new_pseudos)
4089 if (GET_CODE (operands[0]) != REG)
4090 operands[1] = force_reg (DImode, operands[1]);
4096 (define_insn "*arm_movdi"
4097 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4098 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
4100 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4103 switch (which_alternative)
4110 return output_move_double (operands);
4113 [(set_attr "length" "8,12,16,8,8")
4114 (set_attr "type" "*,*,*,load2,store2")
4115 (set_attr "pool_range" "*,*,*,1020,*")
4116 (set_attr "neg_pool_range" "*,*,*,1008,*")]
4120 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4121 (match_operand:ANY64 1 "const_double_operand" ""))]
4124 && (arm_const_double_inline_cost (operands[1])
4125 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4128 arm_split_constant (SET, SImode, curr_insn,
4129 INTVAL (gen_lowpart (SImode, operands[1])),
4130 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4131 arm_split_constant (SET, SImode, curr_insn,
4132 INTVAL (gen_highpart_mode (SImode,
4133 GET_MODE (operands[0]),
4135 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4140 ; If optimizing for size, or if we have load delay slots, then
4141 ; we want to split the constant into two separate operations.
4142 ; In both cases this may split a trivial part into a single data op
4143 ; leaving a single complex constant to load. We can also get longer
4144 ; offsets in a LDR which means we get better chances of sharing the pool
4145 ; entries. Finally, we can normally do a better job of scheduling
4146 ; LDR instructions than we can with LDM.
4147 ; This pattern will only match if the one above did not.
4149 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4150 (match_operand:ANY64 1 "const_double_operand" ""))]
4151 "TARGET_ARM && reload_completed
4152 && arm_const_double_by_parts (operands[1])"
4153 [(set (match_dup 0) (match_dup 1))
4154 (set (match_dup 2) (match_dup 3))]
4156 operands[2] = gen_highpart (SImode, operands[0]);
4157 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4159 operands[0] = gen_lowpart (SImode, operands[0]);
4160 operands[1] = gen_lowpart (SImode, operands[1]);
4165 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4166 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4167 "TARGET_EITHER && reload_completed"
4168 [(set (match_dup 0) (match_dup 1))
4169 (set (match_dup 2) (match_dup 3))]
4171 operands[2] = gen_highpart (SImode, operands[0]);
4172 operands[3] = gen_highpart (SImode, operands[1]);
4173 operands[0] = gen_lowpart (SImode, operands[0]);
4174 operands[1] = gen_lowpart (SImode, operands[1]);
4176 /* Handle a partial overlap. */
4177 if (rtx_equal_p (operands[0], operands[3]))
4179 rtx tmp0 = operands[0];
4180 rtx tmp1 = operands[1];
4182 operands[0] = operands[2];
4183 operands[1] = operands[3];
4190 ;; We can't actually do base+index doubleword loads if the index and
4191 ;; destination overlap. Split here so that we at least have chance to
4194 [(set (match_operand:DI 0 "s_register_operand" "")
4195 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4196 (match_operand:SI 2 "s_register_operand" ""))))]
4198 && reg_overlap_mentioned_p (operands[0], operands[1])
4199 && reg_overlap_mentioned_p (operands[0], operands[2])"
4201 (plus:SI (match_dup 1)
4204 (mem:DI (match_dup 4)))]
4206 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4210 ;;; ??? This should have alternatives for constants.
4211 ;;; ??? This was originally identical to the movdf_insn pattern.
4212 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4213 ;;; thumb_reorg with a memory reference.
4214 (define_insn "*thumb_movdi_insn"
4215 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4216 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
4218 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4219 && ( register_operand (operands[0], DImode)
4220 || register_operand (operands[1], DImode))"
4223 switch (which_alternative)
4227 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4228 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4229 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4231 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4233 operands[1] = GEN_INT (- INTVAL (operands[1]));
4234 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4236 return \"ldmia\\t%1, {%0, %H0}\";
4238 return \"stmia\\t%0, {%1, %H1}\";
4240 return thumb_load_double_from_address (operands);
4242 operands[2] = gen_rtx_MEM (SImode,
4243 plus_constant (XEXP (operands[0], 0), 4));
4244 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4247 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4248 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4249 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4252 [(set_attr "length" "4,4,6,2,2,6,4,4")
4253 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4254 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4257 (define_expand "movsi"
4258 [(set (match_operand:SI 0 "general_operand" "")
4259 (match_operand:SI 1 "general_operand" ""))]
4264 /* Everything except mem = const or mem = mem can be done easily. */
4265 if (GET_CODE (operands[0]) == MEM)
4266 operands[1] = force_reg (SImode, operands[1]);
4267 if (arm_general_register_operand (operands[0], SImode)
4268 && GET_CODE (operands[1]) == CONST_INT
4269 && !(const_ok_for_arm (INTVAL (operands[1]))
4270 || const_ok_for_arm (~INTVAL (operands[1]))))
4272 arm_split_constant (SET, SImode, NULL_RTX,
4273 INTVAL (operands[1]), operands[0], NULL_RTX,
4274 optimize && !no_new_pseudos);
4278 else /* TARGET_THUMB.... */
4280 if (!no_new_pseudos)
4282 if (GET_CODE (operands[0]) != REG)
4283 operands[1] = force_reg (SImode, operands[1]);
4287 /* Recognize the case where operand[1] is a reference to thread-local
4288 data and load its address to a register. */
4289 if (arm_tls_referenced_p (operands[1]))
4291 rtx tmp = operands[1];
4294 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
4296 addend = XEXP (XEXP (tmp, 0), 1);
4297 tmp = XEXP (XEXP (tmp, 0), 0);
4300 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
4301 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
4303 tmp = legitimize_tls_address (tmp, no_new_pseudos ? operands[0] : 0);
4306 tmp = gen_rtx_PLUS (SImode, tmp, addend);
4307 tmp = force_operand (tmp, operands[0]);
4312 && (CONSTANT_P (operands[1])
4313 || symbol_mentioned_p (operands[1])
4314 || label_mentioned_p (operands[1])))
4315 operands[1] = legitimize_pic_address (operands[1], SImode,
4316 (no_new_pseudos ? operands[0] : 0));
4320 (define_insn "*arm_movsi_insn"
4321 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4322 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
4323 "TARGET_ARM && ! TARGET_IWMMXT
4324 && !(TARGET_HARD_FLOAT && TARGET_VFP)
4325 && ( register_operand (operands[0], SImode)
4326 || register_operand (operands[1], SImode))"
4332 [(set_attr "type" "*,*,load1,store1")
4333 (set_attr "predicable" "yes")
4334 (set_attr "pool_range" "*,*,4096,*")
4335 (set_attr "neg_pool_range" "*,*,4084,*")]
4339 [(set (match_operand:SI 0 "arm_general_register_operand" "")
4340 (match_operand:SI 1 "const_int_operand" ""))]
4342 && (!(const_ok_for_arm (INTVAL (operands[1]))
4343 || const_ok_for_arm (~INTVAL (operands[1]))))"
4344 [(clobber (const_int 0))]
4346 arm_split_constant (SET, SImode, NULL_RTX,
4347 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4352 (define_insn "*thumb_movsi_insn"
4353 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4354 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
4356 && ( register_operand (operands[0], SImode)
4357 || register_operand (operands[1], SImode))"
4368 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4369 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4370 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4374 [(set (match_operand:SI 0 "register_operand" "")
4375 (match_operand:SI 1 "const_int_operand" ""))]
4376 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4377 [(set (match_dup 0) (match_dup 1))
4378 (set (match_dup 0) (neg:SI (match_dup 0)))]
4379 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
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]), 'K')"
4386 [(set (match_dup 0) (match_dup 1))
4387 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4390 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4391 unsigned HOST_WIDE_INT mask = 0xff;
4394 for (i = 0; i < 25; i++)
4395 if ((val & (mask << i)) == val)
4398 /* Shouldn't happen, but we don't want to split if the shift is zero. */
4402 operands[1] = GEN_INT (val >> i);
4403 operands[2] = GEN_INT (i);
4407 ;; When generating pic, we need to load the symbol offset into a register.
4408 ;; So that the optimizer does not confuse this with a normal symbol load
4409 ;; we use an unspec. The offset will be loaded from a constant pool entry,
4410 ;; since that is the only type of relocation we can use.
4412 ;; The rather odd constraints on the following are to force reload to leave
4413 ;; the insn alone, and to force the minipool generation pass to then move
4414 ;; the GOT symbol to memory.
4416 (define_insn "pic_load_addr_arm"
4417 [(set (match_operand:SI 0 "s_register_operand" "=r")
4418 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4419 "TARGET_ARM && flag_pic"
4421 [(set_attr "type" "load1")
4422 (set (attr "pool_range") (const_int 4096))
4423 (set (attr "neg_pool_range") (const_int 4084))]
4426 (define_insn "pic_load_addr_thumb"
4427 [(set (match_operand:SI 0 "s_register_operand" "=l")
4428 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4429 "TARGET_THUMB && flag_pic"
4431 [(set_attr "type" "load1")
4432 (set (attr "pool_range") (const_int 1024))]
4435 ;; This variant is used for AOF assembly, since it needs to mention the
4436 ;; pic register in the rtl.
4437 (define_expand "pic_load_addr_based"
4438 [(set (match_operand:SI 0 "s_register_operand" "")
4439 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4440 "TARGET_ARM && flag_pic"
4441 "operands[2] = pic_offset_table_rtx;"
4444 (define_insn "*pic_load_addr_based_insn"
4445 [(set (match_operand:SI 0 "s_register_operand" "=r")
4446 (unspec:SI [(match_operand 1 "" "")
4447 (match_operand 2 "s_register_operand" "r")]
4449 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4451 #ifdef AOF_ASSEMBLER
4452 operands[1] = aof_pic_entry (operands[1]);
4454 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4457 [(set_attr "type" "load1")
4458 (set (attr "pool_range")
4459 (if_then_else (eq_attr "is_thumb" "yes")
4462 (set (attr "neg_pool_range")
4463 (if_then_else (eq_attr "is_thumb" "yes")
4468 (define_insn "pic_add_dot_plus_four"
4469 [(set (match_operand:SI 0 "register_operand" "=r")
4470 (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
4471 (const (plus:SI (pc) (const_int 4))))]
4473 (use (match_operand 2 "" ""))]
4476 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4477 INTVAL (operands[2]));
4478 return \"add\\t%0, %|pc\";
4480 [(set_attr "length" "2")]
4483 (define_insn "pic_add_dot_plus_eight"
4484 [(set (match_operand:SI 0 "register_operand" "=r")
4485 (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4486 (const (plus:SI (pc) (const_int 8))))]
4488 (use (match_operand 2 "" ""))]
4491 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4492 INTVAL (operands[2]));
4493 return \"add%?\\t%0, %|pc, %1\";
4495 [(set_attr "predicable" "yes")]
4498 (define_insn "tls_load_dot_plus_eight"
4499 [(set (match_operand:SI 0 "register_operand" "+r")
4500 (mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4501 (const (plus:SI (pc) (const_int 8))))]
4503 (use (match_operand 2 "" ""))]
4506 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4507 INTVAL (operands[2]));
4508 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
4510 [(set_attr "predicable" "yes")]
4513 ;; PIC references to local variables can generate pic_add_dot_plus_eight
4514 ;; followed by a load. These sequences can be crunched down to
4515 ;; tls_load_dot_plus_eight by a peephole.
4518 [(parallel [(set (match_operand:SI 0 "register_operand" "")
4519 (unspec:SI [(plus:SI (match_operand:SI 3 "register_operand" "")
4520 (const (plus:SI (pc) (const_int 8))))]
4522 (use (label_ref (match_operand 1 "" "")))])
4523 (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
4524 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
4525 [(parallel [(set (match_dup 2)
4526 (mem:SI (unspec:SI [(plus:SI (match_dup 3)
4527 (const (plus:SI (pc) (const_int 8))))]
4529 (use (label_ref (match_dup 1)))])]
4533 (define_expand "builtin_setjmp_receiver"
4534 [(label_ref (match_operand 0 "" ""))]
4538 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4540 arm_load_pic_register (3);
4544 ;; If copying one reg to another we can set the condition codes according to
4545 ;; its value. Such a move is common after a return from subroutine and the
4546 ;; result is being tested against zero.
4548 (define_insn "*movsi_compare0"
4549 [(set (reg:CC CC_REGNUM)
4550 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4552 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4557 sub%?s\\t%0, %1, #0"
4558 [(set_attr "conds" "set")]
4561 ;; Subroutine to store a half word from a register into memory.
4562 ;; Operand 0 is the source register (HImode)
4563 ;; Operand 1 is the destination address in a register (SImode)
4565 ;; In both this routine and the next, we must be careful not to spill
4566 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4567 ;; can generate unrecognizable rtl.
4569 (define_expand "storehi"
4570 [;; store the low byte
4571 (set (match_operand 1 "" "") (match_dup 3))
4572 ;; extract the high byte
4574 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4575 ;; store the high byte
4576 (set (match_dup 4) (match_dup 5))]
4580 rtx op1 = operands[1];
4581 rtx addr = XEXP (op1, 0);
4582 enum rtx_code code = GET_CODE (addr);
4584 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4586 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4588 operands[4] = adjust_address (op1, QImode, 1);
4589 operands[1] = adjust_address (operands[1], QImode, 0);
4590 operands[3] = gen_lowpart (QImode, operands[0]);
4591 operands[0] = gen_lowpart (SImode, operands[0]);
4592 operands[2] = gen_reg_rtx (SImode);
4593 operands[5] = gen_lowpart (QImode, operands[2]);
4597 (define_expand "storehi_bigend"
4598 [(set (match_dup 4) (match_dup 3))
4600 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4601 (set (match_operand 1 "" "") (match_dup 5))]
4605 rtx op1 = operands[1];
4606 rtx addr = XEXP (op1, 0);
4607 enum rtx_code code = GET_CODE (addr);
4609 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4611 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4613 operands[4] = adjust_address (op1, QImode, 1);
4614 operands[1] = adjust_address (operands[1], QImode, 0);
4615 operands[3] = gen_lowpart (QImode, operands[0]);
4616 operands[0] = gen_lowpart (SImode, operands[0]);
4617 operands[2] = gen_reg_rtx (SImode);
4618 operands[5] = gen_lowpart (QImode, operands[2]);
4622 ;; Subroutine to store a half word integer constant into memory.
4623 (define_expand "storeinthi"
4624 [(set (match_operand 0 "" "")
4625 (match_operand 1 "" ""))
4626 (set (match_dup 3) (match_dup 2))]
4630 HOST_WIDE_INT value = INTVAL (operands[1]);
4631 rtx addr = XEXP (operands[0], 0);
4632 rtx op0 = operands[0];
4633 enum rtx_code code = GET_CODE (addr);
4635 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4637 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4639 operands[1] = gen_reg_rtx (SImode);
4640 if (BYTES_BIG_ENDIAN)
4642 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4643 if ((value & 255) == ((value >> 8) & 255))
4644 operands[2] = operands[1];
4647 operands[2] = gen_reg_rtx (SImode);
4648 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4653 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4654 if ((value & 255) == ((value >> 8) & 255))
4655 operands[2] = operands[1];
4658 operands[2] = gen_reg_rtx (SImode);
4659 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4663 operands[3] = adjust_address (op0, QImode, 1);
4664 operands[0] = adjust_address (operands[0], QImode, 0);
4665 operands[2] = gen_lowpart (QImode, operands[2]);
4666 operands[1] = gen_lowpart (QImode, operands[1]);
4670 (define_expand "storehi_single_op"
4671 [(set (match_operand:HI 0 "memory_operand" "")
4672 (match_operand:HI 1 "general_operand" ""))]
4673 "TARGET_ARM && arm_arch4"
4675 if (!s_register_operand (operands[1], HImode))
4676 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4680 (define_expand "movhi"
4681 [(set (match_operand:HI 0 "general_operand" "")
4682 (match_operand:HI 1 "general_operand" ""))]
4687 if (!no_new_pseudos)
4689 if (GET_CODE (operands[0]) == MEM)
4693 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4696 if (GET_CODE (operands[1]) == CONST_INT)
4697 emit_insn (gen_storeinthi (operands[0], operands[1]));
4700 if (GET_CODE (operands[1]) == MEM)
4701 operands[1] = force_reg (HImode, operands[1]);
4702 if (BYTES_BIG_ENDIAN)
4703 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4705 emit_insn (gen_storehi (operands[1], operands[0]));
4709 /* Sign extend a constant, and keep it in an SImode reg. */
4710 else if (GET_CODE (operands[1]) == CONST_INT)
4712 rtx reg = gen_reg_rtx (SImode);
4713 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4715 /* If the constant is already valid, leave it alone. */
4716 if (!const_ok_for_arm (val))
4718 /* If setting all the top bits will make the constant
4719 loadable in a single instruction, then set them.
4720 Otherwise, sign extend the number. */
4722 if (const_ok_for_arm (~(val | ~0xffff)))
4724 else if (val & 0x8000)
4728 emit_insn (gen_movsi (reg, GEN_INT (val)));
4729 operands[1] = gen_lowpart (HImode, reg);
4731 else if (arm_arch4 && optimize && !no_new_pseudos
4732 && GET_CODE (operands[1]) == MEM)
4734 rtx reg = gen_reg_rtx (SImode);
4736 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4737 operands[1] = gen_lowpart (HImode, reg);
4739 else if (!arm_arch4)
4741 if (GET_CODE (operands[1]) == MEM)
4744 rtx offset = const0_rtx;
4745 rtx reg = gen_reg_rtx (SImode);
4747 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4748 || (GET_CODE (base) == PLUS
4749 && (GET_CODE (offset = XEXP (base, 1))
4751 && ((INTVAL(offset) & 1) != 1)
4752 && GET_CODE (base = XEXP (base, 0)) == REG))
4753 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4757 new = widen_memory_access (operands[1], SImode,
4758 ((INTVAL (offset) & ~3)
4759 - INTVAL (offset)));
4760 emit_insn (gen_movsi (reg, new));
4761 if (((INTVAL (offset) & 2) != 0)
4762 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4764 rtx reg2 = gen_reg_rtx (SImode);
4766 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4771 emit_insn (gen_movhi_bytes (reg, operands[1]));
4773 operands[1] = gen_lowpart (HImode, reg);
4777 /* Handle loading a large integer during reload. */
4778 else if (GET_CODE (operands[1]) == CONST_INT
4779 && !const_ok_for_arm (INTVAL (operands[1]))
4780 && !const_ok_for_arm (~INTVAL (operands[1])))
4782 /* Writing a constant to memory needs a scratch, which should
4783 be handled with SECONDARY_RELOADs. */
4784 gcc_assert (GET_CODE (operands[0]) == REG);
4786 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4787 emit_insn (gen_movsi (operands[0], operands[1]));
4791 else /* TARGET_THUMB */
4793 if (!no_new_pseudos)
4795 if (GET_CODE (operands[1]) == CONST_INT)
4797 rtx reg = gen_reg_rtx (SImode);
4799 emit_insn (gen_movsi (reg, operands[1]));
4800 operands[1] = gen_lowpart (HImode, reg);
4803 /* ??? We shouldn't really get invalid addresses here, but this can
4804 happen if we are passed a SP (never OK for HImode/QImode) or
4805 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4806 HImode/QImode) relative address. */
4807 /* ??? This should perhaps be fixed elsewhere, for instance, in
4808 fixup_stack_1, by checking for other kinds of invalid addresses,
4809 e.g. a bare reference to a virtual register. This may confuse the
4810 alpha though, which must handle this case differently. */
4811 if (GET_CODE (operands[0]) == MEM
4812 && !memory_address_p (GET_MODE (operands[0]),
4813 XEXP (operands[0], 0)))
4815 = replace_equiv_address (operands[0],
4816 copy_to_reg (XEXP (operands[0], 0)));
4818 if (GET_CODE (operands[1]) == MEM
4819 && !memory_address_p (GET_MODE (operands[1]),
4820 XEXP (operands[1], 0)))
4822 = replace_equiv_address (operands[1],
4823 copy_to_reg (XEXP (operands[1], 0)));
4825 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4827 rtx reg = gen_reg_rtx (SImode);
4829 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4830 operands[1] = gen_lowpart (HImode, reg);
4833 if (GET_CODE (operands[0]) == MEM)
4834 operands[1] = force_reg (HImode, operands[1]);
4836 else if (GET_CODE (operands[1]) == CONST_INT
4837 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4839 /* Handle loading a large integer during reload. */
4841 /* Writing a constant to memory needs a scratch, which should
4842 be handled with SECONDARY_RELOADs. */
4843 gcc_assert (GET_CODE (operands[0]) == REG);
4845 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4846 emit_insn (gen_movsi (operands[0], operands[1]));
4853 (define_insn "*thumb_movhi_insn"
4854 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4855 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
4857 && ( register_operand (operands[0], HImode)
4858 || register_operand (operands[1], HImode))"
4860 switch (which_alternative)
4862 case 0: return \"add %0, %1, #0\";
4863 case 2: return \"strh %1, %0\";
4864 case 3: return \"mov %0, %1\";
4865 case 4: return \"mov %0, %1\";
4866 case 5: return \"mov %0, %1\";
4867 default: gcc_unreachable ();
4869 /* The stack pointer can end up being taken as an index register.
4870 Catch this case here and deal with it. */
4871 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4872 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4873 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4876 ops[0] = operands[0];
4877 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4879 output_asm_insn (\"mov %0, %1\", ops);
4881 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4884 return \"ldrh %0, %1\";
4886 [(set_attr "length" "2,4,2,2,2,2")
4887 (set_attr "type" "*,load1,store1,*,*,*")]
4891 (define_expand "movhi_bytes"
4892 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4894 (zero_extend:SI (match_dup 6)))
4895 (set (match_operand:SI 0 "" "")
4896 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4901 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4903 mem1 = change_address (operands[1], QImode, addr);
4904 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
4905 operands[0] = gen_lowpart (SImode, operands[0]);
4907 operands[2] = gen_reg_rtx (SImode);
4908 operands[3] = gen_reg_rtx (SImode);
4911 if (BYTES_BIG_ENDIAN)
4913 operands[4] = operands[2];
4914 operands[5] = operands[3];
4918 operands[4] = operands[3];
4919 operands[5] = operands[2];
4924 (define_expand "movhi_bigend"
4926 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4929 (ashiftrt:SI (match_dup 2) (const_int 16)))
4930 (set (match_operand:HI 0 "s_register_operand" "")
4934 operands[2] = gen_reg_rtx (SImode);
4935 operands[3] = gen_reg_rtx (SImode);
4936 operands[4] = gen_lowpart (HImode, operands[3]);
4940 ;; Pattern to recognize insn generated default case above
4941 (define_insn "*movhi_insn_arch4"
4942 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4943 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4946 && (GET_CODE (operands[1]) != CONST_INT
4947 || const_ok_for_arm (INTVAL (operands[1]))
4948 || const_ok_for_arm (~INTVAL (operands[1])))"
4950 mov%?\\t%0, %1\\t%@ movhi
4951 mvn%?\\t%0, #%B1\\t%@ movhi
4952 str%?h\\t%1, %0\\t%@ movhi
4953 ldr%?h\\t%0, %1\\t%@ movhi"
4954 [(set_attr "type" "*,*,store1,load1")
4955 (set_attr "predicable" "yes")
4956 (set_attr "pool_range" "*,*,*,256")
4957 (set_attr "neg_pool_range" "*,*,*,244")]
4960 (define_insn "*movhi_bytes"
4961 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4962 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4965 mov%?\\t%0, %1\\t%@ movhi
4966 mvn%?\\t%0, #%B1\\t%@ movhi"
4967 [(set_attr "predicable" "yes")]
4970 (define_expand "thumb_movhi_clobber"
4971 [(set (match_operand:HI 0 "memory_operand" "")
4972 (match_operand:HI 1 "register_operand" ""))
4973 (clobber (match_operand:DI 2 "register_operand" ""))]
4976 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
4977 && REGNO (operands[1]) <= LAST_LO_REGNUM)
4979 emit_insn (gen_movhi (operands[0], operands[1]));
4982 /* XXX Fixme, need to handle other cases here as well. */
4987 ;; We use a DImode scratch because we may occasionally need an additional
4988 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4989 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4990 (define_expand "reload_outhi"
4991 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4992 (match_operand:HI 1 "s_register_operand" "r")
4993 (match_operand:DI 2 "s_register_operand" "=&l")])]
4996 arm_reload_out_hi (operands);
4998 thumb_reload_out_hi (operands);
5003 (define_expand "reload_inhi"
5004 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
5005 (match_operand:HI 1 "arm_reload_memory_operand" "o")
5006 (match_operand:DI 2 "s_register_operand" "=&r")])]
5010 arm_reload_in_hi (operands);
5012 thumb_reload_out_hi (operands);
5016 (define_expand "movqi"
5017 [(set (match_operand:QI 0 "general_operand" "")
5018 (match_operand:QI 1 "general_operand" ""))]
5021 /* Everything except mem = const or mem = mem can be done easily */
5023 if (!no_new_pseudos)
5025 if (GET_CODE (operands[1]) == CONST_INT)
5027 rtx reg = gen_reg_rtx (SImode);
5029 emit_insn (gen_movsi (reg, operands[1]));
5030 operands[1] = gen_lowpart (QImode, reg);
5035 /* ??? We shouldn't really get invalid addresses here, but this can
5036 happen if we are passed a SP (never OK for HImode/QImode) or
5037 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5038 HImode/QImode) relative address. */
5039 /* ??? This should perhaps be fixed elsewhere, for instance, in
5040 fixup_stack_1, by checking for other kinds of invalid addresses,
5041 e.g. a bare reference to a virtual register. This may confuse the
5042 alpha though, which must handle this case differently. */
5043 if (GET_CODE (operands[0]) == MEM
5044 && !memory_address_p (GET_MODE (operands[0]),
5045 XEXP (operands[0], 0)))
5047 = replace_equiv_address (operands[0],
5048 copy_to_reg (XEXP (operands[0], 0)));
5049 if (GET_CODE (operands[1]) == MEM
5050 && !memory_address_p (GET_MODE (operands[1]),
5051 XEXP (operands[1], 0)))
5053 = replace_equiv_address (operands[1],
5054 copy_to_reg (XEXP (operands[1], 0)));
5057 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5059 rtx reg = gen_reg_rtx (SImode);
5061 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5062 operands[1] = gen_lowpart (QImode, reg);
5065 if (GET_CODE (operands[0]) == MEM)
5066 operands[1] = force_reg (QImode, operands[1]);
5068 else if (TARGET_THUMB
5069 && GET_CODE (operands[1]) == CONST_INT
5070 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
5072 /* Handle loading a large integer during reload. */
5074 /* Writing a constant to memory needs a scratch, which should
5075 be handled with SECONDARY_RELOADs. */
5076 gcc_assert (GET_CODE (operands[0]) == REG);
5078 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5079 emit_insn (gen_movsi (operands[0], operands[1]));
5086 (define_insn "*arm_movqi_insn"
5087 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5088 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5090 && ( register_operand (operands[0], QImode)
5091 || register_operand (operands[1], QImode))"
5097 [(set_attr "type" "*,*,load1,store1")
5098 (set_attr "predicable" "yes")]
5101 (define_insn "*thumb_movqi_insn"
5102 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5103 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
5105 && ( register_operand (operands[0], QImode)
5106 || register_operand (operands[1], QImode))"
5114 [(set_attr "length" "2")
5115 (set_attr "type" "*,load1,store1,*,*,*")
5116 (set_attr "pool_range" "*,32,*,*,*,*")]
5119 (define_expand "movsf"
5120 [(set (match_operand:SF 0 "general_operand" "")
5121 (match_operand:SF 1 "general_operand" ""))]
5126 if (GET_CODE (operands[0]) == MEM)
5127 operands[1] = force_reg (SFmode, operands[1]);
5129 else /* TARGET_THUMB */
5131 if (!no_new_pseudos)
5133 if (GET_CODE (operands[0]) != REG)
5134 operands[1] = force_reg (SFmode, operands[1]);
5141 [(set (match_operand:SF 0 "nonimmediate_operand" "")
5142 (match_operand:SF 1 "immediate_operand" ""))]
5144 && !(TARGET_HARD_FLOAT && TARGET_FPA)
5146 && GET_CODE (operands[1]) == CONST_DOUBLE"
5147 [(set (match_dup 2) (match_dup 3))]
5149 operands[2] = gen_lowpart (SImode, operands[0]);
5150 operands[3] = gen_lowpart (SImode, operands[1]);
5151 if (operands[2] == 0 || operands[3] == 0)
5156 (define_insn "*arm_movsf_soft_insn"
5157 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5158 (match_operand:SF 1 "general_operand" "r,mE,r"))]
5160 && TARGET_SOFT_FLOAT
5161 && (GET_CODE (operands[0]) != MEM
5162 || register_operand (operands[1], SFmode))"
5165 ldr%?\\t%0, %1\\t%@ float
5166 str%?\\t%1, %0\\t%@ float"
5167 [(set_attr "length" "4,4,4")
5168 (set_attr "predicable" "yes")
5169 (set_attr "type" "*,load1,store1")
5170 (set_attr "pool_range" "*,4096,*")
5171 (set_attr "neg_pool_range" "*,4084,*")]
5174 ;;; ??? This should have alternatives for constants.
5175 (define_insn "*thumb_movsf_insn"
5176 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5177 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
5179 && ( register_operand (operands[0], SFmode)
5180 || register_operand (operands[1], SFmode))"
5189 [(set_attr "length" "2")
5190 (set_attr "type" "*,load1,store1,load1,store1,*,*")
5191 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5194 (define_expand "movdf"
5195 [(set (match_operand:DF 0 "general_operand" "")
5196 (match_operand:DF 1 "general_operand" ""))]
5201 if (GET_CODE (operands[0]) == MEM)
5202 operands[1] = force_reg (DFmode, operands[1]);
5204 else /* TARGET_THUMB */
5206 if (!no_new_pseudos)
5208 if (GET_CODE (operands[0]) != REG)
5209 operands[1] = force_reg (DFmode, operands[1]);
5215 ;; Reloading a df mode value stored in integer regs to memory can require a
5217 (define_expand "reload_outdf"
5218 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5219 (match_operand:DF 1 "s_register_operand" "r")
5220 (match_operand:SI 2 "s_register_operand" "=&r")]
5224 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5227 operands[2] = XEXP (operands[0], 0);
5228 else if (code == POST_INC || code == PRE_DEC)
5230 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5231 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5232 emit_insn (gen_movdi (operands[0], operands[1]));
5235 else if (code == PRE_INC)
5237 rtx reg = XEXP (XEXP (operands[0], 0), 0);
5239 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5242 else if (code == POST_DEC)
5243 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5245 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5246 XEXP (XEXP (operands[0], 0), 1)));
5248 emit_insn (gen_rtx_SET (VOIDmode,
5249 replace_equiv_address (operands[0], operands[2]),
5252 if (code == POST_DEC)
5253 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5259 (define_insn "*movdf_soft_insn"
5260 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5261 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5262 "TARGET_ARM && TARGET_SOFT_FLOAT
5265 switch (which_alternative)
5272 return output_move_double (operands);
5275 [(set_attr "length" "8,12,16,8,8")
5276 (set_attr "type" "*,*,*,load2,store2")
5277 (set_attr "pool_range" "1020")
5278 (set_attr "neg_pool_range" "1008")]
5281 ;;; ??? This should have alternatives for constants.
5282 ;;; ??? This was originally identical to the movdi_insn pattern.
5283 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5284 ;;; thumb_reorg with a memory reference.
5285 (define_insn "*thumb_movdf_insn"
5286 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5287 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
5289 && ( register_operand (operands[0], DFmode)
5290 || register_operand (operands[1], DFmode))"
5292 switch (which_alternative)
5296 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5297 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5298 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5300 return \"ldmia\\t%1, {%0, %H0}\";
5302 return \"stmia\\t%0, {%1, %H1}\";
5304 return thumb_load_double_from_address (operands);
5306 operands[2] = gen_rtx_MEM (SImode,
5307 plus_constant (XEXP (operands[0], 0), 4));
5308 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5311 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5312 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5313 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5316 [(set_attr "length" "4,2,2,6,4,4")
5317 (set_attr "type" "*,load2,store2,load2,store2,*")
5318 (set_attr "pool_range" "*,*,*,1020,*,*")]
5321 (define_expand "movxf"
5322 [(set (match_operand:XF 0 "general_operand" "")
5323 (match_operand:XF 1 "general_operand" ""))]
5324 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5326 if (GET_CODE (operands[0]) == MEM)
5327 operands[1] = force_reg (XFmode, operands[1]);
5332 (define_expand "movv2si"
5333 [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5334 (match_operand:V2SI 1 "general_operand" ""))]
5335 "TARGET_REALLY_IWMMXT"
5339 (define_expand "movv4hi"
5340 [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5341 (match_operand:V4HI 1 "general_operand" ""))]
5342 "TARGET_REALLY_IWMMXT"
5346 (define_expand "movv8qi"
5347 [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5348 (match_operand:V8QI 1 "general_operand" ""))]
5349 "TARGET_REALLY_IWMMXT"
5354 ;; load- and store-multiple insns
5355 ;; The arm can load/store any set of registers, provided that they are in
5356 ;; ascending order; but that is beyond GCC so stick with what it knows.
5358 (define_expand "load_multiple"
5359 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5360 (match_operand:SI 1 "" ""))
5361 (use (match_operand:SI 2 "" ""))])]
5364 HOST_WIDE_INT offset = 0;
5366 /* Support only fixed point registers. */
5367 if (GET_CODE (operands[2]) != CONST_INT
5368 || INTVAL (operands[2]) > 14
5369 || INTVAL (operands[2]) < 2
5370 || GET_CODE (operands[1]) != MEM
5371 || GET_CODE (operands[0]) != REG
5372 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5373 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5377 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5378 force_reg (SImode, XEXP (operands[1], 0)),
5379 TRUE, FALSE, operands[1], &offset);
5382 ;; Load multiple with write-back
5384 (define_insn "*ldmsi_postinc4"
5385 [(match_parallel 0 "load_multiple_operation"
5386 [(set (match_operand:SI 1 "s_register_operand" "=r")
5387 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5389 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5390 (mem:SI (match_dup 2)))
5391 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5392 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5393 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5394 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5395 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5396 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5397 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5398 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5399 [(set_attr "type" "load4")
5400 (set_attr "predicable" "yes")]
5403 (define_insn "*ldmsi_postinc4_thumb"
5404 [(match_parallel 0 "load_multiple_operation"
5405 [(set (match_operand:SI 1 "s_register_operand" "=l")
5406 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5408 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5409 (mem:SI (match_dup 2)))
5410 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5411 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5412 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5413 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5414 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5415 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5416 "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5417 "ldmia\\t%1!, {%3, %4, %5, %6}"
5418 [(set_attr "type" "load4")]
5421 (define_insn "*ldmsi_postinc3"
5422 [(match_parallel 0 "load_multiple_operation"
5423 [(set (match_operand:SI 1 "s_register_operand" "=r")
5424 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5426 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5427 (mem:SI (match_dup 2)))
5428 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5429 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5430 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5431 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5432 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5433 "ldm%?ia\\t%1!, {%3, %4, %5}"
5434 [(set_attr "type" "load3")
5435 (set_attr "predicable" "yes")]
5438 (define_insn "*ldmsi_postinc2"
5439 [(match_parallel 0 "load_multiple_operation"
5440 [(set (match_operand:SI 1 "s_register_operand" "=r")
5441 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5443 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5444 (mem:SI (match_dup 2)))
5445 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5446 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5447 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5448 "ldm%?ia\\t%1!, {%3, %4}"
5449 [(set_attr "type" "load2")
5450 (set_attr "predicable" "yes")]
5453 ;; Ordinary load multiple
5455 (define_insn "*ldmsi4"
5456 [(match_parallel 0 "load_multiple_operation"
5457 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5458 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5459 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5460 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5461 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5462 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5463 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5464 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5465 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5466 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5467 [(set_attr "type" "load4")
5468 (set_attr "predicable" "yes")]
5471 (define_insn "*ldmsi3"
5472 [(match_parallel 0 "load_multiple_operation"
5473 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5474 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5475 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5476 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5477 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5478 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5479 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5480 "ldm%?ia\\t%1, {%2, %3, %4}"
5481 [(set_attr "type" "load3")
5482 (set_attr "predicable" "yes")]
5485 (define_insn "*ldmsi2"
5486 [(match_parallel 0 "load_multiple_operation"
5487 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5488 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5489 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5490 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5491 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5492 "ldm%?ia\\t%1, {%2, %3}"
5493 [(set_attr "type" "load2")
5494 (set_attr "predicable" "yes")]
5497 (define_expand "store_multiple"
5498 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5499 (match_operand:SI 1 "" ""))
5500 (use (match_operand:SI 2 "" ""))])]
5503 HOST_WIDE_INT offset = 0;
5505 /* Support only fixed point registers. */
5506 if (GET_CODE (operands[2]) != CONST_INT
5507 || INTVAL (operands[2]) > 14
5508 || INTVAL (operands[2]) < 2
5509 || GET_CODE (operands[1]) != REG
5510 || GET_CODE (operands[0]) != MEM
5511 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5512 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5516 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5517 force_reg (SImode, XEXP (operands[0], 0)),
5518 TRUE, FALSE, operands[0], &offset);
5521 ;; Store multiple with write-back
5523 (define_insn "*stmsi_postinc4"
5524 [(match_parallel 0 "store_multiple_operation"
5525 [(set (match_operand:SI 1 "s_register_operand" "=r")
5526 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5528 (set (mem:SI (match_dup 2))
5529 (match_operand:SI 3 "arm_hard_register_operand" ""))
5530 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5531 (match_operand:SI 4 "arm_hard_register_operand" ""))
5532 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5533 (match_operand:SI 5 "arm_hard_register_operand" ""))
5534 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5535 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5536 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5537 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5538 [(set_attr "predicable" "yes")
5539 (set_attr "type" "store4")]
5542 (define_insn "*stmsi_postinc4_thumb"
5543 [(match_parallel 0 "store_multiple_operation"
5544 [(set (match_operand:SI 1 "s_register_operand" "=l")
5545 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5547 (set (mem:SI (match_dup 2))
5548 (match_operand:SI 3 "arm_hard_register_operand" ""))
5549 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5550 (match_operand:SI 4 "arm_hard_register_operand" ""))
5551 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5552 (match_operand:SI 5 "arm_hard_register_operand" ""))
5553 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5554 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5555 "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5556 "stmia\\t%1!, {%3, %4, %5, %6}"
5557 [(set_attr "type" "store4")]
5560 (define_insn "*stmsi_postinc3"
5561 [(match_parallel 0 "store_multiple_operation"
5562 [(set (match_operand:SI 1 "s_register_operand" "=r")
5563 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5565 (set (mem:SI (match_dup 2))
5566 (match_operand:SI 3 "arm_hard_register_operand" ""))
5567 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5568 (match_operand:SI 4 "arm_hard_register_operand" ""))
5569 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5570 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5571 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5572 "stm%?ia\\t%1!, {%3, %4, %5}"
5573 [(set_attr "predicable" "yes")
5574 (set_attr "type" "store3")]
5577 (define_insn "*stmsi_postinc2"
5578 [(match_parallel 0 "store_multiple_operation"
5579 [(set (match_operand:SI 1 "s_register_operand" "=r")
5580 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5582 (set (mem:SI (match_dup 2))
5583 (match_operand:SI 3 "arm_hard_register_operand" ""))
5584 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5585 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5586 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5587 "stm%?ia\\t%1!, {%3, %4}"
5588 [(set_attr "predicable" "yes")
5589 (set_attr "type" "store2")]
5592 ;; Ordinary store multiple
5594 (define_insn "*stmsi4"
5595 [(match_parallel 0 "store_multiple_operation"
5596 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5597 (match_operand:SI 2 "arm_hard_register_operand" ""))
5598 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5599 (match_operand:SI 3 "arm_hard_register_operand" ""))
5600 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5601 (match_operand:SI 4 "arm_hard_register_operand" ""))
5602 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5603 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5604 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5605 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5606 [(set_attr "predicable" "yes")
5607 (set_attr "type" "store4")]
5610 (define_insn "*stmsi3"
5611 [(match_parallel 0 "store_multiple_operation"
5612 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5613 (match_operand:SI 2 "arm_hard_register_operand" ""))
5614 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5615 (match_operand:SI 3 "arm_hard_register_operand" ""))
5616 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5617 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5618 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5619 "stm%?ia\\t%1, {%2, %3, %4}"
5620 [(set_attr "predicable" "yes")
5621 (set_attr "type" "store3")]
5624 (define_insn "*stmsi2"
5625 [(match_parallel 0 "store_multiple_operation"
5626 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5627 (match_operand:SI 2 "arm_hard_register_operand" ""))
5628 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5629 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5630 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5631 "stm%?ia\\t%1, {%2, %3}"
5632 [(set_attr "predicable" "yes")
5633 (set_attr "type" "store2")]
5636 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5637 ;; We could let this apply for blocks of less than this, but it clobbers so
5638 ;; many registers that there is then probably a better way.
5640 (define_expand "movmemqi"
5641 [(match_operand:BLK 0 "general_operand" "")
5642 (match_operand:BLK 1 "general_operand" "")
5643 (match_operand:SI 2 "const_int_operand" "")
5644 (match_operand:SI 3 "const_int_operand" "")]
5649 if (arm_gen_movmemqi (operands))
5653 else /* TARGET_THUMB */
5655 if ( INTVAL (operands[3]) != 4
5656 || INTVAL (operands[2]) > 48)
5659 thumb_expand_movmemqi (operands);
5665 ;; Thumb block-move insns
5667 (define_insn "movmem12b"
5668 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5669 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5670 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5671 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5672 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5673 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5674 (set (match_operand:SI 0 "register_operand" "=l")
5675 (plus:SI (match_dup 2) (const_int 12)))
5676 (set (match_operand:SI 1 "register_operand" "=l")
5677 (plus:SI (match_dup 3) (const_int 12)))
5678 (clobber (match_scratch:SI 4 "=&l"))
5679 (clobber (match_scratch:SI 5 "=&l"))
5680 (clobber (match_scratch:SI 6 "=&l"))]
5682 "* return thumb_output_move_mem_multiple (3, operands);"
5683 [(set_attr "length" "4")
5684 ; This isn't entirely accurate... It loads as well, but in terms of
5685 ; scheduling the following insn it is better to consider it as a store
5686 (set_attr "type" "store3")]
5689 (define_insn "movmem8b"
5690 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5691 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5692 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5693 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5694 (set (match_operand:SI 0 "register_operand" "=l")
5695 (plus:SI (match_dup 2) (const_int 8)))
5696 (set (match_operand:SI 1 "register_operand" "=l")
5697 (plus:SI (match_dup 3) (const_int 8)))
5698 (clobber (match_scratch:SI 4 "=&l"))
5699 (clobber (match_scratch:SI 5 "=&l"))]
5701 "* return thumb_output_move_mem_multiple (2, operands);"
5702 [(set_attr "length" "4")
5703 ; This isn't entirely accurate... It loads as well, but in terms of
5704 ; scheduling the following insn it is better to consider it as a store
5705 (set_attr "type" "store2")]
5710 ;; Compare & branch insns
5711 ;; The range calculations are based as follows:
5712 ;; For forward branches, the address calculation returns the address of
5713 ;; the next instruction. This is 2 beyond the branch instruction.
5714 ;; For backward branches, the address calculation returns the address of
5715 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5716 ;; instruction for the shortest sequence, and 4 before the branch instruction
5717 ;; if we have to jump around an unconditional branch.
5718 ;; To the basic branch range the PC offset must be added (this is +4).
5719 ;; So for forward branches we have
5720 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5721 ;; And for backward branches we have
5722 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5724 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5725 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5727 (define_expand "cbranchsi4"
5728 [(set (pc) (if_then_else
5729 (match_operator 0 "arm_comparison_operator"
5730 [(match_operand:SI 1 "s_register_operand" "")
5731 (match_operand:SI 2 "nonmemory_operand" "")])
5732 (label_ref (match_operand 3 "" ""))
5736 if (thumb_cmpneg_operand (operands[2], SImode))
5738 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5739 operands[3], operands[0]));
5742 if (!thumb_cmp_operand (operands[2], SImode))
5743 operands[2] = force_reg (SImode, operands[2]);
5746 (define_insn "*cbranchsi4_insn"
5747 [(set (pc) (if_then_else
5748 (match_operator 0 "arm_comparison_operator"
5749 [(match_operand:SI 1 "s_register_operand" "l,*h")
5750 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5751 (label_ref (match_operand 3 "" ""))
5755 output_asm_insn (\"cmp\\t%1, %2\", operands);
5757 switch (get_attr_length (insn))
5759 case 4: return \"b%d0\\t%l3\";
5760 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5761 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5764 [(set (attr "far_jump")
5766 (eq_attr "length" "8")
5767 (const_string "yes")
5768 (const_string "no")))
5769 (set (attr "length")
5771 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5772 (le (minus (match_dup 3) (pc)) (const_int 256)))
5775 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5776 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5781 (define_insn "cbranchsi4_scratch"
5782 [(set (pc) (if_then_else
5783 (match_operator 4 "arm_comparison_operator"
5784 [(match_operand:SI 1 "s_register_operand" "l,0")
5785 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5786 (label_ref (match_operand 3 "" ""))
5788 (clobber (match_scratch:SI 0 "=l,l"))]
5791 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5793 switch (get_attr_length (insn))
5795 case 4: return \"b%d4\\t%l3\";
5796 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5797 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5800 [(set (attr "far_jump")
5802 (eq_attr "length" "8")
5803 (const_string "yes")
5804 (const_string "no")))
5805 (set (attr "length")
5807 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5808 (le (minus (match_dup 3) (pc)) (const_int 256)))
5811 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5812 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5816 (define_insn "*movsi_cbranchsi4"
5819 (match_operator 3 "arm_comparison_operator"
5820 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5822 (label_ref (match_operand 2 "" ""))
5824 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5828 if (which_alternative == 0)
5829 output_asm_insn (\"cmp\t%0, #0\", operands);
5830 else if (which_alternative == 1)
5831 output_asm_insn (\"sub\t%0, %1, #0\", operands);
5834 output_asm_insn (\"cmp\t%1, #0\", operands);
5835 if (which_alternative == 2)
5836 output_asm_insn (\"mov\t%0, %1\", operands);
5838 output_asm_insn (\"str\t%1, %0\", operands);
5840 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5842 case 4: return \"b%d3\\t%l2\";
5843 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5844 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5847 [(set (attr "far_jump")
5849 (ior (and (gt (symbol_ref ("which_alternative"))
5851 (eq_attr "length" "8"))
5852 (eq_attr "length" "10"))
5853 (const_string "yes")
5854 (const_string "no")))
5855 (set (attr "length")
5857 (le (symbol_ref ("which_alternative"))
5860 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5861 (le (minus (match_dup 2) (pc)) (const_int 256)))
5864 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5865 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5869 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5870 (le (minus (match_dup 2) (pc)) (const_int 256)))
5873 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5874 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5879 (define_insn "*negated_cbranchsi4"
5882 (match_operator 0 "equality_operator"
5883 [(match_operand:SI 1 "s_register_operand" "l")
5884 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5885 (label_ref (match_operand 3 "" ""))
5889 output_asm_insn (\"cmn\\t%1, %2\", operands);
5890 switch (get_attr_length (insn))
5892 case 4: return \"b%d0\\t%l3\";
5893 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5894 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5897 [(set (attr "far_jump")
5899 (eq_attr "length" "8")
5900 (const_string "yes")
5901 (const_string "no")))
5902 (set (attr "length")
5904 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5905 (le (minus (match_dup 3) (pc)) (const_int 256)))
5908 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5909 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5914 (define_insn "*tbit_cbranch"
5917 (match_operator 0 "equality_operator"
5918 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5920 (match_operand:SI 2 "const_int_operand" "i"))
5922 (label_ref (match_operand 3 "" ""))
5924 (clobber (match_scratch:SI 4 "=l"))]
5929 op[0] = operands[4];
5930 op[1] = operands[1];
5931 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5933 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5934 switch (get_attr_length (insn))
5936 case 4: return \"b%d0\\t%l3\";
5937 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5938 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5941 [(set (attr "far_jump")
5943 (eq_attr "length" "8")
5944 (const_string "yes")
5945 (const_string "no")))
5946 (set (attr "length")
5948 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5949 (le (minus (match_dup 3) (pc)) (const_int 256)))
5952 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5953 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5958 (define_insn "*tstsi3_cbranch"
5961 (match_operator 3 "equality_operator"
5962 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5963 (match_operand:SI 1 "s_register_operand" "l"))
5965 (label_ref (match_operand 2 "" ""))
5970 output_asm_insn (\"tst\\t%0, %1\", operands);
5971 switch (get_attr_length (insn))
5973 case 4: return \"b%d3\\t%l2\";
5974 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5975 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5978 [(set (attr "far_jump")
5980 (eq_attr "length" "8")
5981 (const_string "yes")
5982 (const_string "no")))
5983 (set (attr "length")
5985 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5986 (le (minus (match_dup 2) (pc)) (const_int 256)))
5989 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5990 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5995 (define_insn "*andsi3_cbranch"
5998 (match_operator 5 "equality_operator"
5999 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6000 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6002 (label_ref (match_operand 4 "" ""))
6004 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6005 (and:SI (match_dup 2) (match_dup 3)))
6006 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6010 if (which_alternative == 0)
6011 output_asm_insn (\"and\\t%0, %3\", operands);
6012 else if (which_alternative == 1)
6014 output_asm_insn (\"and\\t%1, %3\", operands);
6015 output_asm_insn (\"mov\\t%0, %1\", operands);
6019 output_asm_insn (\"and\\t%1, %3\", operands);
6020 output_asm_insn (\"str\\t%1, %0\", operands);
6023 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6025 case 4: return \"b%d5\\t%l4\";
6026 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6027 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6030 [(set (attr "far_jump")
6032 (ior (and (eq (symbol_ref ("which_alternative"))
6034 (eq_attr "length" "8"))
6035 (eq_attr "length" "10"))
6036 (const_string "yes")
6037 (const_string "no")))
6038 (set (attr "length")
6040 (eq (symbol_ref ("which_alternative"))
6043 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6044 (le (minus (match_dup 4) (pc)) (const_int 256)))
6047 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6048 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6052 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6053 (le (minus (match_dup 4) (pc)) (const_int 256)))
6056 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6057 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6062 (define_insn "*orrsi3_cbranch_scratch"
6065 (match_operator 4 "equality_operator"
6066 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6067 (match_operand:SI 2 "s_register_operand" "l"))
6069 (label_ref (match_operand 3 "" ""))
6071 (clobber (match_scratch:SI 0 "=l"))]
6075 output_asm_insn (\"orr\\t%0, %2\", operands);
6076 switch (get_attr_length (insn))
6078 case 4: return \"b%d4\\t%l3\";
6079 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6080 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6083 [(set (attr "far_jump")
6085 (eq_attr "length" "8")
6086 (const_string "yes")
6087 (const_string "no")))
6088 (set (attr "length")
6090 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6091 (le (minus (match_dup 3) (pc)) (const_int 256)))
6094 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6095 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6100 (define_insn "*orrsi3_cbranch"
6103 (match_operator 5 "equality_operator"
6104 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6105 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6107 (label_ref (match_operand 4 "" ""))
6109 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6110 (ior:SI (match_dup 2) (match_dup 3)))
6111 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6115 if (which_alternative == 0)
6116 output_asm_insn (\"orr\\t%0, %3\", operands);
6117 else if (which_alternative == 1)
6119 output_asm_insn (\"orr\\t%1, %3\", operands);
6120 output_asm_insn (\"mov\\t%0, %1\", operands);
6124 output_asm_insn (\"orr\\t%1, %3\", operands);
6125 output_asm_insn (\"str\\t%1, %0\", operands);
6128 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6130 case 4: return \"b%d5\\t%l4\";
6131 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6132 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6135 [(set (attr "far_jump")
6137 (ior (and (eq (symbol_ref ("which_alternative"))
6139 (eq_attr "length" "8"))
6140 (eq_attr "length" "10"))
6141 (const_string "yes")
6142 (const_string "no")))
6143 (set (attr "length")
6145 (eq (symbol_ref ("which_alternative"))
6148 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6149 (le (minus (match_dup 4) (pc)) (const_int 256)))
6152 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6153 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6157 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6158 (le (minus (match_dup 4) (pc)) (const_int 256)))
6161 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6162 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6167 (define_insn "*xorsi3_cbranch_scratch"
6170 (match_operator 4 "equality_operator"
6171 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6172 (match_operand:SI 2 "s_register_operand" "l"))
6174 (label_ref (match_operand 3 "" ""))
6176 (clobber (match_scratch:SI 0 "=l"))]
6180 output_asm_insn (\"eor\\t%0, %2\", operands);
6181 switch (get_attr_length (insn))
6183 case 4: return \"b%d4\\t%l3\";
6184 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6185 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6188 [(set (attr "far_jump")
6190 (eq_attr "length" "8")
6191 (const_string "yes")
6192 (const_string "no")))
6193 (set (attr "length")
6195 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6196 (le (minus (match_dup 3) (pc)) (const_int 256)))
6199 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6200 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6205 (define_insn "*xorsi3_cbranch"
6208 (match_operator 5 "equality_operator"
6209 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6210 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6212 (label_ref (match_operand 4 "" ""))
6214 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6215 (xor:SI (match_dup 2) (match_dup 3)))
6216 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6220 if (which_alternative == 0)
6221 output_asm_insn (\"eor\\t%0, %3\", operands);
6222 else if (which_alternative == 1)
6224 output_asm_insn (\"eor\\t%1, %3\", operands);
6225 output_asm_insn (\"mov\\t%0, %1\", operands);
6229 output_asm_insn (\"eor\\t%1, %3\", operands);
6230 output_asm_insn (\"str\\t%1, %0\", operands);
6233 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6235 case 4: return \"b%d5\\t%l4\";
6236 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6237 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6240 [(set (attr "far_jump")
6242 (ior (and (eq (symbol_ref ("which_alternative"))
6244 (eq_attr "length" "8"))
6245 (eq_attr "length" "10"))
6246 (const_string "yes")
6247 (const_string "no")))
6248 (set (attr "length")
6250 (eq (symbol_ref ("which_alternative"))
6253 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6254 (le (minus (match_dup 4) (pc)) (const_int 256)))
6257 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6258 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6262 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6263 (le (minus (match_dup 4) (pc)) (const_int 256)))
6266 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6267 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6272 (define_insn "*bicsi3_cbranch_scratch"
6275 (match_operator 4 "equality_operator"
6276 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6277 (match_operand:SI 1 "s_register_operand" "0"))
6279 (label_ref (match_operand 3 "" ""))
6281 (clobber (match_scratch:SI 0 "=l"))]
6285 output_asm_insn (\"bic\\t%0, %2\", operands);
6286 switch (get_attr_length (insn))
6288 case 4: return \"b%d4\\t%l3\";
6289 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6290 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6293 [(set (attr "far_jump")
6295 (eq_attr "length" "8")
6296 (const_string "yes")
6297 (const_string "no")))
6298 (set (attr "length")
6300 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6301 (le (minus (match_dup 3) (pc)) (const_int 256)))
6304 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6305 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6310 (define_insn "*bicsi3_cbranch"
6313 (match_operator 5 "equality_operator"
6314 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6315 (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6317 (label_ref (match_operand 4 "" ""))
6319 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6320 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6321 (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6325 if (which_alternative == 0)
6326 output_asm_insn (\"bic\\t%0, %3\", operands);
6327 else if (which_alternative <= 2)
6329 output_asm_insn (\"bic\\t%1, %3\", operands);
6330 /* It's ok if OP0 is a lo-reg, even though the mov will set the
6331 conditions again, since we're only testing for equality. */
6332 output_asm_insn (\"mov\\t%0, %1\", operands);
6336 output_asm_insn (\"bic\\t%1, %3\", operands);
6337 output_asm_insn (\"str\\t%1, %0\", operands);
6340 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6342 case 4: return \"b%d5\\t%l4\";
6343 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6344 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6347 [(set (attr "far_jump")
6349 (ior (and (eq (symbol_ref ("which_alternative"))
6351 (eq_attr "length" "8"))
6352 (eq_attr "length" "10"))
6353 (const_string "yes")
6354 (const_string "no")))
6355 (set (attr "length")
6357 (eq (symbol_ref ("which_alternative"))
6360 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6361 (le (minus (match_dup 4) (pc)) (const_int 256)))
6364 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6365 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6369 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6370 (le (minus (match_dup 4) (pc)) (const_int 256)))
6373 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6374 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6379 (define_insn "*cbranchne_decr1"
6381 (if_then_else (match_operator 3 "equality_operator"
6382 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6384 (label_ref (match_operand 4 "" ""))
6386 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6387 (plus:SI (match_dup 2) (const_int -1)))
6388 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6393 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6395 VOIDmode, operands[2], const1_rtx);
6396 cond[1] = operands[4];
6398 if (which_alternative == 0)
6399 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6400 else if (which_alternative == 1)
6402 /* We must provide an alternative for a hi reg because reload
6403 cannot handle output reloads on a jump instruction, but we
6404 can't subtract into that. Fortunately a mov from lo to hi
6405 does not clobber the condition codes. */
6406 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6407 output_asm_insn (\"mov\\t%0, %1\", operands);
6411 /* Similarly, but the target is memory. */
6412 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6413 output_asm_insn (\"str\\t%1, %0\", operands);
6416 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6419 output_asm_insn (\"b%d0\\t%l1\", cond);
6422 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6423 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6425 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6426 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6430 [(set (attr "far_jump")
6432 (ior (and (eq (symbol_ref ("which_alternative"))
6434 (eq_attr "length" "8"))
6435 (eq_attr "length" "10"))
6436 (const_string "yes")
6437 (const_string "no")))
6438 (set_attr_alternative "length"
6442 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6443 (le (minus (match_dup 4) (pc)) (const_int 256)))
6446 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6447 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6452 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6453 (le (minus (match_dup 4) (pc)) (const_int 256)))
6456 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6457 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6462 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6463 (le (minus (match_dup 4) (pc)) (const_int 256)))
6466 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6467 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6472 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6473 (le (minus (match_dup 4) (pc)) (const_int 256)))
6476 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6477 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6482 (define_insn "*addsi3_cbranch"
6485 (match_operator 4 "comparison_operator"
6487 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6488 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6490 (label_ref (match_operand 5 "" ""))
6493 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6494 (plus:SI (match_dup 2) (match_dup 3)))
6495 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6497 && (GET_CODE (operands[4]) == EQ
6498 || GET_CODE (operands[4]) == NE
6499 || GET_CODE (operands[4]) == GE
6500 || GET_CODE (operands[4]) == LT)"
6506 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6507 cond[1] = operands[2];
6508 cond[2] = operands[3];
6510 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6511 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6513 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6515 if (which_alternative >= 3
6516 && which_alternative < 4)
6517 output_asm_insn (\"mov\\t%0, %1\", operands);
6518 else if (which_alternative >= 4)
6519 output_asm_insn (\"str\\t%1, %0\", operands);
6521 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6524 return \"b%d4\\t%l5\";
6526 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6528 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6532 [(set (attr "far_jump")
6534 (ior (and (lt (symbol_ref ("which_alternative"))
6536 (eq_attr "length" "8"))
6537 (eq_attr "length" "10"))
6538 (const_string "yes")
6539 (const_string "no")))
6540 (set (attr "length")
6542 (lt (symbol_ref ("which_alternative"))
6545 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6546 (le (minus (match_dup 5) (pc)) (const_int 256)))
6549 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6550 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6554 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6555 (le (minus (match_dup 5) (pc)) (const_int 256)))
6558 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6559 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6564 (define_insn "*addsi3_cbranch_scratch"
6567 (match_operator 3 "comparison_operator"
6569 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6570 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6572 (label_ref (match_operand 4 "" ""))
6574 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6576 && (GET_CODE (operands[3]) == EQ
6577 || GET_CODE (operands[3]) == NE
6578 || GET_CODE (operands[3]) == GE
6579 || GET_CODE (operands[3]) == LT)"
6582 switch (which_alternative)
6585 output_asm_insn (\"cmp\t%1, #%n2\", operands);
6588 output_asm_insn (\"cmn\t%1, %2\", operands);
6591 if (INTVAL (operands[2]) < 0)
6592 output_asm_insn (\"sub\t%0, %1, %2\", operands);
6594 output_asm_insn (\"add\t%0, %1, %2\", operands);
6597 if (INTVAL (operands[2]) < 0)
6598 output_asm_insn (\"sub\t%0, %0, %2\", operands);
6600 output_asm_insn (\"add\t%0, %0, %2\", operands);
6604 switch (get_attr_length (insn))
6607 return \"b%d3\\t%l4\";
6609 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6611 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6615 [(set (attr "far_jump")
6617 (eq_attr "length" "8")
6618 (const_string "yes")
6619 (const_string "no")))
6620 (set (attr "length")
6622 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6623 (le (minus (match_dup 4) (pc)) (const_int 256)))
6626 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6627 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6632 (define_insn "*subsi3_cbranch"
6635 (match_operator 4 "comparison_operator"
6637 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6638 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6640 (label_ref (match_operand 5 "" ""))
6642 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6643 (minus:SI (match_dup 2) (match_dup 3)))
6644 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6646 && (GET_CODE (operands[4]) == EQ
6647 || GET_CODE (operands[4]) == NE
6648 || GET_CODE (operands[4]) == GE
6649 || GET_CODE (operands[4]) == LT)"
6652 if (which_alternative == 0)
6653 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6654 else if (which_alternative == 1)
6656 /* We must provide an alternative for a hi reg because reload
6657 cannot handle output reloads on a jump instruction, but we
6658 can't subtract into that. Fortunately a mov from lo to hi
6659 does not clobber the condition codes. */
6660 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6661 output_asm_insn (\"mov\\t%0, %1\", operands);
6665 /* Similarly, but the target is memory. */
6666 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6667 output_asm_insn (\"str\\t%1, %0\", operands);
6670 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6673 return \"b%d4\\t%l5\";
6675 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6677 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6681 [(set (attr "far_jump")
6683 (ior (and (eq (symbol_ref ("which_alternative"))
6685 (eq_attr "length" "8"))
6686 (eq_attr "length" "10"))
6687 (const_string "yes")
6688 (const_string "no")))
6689 (set (attr "length")
6691 (eq (symbol_ref ("which_alternative"))
6694 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6695 (le (minus (match_dup 5) (pc)) (const_int 256)))
6698 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6699 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6703 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6704 (le (minus (match_dup 5) (pc)) (const_int 256)))
6707 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6708 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6713 (define_insn "*subsi3_cbranch_scratch"
6716 (match_operator 0 "arm_comparison_operator"
6717 [(minus:SI (match_operand:SI 1 "register_operand" "l")
6718 (match_operand:SI 2 "nonmemory_operand" "l"))
6720 (label_ref (match_operand 3 "" ""))
6723 && (GET_CODE (operands[0]) == EQ
6724 || GET_CODE (operands[0]) == NE
6725 || GET_CODE (operands[0]) == GE
6726 || GET_CODE (operands[0]) == LT)"
6728 output_asm_insn (\"cmp\\t%1, %2\", operands);
6729 switch (get_attr_length (insn))
6731 case 4: return \"b%d0\\t%l3\";
6732 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6733 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6736 [(set (attr "far_jump")
6738 (eq_attr "length" "8")
6739 (const_string "yes")
6740 (const_string "no")))
6741 (set (attr "length")
6743 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6744 (le (minus (match_dup 3) (pc)) (const_int 256)))
6747 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6748 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6753 ;; Comparison and test insns
6755 (define_expand "cmpsi"
6756 [(match_operand:SI 0 "s_register_operand" "")
6757 (match_operand:SI 1 "arm_add_operand" "")]
6760 arm_compare_op0 = operands[0];
6761 arm_compare_op1 = operands[1];
6766 (define_expand "cmpsf"
6767 [(match_operand:SF 0 "s_register_operand" "")
6768 (match_operand:SF 1 "arm_float_compare_operand" "")]
6769 "TARGET_ARM && TARGET_HARD_FLOAT"
6771 arm_compare_op0 = operands[0];
6772 arm_compare_op1 = operands[1];
6777 (define_expand "cmpdf"
6778 [(match_operand:DF 0 "s_register_operand" "")
6779 (match_operand:DF 1 "arm_float_compare_operand" "")]
6780 "TARGET_ARM && TARGET_HARD_FLOAT"
6782 arm_compare_op0 = operands[0];
6783 arm_compare_op1 = operands[1];
6788 (define_insn "*arm_cmpsi_insn"
6789 [(set (reg:CC CC_REGNUM)
6790 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6791 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
6796 [(set_attr "conds" "set")]
6799 (define_insn "*cmpsi_shiftsi"
6800 [(set (reg:CC CC_REGNUM)
6801 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6802 (match_operator:SI 3 "shift_operator"
6803 [(match_operand:SI 1 "s_register_operand" "r")
6804 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
6807 [(set_attr "conds" "set")
6808 (set_attr "shift" "1")
6809 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6810 (const_string "alu_shift")
6811 (const_string "alu_shift_reg")))]
6814 (define_insn "*cmpsi_shiftsi_swp"
6815 [(set (reg:CC_SWP CC_REGNUM)
6816 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6817 [(match_operand:SI 1 "s_register_operand" "r")
6818 (match_operand:SI 2 "reg_or_int_operand" "rM")])
6819 (match_operand:SI 0 "s_register_operand" "r")))]
6822 [(set_attr "conds" "set")
6823 (set_attr "shift" "1")
6824 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6825 (const_string "alu_shift")
6826 (const_string "alu_shift_reg")))]
6829 (define_insn "*cmpsi_negshiftsi_si"
6830 [(set (reg:CC_Z CC_REGNUM)
6832 (neg:SI (match_operator:SI 1 "shift_operator"
6833 [(match_operand:SI 2 "s_register_operand" "r")
6834 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6835 (match_operand:SI 0 "s_register_operand" "r")))]
6838 [(set_attr "conds" "set")
6839 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6840 (const_string "alu_shift")
6841 (const_string "alu_shift_reg")))]
6844 ;; Cirrus SF compare instruction
6845 (define_insn "*cirrus_cmpsf"
6846 [(set (reg:CCFP CC_REGNUM)
6847 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6848 (match_operand:SF 1 "cirrus_fp_register" "v")))]
6849 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6850 "cfcmps%?\\tr15, %V0, %V1"
6851 [(set_attr "type" "mav_farith")
6852 (set_attr "cirrus" "compare")]
6855 ;; Cirrus DF compare instruction
6856 (define_insn "*cirrus_cmpdf"
6857 [(set (reg:CCFP CC_REGNUM)
6858 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6859 (match_operand:DF 1 "cirrus_fp_register" "v")))]
6860 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6861 "cfcmpd%?\\tr15, %V0, %V1"
6862 [(set_attr "type" "mav_farith")
6863 (set_attr "cirrus" "compare")]
6866 ;; Cirrus DI compare instruction
6867 (define_expand "cmpdi"
6868 [(match_operand:DI 0 "cirrus_fp_register" "")
6869 (match_operand:DI 1 "cirrus_fp_register" "")]
6870 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6872 arm_compare_op0 = operands[0];
6873 arm_compare_op1 = operands[1];
6877 (define_insn "*cirrus_cmpdi"
6878 [(set (reg:CC CC_REGNUM)
6879 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6880 (match_operand:DI 1 "cirrus_fp_register" "v")))]
6881 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6882 "cfcmp64%?\\tr15, %V0, %V1"
6883 [(set_attr "type" "mav_farith")
6884 (set_attr "cirrus" "compare")]
6887 ; This insn allows redundant compares to be removed by cse, nothing should
6888 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6889 ; is deleted later on. The match_dup will match the mode here, so that
6890 ; mode changes of the condition codes aren't lost by this even though we don't
6891 ; specify what they are.
6893 (define_insn "*deleted_compare"
6894 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6896 "\\t%@ deleted compare"
6897 [(set_attr "conds" "set")
6898 (set_attr "length" "0")]
6902 ;; Conditional branch insns
6904 (define_expand "beq"
6906 (if_then_else (eq (match_dup 1) (const_int 0))
6907 (label_ref (match_operand 0 "" ""))
6910 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6913 (define_expand "bne"
6915 (if_then_else (ne (match_dup 1) (const_int 0))
6916 (label_ref (match_operand 0 "" ""))
6919 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6922 (define_expand "bgt"
6924 (if_then_else (gt (match_dup 1) (const_int 0))
6925 (label_ref (match_operand 0 "" ""))
6928 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6931 (define_expand "ble"
6933 (if_then_else (le (match_dup 1) (const_int 0))
6934 (label_ref (match_operand 0 "" ""))
6937 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6940 (define_expand "bge"
6942 (if_then_else (ge (match_dup 1) (const_int 0))
6943 (label_ref (match_operand 0 "" ""))
6946 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6949 (define_expand "blt"
6951 (if_then_else (lt (match_dup 1) (const_int 0))
6952 (label_ref (match_operand 0 "" ""))
6955 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6958 (define_expand "bgtu"
6960 (if_then_else (gtu (match_dup 1) (const_int 0))
6961 (label_ref (match_operand 0 "" ""))
6964 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6967 (define_expand "bleu"
6969 (if_then_else (leu (match_dup 1) (const_int 0))
6970 (label_ref (match_operand 0 "" ""))
6973 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6976 (define_expand "bgeu"
6978 (if_then_else (geu (match_dup 1) (const_int 0))
6979 (label_ref (match_operand 0 "" ""))
6982 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6985 (define_expand "bltu"
6987 (if_then_else (ltu (match_dup 1) (const_int 0))
6988 (label_ref (match_operand 0 "" ""))
6991 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6994 (define_expand "bunordered"
6996 (if_then_else (unordered (match_dup 1) (const_int 0))
6997 (label_ref (match_operand 0 "" ""))
6999 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7000 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7004 (define_expand "bordered"
7006 (if_then_else (ordered (match_dup 1) (const_int 0))
7007 (label_ref (match_operand 0 "" ""))
7009 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7010 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7014 (define_expand "bungt"
7016 (if_then_else (ungt (match_dup 1) (const_int 0))
7017 (label_ref (match_operand 0 "" ""))
7019 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7020 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7023 (define_expand "bunlt"
7025 (if_then_else (unlt (match_dup 1) (const_int 0))
7026 (label_ref (match_operand 0 "" ""))
7028 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7029 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7032 (define_expand "bunge"
7034 (if_then_else (unge (match_dup 1) (const_int 0))
7035 (label_ref (match_operand 0 "" ""))
7037 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7038 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7041 (define_expand "bunle"
7043 (if_then_else (unle (match_dup 1) (const_int 0))
7044 (label_ref (match_operand 0 "" ""))
7046 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7047 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7050 ;; The following two patterns need two branch instructions, since there is
7051 ;; no single instruction that will handle all cases.
7052 (define_expand "buneq"
7054 (if_then_else (uneq (match_dup 1) (const_int 0))
7055 (label_ref (match_operand 0 "" ""))
7057 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7058 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7061 (define_expand "bltgt"
7063 (if_then_else (ltgt (match_dup 1) (const_int 0))
7064 (label_ref (match_operand 0 "" ""))
7066 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7067 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7071 ;; Patterns to match conditional branch insns.
7074 ; Special pattern to match UNEQ.
7075 (define_insn "*arm_buneq"
7077 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7078 (label_ref (match_operand 0 "" ""))
7080 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7082 gcc_assert (!arm_ccfsm_state);
7084 return \"bvs\\t%l0\;beq\\t%l0\";
7086 [(set_attr "conds" "jump_clob")
7087 (set_attr "length" "8")]
7090 ; Special pattern to match LTGT.
7091 (define_insn "*arm_bltgt"
7093 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7094 (label_ref (match_operand 0 "" ""))
7096 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7098 gcc_assert (!arm_ccfsm_state);
7100 return \"bmi\\t%l0\;bgt\\t%l0\";
7102 [(set_attr "conds" "jump_clob")
7103 (set_attr "length" "8")]
7106 (define_insn "*arm_cond_branch"
7108 (if_then_else (match_operator 1 "arm_comparison_operator"
7109 [(match_operand 2 "cc_register" "") (const_int 0)])
7110 (label_ref (match_operand 0 "" ""))
7114 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7116 arm_ccfsm_state += 2;
7119 return \"b%d1\\t%l0\";
7121 [(set_attr "conds" "use")
7122 (set_attr "type" "branch")]
7125 ; Special pattern to match reversed UNEQ.
7126 (define_insn "*arm_buneq_reversed"
7128 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7130 (label_ref (match_operand 0 "" ""))))]
7131 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7133 gcc_assert (!arm_ccfsm_state);
7135 return \"bmi\\t%l0\;bgt\\t%l0\";
7137 [(set_attr "conds" "jump_clob")
7138 (set_attr "length" "8")]
7141 ; Special pattern to match reversed LTGT.
7142 (define_insn "*arm_bltgt_reversed"
7144 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7146 (label_ref (match_operand 0 "" ""))))]
7147 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7149 gcc_assert (!arm_ccfsm_state);
7151 return \"bvs\\t%l0\;beq\\t%l0\";
7153 [(set_attr "conds" "jump_clob")
7154 (set_attr "length" "8")]
7157 (define_insn "*arm_cond_branch_reversed"
7159 (if_then_else (match_operator 1 "arm_comparison_operator"
7160 [(match_operand 2 "cc_register" "") (const_int 0)])
7162 (label_ref (match_operand 0 "" ""))))]
7165 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7167 arm_ccfsm_state += 2;
7170 return \"b%D1\\t%l0\";
7172 [(set_attr "conds" "use")
7173 (set_attr "type" "branch")]
7180 (define_expand "seq"
7181 [(set (match_operand:SI 0 "s_register_operand" "")
7182 (eq:SI (match_dup 1) (const_int 0)))]
7184 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7187 (define_expand "sne"
7188 [(set (match_operand:SI 0 "s_register_operand" "")
7189 (ne:SI (match_dup 1) (const_int 0)))]
7191 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7194 (define_expand "sgt"
7195 [(set (match_operand:SI 0 "s_register_operand" "")
7196 (gt:SI (match_dup 1) (const_int 0)))]
7198 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7201 (define_expand "sle"
7202 [(set (match_operand:SI 0 "s_register_operand" "")
7203 (le:SI (match_dup 1) (const_int 0)))]
7205 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7208 (define_expand "sge"
7209 [(set (match_operand:SI 0 "s_register_operand" "")
7210 (ge:SI (match_dup 1) (const_int 0)))]
7212 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7215 (define_expand "slt"
7216 [(set (match_operand:SI 0 "s_register_operand" "")
7217 (lt:SI (match_dup 1) (const_int 0)))]
7219 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7222 (define_expand "sgtu"
7223 [(set (match_operand:SI 0 "s_register_operand" "")
7224 (gtu:SI (match_dup 1) (const_int 0)))]
7226 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7229 (define_expand "sleu"
7230 [(set (match_operand:SI 0 "s_register_operand" "")
7231 (leu:SI (match_dup 1) (const_int 0)))]
7233 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7236 (define_expand "sgeu"
7237 [(set (match_operand:SI 0 "s_register_operand" "")
7238 (geu:SI (match_dup 1) (const_int 0)))]
7240 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7243 (define_expand "sltu"
7244 [(set (match_operand:SI 0 "s_register_operand" "")
7245 (ltu:SI (match_dup 1) (const_int 0)))]
7247 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7250 (define_expand "sunordered"
7251 [(set (match_operand:SI 0 "s_register_operand" "")
7252 (unordered:SI (match_dup 1) (const_int 0)))]
7253 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7254 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7258 (define_expand "sordered"
7259 [(set (match_operand:SI 0 "s_register_operand" "")
7260 (ordered:SI (match_dup 1) (const_int 0)))]
7261 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7262 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7266 (define_expand "sungt"
7267 [(set (match_operand:SI 0 "s_register_operand" "")
7268 (ungt:SI (match_dup 1) (const_int 0)))]
7269 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7270 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7274 (define_expand "sunge"
7275 [(set (match_operand:SI 0 "s_register_operand" "")
7276 (unge:SI (match_dup 1) (const_int 0)))]
7277 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7278 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7282 (define_expand "sunlt"
7283 [(set (match_operand:SI 0 "s_register_operand" "")
7284 (unlt:SI (match_dup 1) (const_int 0)))]
7285 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7286 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7290 (define_expand "sunle"
7291 [(set (match_operand:SI 0 "s_register_operand" "")
7292 (unle:SI (match_dup 1) (const_int 0)))]
7293 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7294 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7298 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7299 ;;; simple ARM instructions.
7301 ; (define_expand "suneq"
7302 ; [(set (match_operand:SI 0 "s_register_operand" "")
7303 ; (uneq:SI (match_dup 1) (const_int 0)))]
7304 ; "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7305 ; "gcc_unreachable ();"
7308 ; (define_expand "sltgt"
7309 ; [(set (match_operand:SI 0 "s_register_operand" "")
7310 ; (ltgt:SI (match_dup 1) (const_int 0)))]
7311 ; "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7312 ; "gcc_unreachable ();"
7315 (define_insn "*mov_scc"
7316 [(set (match_operand:SI 0 "s_register_operand" "=r")
7317 (match_operator:SI 1 "arm_comparison_operator"
7318 [(match_operand 2 "cc_register" "") (const_int 0)]))]
7320 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7321 [(set_attr "conds" "use")
7322 (set_attr "length" "8")]
7325 (define_insn "*mov_negscc"
7326 [(set (match_operand:SI 0 "s_register_operand" "=r")
7327 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7328 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7330 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7331 [(set_attr "conds" "use")
7332 (set_attr "length" "8")]
7335 (define_insn "*mov_notscc"
7336 [(set (match_operand:SI 0 "s_register_operand" "=r")
7337 (not:SI (match_operator:SI 1 "arm_comparison_operator"
7338 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7340 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7341 [(set_attr "conds" "use")
7342 (set_attr "length" "8")]
7346 ;; Conditional move insns
7348 (define_expand "movsicc"
7349 [(set (match_operand:SI 0 "s_register_operand" "")
7350 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7351 (match_operand:SI 2 "arm_not_operand" "")
7352 (match_operand:SI 3 "arm_not_operand" "")))]
7356 enum rtx_code code = GET_CODE (operands[1]);
7359 if (code == UNEQ || code == LTGT)
7362 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7363 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7367 (define_expand "movsfcc"
7368 [(set (match_operand:SF 0 "s_register_operand" "")
7369 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7370 (match_operand:SF 2 "s_register_operand" "")
7371 (match_operand:SF 3 "nonmemory_operand" "")))]
7375 enum rtx_code code = GET_CODE (operands[1]);
7378 if (code == UNEQ || code == LTGT)
7381 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
7382 Otherwise, ensure it is a valid FP add operand */
7383 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7384 || (!arm_float_add_operand (operands[3], SFmode)))
7385 operands[3] = force_reg (SFmode, operands[3]);
7387 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7388 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7392 (define_expand "movdfcc"
7393 [(set (match_operand:DF 0 "s_register_operand" "")
7394 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7395 (match_operand:DF 2 "s_register_operand" "")
7396 (match_operand:DF 3 "arm_float_add_operand" "")))]
7397 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7400 enum rtx_code code = GET_CODE (operands[1]);
7403 if (code == UNEQ || code == LTGT)
7406 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7407 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7411 (define_insn "*movsicc_insn"
7412 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7414 (match_operator 3 "arm_comparison_operator"
7415 [(match_operand 4 "cc_register" "") (const_int 0)])
7416 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7417 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7424 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7425 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7426 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7427 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7428 [(set_attr "length" "4,4,4,4,8,8,8,8")
7429 (set_attr "conds" "use")]
7432 (define_insn "*movsfcc_soft_insn"
7433 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7434 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7435 [(match_operand 4 "cc_register" "") (const_int 0)])
7436 (match_operand:SF 1 "s_register_operand" "0,r")
7437 (match_operand:SF 2 "s_register_operand" "r,0")))]
7438 "TARGET_ARM && TARGET_SOFT_FLOAT"
7442 [(set_attr "conds" "use")]
7446 ;; Jump and linkage insns
7448 (define_expand "jump"
7450 (label_ref (match_operand 0 "" "")))]
7455 (define_insn "*arm_jump"
7457 (label_ref (match_operand 0 "" "")))]
7461 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7463 arm_ccfsm_state += 2;
7466 return \"b%?\\t%l0\";
7469 [(set_attr "predicable" "yes")]
7472 (define_insn "*thumb_jump"
7474 (label_ref (match_operand 0 "" "")))]
7477 if (get_attr_length (insn) == 2)
7479 return \"bl\\t%l0\\t%@ far jump\";
7481 [(set (attr "far_jump")
7483 (eq_attr "length" "4")
7484 (const_string "yes")
7485 (const_string "no")))
7486 (set (attr "length")
7488 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7489 (le (minus (match_dup 0) (pc)) (const_int 2048)))
7494 (define_expand "call"
7495 [(parallel [(call (match_operand 0 "memory_operand" "")
7496 (match_operand 1 "general_operand" ""))
7497 (use (match_operand 2 "" ""))
7498 (clobber (reg:SI LR_REGNUM))])]
7504 /* In an untyped call, we can get NULL for operand 2. */
7505 if (operands[2] == NULL_RTX)
7506 operands[2] = const0_rtx;
7508 /* This is to decide if we should generate indirect calls by loading the
7509 32 bit address of the callee into a register before performing the
7510 branch and link. operand[2] encodes the long_call/short_call
7511 attribute of the function being called. This attribute is set whenever
7512 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7513 is used, and the short_call attribute can also be set if function is
7514 declared as static or if it has already been defined in the current
7515 compilation unit. See arm.c and arm.h for info about this. The third
7516 parameter to arm_is_longcall_p is used to tell it which pattern
7518 callee = XEXP (operands[0], 0);
7520 if ((GET_CODE (callee) == SYMBOL_REF
7521 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7522 || (GET_CODE (callee) != SYMBOL_REF
7523 && GET_CODE (callee) != REG))
7524 XEXP (operands[0], 0) = force_reg (Pmode, callee);
7528 (define_insn "*call_reg_armv5"
7529 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7530 (match_operand 1 "" ""))
7531 (use (match_operand 2 "" ""))
7532 (clobber (reg:SI LR_REGNUM))]
7533 "TARGET_ARM && arm_arch5"
7535 [(set_attr "type" "call")]
7538 (define_insn "*call_reg_arm"
7539 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7540 (match_operand 1 "" ""))
7541 (use (match_operand 2 "" ""))
7542 (clobber (reg:SI LR_REGNUM))]
7543 "TARGET_ARM && !arm_arch5"
7545 return output_call (operands);
7547 ;; length is worst case, normally it is only two
7548 [(set_attr "length" "12")
7549 (set_attr "type" "call")]
7552 (define_insn "*call_mem"
7553 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7554 (match_operand 1 "" ""))
7555 (use (match_operand 2 "" ""))
7556 (clobber (reg:SI LR_REGNUM))]
7559 return output_call_mem (operands);
7561 [(set_attr "length" "12")
7562 (set_attr "type" "call")]
7565 (define_insn "*call_reg_thumb_v5"
7566 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7567 (match_operand 1 "" ""))
7568 (use (match_operand 2 "" ""))
7569 (clobber (reg:SI LR_REGNUM))]
7570 "TARGET_THUMB && arm_arch5"
7572 [(set_attr "length" "2")
7573 (set_attr "type" "call")]
7576 (define_insn "*call_reg_thumb"
7577 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7578 (match_operand 1 "" ""))
7579 (use (match_operand 2 "" ""))
7580 (clobber (reg:SI LR_REGNUM))]
7581 "TARGET_THUMB && !arm_arch5"
7584 if (!TARGET_CALLER_INTERWORKING)
7585 return thumb_call_via_reg (operands[0]);
7586 else if (operands[1] == const0_rtx)
7587 return \"bl\\t%__interwork_call_via_%0\";
7588 else if (frame_pointer_needed)
7589 return \"bl\\t%__interwork_r7_call_via_%0\";
7591 return \"bl\\t%__interwork_r11_call_via_%0\";
7593 [(set_attr "type" "call")]
7596 (define_expand "call_value"
7597 [(parallel [(set (match_operand 0 "" "")
7598 (call (match_operand 1 "memory_operand" "")
7599 (match_operand 2 "general_operand" "")))
7600 (use (match_operand 3 "" ""))
7601 (clobber (reg:SI LR_REGNUM))])]
7605 rtx callee = XEXP (operands[1], 0);
7607 /* In an untyped call, we can get NULL for operand 2. */
7608 if (operands[3] == 0)
7609 operands[3] = const0_rtx;
7611 /* See the comment in define_expand \"call\". */
7612 if ((GET_CODE (callee) == SYMBOL_REF
7613 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7614 || (GET_CODE (callee) != SYMBOL_REF
7615 && GET_CODE (callee) != REG))
7616 XEXP (operands[1], 0) = force_reg (Pmode, callee);
7620 (define_insn "*call_value_reg_armv5"
7621 [(set (match_operand 0 "" "")
7622 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7623 (match_operand 2 "" "")))
7624 (use (match_operand 3 "" ""))
7625 (clobber (reg:SI LR_REGNUM))]
7626 "TARGET_ARM && arm_arch5"
7628 [(set_attr "type" "call")]
7631 (define_insn "*call_value_reg_arm"
7632 [(set (match_operand 0 "" "")
7633 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7634 (match_operand 2 "" "")))
7635 (use (match_operand 3 "" ""))
7636 (clobber (reg:SI LR_REGNUM))]
7637 "TARGET_ARM && !arm_arch5"
7639 return output_call (&operands[1]);
7641 [(set_attr "length" "12")
7642 (set_attr "type" "call")]
7645 (define_insn "*call_value_mem"
7646 [(set (match_operand 0 "" "")
7647 (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7648 (match_operand 2 "" "")))
7649 (use (match_operand 3 "" ""))
7650 (clobber (reg:SI LR_REGNUM))]
7651 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7653 return output_call_mem (&operands[1]);
7655 [(set_attr "length" "12")
7656 (set_attr "type" "call")]
7659 (define_insn "*call_value_reg_thumb_v5"
7660 [(set (match_operand 0 "" "")
7661 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7662 (match_operand 2 "" "")))
7663 (use (match_operand 3 "" ""))
7664 (clobber (reg:SI LR_REGNUM))]
7665 "TARGET_THUMB && arm_arch5"
7667 [(set_attr "length" "2")
7668 (set_attr "type" "call")]
7671 (define_insn "*call_value_reg_thumb"
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"
7680 if (!TARGET_CALLER_INTERWORKING)
7681 return thumb_call_via_reg (operands[1]);
7682 else if (operands[2] == const0_rtx)
7683 return \"bl\\t%__interwork_call_via_%1\";
7684 else if (frame_pointer_needed)
7685 return \"bl\\t%__interwork_r7_call_via_%1\";
7687 return \"bl\\t%__interwork_r11_call_via_%1\";
7689 [(set_attr "type" "call")]
7692 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7693 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7695 (define_insn "*call_symbol"
7696 [(call (mem:SI (match_operand:SI 0 "" ""))
7697 (match_operand 1 "" ""))
7698 (use (match_operand 2 "" ""))
7699 (clobber (reg:SI LR_REGNUM))]
7701 && (GET_CODE (operands[0]) == SYMBOL_REF)
7702 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7705 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7707 [(set_attr "type" "call")]
7710 (define_insn "*call_value_symbol"
7711 [(set (match_operand 0 "" "")
7712 (call (mem:SI (match_operand:SI 1 "" ""))
7713 (match_operand:SI 2 "" "")))
7714 (use (match_operand 3 "" ""))
7715 (clobber (reg:SI LR_REGNUM))]
7717 && (GET_CODE (operands[1]) == SYMBOL_REF)
7718 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7721 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7723 [(set_attr "type" "call")]
7726 (define_insn "*call_insn"
7727 [(call (mem:SI (match_operand:SI 0 "" ""))
7728 (match_operand:SI 1 "" ""))
7729 (use (match_operand 2 "" ""))
7730 (clobber (reg:SI LR_REGNUM))]
7732 && GET_CODE (operands[0]) == SYMBOL_REF
7733 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7735 [(set_attr "length" "4")
7736 (set_attr "type" "call")]
7739 (define_insn "*call_value_insn"
7740 [(set (match_operand 0 "" "")
7741 (call (mem:SI (match_operand 1 "" ""))
7742 (match_operand 2 "" "")))
7743 (use (match_operand 3 "" ""))
7744 (clobber (reg:SI LR_REGNUM))]
7746 && GET_CODE (operands[1]) == SYMBOL_REF
7747 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7749 [(set_attr "length" "4")
7750 (set_attr "type" "call")]
7753 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7754 (define_expand "sibcall"
7755 [(parallel [(call (match_operand 0 "memory_operand" "")
7756 (match_operand 1 "general_operand" ""))
7758 (use (match_operand 2 "" ""))])]
7762 if (operands[2] == NULL_RTX)
7763 operands[2] = const0_rtx;
7767 (define_expand "sibcall_value"
7768 [(parallel [(set (match_operand 0 "" "")
7769 (call (match_operand 1 "memory_operand" "")
7770 (match_operand 2 "general_operand" "")))
7772 (use (match_operand 3 "" ""))])]
7776 if (operands[3] == NULL_RTX)
7777 operands[3] = const0_rtx;
7781 (define_insn "*sibcall_insn"
7782 [(call (mem:SI (match_operand:SI 0 "" "X"))
7783 (match_operand 1 "" ""))
7785 (use (match_operand 2 "" ""))]
7786 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7788 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7790 [(set_attr "type" "call")]
7793 (define_insn "*sibcall_value_insn"
7794 [(set (match_operand 0 "" "")
7795 (call (mem:SI (match_operand:SI 1 "" "X"))
7796 (match_operand 2 "" "")))
7798 (use (match_operand 3 "" ""))]
7799 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7801 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7803 [(set_attr "type" "call")]
7806 ;; Often the return insn will be the same as loading from memory, so set attr
7807 (define_insn "return"
7809 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7812 if (arm_ccfsm_state == 2)
7814 arm_ccfsm_state += 2;
7817 return output_return_instruction (const_true_rtx, TRUE, FALSE);
7819 [(set_attr "type" "load1")
7820 (set_attr "length" "12")
7821 (set_attr "predicable" "yes")]
7824 (define_insn "*cond_return"
7826 (if_then_else (match_operator 0 "arm_comparison_operator"
7827 [(match_operand 1 "cc_register" "") (const_int 0)])
7830 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7833 if (arm_ccfsm_state == 2)
7835 arm_ccfsm_state += 2;
7838 return output_return_instruction (operands[0], TRUE, FALSE);
7840 [(set_attr "conds" "use")
7841 (set_attr "length" "12")
7842 (set_attr "type" "load1")]
7845 (define_insn "*cond_return_inverted"
7847 (if_then_else (match_operator 0 "arm_comparison_operator"
7848 [(match_operand 1 "cc_register" "") (const_int 0)])
7851 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7854 if (arm_ccfsm_state == 2)
7856 arm_ccfsm_state += 2;
7859 return output_return_instruction (operands[0], TRUE, TRUE);
7861 [(set_attr "conds" "use")
7862 (set_attr "length" "12")
7863 (set_attr "type" "load1")]
7866 ;; Generate a sequence of instructions to determine if the processor is
7867 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7870 (define_expand "return_addr_mask"
7872 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7874 (set (match_operand:SI 0 "s_register_operand" "")
7875 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7877 (const_int 67108860)))] ; 0x03fffffc
7880 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7883 (define_insn "*check_arch2"
7884 [(set (match_operand:CC_NOOV 0 "cc_register" "")
7885 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7888 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7889 [(set_attr "length" "8")
7890 (set_attr "conds" "set")]
7893 ;; Call subroutine returning any type.
7895 (define_expand "untyped_call"
7896 [(parallel [(call (match_operand 0 "" "")
7898 (match_operand 1 "" "")
7899 (match_operand 2 "" "")])]
7904 rtx par = gen_rtx_PARALLEL (VOIDmode,
7905 rtvec_alloc (XVECLEN (operands[2], 0)));
7906 rtx addr = gen_reg_rtx (Pmode);
7910 emit_move_insn (addr, XEXP (operands[1], 0));
7911 mem = change_address (operands[1], BLKmode, addr);
7913 for (i = 0; i < XVECLEN (operands[2], 0); i++)
7915 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
7917 /* Default code only uses r0 as a return value, but we could
7918 be using anything up to 4 registers. */
7919 if (REGNO (src) == R0_REGNUM)
7920 src = gen_rtx_REG (TImode, R0_REGNUM);
7922 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7924 size += GET_MODE_SIZE (GET_MODE (src));
7927 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
7932 for (i = 0; i < XVECLEN (par, 0); i++)
7934 HOST_WIDE_INT offset = 0;
7935 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
7938 emit_move_insn (addr, plus_constant (addr, size));
7940 mem = change_address (mem, GET_MODE (reg), NULL);
7941 if (REGNO (reg) == R0_REGNUM)
7943 /* On thumb we have to use a write-back instruction. */
7944 emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
7945 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7946 size = TARGET_ARM ? 16 : 0;
7950 emit_move_insn (mem, reg);
7951 size = GET_MODE_SIZE (GET_MODE (reg));
7955 /* The optimizer does not know that the call sets the function value
7956 registers we stored in the result block. We avoid problems by
7957 claiming that all hard registers are used and clobbered at this
7959 emit_insn (gen_blockage ());
7965 (define_expand "untyped_return"
7966 [(match_operand:BLK 0 "memory_operand" "")
7967 (match_operand 1 "" "")]
7972 rtx addr = gen_reg_rtx (Pmode);
7976 emit_move_insn (addr, XEXP (operands[0], 0));
7977 mem = change_address (operands[0], BLKmode, addr);
7979 for (i = 0; i < XVECLEN (operands[1], 0); i++)
7981 HOST_WIDE_INT offset = 0;
7982 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
7985 emit_move_insn (addr, plus_constant (addr, size));
7987 mem = change_address (mem, GET_MODE (reg), NULL);
7988 if (REGNO (reg) == R0_REGNUM)
7990 /* On thumb we have to use a write-back instruction. */
7991 emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
7992 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7993 size = TARGET_ARM ? 16 : 0;
7997 emit_move_insn (reg, mem);
7998 size = GET_MODE_SIZE (GET_MODE (reg));
8002 /* Emit USE insns before the return. */
8003 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8004 emit_insn (gen_rtx_USE (VOIDmode,
8005 SET_DEST (XVECEXP (operands[1], 0, i))));
8007 /* Construct the return. */
8008 expand_naked_return ();
8014 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8015 ;; all of memory. This blocks insns from being moved across this point.
8017 (define_insn "blockage"
8018 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8021 [(set_attr "length" "0")
8022 (set_attr "type" "block")]
8025 (define_expand "casesi"
8026 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8027 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8028 (match_operand:SI 2 "const_int_operand" "") ; total range
8029 (match_operand:SI 3 "" "") ; table label
8030 (match_operand:SI 4 "" "")] ; Out of range label
8035 if (operands[1] != const0_rtx)
8037 reg = gen_reg_rtx (SImode);
8039 emit_insn (gen_addsi3 (reg, operands[0],
8040 GEN_INT (-INTVAL (operands[1]))));
8044 if (!const_ok_for_arm (INTVAL (operands[2])))
8045 operands[2] = force_reg (SImode, operands[2]);
8047 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
8053 ;; The USE in this pattern is needed to tell flow analysis that this is
8054 ;; a CASESI insn. It has no other purpose.
8055 (define_insn "casesi_internal"
8056 [(parallel [(set (pc)
8058 (leu (match_operand:SI 0 "s_register_operand" "r")
8059 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8060 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8061 (label_ref (match_operand 2 "" ""))))
8062 (label_ref (match_operand 3 "" ""))))
8063 (clobber (reg:CC CC_REGNUM))
8064 (use (label_ref (match_dup 2)))])]
8068 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8069 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8071 [(set_attr "conds" "clob")
8072 (set_attr "length" "12")]
8075 (define_expand "indirect_jump"
8077 (match_operand:SI 0 "s_register_operand" ""))]
8082 ;; NB Never uses BX.
8083 (define_insn "*arm_indirect_jump"
8085 (match_operand:SI 0 "s_register_operand" "r"))]
8087 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8088 [(set_attr "predicable" "yes")]
8091 (define_insn "*load_indirect_jump"
8093 (match_operand:SI 0 "memory_operand" "m"))]
8095 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8096 [(set_attr "type" "load1")
8097 (set_attr "pool_range" "4096")
8098 (set_attr "neg_pool_range" "4084")
8099 (set_attr "predicable" "yes")]
8102 ;; NB Never uses BX.
8103 (define_insn "*thumb_indirect_jump"
8105 (match_operand:SI 0 "register_operand" "l*r"))]
8108 [(set_attr "conds" "clob")
8109 (set_attr "length" "2")]
8120 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8121 return \"mov\\tr8, r8\";
8123 [(set (attr "length")
8124 (if_then_else (eq_attr "is_thumb" "yes")
8130 ;; Patterns to allow combination of arithmetic, cond code and shifts
8132 (define_insn "*arith_shiftsi"
8133 [(set (match_operand:SI 0 "s_register_operand" "=r")
8134 (match_operator:SI 1 "shiftable_operator"
8135 [(match_operator:SI 3 "shift_operator"
8136 [(match_operand:SI 4 "s_register_operand" "r")
8137 (match_operand:SI 5 "reg_or_int_operand" "rI")])
8138 (match_operand:SI 2 "s_register_operand" "r")]))]
8140 "%i1%?\\t%0, %2, %4%S3"
8141 [(set_attr "predicable" "yes")
8142 (set_attr "shift" "4")
8143 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8144 (const_string "alu_shift")
8145 (const_string "alu_shift_reg")))]
8149 [(set (match_operand:SI 0 "s_register_operand" "")
8150 (match_operator:SI 1 "shiftable_operator"
8151 [(match_operator:SI 2 "shiftable_operator"
8152 [(match_operator:SI 3 "shift_operator"
8153 [(match_operand:SI 4 "s_register_operand" "")
8154 (match_operand:SI 5 "reg_or_int_operand" "")])
8155 (match_operand:SI 6 "s_register_operand" "")])
8156 (match_operand:SI 7 "arm_rhs_operand" "")]))
8157 (clobber (match_operand:SI 8 "s_register_operand" ""))]
8160 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8163 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8166 (define_insn "*arith_shiftsi_compare0"
8167 [(set (reg:CC_NOOV CC_REGNUM)
8168 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8169 [(match_operator:SI 3 "shift_operator"
8170 [(match_operand:SI 4 "s_register_operand" "r")
8171 (match_operand:SI 5 "reg_or_int_operand" "rI")])
8172 (match_operand:SI 2 "s_register_operand" "r")])
8174 (set (match_operand:SI 0 "s_register_operand" "=r")
8175 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8178 "%i1%?s\\t%0, %2, %4%S3"
8179 [(set_attr "conds" "set")
8180 (set_attr "shift" "4")
8181 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8182 (const_string "alu_shift")
8183 (const_string "alu_shift_reg")))]
8186 (define_insn "*arith_shiftsi_compare0_scratch"
8187 [(set (reg:CC_NOOV CC_REGNUM)
8188 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8189 [(match_operator:SI 3 "shift_operator"
8190 [(match_operand:SI 4 "s_register_operand" "r")
8191 (match_operand:SI 5 "reg_or_int_operand" "rI")])
8192 (match_operand:SI 2 "s_register_operand" "r")])
8194 (clobber (match_scratch:SI 0 "=r"))]
8196 "%i1%?s\\t%0, %2, %4%S3"
8197 [(set_attr "conds" "set")
8198 (set_attr "shift" "4")
8199 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8200 (const_string "alu_shift")
8201 (const_string "alu_shift_reg")))]
8204 (define_insn "*sub_shiftsi"
8205 [(set (match_operand:SI 0 "s_register_operand" "=r")
8206 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8207 (match_operator:SI 2 "shift_operator"
8208 [(match_operand:SI 3 "s_register_operand" "r")
8209 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8211 "sub%?\\t%0, %1, %3%S2"
8212 [(set_attr "predicable" "yes")
8213 (set_attr "shift" "3")
8214 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8215 (const_string "alu_shift")
8216 (const_string "alu_shift_reg")))]
8219 (define_insn "*sub_shiftsi_compare0"
8220 [(set (reg:CC_NOOV CC_REGNUM)
8222 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8223 (match_operator:SI 2 "shift_operator"
8224 [(match_operand:SI 3 "s_register_operand" "r")
8225 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8227 (set (match_operand:SI 0 "s_register_operand" "=r")
8228 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8231 "sub%?s\\t%0, %1, %3%S2"
8232 [(set_attr "conds" "set")
8233 (set_attr "shift" "3")
8234 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8235 (const_string "alu_shift")
8236 (const_string "alu_shift_reg")))]
8239 (define_insn "*sub_shiftsi_compare0_scratch"
8240 [(set (reg:CC_NOOV CC_REGNUM)
8242 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8243 (match_operator:SI 2 "shift_operator"
8244 [(match_operand:SI 3 "s_register_operand" "r")
8245 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8247 (clobber (match_scratch:SI 0 "=r"))]
8249 "sub%?s\\t%0, %1, %3%S2"
8250 [(set_attr "conds" "set")
8251 (set_attr "shift" "3")
8252 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8253 (const_string "alu_shift")
8254 (const_string "alu_shift_reg")))]
8259 (define_insn "*and_scc"
8260 [(set (match_operand:SI 0 "s_register_operand" "=r")
8261 (and:SI (match_operator:SI 1 "arm_comparison_operator"
8262 [(match_operand 3 "cc_register" "") (const_int 0)])
8263 (match_operand:SI 2 "s_register_operand" "r")))]
8265 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8266 [(set_attr "conds" "use")
8267 (set_attr "length" "8")]
8270 (define_insn "*ior_scc"
8271 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8272 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8273 [(match_operand 3 "cc_register" "") (const_int 0)])
8274 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8278 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8279 [(set_attr "conds" "use")
8280 (set_attr "length" "4,8")]
8283 (define_insn "*compare_scc"
8284 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8285 (match_operator:SI 1 "arm_comparison_operator"
8286 [(match_operand:SI 2 "s_register_operand" "r,r")
8287 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8288 (clobber (reg:CC CC_REGNUM))]
8291 if (operands[3] == const0_rtx)
8293 if (GET_CODE (operands[1]) == LT)
8294 return \"mov\\t%0, %2, lsr #31\";
8296 if (GET_CODE (operands[1]) == GE)
8297 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8299 if (GET_CODE (operands[1]) == EQ)
8300 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8303 if (GET_CODE (operands[1]) == NE)
8305 if (which_alternative == 1)
8306 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8307 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8309 if (which_alternative == 1)
8310 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8312 output_asm_insn (\"cmp\\t%2, %3\", operands);
8313 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8315 [(set_attr "conds" "clob")
8316 (set_attr "length" "12")]
8319 (define_insn "*cond_move"
8320 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8321 (if_then_else:SI (match_operator 3 "equality_operator"
8322 [(match_operator 4 "arm_comparison_operator"
8323 [(match_operand 5 "cc_register" "") (const_int 0)])
8325 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8326 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8329 if (GET_CODE (operands[3]) == NE)
8331 if (which_alternative != 1)
8332 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8333 if (which_alternative != 0)
8334 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8337 if (which_alternative != 0)
8338 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8339 if (which_alternative != 1)
8340 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8343 [(set_attr "conds" "use")
8344 (set_attr "length" "4,4,8")]
8347 (define_insn "*cond_arith"
8348 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8349 (match_operator:SI 5 "shiftable_operator"
8350 [(match_operator:SI 4 "arm_comparison_operator"
8351 [(match_operand:SI 2 "s_register_operand" "r,r")
8352 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8353 (match_operand:SI 1 "s_register_operand" "0,?r")]))
8354 (clobber (reg:CC CC_REGNUM))]
8357 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8358 return \"%i5\\t%0, %1, %2, lsr #31\";
8360 output_asm_insn (\"cmp\\t%2, %3\", operands);
8361 if (GET_CODE (operands[5]) == AND)
8362 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8363 else if (GET_CODE (operands[5]) == MINUS)
8364 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8365 else if (which_alternative != 0)
8366 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8367 return \"%i5%d4\\t%0, %1, #1\";
8369 [(set_attr "conds" "clob")
8370 (set_attr "length" "12")]
8373 (define_insn "*cond_sub"
8374 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8375 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8376 (match_operator:SI 4 "arm_comparison_operator"
8377 [(match_operand:SI 2 "s_register_operand" "r,r")
8378 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8379 (clobber (reg:CC CC_REGNUM))]
8382 output_asm_insn (\"cmp\\t%2, %3\", operands);
8383 if (which_alternative != 0)
8384 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8385 return \"sub%d4\\t%0, %1, #1\";
8387 [(set_attr "conds" "clob")
8388 (set_attr "length" "8,12")]
8391 (define_insn "*cmp_ite0"
8392 [(set (match_operand 6 "dominant_cc_register" "")
8395 (match_operator 4 "arm_comparison_operator"
8396 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8397 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8398 (match_operator:SI 5 "arm_comparison_operator"
8399 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8400 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8406 static const char * const opcodes[4][2] =
8408 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8409 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8410 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8411 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8412 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8413 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8414 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8415 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8418 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8420 return opcodes[which_alternative][swap];
8422 [(set_attr "conds" "set")
8423 (set_attr "length" "8")]
8426 (define_insn "*cmp_ite1"
8427 [(set (match_operand 6 "dominant_cc_register" "")
8430 (match_operator 4 "arm_comparison_operator"
8431 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8432 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8433 (match_operator:SI 5 "arm_comparison_operator"
8434 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8435 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8441 static const char * const opcodes[4][2] =
8443 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8444 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8445 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8446 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8447 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8448 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8449 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8450 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8453 comparison_dominates_p (GET_CODE (operands[5]),
8454 reverse_condition (GET_CODE (operands[4])));
8456 return opcodes[which_alternative][swap];
8458 [(set_attr "conds" "set")
8459 (set_attr "length" "8")]
8462 (define_insn "*cmp_and"
8463 [(set (match_operand 6 "dominant_cc_register" "")
8466 (match_operator 4 "arm_comparison_operator"
8467 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8468 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8469 (match_operator:SI 5 "arm_comparison_operator"
8470 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8471 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8476 static const char *const opcodes[4][2] =
8478 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8479 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8480 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8481 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8482 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8483 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8484 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8485 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8488 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8490 return opcodes[which_alternative][swap];
8492 [(set_attr "conds" "set")
8493 (set_attr "predicable" "no")
8494 (set_attr "length" "8")]
8497 (define_insn "*cmp_ior"
8498 [(set (match_operand 6 "dominant_cc_register" "")
8501 (match_operator 4 "arm_comparison_operator"
8502 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8503 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8504 (match_operator:SI 5 "arm_comparison_operator"
8505 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8506 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8511 static const char *const opcodes[4][2] =
8513 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8514 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8515 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8516 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8517 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8518 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8519 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8520 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8523 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8525 return opcodes[which_alternative][swap];
8528 [(set_attr "conds" "set")
8529 (set_attr "length" "8")]
8532 (define_insn_and_split "*ior_scc_scc"
8533 [(set (match_operand:SI 0 "s_register_operand" "=r")
8534 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8535 [(match_operand:SI 1 "s_register_operand" "r")
8536 (match_operand:SI 2 "arm_add_operand" "rIL")])
8537 (match_operator:SI 6 "arm_comparison_operator"
8538 [(match_operand:SI 4 "s_register_operand" "r")
8539 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8540 (clobber (reg:CC CC_REGNUM))]
8542 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8545 "TARGET_ARM && reload_completed"
8549 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8550 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8552 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8554 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8557 [(set_attr "conds" "clob")
8558 (set_attr "length" "16")])
8560 ; If the above pattern is followed by a CMP insn, then the compare is
8561 ; redundant, since we can rework the conditional instruction that follows.
8562 (define_insn_and_split "*ior_scc_scc_cmp"
8563 [(set (match_operand 0 "dominant_cc_register" "")
8564 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8565 [(match_operand:SI 1 "s_register_operand" "r")
8566 (match_operand:SI 2 "arm_add_operand" "rIL")])
8567 (match_operator:SI 6 "arm_comparison_operator"
8568 [(match_operand:SI 4 "s_register_operand" "r")
8569 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8571 (set (match_operand:SI 7 "s_register_operand" "=r")
8572 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8573 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8576 "TARGET_ARM && reload_completed"
8580 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8581 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8583 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8585 [(set_attr "conds" "set")
8586 (set_attr "length" "16")])
8588 (define_insn_and_split "*and_scc_scc"
8589 [(set (match_operand:SI 0 "s_register_operand" "=r")
8590 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8591 [(match_operand:SI 1 "s_register_operand" "r")
8592 (match_operand:SI 2 "arm_add_operand" "rIL")])
8593 (match_operator:SI 6 "arm_comparison_operator"
8594 [(match_operand:SI 4 "s_register_operand" "r")
8595 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8596 (clobber (reg:CC CC_REGNUM))]
8598 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8601 "TARGET_ARM && reload_completed
8602 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8607 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8608 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8610 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8612 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8615 [(set_attr "conds" "clob")
8616 (set_attr "length" "16")])
8618 ; If the above pattern is followed by a CMP insn, then the compare is
8619 ; redundant, since we can rework the conditional instruction that follows.
8620 (define_insn_and_split "*and_scc_scc_cmp"
8621 [(set (match_operand 0 "dominant_cc_register" "")
8622 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8623 [(match_operand:SI 1 "s_register_operand" "r")
8624 (match_operand:SI 2 "arm_add_operand" "rIL")])
8625 (match_operator:SI 6 "arm_comparison_operator"
8626 [(match_operand:SI 4 "s_register_operand" "r")
8627 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8629 (set (match_operand:SI 7 "s_register_operand" "=r")
8630 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8631 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8634 "TARGET_ARM && reload_completed"
8638 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8639 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8641 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8643 [(set_attr "conds" "set")
8644 (set_attr "length" "16")])
8646 ;; If there is no dominance in the comparison, then we can still save an
8647 ;; instruction in the AND case, since we can know that the second compare
8648 ;; need only zero the value if false (if true, then the value is already
8650 (define_insn_and_split "*and_scc_scc_nodom"
8651 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8652 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8653 [(match_operand:SI 1 "s_register_operand" "r,r,0")
8654 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8655 (match_operator:SI 6 "arm_comparison_operator"
8656 [(match_operand:SI 4 "s_register_operand" "r,r,r")
8657 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8658 (clobber (reg:CC CC_REGNUM))]
8660 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8663 "TARGET_ARM && reload_completed"
8664 [(parallel [(set (match_dup 0)
8665 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8666 (clobber (reg:CC CC_REGNUM))])
8667 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8669 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8672 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8673 operands[4], operands[5]),
8675 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8677 [(set_attr "conds" "clob")
8678 (set_attr "length" "20")])
8681 [(set (reg:CC_NOOV CC_REGNUM)
8682 (compare:CC_NOOV (ior:SI
8683 (and:SI (match_operand:SI 0 "s_register_operand" "")
8685 (match_operator:SI 1 "comparison_operator"
8686 [(match_operand:SI 2 "s_register_operand" "")
8687 (match_operand:SI 3 "arm_add_operand" "")]))
8689 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8692 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8694 (set (reg:CC_NOOV CC_REGNUM)
8695 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8700 [(set (reg:CC_NOOV CC_REGNUM)
8701 (compare:CC_NOOV (ior:SI
8702 (match_operator:SI 1 "comparison_operator"
8703 [(match_operand:SI 2 "s_register_operand" "")
8704 (match_operand:SI 3 "arm_add_operand" "")])
8705 (and:SI (match_operand:SI 0 "s_register_operand" "")
8708 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8711 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8713 (set (reg:CC_NOOV CC_REGNUM)
8714 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8718 (define_insn "*negscc"
8719 [(set (match_operand:SI 0 "s_register_operand" "=r")
8720 (neg:SI (match_operator 3 "arm_comparison_operator"
8721 [(match_operand:SI 1 "s_register_operand" "r")
8722 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8723 (clobber (reg:CC CC_REGNUM))]
8726 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8727 return \"mov\\t%0, %1, asr #31\";
8729 if (GET_CODE (operands[3]) == NE)
8730 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8732 if (GET_CODE (operands[3]) == GT)
8733 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8735 output_asm_insn (\"cmp\\t%1, %2\", operands);
8736 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8737 return \"mvn%d3\\t%0, #0\";
8739 [(set_attr "conds" "clob")
8740 (set_attr "length" "12")]
8743 (define_insn "movcond"
8744 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8746 (match_operator 5 "arm_comparison_operator"
8747 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8748 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8749 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8750 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8751 (clobber (reg:CC CC_REGNUM))]
8754 if (GET_CODE (operands[5]) == LT
8755 && (operands[4] == const0_rtx))
8757 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8759 if (operands[2] == const0_rtx)
8760 return \"and\\t%0, %1, %3, asr #31\";
8761 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8763 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8765 if (operands[1] == const0_rtx)
8766 return \"bic\\t%0, %2, %3, asr #31\";
8767 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8769 /* The only case that falls through to here is when both ops 1 & 2
8773 if (GET_CODE (operands[5]) == GE
8774 && (operands[4] == const0_rtx))
8776 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8778 if (operands[2] == const0_rtx)
8779 return \"bic\\t%0, %1, %3, asr #31\";
8780 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8782 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8784 if (operands[1] == const0_rtx)
8785 return \"and\\t%0, %2, %3, asr #31\";
8786 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8788 /* The only case that falls through to here is when both ops 1 & 2
8791 if (GET_CODE (operands[4]) == CONST_INT
8792 && !const_ok_for_arm (INTVAL (operands[4])))
8793 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8795 output_asm_insn (\"cmp\\t%3, %4\", operands);
8796 if (which_alternative != 0)
8797 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8798 if (which_alternative != 1)
8799 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8802 [(set_attr "conds" "clob")
8803 (set_attr "length" "8,8,12")]
8806 (define_insn "*ifcompare_plus_move"
8807 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8808 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8809 [(match_operand:SI 4 "s_register_operand" "r,r")
8810 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8812 (match_operand:SI 2 "s_register_operand" "r,r")
8813 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8814 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8815 (clobber (reg:CC CC_REGNUM))]
8818 [(set_attr "conds" "clob")
8819 (set_attr "length" "8,12")]
8822 (define_insn "*if_plus_move"
8823 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8825 (match_operator 4 "arm_comparison_operator"
8826 [(match_operand 5 "cc_register" "") (const_int 0)])
8828 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8829 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8830 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8834 sub%d4\\t%0, %2, #%n3
8835 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8836 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8837 [(set_attr "conds" "use")
8838 (set_attr "length" "4,4,8,8")
8839 (set_attr "type" "*,*,*,*")]
8842 (define_insn "*ifcompare_move_plus"
8843 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8844 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8845 [(match_operand:SI 4 "s_register_operand" "r,r")
8846 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8847 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8849 (match_operand:SI 2 "s_register_operand" "r,r")
8850 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8851 (clobber (reg:CC CC_REGNUM))]
8854 [(set_attr "conds" "clob")
8855 (set_attr "length" "8,12")]
8858 (define_insn "*if_move_plus"
8859 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8861 (match_operator 4 "arm_comparison_operator"
8862 [(match_operand 5 "cc_register" "") (const_int 0)])
8863 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8865 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8866 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8870 sub%D4\\t%0, %2, #%n3
8871 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8872 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8873 [(set_attr "conds" "use")
8874 (set_attr "length" "4,4,8,8")
8875 (set_attr "type" "*,*,*,*")]
8878 (define_insn "*ifcompare_arith_arith"
8879 [(set (match_operand:SI 0 "s_register_operand" "=r")
8880 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8881 [(match_operand:SI 5 "s_register_operand" "r")
8882 (match_operand:SI 6 "arm_add_operand" "rIL")])
8883 (match_operator:SI 8 "shiftable_operator"
8884 [(match_operand:SI 1 "s_register_operand" "r")
8885 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8886 (match_operator:SI 7 "shiftable_operator"
8887 [(match_operand:SI 3 "s_register_operand" "r")
8888 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8889 (clobber (reg:CC CC_REGNUM))]
8892 [(set_attr "conds" "clob")
8893 (set_attr "length" "12")]
8896 (define_insn "*if_arith_arith"
8897 [(set (match_operand:SI 0 "s_register_operand" "=r")
8898 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8899 [(match_operand 8 "cc_register" "") (const_int 0)])
8900 (match_operator:SI 6 "shiftable_operator"
8901 [(match_operand:SI 1 "s_register_operand" "r")
8902 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8903 (match_operator:SI 7 "shiftable_operator"
8904 [(match_operand:SI 3 "s_register_operand" "r")
8905 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8907 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8908 [(set_attr "conds" "use")
8909 (set_attr "length" "8")]
8912 (define_insn "*ifcompare_arith_move"
8913 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8914 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8915 [(match_operand:SI 2 "s_register_operand" "r,r")
8916 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8917 (match_operator:SI 7 "shiftable_operator"
8918 [(match_operand:SI 4 "s_register_operand" "r,r")
8919 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8920 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8921 (clobber (reg:CC CC_REGNUM))]
8924 /* If we have an operation where (op x 0) is the identity operation and
8925 the conditional operator is LT or GE and we are comparing against zero and
8926 everything is in registers then we can do this in two instructions. */
8927 if (operands[3] == const0_rtx
8928 && GET_CODE (operands[7]) != AND
8929 && GET_CODE (operands[5]) == REG
8930 && GET_CODE (operands[1]) == REG
8931 && REGNO (operands[1]) == REGNO (operands[4])
8932 && REGNO (operands[4]) != REGNO (operands[0]))
8934 if (GET_CODE (operands[6]) == LT)
8935 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8936 else if (GET_CODE (operands[6]) == GE)
8937 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8939 if (GET_CODE (operands[3]) == CONST_INT
8940 && !const_ok_for_arm (INTVAL (operands[3])))
8941 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8943 output_asm_insn (\"cmp\\t%2, %3\", operands);
8944 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8945 if (which_alternative != 0)
8946 return \"mov%D6\\t%0, %1\";
8949 [(set_attr "conds" "clob")
8950 (set_attr "length" "8,12")]
8953 (define_insn "*if_arith_move"
8954 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8955 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8956 [(match_operand 6 "cc_register" "") (const_int 0)])
8957 (match_operator:SI 5 "shiftable_operator"
8958 [(match_operand:SI 2 "s_register_operand" "r,r")
8959 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8960 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8964 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8965 [(set_attr "conds" "use")
8966 (set_attr "length" "4,8")
8967 (set_attr "type" "*,*")]
8970 (define_insn "*ifcompare_move_arith"
8971 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8972 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8973 [(match_operand:SI 4 "s_register_operand" "r,r")
8974 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8975 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8976 (match_operator:SI 7 "shiftable_operator"
8977 [(match_operand:SI 2 "s_register_operand" "r,r")
8978 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8979 (clobber (reg:CC CC_REGNUM))]
8982 /* If we have an operation where (op x 0) is the identity operation and
8983 the conditional operator is LT or GE and we are comparing against zero and
8984 everything is in registers then we can do this in two instructions */
8985 if (operands[5] == const0_rtx
8986 && GET_CODE (operands[7]) != AND
8987 && GET_CODE (operands[3]) == REG
8988 && GET_CODE (operands[1]) == REG
8989 && REGNO (operands[1]) == REGNO (operands[2])
8990 && REGNO (operands[2]) != REGNO (operands[0]))
8992 if (GET_CODE (operands[6]) == GE)
8993 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8994 else if (GET_CODE (operands[6]) == LT)
8995 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8998 if (GET_CODE (operands[5]) == CONST_INT
8999 && !const_ok_for_arm (INTVAL (operands[5])))
9000 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9002 output_asm_insn (\"cmp\\t%4, %5\", operands);
9004 if (which_alternative != 0)
9005 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
9006 return \"%I7%D6\\t%0, %2, %3\";
9008 [(set_attr "conds" "clob")
9009 (set_attr "length" "8,12")]
9012 (define_insn "*if_move_arith"
9013 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9015 (match_operator 4 "arm_comparison_operator"
9016 [(match_operand 6 "cc_register" "") (const_int 0)])
9017 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9018 (match_operator:SI 5 "shiftable_operator"
9019 [(match_operand:SI 2 "s_register_operand" "r,r")
9020 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
9024 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9025 [(set_attr "conds" "use")
9026 (set_attr "length" "4,8")
9027 (set_attr "type" "*,*")]
9030 (define_insn "*ifcompare_move_not"
9031 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9033 (match_operator 5 "arm_comparison_operator"
9034 [(match_operand:SI 3 "s_register_operand" "r,r")
9035 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9036 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9038 (match_operand:SI 2 "s_register_operand" "r,r"))))
9039 (clobber (reg:CC CC_REGNUM))]
9042 [(set_attr "conds" "clob")
9043 (set_attr "length" "8,12")]
9046 (define_insn "*if_move_not"
9047 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9049 (match_operator 4 "arm_comparison_operator"
9050 [(match_operand 3 "cc_register" "") (const_int 0)])
9051 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9052 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9056 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9057 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9058 [(set_attr "conds" "use")
9059 (set_attr "length" "4,8,8")]
9062 (define_insn "*ifcompare_not_move"
9063 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9065 (match_operator 5 "arm_comparison_operator"
9066 [(match_operand:SI 3 "s_register_operand" "r,r")
9067 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9069 (match_operand:SI 2 "s_register_operand" "r,r"))
9070 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9071 (clobber (reg:CC CC_REGNUM))]
9074 [(set_attr "conds" "clob")
9075 (set_attr "length" "8,12")]
9078 (define_insn "*if_not_move"
9079 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9081 (match_operator 4 "arm_comparison_operator"
9082 [(match_operand 3 "cc_register" "") (const_int 0)])
9083 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9084 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9088 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9089 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9090 [(set_attr "conds" "use")
9091 (set_attr "length" "4,8,8")]
9094 (define_insn "*ifcompare_shift_move"
9095 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9097 (match_operator 6 "arm_comparison_operator"
9098 [(match_operand:SI 4 "s_register_operand" "r,r")
9099 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9100 (match_operator:SI 7 "shift_operator"
9101 [(match_operand:SI 2 "s_register_operand" "r,r")
9102 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9103 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9104 (clobber (reg:CC CC_REGNUM))]
9107 [(set_attr "conds" "clob")
9108 (set_attr "length" "8,12")]
9111 (define_insn "*if_shift_move"
9112 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9114 (match_operator 5 "arm_comparison_operator"
9115 [(match_operand 6 "cc_register" "") (const_int 0)])
9116 (match_operator:SI 4 "shift_operator"
9117 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9118 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9119 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9123 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9124 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9125 [(set_attr "conds" "use")
9126 (set_attr "shift" "2")
9127 (set_attr "length" "4,8,8")
9128 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9129 (const_string "alu_shift")
9130 (const_string "alu_shift_reg")))]
9133 (define_insn "*ifcompare_move_shift"
9134 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9136 (match_operator 6 "arm_comparison_operator"
9137 [(match_operand:SI 4 "s_register_operand" "r,r")
9138 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9139 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9140 (match_operator:SI 7 "shift_operator"
9141 [(match_operand:SI 2 "s_register_operand" "r,r")
9142 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9143 (clobber (reg:CC CC_REGNUM))]
9146 [(set_attr "conds" "clob")
9147 (set_attr "length" "8,12")]
9150 (define_insn "*if_move_shift"
9151 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9153 (match_operator 5 "arm_comparison_operator"
9154 [(match_operand 6 "cc_register" "") (const_int 0)])
9155 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9156 (match_operator:SI 4 "shift_operator"
9157 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9158 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9162 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9163 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9164 [(set_attr "conds" "use")
9165 (set_attr "shift" "2")
9166 (set_attr "length" "4,8,8")
9167 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9168 (const_string "alu_shift")
9169 (const_string "alu_shift_reg")))]
9172 (define_insn "*ifcompare_shift_shift"
9173 [(set (match_operand:SI 0 "s_register_operand" "=r")
9175 (match_operator 7 "arm_comparison_operator"
9176 [(match_operand:SI 5 "s_register_operand" "r")
9177 (match_operand:SI 6 "arm_add_operand" "rIL")])
9178 (match_operator:SI 8 "shift_operator"
9179 [(match_operand:SI 1 "s_register_operand" "r")
9180 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9181 (match_operator:SI 9 "shift_operator"
9182 [(match_operand:SI 3 "s_register_operand" "r")
9183 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9184 (clobber (reg:CC CC_REGNUM))]
9187 [(set_attr "conds" "clob")
9188 (set_attr "length" "12")]
9191 (define_insn "*if_shift_shift"
9192 [(set (match_operand:SI 0 "s_register_operand" "=r")
9194 (match_operator 5 "arm_comparison_operator"
9195 [(match_operand 8 "cc_register" "") (const_int 0)])
9196 (match_operator:SI 6 "shift_operator"
9197 [(match_operand:SI 1 "s_register_operand" "r")
9198 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9199 (match_operator:SI 7 "shift_operator"
9200 [(match_operand:SI 3 "s_register_operand" "r")
9201 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9203 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9204 [(set_attr "conds" "use")
9205 (set_attr "shift" "1")
9206 (set_attr "length" "8")
9207 (set (attr "type") (if_then_else
9208 (and (match_operand 2 "const_int_operand" "")
9209 (match_operand 4 "const_int_operand" ""))
9210 (const_string "alu_shift")
9211 (const_string "alu_shift_reg")))]
9214 (define_insn "*ifcompare_not_arith"
9215 [(set (match_operand:SI 0 "s_register_operand" "=r")
9217 (match_operator 6 "arm_comparison_operator"
9218 [(match_operand:SI 4 "s_register_operand" "r")
9219 (match_operand:SI 5 "arm_add_operand" "rIL")])
9220 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9221 (match_operator:SI 7 "shiftable_operator"
9222 [(match_operand:SI 2 "s_register_operand" "r")
9223 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9224 (clobber (reg:CC CC_REGNUM))]
9227 [(set_attr "conds" "clob")
9228 (set_attr "length" "12")]
9231 (define_insn "*if_not_arith"
9232 [(set (match_operand:SI 0 "s_register_operand" "=r")
9234 (match_operator 5 "arm_comparison_operator"
9235 [(match_operand 4 "cc_register" "") (const_int 0)])
9236 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9237 (match_operator:SI 6 "shiftable_operator"
9238 [(match_operand:SI 2 "s_register_operand" "r")
9239 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9241 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9242 [(set_attr "conds" "use")
9243 (set_attr "length" "8")]
9246 (define_insn "*ifcompare_arith_not"
9247 [(set (match_operand:SI 0 "s_register_operand" "=r")
9249 (match_operator 6 "arm_comparison_operator"
9250 [(match_operand:SI 4 "s_register_operand" "r")
9251 (match_operand:SI 5 "arm_add_operand" "rIL")])
9252 (match_operator:SI 7 "shiftable_operator"
9253 [(match_operand:SI 2 "s_register_operand" "r")
9254 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9255 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9256 (clobber (reg:CC CC_REGNUM))]
9259 [(set_attr "conds" "clob")
9260 (set_attr "length" "12")]
9263 (define_insn "*if_arith_not"
9264 [(set (match_operand:SI 0 "s_register_operand" "=r")
9266 (match_operator 5 "arm_comparison_operator"
9267 [(match_operand 4 "cc_register" "") (const_int 0)])
9268 (match_operator:SI 6 "shiftable_operator"
9269 [(match_operand:SI 2 "s_register_operand" "r")
9270 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9271 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9273 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9274 [(set_attr "conds" "use")
9275 (set_attr "length" "8")]
9278 (define_insn "*ifcompare_neg_move"
9279 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9281 (match_operator 5 "arm_comparison_operator"
9282 [(match_operand:SI 3 "s_register_operand" "r,r")
9283 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9284 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9285 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9286 (clobber (reg:CC CC_REGNUM))]
9289 [(set_attr "conds" "clob")
9290 (set_attr "length" "8,12")]
9293 (define_insn "*if_neg_move"
9294 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9296 (match_operator 4 "arm_comparison_operator"
9297 [(match_operand 3 "cc_register" "") (const_int 0)])
9298 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9299 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9303 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9304 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9305 [(set_attr "conds" "use")
9306 (set_attr "length" "4,8,8")]
9309 (define_insn "*ifcompare_move_neg"
9310 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9312 (match_operator 5 "arm_comparison_operator"
9313 [(match_operand:SI 3 "s_register_operand" "r,r")
9314 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9315 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9316 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9317 (clobber (reg:CC CC_REGNUM))]
9320 [(set_attr "conds" "clob")
9321 (set_attr "length" "8,12")]
9324 (define_insn "*if_move_neg"
9325 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9327 (match_operator 4 "arm_comparison_operator"
9328 [(match_operand 3 "cc_register" "") (const_int 0)])
9329 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9330 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9334 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9335 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9336 [(set_attr "conds" "use")
9337 (set_attr "length" "4,8,8")]
9340 (define_insn "*arith_adjacentmem"
9341 [(set (match_operand:SI 0 "s_register_operand" "=r")
9342 (match_operator:SI 1 "shiftable_operator"
9343 [(match_operand:SI 2 "memory_operand" "m")
9344 (match_operand:SI 3 "memory_operand" "m")]))
9345 (clobber (match_scratch:SI 4 "=r"))]
9346 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9352 HOST_WIDE_INT val1 = 0, val2 = 0;
9354 if (REGNO (operands[0]) > REGNO (operands[4]))
9356 ldm[1] = operands[4];
9357 ldm[2] = operands[0];
9361 ldm[1] = operands[0];
9362 ldm[2] = operands[4];
9365 base_reg = XEXP (operands[2], 0);
9367 if (!REG_P (base_reg))
9369 val1 = INTVAL (XEXP (base_reg, 1));
9370 base_reg = XEXP (base_reg, 0);
9373 if (!REG_P (XEXP (operands[3], 0)))
9374 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9376 arith[0] = operands[0];
9377 arith[3] = operands[1];
9391 if (val1 !=0 && val2 != 0)
9393 if (val1 == 4 || val2 == 4)
9394 /* Other val must be 8, since we know they are adjacent and neither
9396 output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
9401 ldm[0] = ops[0] = operands[4];
9403 ops[2] = GEN_INT (val1);
9404 output_add_immediate (ops);
9406 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9408 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9414 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9416 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9421 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9423 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9425 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9428 [(set_attr "length" "12")
9429 (set_attr "predicable" "yes")
9430 (set_attr "type" "load1")]
9433 ; This pattern is never tried by combine, so do it as a peephole
9436 [(set (match_operand:SI 0 "arm_general_register_operand" "")
9437 (match_operand:SI 1 "arm_general_register_operand" ""))
9438 (set (reg:CC CC_REGNUM)
9439 (compare:CC (match_dup 1) (const_int 0)))]
9441 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9442 (set (match_dup 0) (match_dup 1))])]
9446 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9447 ; reversed, check that the memory references aren't volatile.
9450 [(set (match_operand:SI 0 "s_register_operand" "=r")
9451 (match_operand:SI 4 "memory_operand" "m"))
9452 (set (match_operand:SI 1 "s_register_operand" "=r")
9453 (match_operand:SI 5 "memory_operand" "m"))
9454 (set (match_operand:SI 2 "s_register_operand" "=r")
9455 (match_operand:SI 6 "memory_operand" "m"))
9456 (set (match_operand:SI 3 "s_register_operand" "=r")
9457 (match_operand:SI 7 "memory_operand" "m"))]
9458 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9460 return emit_ldm_seq (operands, 4);
9465 [(set (match_operand:SI 0 "s_register_operand" "=r")
9466 (match_operand:SI 3 "memory_operand" "m"))
9467 (set (match_operand:SI 1 "s_register_operand" "=r")
9468 (match_operand:SI 4 "memory_operand" "m"))
9469 (set (match_operand:SI 2 "s_register_operand" "=r")
9470 (match_operand:SI 5 "memory_operand" "m"))]
9471 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9473 return emit_ldm_seq (operands, 3);
9478 [(set (match_operand:SI 0 "s_register_operand" "=r")
9479 (match_operand:SI 2 "memory_operand" "m"))
9480 (set (match_operand:SI 1 "s_register_operand" "=r")
9481 (match_operand:SI 3 "memory_operand" "m"))]
9482 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9484 return emit_ldm_seq (operands, 2);
9489 [(set (match_operand:SI 4 "memory_operand" "=m")
9490 (match_operand:SI 0 "s_register_operand" "r"))
9491 (set (match_operand:SI 5 "memory_operand" "=m")
9492 (match_operand:SI 1 "s_register_operand" "r"))
9493 (set (match_operand:SI 6 "memory_operand" "=m")
9494 (match_operand:SI 2 "s_register_operand" "r"))
9495 (set (match_operand:SI 7 "memory_operand" "=m")
9496 (match_operand:SI 3 "s_register_operand" "r"))]
9497 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9499 return emit_stm_seq (operands, 4);
9504 [(set (match_operand:SI 3 "memory_operand" "=m")
9505 (match_operand:SI 0 "s_register_operand" "r"))
9506 (set (match_operand:SI 4 "memory_operand" "=m")
9507 (match_operand:SI 1 "s_register_operand" "r"))
9508 (set (match_operand:SI 5 "memory_operand" "=m")
9509 (match_operand:SI 2 "s_register_operand" "r"))]
9510 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9512 return emit_stm_seq (operands, 3);
9517 [(set (match_operand:SI 2 "memory_operand" "=m")
9518 (match_operand:SI 0 "s_register_operand" "r"))
9519 (set (match_operand:SI 3 "memory_operand" "=m")
9520 (match_operand:SI 1 "s_register_operand" "r"))]
9521 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9523 return emit_stm_seq (operands, 2);
9528 [(set (match_operand:SI 0 "s_register_operand" "")
9529 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9531 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9532 [(match_operand:SI 3 "s_register_operand" "")
9533 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9534 (clobber (match_operand:SI 5 "s_register_operand" ""))]
9536 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9537 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9542 ;; This split can be used because CC_Z mode implies that the following
9543 ;; branch will be an equality, or an unsigned inequality, so the sign
9544 ;; extension is not needed.
9547 [(set (reg:CC_Z CC_REGNUM)
9549 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9551 (match_operand 1 "const_int_operand" "")))
9552 (clobber (match_scratch:SI 2 ""))]
9554 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9555 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9556 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9557 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9559 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9563 (define_expand "prologue"
9564 [(clobber (const_int 0))]
9567 arm_expand_prologue ();
9569 thumb_expand_prologue ();
9574 (define_expand "epilogue"
9575 [(clobber (const_int 0))]
9578 if (current_function_calls_eh_return)
9579 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9581 thumb_expand_epilogue ();
9582 else if (USE_RETURN_INSN (FALSE))
9584 emit_jump_insn (gen_return ());
9587 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9589 gen_rtx_RETURN (VOIDmode)),
9595 ;; Note - although unspec_volatile's USE all hard registers,
9596 ;; USEs are ignored after relaod has completed. Thus we need
9597 ;; to add an unspec of the link register to ensure that flow
9598 ;; does not think that it is unused by the sibcall branch that
9599 ;; will replace the standard function epilogue.
9600 (define_insn "sibcall_epilogue"
9601 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9602 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9605 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9606 return output_return_instruction (const_true_rtx, FALSE, FALSE);
9607 return arm_output_epilogue (next_nonnote_insn (insn));
9609 ;; Length is absolute worst case
9610 [(set_attr "length" "44")
9611 (set_attr "type" "block")
9612 ;; We don't clobber the conditions, but the potential length of this
9613 ;; operation is sufficient to make conditionalizing the sequence
9614 ;; unlikely to be profitable.
9615 (set_attr "conds" "clob")]
9618 (define_insn "*epilogue_insns"
9619 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9623 return arm_output_epilogue (NULL);
9624 else /* TARGET_THUMB */
9625 return thumb_unexpanded_epilogue ();
9627 ; Length is absolute worst case
9628 [(set_attr "length" "44")
9629 (set_attr "type" "block")
9630 ;; We don't clobber the conditions, but the potential length of this
9631 ;; operation is sufficient to make conditionalizing the sequence
9632 ;; unlikely to be profitable.
9633 (set_attr "conds" "clob")]
9636 (define_expand "eh_epilogue"
9637 [(use (match_operand:SI 0 "register_operand" ""))
9638 (use (match_operand:SI 1 "register_operand" ""))
9639 (use (match_operand:SI 2 "register_operand" ""))]
9643 cfun->machine->eh_epilogue_sp_ofs = operands[1];
9644 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9646 rtx ra = gen_rtx_REG (Pmode, 2);
9648 emit_move_insn (ra, operands[2]);
9651 /* This is a hack -- we may have crystalized the function type too
9653 cfun->machine->func_type = 0;
9657 ;; This split is only used during output to reduce the number of patterns
9658 ;; that need assembler instructions adding to them. We allowed the setting
9659 ;; of the conditions to be implicit during rtl generation so that
9660 ;; the conditional compare patterns would work. However this conflicts to
9661 ;; some extent with the conditional data operations, so we have to split them
9665 [(set (match_operand:SI 0 "s_register_operand" "")
9666 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9667 [(match_operand 2 "" "") (match_operand 3 "" "")])
9669 (match_operand 4 "" "")))
9670 (clobber (reg:CC CC_REGNUM))]
9671 "TARGET_ARM && reload_completed"
9672 [(set (match_dup 5) (match_dup 6))
9673 (cond_exec (match_dup 7)
9674 (set (match_dup 0) (match_dup 4)))]
9677 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9678 operands[2], operands[3]);
9679 enum rtx_code rc = GET_CODE (operands[1]);
9681 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9682 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9683 if (mode == CCFPmode || mode == CCFPEmode)
9684 rc = reverse_condition_maybe_unordered (rc);
9686 rc = reverse_condition (rc);
9688 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9693 [(set (match_operand:SI 0 "s_register_operand" "")
9694 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9695 [(match_operand 2 "" "") (match_operand 3 "" "")])
9696 (match_operand 4 "" "")
9698 (clobber (reg:CC CC_REGNUM))]
9699 "TARGET_ARM && reload_completed"
9700 [(set (match_dup 5) (match_dup 6))
9701 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9702 (set (match_dup 0) (match_dup 4)))]
9705 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9706 operands[2], operands[3]);
9708 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9709 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9714 [(set (match_operand:SI 0 "s_register_operand" "")
9715 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9716 [(match_operand 2 "" "") (match_operand 3 "" "")])
9717 (match_operand 4 "" "")
9718 (match_operand 5 "" "")))
9719 (clobber (reg:CC CC_REGNUM))]
9720 "TARGET_ARM && reload_completed"
9721 [(set (match_dup 6) (match_dup 7))
9722 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9723 (set (match_dup 0) (match_dup 4)))
9724 (cond_exec (match_dup 8)
9725 (set (match_dup 0) (match_dup 5)))]
9728 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9729 operands[2], operands[3]);
9730 enum rtx_code rc = GET_CODE (operands[1]);
9732 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9733 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9734 if (mode == CCFPmode || mode == CCFPEmode)
9735 rc = reverse_condition_maybe_unordered (rc);
9737 rc = reverse_condition (rc);
9739 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9744 [(set (match_operand:SI 0 "s_register_operand" "")
9745 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9746 [(match_operand:SI 2 "s_register_operand" "")
9747 (match_operand:SI 3 "arm_add_operand" "")])
9748 (match_operand:SI 4 "arm_rhs_operand" "")
9750 (match_operand:SI 5 "s_register_operand" ""))))
9751 (clobber (reg:CC CC_REGNUM))]
9752 "TARGET_ARM && reload_completed"
9753 [(set (match_dup 6) (match_dup 7))
9754 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9755 (set (match_dup 0) (match_dup 4)))
9756 (cond_exec (match_dup 8)
9757 (set (match_dup 0) (not:SI (match_dup 5))))]
9760 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9761 operands[2], operands[3]);
9762 enum rtx_code rc = GET_CODE (operands[1]);
9764 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9765 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9766 if (mode == CCFPmode || mode == CCFPEmode)
9767 rc = reverse_condition_maybe_unordered (rc);
9769 rc = reverse_condition (rc);
9771 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9775 (define_insn "*cond_move_not"
9776 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9777 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9778 [(match_operand 3 "cc_register" "") (const_int 0)])
9779 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9781 (match_operand:SI 2 "s_register_operand" "r,r"))))]
9785 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9786 [(set_attr "conds" "use")
9787 (set_attr "length" "4,8")]
9790 ;; The next two patterns occur when an AND operation is followed by a
9791 ;; scc insn sequence
9793 (define_insn "*sign_extract_onebit"
9794 [(set (match_operand:SI 0 "s_register_operand" "=r")
9795 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9797 (match_operand:SI 2 "const_int_operand" "n")))
9798 (clobber (reg:CC CC_REGNUM))]
9801 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9802 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9803 return \"mvnne\\t%0, #0\";
9805 [(set_attr "conds" "clob")
9806 (set_attr "length" "8")]
9809 (define_insn "*not_signextract_onebit"
9810 [(set (match_operand:SI 0 "s_register_operand" "=r")
9812 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9814 (match_operand:SI 2 "const_int_operand" "n"))))
9815 (clobber (reg:CC CC_REGNUM))]
9818 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9819 output_asm_insn (\"tst\\t%1, %2\", operands);
9820 output_asm_insn (\"mvneq\\t%0, #0\", operands);
9821 return \"movne\\t%0, #0\";
9823 [(set_attr "conds" "clob")
9824 (set_attr "length" "12")]
9827 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
9828 ;; expressions. For simplicity, the first register is also in the unspec
9830 (define_insn "*push_multi"
9831 [(match_parallel 2 "multi_register_push"
9832 [(set (match_operand:BLK 0 "memory_operand" "=m")
9833 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9834 UNSPEC_PUSH_MULT))])]
9838 int num_saves = XVECLEN (operands[2], 0);
9840 /* For the StrongARM at least it is faster to
9841 use STR to store only a single register. */
9843 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9849 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9851 for (i = 1; i < num_saves; i++)
9853 strcat (pattern, \", %|\");
9855 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9858 strcat (pattern, \"}\");
9859 output_asm_insn (pattern, operands);
9864 [(set_attr "type" "store4")]
9867 (define_insn "stack_tie"
9868 [(set (mem:BLK (scratch))
9869 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9870 (match_operand:SI 1 "s_register_operand" "r")]
9874 [(set_attr "length" "0")]
9877 ;; Similarly for the floating point registers
9878 (define_insn "*push_fp_multi"
9879 [(match_parallel 2 "multi_register_push"
9880 [(set (match_operand:BLK 0 "memory_operand" "=m")
9881 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9882 UNSPEC_PUSH_MULT))])]
9883 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
9888 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9889 output_asm_insn (pattern, operands);
9892 [(set_attr "type" "f_store")]
9895 ;; Special patterns for dealing with the constant pool
9897 (define_insn "align_4"
9898 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9901 assemble_align (32);
9906 (define_insn "align_8"
9907 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
9910 assemble_align (64);
9915 (define_insn "consttable_end"
9916 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9919 making_const_table = FALSE;
9924 (define_insn "consttable_1"
9925 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9928 making_const_table = TRUE;
9929 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9933 [(set_attr "length" "4")]
9936 (define_insn "consttable_2"
9937 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9940 making_const_table = TRUE;
9941 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9945 [(set_attr "length" "4")]
9948 (define_insn "consttable_4"
9949 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9953 making_const_table = TRUE;
9954 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9959 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9960 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9964 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9969 [(set_attr "length" "4")]
9972 (define_insn "consttable_8"
9973 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9977 making_const_table = TRUE;
9978 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9983 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9984 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9988 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9993 [(set_attr "length" "8")]
9996 ;; Miscellaneous Thumb patterns
9998 (define_expand "tablejump"
9999 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10000 (use (label_ref (match_operand 1 "" "")))])]
10005 /* Hopefully, CSE will eliminate this copy. */
10006 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10007 rtx reg2 = gen_reg_rtx (SImode);
10009 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10010 operands[0] = reg2;
10015 ;; NB never uses BX.
10016 (define_insn "*thumb_tablejump"
10017 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10018 (use (label_ref (match_operand 1 "" "")))]
10021 [(set_attr "length" "2")]
10024 ;; V5 Instructions,
10026 (define_insn "clzsi2"
10027 [(set (match_operand:SI 0 "s_register_operand" "=r")
10028 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10029 "TARGET_ARM && arm_arch5"
10031 [(set_attr "predicable" "yes")])
10033 (define_expand "ffssi2"
10034 [(set (match_operand:SI 0 "s_register_operand" "")
10035 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10036 "TARGET_ARM && arm_arch5"
10041 t1 = gen_reg_rtx (SImode);
10042 t2 = gen_reg_rtx (SImode);
10043 t3 = gen_reg_rtx (SImode);
10045 emit_insn (gen_negsi2 (t1, operands[1]));
10046 emit_insn (gen_andsi3 (t2, operands[1], t1));
10047 emit_insn (gen_clzsi2 (t3, t2));
10048 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10053 (define_expand "ctzsi2"
10054 [(set (match_operand:SI 0 "s_register_operand" "")
10055 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10056 "TARGET_ARM && arm_arch5"
10061 t1 = gen_reg_rtx (SImode);
10062 t2 = gen_reg_rtx (SImode);
10063 t3 = gen_reg_rtx (SImode);
10065 emit_insn (gen_negsi2 (t1, operands[1]));
10066 emit_insn (gen_andsi3 (t2, operands[1], t1));
10067 emit_insn (gen_clzsi2 (t3, t2));
10068 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10073 ;; V5E instructions.
10075 (define_insn "prefetch"
10076 [(prefetch (match_operand:SI 0 "address_operand" "p")
10077 (match_operand:SI 1 "" "")
10078 (match_operand:SI 2 "" ""))]
10079 "TARGET_ARM && arm_arch5e"
10082 ;; General predication pattern
10085 [(match_operator 0 "arm_comparison_operator"
10086 [(match_operand 1 "cc_register" "")
10092 (define_insn "prologue_use"
10093 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10095 "%@ %0 needed for prologue"
10099 ;; Patterns for exception handling
10101 (define_expand "eh_return"
10102 [(use (match_operand 0 "general_operand" ""))]
10107 emit_insn (gen_arm_eh_return (operands[0]));
10109 emit_insn (gen_thumb_eh_return (operands[0]));
10114 ;; We can't expand this before we know where the link register is stored.
10115 (define_insn_and_split "arm_eh_return"
10116 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10118 (clobber (match_scratch:SI 1 "=&r"))]
10121 "&& reload_completed"
10125 arm_set_return_address (operands[0], operands[1]);
10130 (define_insn_and_split "thumb_eh_return"
10131 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10133 (clobber (match_scratch:SI 1 "=&l"))]
10136 "&& reload_completed"
10140 thumb_set_return_address (operands[0], operands[1]);
10148 (define_insn "load_tp_hard"
10149 [(set (match_operand:SI 0 "register_operand" "=r")
10150 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10152 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10153 [(set_attr "predicable" "yes")]
10156 ;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10157 (define_insn "load_tp_soft"
10158 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10159 (clobber (reg:SI LR_REGNUM))
10160 (clobber (reg:SI IP_REGNUM))
10161 (clobber (reg:CC CC_REGNUM))]
10163 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10164 [(set_attr "conds" "clob")]
10167 ;; Load the FPA co-processor patterns
10169 ;; Load the Maverick co-processor patterns
10170 (include "cirrus.md")
10171 ;; Load the Intel Wireless Multimedia Extension patterns
10172 (include "iwmmxt.md")
10173 ;; Load the VFP co-processor patterns