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 Free Software Foundation, Inc.
4 ;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;; and Martin Simmons (@harleqn.co.uk).
6 ;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
8 ;; This file is part of GCC.
10 ;; GCC is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 2, or (at your
13 ;; option) any later version.
15 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
18 ;; License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; see the file COPYING. If not, write to
22 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
28 ;;---------------------------------------------------------------------------
33 [(IP_REGNUM 12) ; Scratch register
34 (SP_REGNUM 13) ; Stack pointer
35 (LR_REGNUM 14) ; Return address register
36 (PC_REGNUM 15) ; Program counter
37 (CC_REGNUM 24) ; Condition code pseudo register
41 ;; 3rd operand to select_dominance_cc_mode
50 ;; Note: sin and cos are no-longer used.
53 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
54 ; operand 0 is the result,
55 ; operand 1 the parameter.
56 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
57 ; operand 0 is the result,
58 ; operand 1 the parameter.
59 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
60 ; operand 0 is the first register,
61 ; subsequent registers are in parallel (use ...)
63 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
64 ; usage, that is, we will add the pic_register
65 ; value to it before trying to dereference it.
66 (UNSPEC_PIC_BASE 4) ; Adding the PC value to the offset to the
67 ; GLOBAL_OFFSET_TABLE. The operation is fully
68 ; described by the RTL but must be wrapped to
69 ; prevent combine from trying to rip it apart.
70 (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses
71 ; being scheduled before the stack adjustment insn.
72 (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
73 ; this unspec is used to prevent the deletion of
74 ; instructions setting registers for EH handling
75 ; and stack frame generation. Operand 0 is the
77 (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
78 (UNSPEC_WSHUFH 8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
79 (UNSPEC_WACC 9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
80 (UNSPEC_TMOVMSK 10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
81 (UNSPEC_WSAD 11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
82 (UNSPEC_WSADZ 12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
83 (UNSPEC_WMACS 13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
84 (UNSPEC_WMACU 14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
85 (UNSPEC_WMACSZ 15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
86 (UNSPEC_WMACUZ 16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
87 (UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
88 (UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
89 (UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
93 ;; UNSPEC_VOLATILE Usage:
96 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
98 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
99 ; instruction epilogue sequence that isn't expanded
100 ; into normal RTL. Used for both normal and sibcall
102 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
103 ; for inlined constants.
104 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
106 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
108 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
110 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
112 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
114 (VUNSPEC_TMRC 8) ; Used by the iWMMXt TMRC instruction.
115 (VUNSPEC_TMCR 9) ; Used by the iWMMXt TMCR instruction.
116 (VUNSPEC_ALIGN8 10) ; 8-byte alignment version of VUNSPEC_ALIGN
117 (VUNSPEC_WCMP_EQ 11) ; Used by the iWMMXt WCMPEQ instructions
118 (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
119 (VUNSPEC_WCMP_GT 13) ; Used by the iwMMXT WCMPGT instructions
123 ;;---------------------------------------------------------------------------
126 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
127 ; generating ARM code. This is used to control the length of some insn
128 ; patterns that share the same RTL in both ARM and Thumb code.
129 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
131 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
132 ; scheduling decisions for the load unit and the multiplier.
133 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
135 ; IS_XSCALE is set to 'yes' when compiling for XScale.
136 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
138 ;; Operand number of an input operand that is shifted. Zero if the
139 ;; given instruction does not shift one of its input operands.
140 (define_attr "shift" "" (const_int 0))
142 ; Floating Point Unit. If we only have floating point emulation, then there
143 ; is no point in scheduling the floating point insns. (Well, for best
144 ; performance we should try and group them together).
145 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
146 (const (symbol_ref "arm_fpu_attr")))
148 ; LENGTH of an instruction (in bytes)
149 (define_attr "length" "" (const_int 4))
151 ; POOL_RANGE is how far away from a constant pool entry that this insn
152 ; can be placed. If the distance is zero, then this insn will never
153 ; reference the pool.
154 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
155 ; before its address.
156 (define_attr "pool_range" "" (const_int 0))
157 (define_attr "neg_pool_range" "" (const_int 0))
159 ; An assembler sequence may clobber the condition codes without us knowing.
160 ; If such an insn references the pool, then we have no way of knowing how,
161 ; so use the most conservative value for pool_range.
162 (define_asm_attributes
163 [(set_attr "conds" "clob")
164 (set_attr "length" "4")
165 (set_attr "pool_range" "250")])
167 ;; The instruction used to implement a particular pattern. This
168 ;; information is used by pipeline descriptions to provide accurate
169 ;; scheduling information.
172 "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"
173 (const_string "other"))
175 ; TYPE attribute is used to detect floating point instructions which, if
176 ; running on a co-processor can run in parallel with other, basic instructions
177 ; If write-buffer scheduling is enabled then it can also be used in the
178 ; scheduling of writes.
180 ; Classification of each insn
181 ; alu any alu instruction that doesn't hit memory or fp
182 ; regs or have a shifted source operand
183 ; alu_shift any data instruction that doesn't hit memory or fp
184 ; regs, but has a source operand shifted by a constant
185 ; alu_shift_reg any data instruction that doesn't hit memory or fp
186 ; regs, but has a source operand shifted by a register value
187 ; mult a multiply instruction
188 ; block blockage insn, this blocks all functional units
189 ; float a floating point arithmetic operation (subject to expansion)
190 ; fdivd DFmode floating point division
191 ; fdivs SFmode floating point division
192 ; fmul Floating point multiply
193 ; ffmul Fast floating point multiply
194 ; farith Floating point arithmetic (4 cycle)
195 ; ffarith Fast floating point arithmetic (2 cycle)
196 ; float_em a floating point arithmetic operation that is normally emulated
197 ; even on a machine with an fpa.
198 ; f_load a floating point load from memory
199 ; f_store a floating point store to memory
200 ; f_mem_r a transfer of a floating point register to a real reg via mem
201 ; r_mem_f the reverse of f_mem_r
202 ; f_2_r fast transfer float to arm (no memory needed)
203 ; r_2_f fast transfer arm to float
205 ; call a subroutine call
206 ; load_byte load byte(s) from memory to arm registers
207 ; load1 load 1 word from memory to arm registers
208 ; load2 load 2 words from memory to arm registers
209 ; load3 load 3 words from memory to arm registers
210 ; load4 load 4 words from memory to arm registers
211 ; store store 1 word to memory from arm registers
212 ; store2 store 2 words
213 ; store3 store 3 words
214 ; store4 store 4 (or more) words
215 ; Additions for Cirrus Maverick co-processor:
216 ; mav_farith Floating point arithmetic (4 cycle)
217 ; mav_dmult Double multiplies (7 cycle)
220 "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult"
222 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
223 (const_string "mult")
224 (const_string "alu")))
226 ; Load scheduling, set from the arm_ld_sched variable
227 ; initialized by arm_override_options()
228 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
230 ; condition codes: this one is used by final_prescan_insn to speed up
231 ; conditionalizing instructions. It saves having to scan the rtl to see if
232 ; it uses or alters the condition codes.
234 ; USE means that the condition codes are used by the insn in the process of
235 ; outputting code, this means (at present) that we can't use the insn in
238 ; SET means that the purpose of the insn is to set the condition codes in a
239 ; well defined manner.
241 ; CLOB means that the condition codes are altered in an undefined manner, if
242 ; they are altered at all
244 ; JUMP_CLOB is used when the condition cannot be represented by a single
245 ; instruction (UNEQ and LTGT). These cannot be predicated.
247 ; NOCOND means that the condition codes are neither altered nor affect the
248 ; output of this insn
250 (define_attr "conds" "use,set,clob,jump_clob,nocond"
251 (if_then_else (eq_attr "type" "call")
252 (const_string "clob")
253 (const_string "nocond")))
255 ; Predicable means that the insn can be conditionally executed based on
256 ; an automatically added predicate (additional patterns are generated by
257 ; gen...). We default to 'no' because no Thumb patterns match this rule
258 ; and not all ARM patterns do.
259 (define_attr "predicable" "no,yes" (const_string "no"))
261 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
262 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
263 ; suffer blockages enough to warrant modelling this (and it can adversely
264 ; affect the schedule).
265 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
267 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
268 ; to stall the processor. Used with model_wbuf above.
269 (define_attr "write_conflict" "no,yes"
270 (if_then_else (eq_attr "type"
271 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
273 (const_string "no")))
275 ; Classify the insns into those that take one cycle and those that take more
276 ; than one on the main cpu execution unit.
277 (define_attr "core_cycles" "single,multi"
278 (if_then_else (eq_attr "type"
279 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
280 (const_string "single")
281 (const_string "multi")))
283 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
284 ;; distant label. Only applicable to Thumb code.
285 (define_attr "far_jump" "yes,no" (const_string "no"))
287 ;;---------------------------------------------------------------------------
288 ;; Pipeline descriptions
290 ;; Processor type. This attribute must exactly match the table in
293 "arm2,arm250,arm3,arm6,arm60,arm600,arm610,arm620,arm7,arm7m,arm7d,arm7dm,arm7di,arm7dmi,arm70,arm700,arm700i,arm710,arm720,arm710c,arm7100,arm7500,arm7500fe,arm7tdmi,arm710t,arm720t,arm740t,arm8,arm810,arm9,arm920,arm920t,arm940t,arm9tdmi,arm9e,ep9312,strongarm,strongarm110,strongarm1100,strongarm1110,arm10tdmi,arm1020t,arm926ejs,arm1026ejs,xscale,iwmmxt,arm1136js,arm1136jfs"
294 (const (symbol_ref "arm_tune")))
296 ;; True if the generic scheduling description should be used.
298 (define_attr "generic_sched" "yes,no"
300 (eq_attr "tune" "arm926ejs,arm1026ejs,arm1136js,arm1136jfs")
302 (const_string "yes")))
304 (include "arm-generic.md")
305 (include "arm926ejs.md")
306 (include "arm1026ejs.md")
307 (include "arm1136jfs.md")
310 ;;---------------------------------------------------------------------------
315 ;; Note: For DImode insns, there is normally no reason why operands should
316 ;; not be in the same register, what we don't want is for something being
317 ;; written to partially overlap something that is an input.
318 ;; Cirrus 64bit additions should not be split because we have a native
319 ;; 64bit addition instructions.
321 (define_expand "adddi3"
323 [(set (match_operand:DI 0 "s_register_operand" "")
324 (plus:DI (match_operand:DI 1 "s_register_operand" "")
325 (match_operand:DI 2 "s_register_operand" "")))
326 (clobber (reg:CC CC_REGNUM))])]
329 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
331 if (!cirrus_fp_register (operands[0], DImode))
332 operands[0] = force_reg (DImode, operands[0]);
333 if (!cirrus_fp_register (operands[1], DImode))
334 operands[1] = force_reg (DImode, operands[1]);
335 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
341 if (GET_CODE (operands[1]) != REG)
342 operands[1] = force_reg (SImode, operands[1]);
343 if (GET_CODE (operands[2]) != REG)
344 operands[2] = force_reg (SImode, operands[2]);
349 (define_insn "*thumb_adddi3"
350 [(set (match_operand:DI 0 "register_operand" "=l")
351 (plus:DI (match_operand:DI 1 "register_operand" "%0")
352 (match_operand:DI 2 "register_operand" "l")))
353 (clobber (reg:CC CC_REGNUM))
356 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
357 [(set_attr "length" "4")]
360 (define_insn_and_split "*arm_adddi3"
361 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
362 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
363 (match_operand:DI 2 "s_register_operand" "r, 0")))
364 (clobber (reg:CC CC_REGNUM))]
365 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
367 "TARGET_ARM && reload_completed"
368 [(parallel [(set (reg:CC_C CC_REGNUM)
369 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
371 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
372 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
373 (plus:SI (match_dup 4) (match_dup 5))))]
376 operands[3] = gen_highpart (SImode, operands[0]);
377 operands[0] = gen_lowpart (SImode, operands[0]);
378 operands[4] = gen_highpart (SImode, operands[1]);
379 operands[1] = gen_lowpart (SImode, operands[1]);
380 operands[5] = gen_highpart (SImode, operands[2]);
381 operands[2] = gen_lowpart (SImode, operands[2]);
383 [(set_attr "conds" "clob")
384 (set_attr "length" "8")]
387 (define_insn_and_split "*adddi_sesidi_di"
388 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
389 (plus:DI (sign_extend:DI
390 (match_operand:SI 2 "s_register_operand" "r,r"))
391 (match_operand:DI 1 "s_register_operand" "r,0")))
392 (clobber (reg:CC CC_REGNUM))]
393 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
395 "TARGET_ARM && reload_completed"
396 [(parallel [(set (reg:CC_C CC_REGNUM)
397 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
399 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
400 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
401 (plus:SI (ashiftrt:SI (match_dup 2)
406 operands[3] = gen_highpart (SImode, operands[0]);
407 operands[0] = gen_lowpart (SImode, operands[0]);
408 operands[4] = gen_highpart (SImode, operands[1]);
409 operands[1] = gen_lowpart (SImode, operands[1]);
410 operands[2] = gen_lowpart (SImode, operands[2]);
412 [(set_attr "conds" "clob")
413 (set_attr "length" "8")]
416 (define_insn_and_split "*adddi_zesidi_di"
417 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
418 (plus:DI (zero_extend:DI
419 (match_operand:SI 2 "s_register_operand" "r,r"))
420 (match_operand:DI 1 "s_register_operand" "r,0")))
421 (clobber (reg:CC CC_REGNUM))]
422 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
424 "TARGET_ARM && reload_completed"
425 [(parallel [(set (reg:CC_C CC_REGNUM)
426 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
428 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
429 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
430 (plus:SI (match_dup 4) (const_int 0))))]
433 operands[3] = gen_highpart (SImode, operands[0]);
434 operands[0] = gen_lowpart (SImode, operands[0]);
435 operands[4] = gen_highpart (SImode, operands[1]);
436 operands[1] = gen_lowpart (SImode, operands[1]);
437 operands[2] = gen_lowpart (SImode, operands[2]);
439 [(set_attr "conds" "clob")
440 (set_attr "length" "8")]
443 (define_expand "addsi3"
444 [(set (match_operand:SI 0 "s_register_operand" "")
445 (plus:SI (match_operand:SI 1 "s_register_operand" "")
446 (match_operand:SI 2 "reg_or_int_operand" "")))]
449 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
451 arm_split_constant (PLUS, SImode, NULL_RTX,
452 INTVAL (operands[2]), operands[0], operands[1],
453 (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
459 ; If there is a scratch available, this will be faster than synthesizing the
462 [(match_scratch:SI 3 "r")
463 (set (match_operand:SI 0 "arm_general_register_operand" "")
464 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
465 (match_operand:SI 2 "const_int_operand" "")))]
467 !(const_ok_for_arm (INTVAL (operands[2]))
468 || const_ok_for_arm (-INTVAL (operands[2])))
469 && const_ok_for_arm (~INTVAL (operands[2]))"
470 [(set (match_dup 3) (match_dup 2))
471 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
475 (define_insn_and_split "*arm_addsi3"
476 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
477 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
478 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
485 GET_CODE (operands[2]) == CONST_INT
486 && !(const_ok_for_arm (INTVAL (operands[2]))
487 || const_ok_for_arm (-INTVAL (operands[2])))"
488 [(clobber (const_int 0))]
490 arm_split_constant (PLUS, SImode, curr_insn,
491 INTVAL (operands[2]), operands[0],
495 [(set_attr "length" "4,4,16")
496 (set_attr "predicable" "yes")]
499 ;; Register group 'k' is a single register group containing only the stack
500 ;; register. Trying to reload it will always fail catastrophically,
501 ;; so never allow those alternatives to match if reloading is needed.
503 (define_insn "*thumb_addsi3"
504 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
505 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
506 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
509 static const char * const asms[] =
511 \"add\\t%0, %0, %2\",
512 \"sub\\t%0, %0, #%n2\",
513 \"add\\t%0, %1, %2\",
514 \"add\\t%0, %0, %2\",
515 \"add\\t%0, %0, %2\",
516 \"add\\t%0, %1, %2\",
519 if ((which_alternative == 2 || which_alternative == 6)
520 && GET_CODE (operands[2]) == CONST_INT
521 && INTVAL (operands[2]) < 0)
522 return \"sub\\t%0, %1, #%n2\";
523 return asms[which_alternative];
525 [(set_attr "length" "2")]
528 ;; Reloading and elimination of the frame pointer can
529 ;; sometimes cause this optimization to be missed.
531 [(set (match_operand:SI 0 "arm_general_register_operand" "")
532 (match_operand:SI 1 "const_int_operand" ""))
534 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
536 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
537 && (INTVAL (operands[1]) & 3) == 0"
538 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
542 (define_insn "*addsi3_compare0"
543 [(set (reg:CC_NOOV CC_REGNUM)
545 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
546 (match_operand:SI 2 "arm_add_operand" "rI,L"))
548 (set (match_operand:SI 0 "s_register_operand" "=r,r")
549 (plus:SI (match_dup 1) (match_dup 2)))]
553 sub%?s\\t%0, %1, #%n2"
554 [(set_attr "conds" "set")]
557 (define_insn "*addsi3_compare0_scratch"
558 [(set (reg:CC_NOOV CC_REGNUM)
560 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
561 (match_operand:SI 1 "arm_add_operand" "rI,L"))
567 [(set_attr "conds" "set")]
570 ;; These patterns are the same ones as the two regular addsi3_compare0
571 ;; patterns, except we write them slightly different - the combiner
572 ;; tends to generate them this way.
573 (define_insn "*addsi3_compare0_for_combiner"
574 [(set (reg:CC CC_REGNUM)
576 (match_operand:SI 1 "s_register_operand" "r,r")
577 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
578 (set (match_operand:SI 0 "s_register_operand" "=r,r")
579 (plus:SI (match_dup 1) (match_dup 2)))]
583 sub%?s\\t%0, %1, #%n2"
584 [(set_attr "conds" "set")]
587 (define_insn "*addsi3_compare0_scratch_for_combiner"
588 [(set (reg:CC CC_REGNUM)
590 (match_operand:SI 0 "s_register_operand" "r,r")
591 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
596 [(set_attr "conds" "set")]
599 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
600 ;; addend is a constant.
601 (define_insn "*cmpsi2_addneg"
602 [(set (reg:CC CC_REGNUM)
604 (match_operand:SI 1 "s_register_operand" "r,r")
605 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
606 (set (match_operand:SI 0 "s_register_operand" "=r,r")
607 (plus:SI (match_dup 1)
608 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
609 "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
612 add%?s\\t%0, %1, #%n2"
613 [(set_attr "conds" "set")]
616 ;; Convert the sequence
618 ;; cmn rd, #1 (equivalent to cmp rd, #-1)
622 ;; bcs dest ((unsigned)rn >= 1)
623 ;; similarly for the beq variant using bcc.
624 ;; This is a common looping idiom (while (n--))
626 [(set (match_operand:SI 0 "arm_general_register_operand" "")
627 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
629 (set (match_operand 2 "cc_register" "")
630 (compare (match_dup 0) (const_int -1)))
632 (if_then_else (match_operator 3 "equality_operator"
633 [(match_dup 2) (const_int 0)])
634 (match_operand 4 "" "")
635 (match_operand 5 "" "")))]
636 "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
640 (match_dup 1) (const_int 1)))
641 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
643 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
646 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
647 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
650 operands[2], const0_rtx);"
653 ;; The next four insns work because they compare the result with one of
654 ;; the operands, and we know that the use of the condition code is
655 ;; either GEU or LTU, so we can use the carry flag from the addition
656 ;; instead of doing the compare a second time.
657 (define_insn "*addsi3_compare_op1"
658 [(set (reg:CC_C CC_REGNUM)
660 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
661 (match_operand:SI 2 "arm_add_operand" "rI,L"))
663 (set (match_operand:SI 0 "s_register_operand" "=r,r")
664 (plus:SI (match_dup 1) (match_dup 2)))]
668 sub%?s\\t%0, %1, #%n2"
669 [(set_attr "conds" "set")]
672 (define_insn "*addsi3_compare_op2"
673 [(set (reg:CC_C CC_REGNUM)
675 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
676 (match_operand:SI 2 "arm_add_operand" "rI,L"))
678 (set (match_operand:SI 0 "s_register_operand" "=r,r")
679 (plus:SI (match_dup 1) (match_dup 2)))]
683 sub%?s\\t%0, %1, #%n2"
684 [(set_attr "conds" "set")]
687 (define_insn "*compare_addsi2_op0"
688 [(set (reg:CC_C CC_REGNUM)
690 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
691 (match_operand:SI 1 "arm_add_operand" "rI,L"))
697 [(set_attr "conds" "set")]
700 (define_insn "*compare_addsi2_op1"
701 [(set (reg:CC_C CC_REGNUM)
703 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
704 (match_operand:SI 1 "arm_add_operand" "rI,L"))
710 [(set_attr "conds" "set")]
713 (define_insn "*addsi3_carryin"
714 [(set (match_operand:SI 0 "s_register_operand" "=r")
715 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
716 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
717 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
720 [(set_attr "conds" "use")]
723 (define_insn "*addsi3_carryin_shift"
724 [(set (match_operand:SI 0 "s_register_operand" "=r")
725 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
727 (match_operator:SI 2 "shift_operator"
728 [(match_operand:SI 3 "s_register_operand" "r")
729 (match_operand:SI 4 "reg_or_int_operand" "rM")])
730 (match_operand:SI 1 "s_register_operand" "r"))))]
732 "adc%?\\t%0, %1, %3%S2"
733 [(set_attr "conds" "use")
734 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
735 (const_string "alu_shift")
736 (const_string "alu_shift_reg")))]
739 (define_insn "*addsi3_carryin_alt1"
740 [(set (match_operand:SI 0 "s_register_operand" "=r")
741 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
742 (match_operand:SI 2 "arm_rhs_operand" "rI"))
743 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
746 [(set_attr "conds" "use")]
749 (define_insn "*addsi3_carryin_alt2"
750 [(set (match_operand:SI 0 "s_register_operand" "=r")
751 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
752 (match_operand:SI 1 "s_register_operand" "r"))
753 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
756 [(set_attr "conds" "use")]
759 (define_insn "*addsi3_carryin_alt3"
760 [(set (match_operand:SI 0 "s_register_operand" "=r")
761 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
762 (match_operand:SI 2 "arm_rhs_operand" "rI"))
763 (match_operand:SI 1 "s_register_operand" "r")))]
766 [(set_attr "conds" "use")]
769 (define_insn "incscc"
770 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
771 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
772 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
773 (match_operand:SI 1 "s_register_operand" "0,?r")))]
777 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
778 [(set_attr "conds" "use")
779 (set_attr "length" "4,8")]
782 ; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
784 [(set (match_operand:SI 0 "s_register_operand" "")
785 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
786 (match_operand:SI 2 "s_register_operand" ""))
788 (clobber (match_operand:SI 3 "s_register_operand" ""))]
790 [(set (match_dup 3) (match_dup 1))
791 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
793 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
796 (define_expand "addsf3"
797 [(set (match_operand:SF 0 "s_register_operand" "")
798 (plus:SF (match_operand:SF 1 "s_register_operand" "")
799 (match_operand:SF 2 "arm_float_add_operand" "")))]
800 "TARGET_ARM && TARGET_HARD_FLOAT"
803 && !cirrus_fp_register (operands[2], SFmode))
804 operands[2] = force_reg (SFmode, operands[2]);
807 (define_expand "adddf3"
808 [(set (match_operand:DF 0 "s_register_operand" "")
809 (plus:DF (match_operand:DF 1 "s_register_operand" "")
810 (match_operand:DF 2 "arm_float_add_operand" "")))]
811 "TARGET_ARM && TARGET_HARD_FLOAT"
814 && !cirrus_fp_register (operands[2], DFmode))
815 operands[2] = force_reg (DFmode, operands[2]);
818 (define_expand "subdi3"
820 [(set (match_operand:DI 0 "s_register_operand" "")
821 (minus:DI (match_operand:DI 1 "s_register_operand" "")
822 (match_operand:DI 2 "s_register_operand" "")))
823 (clobber (reg:CC CC_REGNUM))])]
826 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
828 && cirrus_fp_register (operands[0], DImode)
829 && cirrus_fp_register (operands[1], DImode))
831 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
837 if (GET_CODE (operands[1]) != REG)
838 operands[1] = force_reg (SImode, operands[1]);
839 if (GET_CODE (operands[2]) != REG)
840 operands[2] = force_reg (SImode, operands[2]);
845 (define_insn "*arm_subdi3"
846 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
847 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
848 (match_operand:DI 2 "s_register_operand" "r,0,0")))
849 (clobber (reg:CC CC_REGNUM))]
851 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
852 [(set_attr "conds" "clob")
853 (set_attr "length" "8")]
856 (define_insn "*thumb_subdi3"
857 [(set (match_operand:DI 0 "register_operand" "=l")
858 (minus:DI (match_operand:DI 1 "register_operand" "0")
859 (match_operand:DI 2 "register_operand" "l")))
860 (clobber (reg:CC CC_REGNUM))]
862 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
863 [(set_attr "length" "4")]
866 (define_insn "*subdi_di_zesidi"
867 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
868 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
870 (match_operand:SI 2 "s_register_operand" "r,r"))))
871 (clobber (reg:CC CC_REGNUM))]
873 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
874 [(set_attr "conds" "clob")
875 (set_attr "length" "8")]
878 (define_insn "*subdi_di_sesidi"
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, %2, asr #31"
886 [(set_attr "conds" "clob")
887 (set_attr "length" "8")]
890 (define_insn "*subdi_zesidi_di"
891 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
892 (minus:DI (zero_extend:DI
893 (match_operand:SI 2 "s_register_operand" "r,r"))
894 (match_operand:DI 1 "s_register_operand" "?r,0")))
895 (clobber (reg:CC CC_REGNUM))]
897 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
898 [(set_attr "conds" "clob")
899 (set_attr "length" "8")]
902 (define_insn "*subdi_sesidi_di"
903 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
904 (minus:DI (sign_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, %2, asr #31"
910 [(set_attr "conds" "clob")
911 (set_attr "length" "8")]
914 (define_insn "*subdi_zesidi_zesidi"
915 [(set (match_operand:DI 0 "s_register_operand" "=r")
916 (minus:DI (zero_extend:DI
917 (match_operand:SI 1 "s_register_operand" "r"))
919 (match_operand:SI 2 "s_register_operand" "r"))))
920 (clobber (reg:CC CC_REGNUM))]
922 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
923 [(set_attr "conds" "clob")
924 (set_attr "length" "8")]
927 (define_expand "subsi3"
928 [(set (match_operand:SI 0 "s_register_operand" "")
929 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
930 (match_operand:SI 2 "s_register_operand" "")))]
933 if (GET_CODE (operands[1]) == CONST_INT)
937 arm_split_constant (MINUS, SImode, NULL_RTX,
938 INTVAL (operands[1]), operands[0],
941 : preserve_subexpressions_p ()));
944 else /* TARGET_THUMB */
945 operands[1] = force_reg (SImode, operands[1]);
950 (define_insn "*thumb_subsi3_insn"
951 [(set (match_operand:SI 0 "register_operand" "=l")
952 (minus:SI (match_operand:SI 1 "register_operand" "l")
953 (match_operand:SI 2 "register_operand" "l")))]
956 [(set_attr "length" "2")]
959 (define_insn_and_split "*arm_subsi3_insn"
960 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
961 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
962 (match_operand:SI 2 "s_register_operand" "r,r")))]
968 && GET_CODE (operands[1]) == CONST_INT
969 && !const_ok_for_arm (INTVAL (operands[1]))"
970 [(clobber (const_int 0))]
972 arm_split_constant (MINUS, SImode, curr_insn,
973 INTVAL (operands[1]), operands[0], operands[2], 0);
976 [(set_attr "length" "4,16")
977 (set_attr "predicable" "yes")]
981 [(match_scratch:SI 3 "r")
982 (set (match_operand:SI 0 "arm_general_register_operand" "")
983 (minus:SI (match_operand:SI 1 "const_int_operand" "")
984 (match_operand:SI 2 "arm_general_register_operand" "")))]
986 && !const_ok_for_arm (INTVAL (operands[1]))
987 && const_ok_for_arm (~INTVAL (operands[1]))"
988 [(set (match_dup 3) (match_dup 1))
989 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
993 (define_insn "*subsi3_compare0"
994 [(set (reg:CC_NOOV CC_REGNUM)
996 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
997 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
999 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1000 (minus:SI (match_dup 1) (match_dup 2)))]
1004 rsb%?s\\t%0, %2, %1"
1005 [(set_attr "conds" "set")]
1008 (define_insn "decscc"
1009 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1010 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1011 (match_operator:SI 2 "arm_comparison_operator"
1012 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1016 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1017 [(set_attr "conds" "use")
1018 (set_attr "length" "*,8")]
1021 (define_expand "subsf3"
1022 [(set (match_operand:SF 0 "s_register_operand" "")
1023 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1024 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1025 "TARGET_ARM && TARGET_HARD_FLOAT"
1027 if (TARGET_MAVERICK)
1029 if (!cirrus_fp_register (operands[1], SFmode))
1030 operands[1] = force_reg (SFmode, operands[1]);
1031 if (!cirrus_fp_register (operands[2], SFmode))
1032 operands[2] = force_reg (SFmode, operands[2]);
1036 (define_expand "subdf3"
1037 [(set (match_operand:DF 0 "s_register_operand" "")
1038 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1039 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1040 "TARGET_ARM && TARGET_HARD_FLOAT"
1042 if (TARGET_MAVERICK)
1044 if (!cirrus_fp_register (operands[1], DFmode))
1045 operands[1] = force_reg (DFmode, operands[1]);
1046 if (!cirrus_fp_register (operands[2], DFmode))
1047 operands[2] = force_reg (DFmode, operands[2]);
1052 ;; Multiplication insns
1054 (define_expand "mulsi3"
1055 [(set (match_operand:SI 0 "s_register_operand" "")
1056 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1057 (match_operand:SI 1 "s_register_operand" "")))]
1062 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1063 (define_insn "*arm_mulsi3"
1064 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1065 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1066 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1068 "mul%?\\t%0, %2, %1"
1069 [(set_attr "insn" "mul")
1070 (set_attr "predicable" "yes")]
1073 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1074 ; 1 and 2; are the same, because reload will make operand 0 match
1075 ; operand 1 without realizing that this conflicts with operand 2. We fix
1076 ; this by adding another alternative to match this case, and then `reload'
1077 ; it ourselves. This alternative must come first.
1078 (define_insn "*thumb_mulsi3"
1079 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1080 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1081 (match_operand:SI 2 "register_operand" "l,l,l")))]
1084 if (which_alternative < 2)
1085 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1087 return \"mul\\t%0, %0, %2\";
1089 [(set_attr "length" "4,4,2")
1090 (set_attr "insn" "mul")]
1093 (define_insn "*mulsi3_compare0"
1094 [(set (reg:CC_NOOV CC_REGNUM)
1095 (compare:CC_NOOV (mult:SI
1096 (match_operand:SI 2 "s_register_operand" "r,r")
1097 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1099 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1100 (mult:SI (match_dup 2) (match_dup 1)))]
1101 "TARGET_ARM && !arm_arch_xscale"
1102 "mul%?s\\t%0, %2, %1"
1103 [(set_attr "conds" "set")
1104 (set_attr "insn" "muls")]
1107 (define_insn "*mulsi_compare0_scratch"
1108 [(set (reg:CC_NOOV CC_REGNUM)
1109 (compare:CC_NOOV (mult:SI
1110 (match_operand:SI 2 "s_register_operand" "r,r")
1111 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1113 (clobber (match_scratch:SI 0 "=&r,&r"))]
1114 "TARGET_ARM && !arm_arch_xscale"
1115 "mul%?s\\t%0, %2, %1"
1116 [(set_attr "conds" "set")
1117 (set_attr "insn" "muls")]
1120 ;; Unnamed templates to match MLA instruction.
1122 (define_insn "*mulsi3addsi"
1123 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1125 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1126 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1127 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1129 "mla%?\\t%0, %2, %1, %3"
1130 [(set_attr "insn" "mla")
1131 (set_attr "predicable" "yes")]
1134 (define_insn "*mulsi3addsi_compare0"
1135 [(set (reg:CC_NOOV CC_REGNUM)
1138 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1139 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1140 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1142 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1143 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1145 "TARGET_ARM && !arm_arch_xscale"
1146 "mla%?s\\t%0, %2, %1, %3"
1147 [(set_attr "conds" "set")
1148 (set_attr "insn" "mlas")]
1151 (define_insn "*mulsi3addsi_compare0_scratch"
1152 [(set (reg:CC_NOOV CC_REGNUM)
1155 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1156 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1157 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1159 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1160 "TARGET_ARM && !arm_arch_xscale"
1161 "mla%?s\\t%0, %2, %1, %3"
1162 [(set_attr "conds" "set")
1163 (set_attr "insn" "mlas")]
1166 ;; Unnamed template to match long long multiply-accumulate (smlal)
1168 (define_insn "*mulsidi3adddi"
1169 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1172 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1173 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1174 (match_operand:DI 1 "s_register_operand" "0")))]
1175 "TARGET_ARM && arm_arch3m"
1176 "smlal%?\\t%Q0, %R0, %3, %2"
1177 [(set_attr "insn" "smlal")
1178 (set_attr "predicable" "yes")]
1181 (define_insn "mulsidi3"
1182 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1184 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1185 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1186 "TARGET_ARM && arm_arch3m"
1187 "smull%?\\t%Q0, %R0, %1, %2"
1188 [(set_attr "insn" "smull")
1189 (set_attr "predicable" "yes")]
1192 (define_insn "umulsidi3"
1193 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1195 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1196 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1197 "TARGET_ARM && arm_arch3m"
1198 "umull%?\\t%Q0, %R0, %1, %2"
1199 [(set_attr "insn" "umull")
1200 (set_attr "predicable" "yes")]
1203 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1205 (define_insn "*umulsidi3adddi"
1206 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1209 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1210 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1211 (match_operand:DI 1 "s_register_operand" "0")))]
1212 "TARGET_ARM && arm_arch3m"
1213 "umlal%?\\t%Q0, %R0, %3, %2"
1214 [(set_attr "insn" "umlal")
1215 (set_attr "predicable" "yes")]
1218 (define_insn "smulsi3_highpart"
1219 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1223 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1224 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1226 (clobber (match_scratch:SI 3 "=&r,&r"))]
1227 "TARGET_ARM && arm_arch3m"
1228 "smull%?\\t%3, %0, %2, %1"
1229 [(set_attr "insn" "smull")
1230 (set_attr "predicable" "yes")]
1233 (define_insn "umulsi3_highpart"
1234 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1238 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1239 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1241 (clobber (match_scratch:SI 3 "=&r,&r"))]
1242 "TARGET_ARM && arm_arch3m"
1243 "umull%?\\t%3, %0, %2, %1"
1244 [(set_attr "insn" "umull")
1245 (set_attr "predicable" "yes")]
1248 (define_insn "mulhisi3"
1249 [(set (match_operand:SI 0 "s_register_operand" "=r")
1250 (mult:SI (sign_extend:SI
1251 (match_operand:HI 1 "s_register_operand" "%r"))
1253 (match_operand:HI 2 "s_register_operand" "r"))))]
1254 "TARGET_ARM && arm_arch5e"
1255 "smulbb%?\\t%0, %1, %2"
1256 [(set_attr "insn" "smulxy")
1257 (set_attr "predicable" "yes")]
1260 (define_insn "*mulhisi3tb"
1261 [(set (match_operand:SI 0 "s_register_operand" "=r")
1262 (mult:SI (ashiftrt:SI
1263 (match_operand:SI 1 "s_register_operand" "r")
1266 (match_operand:HI 2 "s_register_operand" "r"))))]
1267 "TARGET_ARM && arm_arch5e"
1268 "smultb%?\\t%0, %1, %2"
1269 [(set_attr "insn" "smulxy")
1270 (set_attr "predicable" "yes")]
1273 (define_insn "*mulhisi3bt"
1274 [(set (match_operand:SI 0 "s_register_operand" "=r")
1275 (mult:SI (sign_extend:SI
1276 (match_operand:HI 1 "s_register_operand" "r"))
1278 (match_operand:SI 2 "s_register_operand" "r")
1280 "TARGET_ARM && arm_arch5e"
1281 "smulbt%?\\t%0, %1, %2"
1282 [(set_attr "insn" "smulxy")
1283 (set_attr "predicable" "yes")]
1286 (define_insn "*mulhisi3tt"
1287 [(set (match_operand:SI 0 "s_register_operand" "=r")
1288 (mult:SI (ashiftrt:SI
1289 (match_operand:SI 1 "s_register_operand" "r")
1292 (match_operand:SI 2 "s_register_operand" "r")
1294 "TARGET_ARM && arm_arch5e"
1295 "smultt%?\\t%0, %1, %2"
1296 [(set_attr "insn" "smulxy")
1297 (set_attr "predicable" "yes")]
1300 (define_insn "*mulhisi3addsi"
1301 [(set (match_operand:SI 0 "s_register_operand" "=r")
1302 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1303 (mult:SI (sign_extend:SI
1304 (match_operand:HI 2 "s_register_operand" "%r"))
1306 (match_operand:HI 3 "s_register_operand" "r")))))]
1307 "TARGET_ARM && arm_arch5e"
1308 "smlabb%?\\t%0, %2, %3, %1"
1309 [(set_attr "insn" "smlaxy")
1310 (set_attr "predicable" "yes")]
1313 (define_insn "*mulhidi3adddi"
1314 [(set (match_operand:DI 0 "s_register_operand" "=r")
1316 (match_operand:DI 1 "s_register_operand" "0")
1317 (mult:DI (sign_extend:DI
1318 (match_operand:HI 2 "s_register_operand" "%r"))
1320 (match_operand:HI 3 "s_register_operand" "r")))))]
1321 "TARGET_ARM && arm_arch5e"
1322 "smlalbb%?\\t%Q0, %R0, %2, %3"
1323 [(set_attr "insn" "smlalxy")
1324 (set_attr "predicable" "yes")])
1326 (define_expand "mulsf3"
1327 [(set (match_operand:SF 0 "s_register_operand" "")
1328 (mult:SF (match_operand:SF 1 "s_register_operand" "")
1329 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1330 "TARGET_ARM && TARGET_HARD_FLOAT"
1333 && !cirrus_fp_register (operands[2], SFmode))
1334 operands[2] = force_reg (SFmode, operands[2]);
1337 (define_expand "muldf3"
1338 [(set (match_operand:DF 0 "s_register_operand" "")
1339 (mult:DF (match_operand:DF 1 "s_register_operand" "")
1340 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1341 "TARGET_ARM && TARGET_HARD_FLOAT"
1344 && !cirrus_fp_register (operands[2], DFmode))
1345 operands[2] = force_reg (DFmode, operands[2]);
1350 (define_expand "divsf3"
1351 [(set (match_operand:SF 0 "s_register_operand" "")
1352 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1353 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1354 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1357 (define_expand "divdf3"
1358 [(set (match_operand:DF 0 "s_register_operand" "")
1359 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1360 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1361 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1366 (define_expand "modsf3"
1367 [(set (match_operand:SF 0 "s_register_operand" "")
1368 (mod:SF (match_operand:SF 1 "s_register_operand" "")
1369 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1370 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1373 (define_expand "moddf3"
1374 [(set (match_operand:DF 0 "s_register_operand" "")
1375 (mod:DF (match_operand:DF 1 "s_register_operand" "")
1376 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1377 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1380 ;; Boolean and,ior,xor insns
1382 ;; Split up double word logical operations
1384 ;; Split up simple DImode logical operations. Simply perform the logical
1385 ;; operation on the upper and lower halves of the registers.
1387 [(set (match_operand:DI 0 "s_register_operand" "")
1388 (match_operator:DI 6 "logical_binary_operator"
1389 [(match_operand:DI 1 "s_register_operand" "")
1390 (match_operand:DI 2 "s_register_operand" "")]))]
1391 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1392 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1393 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1396 operands[3] = gen_highpart (SImode, operands[0]);
1397 operands[0] = gen_lowpart (SImode, operands[0]);
1398 operands[4] = gen_highpart (SImode, operands[1]);
1399 operands[1] = gen_lowpart (SImode, operands[1]);
1400 operands[5] = gen_highpart (SImode, operands[2]);
1401 operands[2] = gen_lowpart (SImode, operands[2]);
1406 [(set (match_operand:DI 0 "s_register_operand" "")
1407 (match_operator:DI 6 "logical_binary_operator"
1408 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1409 (match_operand:DI 1 "s_register_operand" "")]))]
1410 "TARGET_ARM && reload_completed"
1411 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1412 (set (match_dup 3) (match_op_dup:SI 6
1413 [(ashiftrt:SI (match_dup 2) (const_int 31))
1417 operands[3] = gen_highpart (SImode, operands[0]);
1418 operands[0] = gen_lowpart (SImode, operands[0]);
1419 operands[4] = gen_highpart (SImode, operands[1]);
1420 operands[1] = gen_lowpart (SImode, operands[1]);
1421 operands[5] = gen_highpart (SImode, operands[2]);
1422 operands[2] = gen_lowpart (SImode, operands[2]);
1426 ;; The zero extend of operand 2 means we can just copy the high part of
1427 ;; operand1 into operand0.
1429 [(set (match_operand:DI 0 "s_register_operand" "")
1431 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1432 (match_operand:DI 1 "s_register_operand" "")))]
1433 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1434 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1435 (set (match_dup 3) (match_dup 4))]
1438 operands[4] = gen_highpart (SImode, operands[1]);
1439 operands[3] = gen_highpart (SImode, operands[0]);
1440 operands[0] = gen_lowpart (SImode, operands[0]);
1441 operands[1] = gen_lowpart (SImode, operands[1]);
1445 ;; The zero extend of operand 2 means we can just copy the high part of
1446 ;; operand1 into operand0.
1448 [(set (match_operand:DI 0 "s_register_operand" "")
1450 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1451 (match_operand:DI 1 "s_register_operand" "")))]
1452 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1453 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1454 (set (match_dup 3) (match_dup 4))]
1457 operands[4] = gen_highpart (SImode, operands[1]);
1458 operands[3] = gen_highpart (SImode, operands[0]);
1459 operands[0] = gen_lowpart (SImode, operands[0]);
1460 operands[1] = gen_lowpart (SImode, operands[1]);
1464 (define_insn "anddi3"
1465 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1466 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1467 (match_operand:DI 2 "s_register_operand" "r,r")))]
1468 "TARGET_ARM && ! TARGET_IWMMXT"
1470 [(set_attr "length" "8")]
1473 (define_insn_and_split "*anddi_zesidi_di"
1474 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1475 (and:DI (zero_extend:DI
1476 (match_operand:SI 2 "s_register_operand" "r,r"))
1477 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1480 "TARGET_ARM && reload_completed"
1481 ; The zero extend of operand 2 clears the high word of the output
1483 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1484 (set (match_dup 3) (const_int 0))]
1487 operands[3] = gen_highpart (SImode, operands[0]);
1488 operands[0] = gen_lowpart (SImode, operands[0]);
1489 operands[1] = gen_lowpart (SImode, operands[1]);
1491 [(set_attr "length" "8")]
1494 (define_insn "*anddi_sesdi_di"
1495 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1496 (and:DI (sign_extend:DI
1497 (match_operand:SI 2 "s_register_operand" "r,r"))
1498 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1501 [(set_attr "length" "8")]
1504 (define_expand "andsi3"
1505 [(set (match_operand:SI 0 "s_register_operand" "")
1506 (and:SI (match_operand:SI 1 "s_register_operand" "")
1507 (match_operand:SI 2 "reg_or_int_operand" "")))]
1512 if (GET_CODE (operands[2]) == CONST_INT)
1514 arm_split_constant (AND, SImode, NULL_RTX,
1515 INTVAL (operands[2]), operands[0],
1518 ? 0 : preserve_subexpressions_p ()));
1522 else /* TARGET_THUMB */
1524 if (GET_CODE (operands[2]) != CONST_INT)
1525 operands[2] = force_reg (SImode, operands[2]);
1530 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1532 operands[2] = force_reg (SImode,
1533 GEN_INT (~INTVAL (operands[2])));
1535 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1540 for (i = 9; i <= 31; i++)
1542 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1544 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1548 else if ((((HOST_WIDE_INT) 1) << i) - 1
1549 == ~INTVAL (operands[2]))
1551 rtx shift = GEN_INT (i);
1552 rtx reg = gen_reg_rtx (SImode);
1554 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1555 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1561 operands[2] = force_reg (SImode, operands[2]);
1567 (define_insn_and_split "*arm_andsi3_insn"
1568 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1569 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1570 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1574 bic%?\\t%0, %1, #%B2
1577 && GET_CODE (operands[2]) == CONST_INT
1578 && !(const_ok_for_arm (INTVAL (operands[2]))
1579 || const_ok_for_arm (~INTVAL (operands[2])))"
1580 [(clobber (const_int 0))]
1582 arm_split_constant (AND, SImode, curr_insn,
1583 INTVAL (operands[2]), operands[0], operands[1], 0);
1586 [(set_attr "length" "4,4,16")
1587 (set_attr "predicable" "yes")]
1590 (define_insn "*thumb_andsi3_insn"
1591 [(set (match_operand:SI 0 "register_operand" "=l")
1592 (and:SI (match_operand:SI 1 "register_operand" "%0")
1593 (match_operand:SI 2 "register_operand" "l")))]
1596 [(set_attr "length" "2")]
1599 (define_insn "*andsi3_compare0"
1600 [(set (reg:CC_NOOV CC_REGNUM)
1602 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1603 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1605 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1606 (and:SI (match_dup 1) (match_dup 2)))]
1610 bic%?s\\t%0, %1, #%B2"
1611 [(set_attr "conds" "set")]
1614 (define_insn "*andsi3_compare0_scratch"
1615 [(set (reg:CC_NOOV CC_REGNUM)
1617 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1618 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1620 (clobber (match_scratch:SI 2 "=X,r"))]
1624 bic%?s\\t%2, %0, #%B1"
1625 [(set_attr "conds" "set")]
1628 (define_insn "*zeroextractsi_compare0_scratch"
1629 [(set (reg:CC_NOOV CC_REGNUM)
1630 (compare:CC_NOOV (zero_extract:SI
1631 (match_operand:SI 0 "s_register_operand" "r")
1632 (match_operand 1 "const_int_operand" "n")
1633 (match_operand 2 "const_int_operand" "n"))
1636 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1637 && INTVAL (operands[1]) > 0
1638 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1639 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1641 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1642 << INTVAL (operands[2]));
1643 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1646 [(set_attr "conds" "set")]
1649 (define_insn "*ne_zeroextractsi"
1650 [(set (match_operand:SI 0 "s_register_operand" "=r")
1651 (ne:SI (zero_extract:SI
1652 (match_operand:SI 1 "s_register_operand" "r")
1653 (match_operand:SI 2 "const_int_operand" "n")
1654 (match_operand:SI 3 "const_int_operand" "n"))
1656 (clobber (reg:CC CC_REGNUM))]
1658 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1659 && INTVAL (operands[2]) > 0
1660 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1661 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1663 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1664 << INTVAL (operands[3]));
1665 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1666 return \"movne\\t%0, #1\";
1668 [(set_attr "conds" "clob")
1669 (set_attr "length" "8")]
1673 [(set (match_operand:SI 0 "s_register_operand" "")
1674 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1675 (match_operand:SI 2 "const_int_operand" "")
1676 (match_operand:SI 3 "const_int_operand" "")))
1677 (clobber (match_operand:SI 4 "s_register_operand" ""))]
1679 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1680 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1682 HOST_WIDE_INT temp = INTVAL (operands[2]);
1684 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1685 operands[3] = GEN_INT (32 - temp);
1690 [(set (match_operand:SI 0 "s_register_operand" "")
1691 (match_operator:SI 1 "shiftable_operator"
1692 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1693 (match_operand:SI 3 "const_int_operand" "")
1694 (match_operand:SI 4 "const_int_operand" ""))
1695 (match_operand:SI 5 "s_register_operand" "")]))
1696 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1698 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1701 [(lshiftrt:SI (match_dup 6) (match_dup 4))
1704 HOST_WIDE_INT temp = INTVAL (operands[3]);
1706 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1707 operands[4] = GEN_INT (32 - temp);
1712 [(set (match_operand:SI 0 "s_register_operand" "")
1713 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1714 (match_operand:SI 2 "const_int_operand" "")
1715 (match_operand:SI 3 "const_int_operand" "")))]
1717 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1718 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1720 HOST_WIDE_INT temp = INTVAL (operands[2]);
1722 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1723 operands[3] = GEN_INT (32 - temp);
1728 [(set (match_operand:SI 0 "s_register_operand" "")
1729 (match_operator:SI 1 "shiftable_operator"
1730 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1731 (match_operand:SI 3 "const_int_operand" "")
1732 (match_operand:SI 4 "const_int_operand" ""))
1733 (match_operand:SI 5 "s_register_operand" "")]))
1734 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1736 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1739 [(ashiftrt:SI (match_dup 6) (match_dup 4))
1742 HOST_WIDE_INT temp = INTVAL (operands[3]);
1744 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1745 operands[4] = GEN_INT (32 - temp);
1749 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1750 ;;; represented by the bitfield, then this will produce incorrect results.
1751 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1752 ;;; which have a real bit-field insert instruction, the truncation happens
1753 ;;; in the bit-field insert instruction itself. Since arm does not have a
1754 ;;; bit-field insert instruction, we would have to emit code here to truncate
1755 ;;; the value before we insert. This loses some of the advantage of having
1756 ;;; this insv pattern, so this pattern needs to be reevalutated.
1758 (define_expand "insv"
1759 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1760 (match_operand:SI 1 "general_operand" "")
1761 (match_operand:SI 2 "general_operand" ""))
1762 (match_operand:SI 3 "reg_or_int_operand" ""))]
1766 int start_bit = INTVAL (operands[2]);
1767 int width = INTVAL (operands[1]);
1768 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1769 rtx target, subtarget;
1771 target = operands[0];
1772 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1773 subreg as the final target. */
1774 if (GET_CODE (target) == SUBREG)
1776 subtarget = gen_reg_rtx (SImode);
1777 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1778 < GET_MODE_SIZE (SImode))
1779 target = SUBREG_REG (target);
1784 if (GET_CODE (operands[3]) == CONST_INT)
1786 /* Since we are inserting a known constant, we may be able to
1787 reduce the number of bits that we have to clear so that
1788 the mask becomes simple. */
1789 /* ??? This code does not check to see if the new mask is actually
1790 simpler. It may not be. */
1791 rtx op1 = gen_reg_rtx (SImode);
1792 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1793 start of this pattern. */
1794 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1795 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1797 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1798 emit_insn (gen_iorsi3 (subtarget, op1,
1799 GEN_INT (op3_value << start_bit)));
1801 else if (start_bit == 0
1802 && !(const_ok_for_arm (mask)
1803 || const_ok_for_arm (~mask)))
1805 /* A Trick, since we are setting the bottom bits in the word,
1806 we can shift operand[3] up, operand[0] down, OR them together
1807 and rotate the result back again. This takes 3 insns, and
1808 the third might be mergeable into another op. */
1809 /* The shift up copes with the possibility that operand[3] is
1810 wider than the bitfield. */
1811 rtx op0 = gen_reg_rtx (SImode);
1812 rtx op1 = gen_reg_rtx (SImode);
1814 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1815 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1816 emit_insn (gen_iorsi3 (op1, op1, op0));
1817 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1819 else if ((width + start_bit == 32)
1820 && !(const_ok_for_arm (mask)
1821 || const_ok_for_arm (~mask)))
1823 /* Similar trick, but slightly less efficient. */
1825 rtx op0 = gen_reg_rtx (SImode);
1826 rtx op1 = gen_reg_rtx (SImode);
1828 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1829 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1830 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1831 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1835 rtx op0 = GEN_INT (mask);
1836 rtx op1 = gen_reg_rtx (SImode);
1837 rtx op2 = gen_reg_rtx (SImode);
1839 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1841 rtx tmp = gen_reg_rtx (SImode);
1843 emit_insn (gen_movsi (tmp, op0));
1847 /* Mask out any bits in operand[3] that are not needed. */
1848 emit_insn (gen_andsi3 (op1, operands[3], op0));
1850 if (GET_CODE (op0) == CONST_INT
1851 && (const_ok_for_arm (mask << start_bit)
1852 || const_ok_for_arm (~(mask << start_bit))))
1854 op0 = GEN_INT (~(mask << start_bit));
1855 emit_insn (gen_andsi3 (op2, operands[0], op0));
1859 if (GET_CODE (op0) == CONST_INT)
1861 rtx tmp = gen_reg_rtx (SImode);
1863 emit_insn (gen_movsi (tmp, op0));
1868 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1870 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1874 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1876 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1879 if (subtarget != target)
1881 /* If TARGET is still a SUBREG, then it must be wider than a word,
1882 so we must be careful only to set the subword we were asked to. */
1883 if (GET_CODE (target) == SUBREG)
1884 emit_move_insn (target, subtarget);
1886 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1893 ; constants for op 2 will never be given to these patterns.
1894 (define_insn_and_split "*anddi_notdi_di"
1895 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1896 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1897 (match_operand:DI 2 "s_register_operand" "0,r")))]
1900 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1901 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1902 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1905 operands[3] = gen_highpart (SImode, operands[0]);
1906 operands[0] = gen_lowpart (SImode, operands[0]);
1907 operands[4] = gen_highpart (SImode, operands[1]);
1908 operands[1] = gen_lowpart (SImode, operands[1]);
1909 operands[5] = gen_highpart (SImode, operands[2]);
1910 operands[2] = gen_lowpart (SImode, operands[2]);
1912 [(set_attr "length" "8")
1913 (set_attr "predicable" "yes")]
1916 (define_insn_and_split "*anddi_notzesidi_di"
1917 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1918 (and:DI (not:DI (zero_extend:DI
1919 (match_operand:SI 2 "s_register_operand" "r,r")))
1920 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1923 bic%?\\t%Q0, %Q1, %2
1925 ; (not (zero_extend ...)) allows us to just copy the high word from
1926 ; operand1 to operand0.
1929 && operands[0] != operands[1]"
1930 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1931 (set (match_dup 3) (match_dup 4))]
1934 operands[3] = gen_highpart (SImode, operands[0]);
1935 operands[0] = gen_lowpart (SImode, operands[0]);
1936 operands[4] = gen_highpart (SImode, operands[1]);
1937 operands[1] = gen_lowpart (SImode, operands[1]);
1939 [(set_attr "length" "4,8")
1940 (set_attr "predicable" "yes")]
1943 (define_insn_and_split "*anddi_notsesidi_di"
1944 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1945 (and:DI (not:DI (sign_extend:DI
1946 (match_operand:SI 2 "s_register_operand" "r,r")))
1947 (match_operand:DI 1 "s_register_operand" "0,r")))]
1950 "TARGET_ARM && reload_completed"
1951 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1952 (set (match_dup 3) (and:SI (not:SI
1953 (ashiftrt:SI (match_dup 2) (const_int 31)))
1957 operands[3] = gen_highpart (SImode, operands[0]);
1958 operands[0] = gen_lowpart (SImode, operands[0]);
1959 operands[4] = gen_highpart (SImode, operands[1]);
1960 operands[1] = gen_lowpart (SImode, operands[1]);
1962 [(set_attr "length" "8")
1963 (set_attr "predicable" "yes")]
1966 (define_insn "andsi_notsi_si"
1967 [(set (match_operand:SI 0 "s_register_operand" "=r")
1968 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1969 (match_operand:SI 1 "s_register_operand" "r")))]
1971 "bic%?\\t%0, %1, %2"
1972 [(set_attr "predicable" "yes")]
1975 (define_insn "bicsi3"
1976 [(set (match_operand:SI 0 "register_operand" "=l")
1977 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
1978 (match_operand:SI 2 "register_operand" "0")))]
1981 [(set_attr "length" "2")]
1984 (define_insn "andsi_not_shiftsi_si"
1985 [(set (match_operand:SI 0 "s_register_operand" "=r")
1986 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
1987 [(match_operand:SI 2 "s_register_operand" "r")
1988 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
1989 (match_operand:SI 1 "s_register_operand" "r")))]
1991 "bic%?\\t%0, %1, %2%S4"
1992 [(set_attr "predicable" "yes")
1993 (set_attr "shift" "2")
1994 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
1995 (const_string "alu_shift")
1996 (const_string "alu_shift_reg")))]
1999 (define_insn "*andsi_notsi_si_compare0"
2000 [(set (reg:CC_NOOV CC_REGNUM)
2002 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2003 (match_operand:SI 1 "s_register_operand" "r"))
2005 (set (match_operand:SI 0 "s_register_operand" "=r")
2006 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2008 "bic%?s\\t%0, %1, %2"
2009 [(set_attr "conds" "set")]
2012 (define_insn "*andsi_notsi_si_compare0_scratch"
2013 [(set (reg:CC_NOOV CC_REGNUM)
2015 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2016 (match_operand:SI 1 "s_register_operand" "r"))
2018 (clobber (match_scratch:SI 0 "=r"))]
2020 "bic%?s\\t%0, %1, %2"
2021 [(set_attr "conds" "set")]
2024 (define_insn "iordi3"
2025 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2026 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2027 (match_operand:DI 2 "s_register_operand" "r,r")))]
2028 "TARGET_ARM && ! TARGET_IWMMXT"
2030 [(set_attr "length" "8")
2031 (set_attr "predicable" "yes")]
2034 (define_insn "*iordi_zesidi_di"
2035 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2036 (ior:DI (zero_extend:DI
2037 (match_operand:SI 2 "s_register_operand" "r,r"))
2038 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2041 orr%?\\t%Q0, %Q1, %2
2043 [(set_attr "length" "4,8")
2044 (set_attr "predicable" "yes")]
2047 (define_insn "*iordi_sesidi_di"
2048 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2049 (ior:DI (sign_extend:DI
2050 (match_operand:SI 2 "s_register_operand" "r,r"))
2051 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2054 [(set_attr "length" "8")
2055 (set_attr "predicable" "yes")]
2058 (define_expand "iorsi3"
2059 [(set (match_operand:SI 0 "s_register_operand" "")
2060 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2061 (match_operand:SI 2 "reg_or_int_operand" "")))]
2064 if (GET_CODE (operands[2]) == CONST_INT)
2068 arm_split_constant (IOR, SImode, NULL_RTX,
2069 INTVAL (operands[2]), operands[0], operands[1],
2071 ? 0 : preserve_subexpressions_p ()));
2074 else /* TARGET_THUMB */
2075 operands [2] = force_reg (SImode, operands [2]);
2080 (define_insn_and_split "*arm_iorsi3"
2081 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2082 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2083 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2089 && GET_CODE (operands[2]) == CONST_INT
2090 && !const_ok_for_arm (INTVAL (operands[2]))"
2091 [(clobber (const_int 0))]
2093 arm_split_constant (IOR, SImode, curr_insn,
2094 INTVAL (operands[2]), operands[0], operands[1], 0);
2097 [(set_attr "length" "4,16")
2098 (set_attr "predicable" "yes")]
2101 (define_insn "*thumb_iorsi3"
2102 [(set (match_operand:SI 0 "register_operand" "=l")
2103 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2104 (match_operand:SI 2 "register_operand" "l")))]
2107 [(set_attr "length" "2")]
2111 [(match_scratch:SI 3 "r")
2112 (set (match_operand:SI 0 "arm_general_register_operand" "")
2113 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2114 (match_operand:SI 2 "const_int_operand" "")))]
2116 && !const_ok_for_arm (INTVAL (operands[2]))
2117 && const_ok_for_arm (~INTVAL (operands[2]))"
2118 [(set (match_dup 3) (match_dup 2))
2119 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2123 (define_insn "*iorsi3_compare0"
2124 [(set (reg:CC_NOOV CC_REGNUM)
2125 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2126 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2128 (set (match_operand:SI 0 "s_register_operand" "=r")
2129 (ior:SI (match_dup 1) (match_dup 2)))]
2131 "orr%?s\\t%0, %1, %2"
2132 [(set_attr "conds" "set")]
2135 (define_insn "*iorsi3_compare0_scratch"
2136 [(set (reg:CC_NOOV CC_REGNUM)
2137 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2138 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2140 (clobber (match_scratch:SI 0 "=r"))]
2142 "orr%?s\\t%0, %1, %2"
2143 [(set_attr "conds" "set")]
2146 (define_insn "xordi3"
2147 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2148 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2149 (match_operand:DI 2 "s_register_operand" "r,r")))]
2150 "TARGET_ARM && !TARGET_IWMMXT"
2152 [(set_attr "length" "8")
2153 (set_attr "predicable" "yes")]
2156 (define_insn "*xordi_zesidi_di"
2157 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2158 (xor:DI (zero_extend:DI
2159 (match_operand:SI 2 "s_register_operand" "r,r"))
2160 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2163 eor%?\\t%Q0, %Q1, %2
2165 [(set_attr "length" "4,8")
2166 (set_attr "predicable" "yes")]
2169 (define_insn "*xordi_sesidi_di"
2170 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2171 (xor:DI (sign_extend:DI
2172 (match_operand:SI 2 "s_register_operand" "r,r"))
2173 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2176 [(set_attr "length" "8")
2177 (set_attr "predicable" "yes")]
2180 (define_expand "xorsi3"
2181 [(set (match_operand:SI 0 "s_register_operand" "")
2182 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2183 (match_operand:SI 2 "arm_rhs_operand" "")))]
2186 if (GET_CODE (operands[2]) == CONST_INT)
2187 operands[2] = force_reg (SImode, operands[2]);
2191 (define_insn "*arm_xorsi3"
2192 [(set (match_operand:SI 0 "s_register_operand" "=r")
2193 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2194 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2196 "eor%?\\t%0, %1, %2"
2197 [(set_attr "predicable" "yes")]
2200 (define_insn "*thumb_xorsi3"
2201 [(set (match_operand:SI 0 "register_operand" "=l")
2202 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2203 (match_operand:SI 2 "register_operand" "l")))]
2206 [(set_attr "length" "2")]
2209 (define_insn "*xorsi3_compare0"
2210 [(set (reg:CC_NOOV CC_REGNUM)
2211 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2212 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2214 (set (match_operand:SI 0 "s_register_operand" "=r")
2215 (xor:SI (match_dup 1) (match_dup 2)))]
2217 "eor%?s\\t%0, %1, %2"
2218 [(set_attr "conds" "set")]
2221 (define_insn "*xorsi3_compare0_scratch"
2222 [(set (reg:CC_NOOV CC_REGNUM)
2223 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2224 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2228 [(set_attr "conds" "set")]
2231 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2232 ; (NOT D) we can sometimes merge the final NOT into one of the following
2236 [(set (match_operand:SI 0 "s_register_operand" "")
2237 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2238 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2239 (match_operand:SI 3 "arm_rhs_operand" "")))
2240 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2242 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2243 (not:SI (match_dup 3))))
2244 (set (match_dup 0) (not:SI (match_dup 4)))]
2248 (define_insn "*andsi_iorsi3_notsi"
2249 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2250 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2251 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2252 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2254 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2255 [(set_attr "length" "8")
2256 (set_attr "predicable" "yes")]
2260 [(set (match_operand:SI 0 "s_register_operand" "")
2261 (match_operator:SI 1 "logical_binary_operator"
2262 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2263 (match_operand:SI 3 "const_int_operand" "")
2264 (match_operand:SI 4 "const_int_operand" ""))
2265 (match_operator:SI 9 "logical_binary_operator"
2266 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2267 (match_operand:SI 6 "const_int_operand" ""))
2268 (match_operand:SI 7 "s_register_operand" "")])]))
2269 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2271 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2272 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2275 [(ashift:SI (match_dup 2) (match_dup 4))
2279 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2282 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2286 [(set (match_operand:SI 0 "s_register_operand" "")
2287 (match_operator:SI 1 "logical_binary_operator"
2288 [(match_operator:SI 9 "logical_binary_operator"
2289 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2290 (match_operand:SI 6 "const_int_operand" ""))
2291 (match_operand:SI 7 "s_register_operand" "")])
2292 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2293 (match_operand:SI 3 "const_int_operand" "")
2294 (match_operand:SI 4 "const_int_operand" ""))]))
2295 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2297 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2298 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2301 [(ashift:SI (match_dup 2) (match_dup 4))
2305 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2308 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2312 [(set (match_operand:SI 0 "s_register_operand" "")
2313 (match_operator:SI 1 "logical_binary_operator"
2314 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2315 (match_operand:SI 3 "const_int_operand" "")
2316 (match_operand:SI 4 "const_int_operand" ""))
2317 (match_operator:SI 9 "logical_binary_operator"
2318 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2319 (match_operand:SI 6 "const_int_operand" ""))
2320 (match_operand:SI 7 "s_register_operand" "")])]))
2321 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2323 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2324 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2327 [(ashift:SI (match_dup 2) (match_dup 4))
2331 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2334 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2338 [(set (match_operand:SI 0 "s_register_operand" "")
2339 (match_operator:SI 1 "logical_binary_operator"
2340 [(match_operator:SI 9 "logical_binary_operator"
2341 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2342 (match_operand:SI 6 "const_int_operand" ""))
2343 (match_operand:SI 7 "s_register_operand" "")])
2344 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2345 (match_operand:SI 3 "const_int_operand" "")
2346 (match_operand:SI 4 "const_int_operand" ""))]))
2347 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2349 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2350 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2353 [(ashift:SI (match_dup 2) (match_dup 4))
2357 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2360 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2364 ;; Minimum and maximum insns
2366 (define_insn "smaxsi3"
2367 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2368 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2369 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2370 (clobber (reg:CC CC_REGNUM))]
2373 cmp\\t%1, %2\;movlt\\t%0, %2
2374 cmp\\t%1, %2\;movge\\t%0, %1
2375 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2376 [(set_attr "conds" "clob")
2377 (set_attr "length" "8,8,12")]
2380 (define_insn "sminsi3"
2381 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2382 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2383 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2384 (clobber (reg:CC CC_REGNUM))]
2387 cmp\\t%1, %2\;movge\\t%0, %2
2388 cmp\\t%1, %2\;movlt\\t%0, %1
2389 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2390 [(set_attr "conds" "clob")
2391 (set_attr "length" "8,8,12")]
2394 (define_insn "umaxsi3"
2395 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2396 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2397 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2398 (clobber (reg:CC CC_REGNUM))]
2401 cmp\\t%1, %2\;movcc\\t%0, %2
2402 cmp\\t%1, %2\;movcs\\t%0, %1
2403 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2404 [(set_attr "conds" "clob")
2405 (set_attr "length" "8,8,12")]
2408 (define_insn "uminsi3"
2409 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2410 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2411 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2412 (clobber (reg:CC CC_REGNUM))]
2415 cmp\\t%1, %2\;movcs\\t%0, %2
2416 cmp\\t%1, %2\;movcc\\t%0, %1
2417 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2418 [(set_attr "conds" "clob")
2419 (set_attr "length" "8,8,12")]
2422 (define_insn "*store_minmaxsi"
2423 [(set (match_operand:SI 0 "memory_operand" "=m")
2424 (match_operator:SI 3 "minmax_operator"
2425 [(match_operand:SI 1 "s_register_operand" "r")
2426 (match_operand:SI 2 "s_register_operand" "r")]))
2427 (clobber (reg:CC CC_REGNUM))]
2430 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2431 operands[1], operands[2]);
2432 output_asm_insn (\"cmp\\t%1, %2\", operands);
2433 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2434 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2437 [(set_attr "conds" "clob")
2438 (set_attr "length" "12")
2439 (set_attr "type" "store1")]
2442 ; Reject the frame pointer in operand[1], since reloading this after
2443 ; it has been eliminated can cause carnage.
2444 (define_insn "*minmax_arithsi"
2445 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2446 (match_operator:SI 4 "shiftable_operator"
2447 [(match_operator:SI 5 "minmax_operator"
2448 [(match_operand:SI 2 "s_register_operand" "r,r")
2449 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2450 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2451 (clobber (reg:CC CC_REGNUM))]
2453 && (GET_CODE (operands[1]) != REG
2454 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2455 && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2458 enum rtx_code code = GET_CODE (operands[4]);
2460 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2461 operands[2], operands[3]);
2462 output_asm_insn (\"cmp\\t%2, %3\", operands);
2463 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2464 if (which_alternative != 0 || operands[3] != const0_rtx
2465 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2466 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2469 [(set_attr "conds" "clob")
2470 (set_attr "length" "12")]
2474 ;; Shift and rotation insns
2476 (define_expand "ashldi3"
2477 [(set (match_operand:DI 0 "s_register_operand" "")
2478 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2479 (match_operand:SI 2 "reg_or_int_operand" "")))]
2482 if (GET_CODE (operands[2]) == CONST_INT)
2484 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2486 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2489 /* Ideally we shouldn't fail here if we could know that operands[1]
2490 ends up already living in an iwmmxt register. Otherwise it's
2491 cheaper to have the alternate code being generated than moving
2492 values to iwmmxt regs and back. */
2495 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2500 (define_insn "arm_ashldi3_1bit"
2501 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2502 (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2504 (clobber (reg:CC CC_REGNUM))]
2506 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2507 [(set_attr "conds" "clob")
2508 (set_attr "length" "8")]
2511 (define_expand "ashlsi3"
2512 [(set (match_operand:SI 0 "s_register_operand" "")
2513 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2514 (match_operand:SI 2 "arm_rhs_operand" "")))]
2517 if (GET_CODE (operands[2]) == CONST_INT
2518 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2520 emit_insn (gen_movsi (operands[0], const0_rtx));
2526 (define_insn "*thumb_ashlsi3"
2527 [(set (match_operand:SI 0 "register_operand" "=l,l")
2528 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2529 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2532 [(set_attr "length" "2")]
2535 (define_expand "ashrdi3"
2536 [(set (match_operand:DI 0 "s_register_operand" "")
2537 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2538 (match_operand:SI 2 "reg_or_int_operand" "")))]
2541 if (GET_CODE (operands[2]) == CONST_INT)
2543 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2545 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2548 /* Ideally we shouldn't fail here if we could know that operands[1]
2549 ends up already living in an iwmmxt register. Otherwise it's
2550 cheaper to have the alternate code being generated than moving
2551 values to iwmmxt regs and back. */
2554 else if (!TARGET_REALLY_IWMMXT)
2559 (define_insn "arm_ashrdi3_1bit"
2560 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2561 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2563 (clobber (reg:CC CC_REGNUM))]
2565 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2566 [(set_attr "conds" "clob")
2567 (set_attr "length" "8")]
2570 (define_expand "ashrsi3"
2571 [(set (match_operand:SI 0 "s_register_operand" "")
2572 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2573 (match_operand:SI 2 "arm_rhs_operand" "")))]
2576 if (GET_CODE (operands[2]) == CONST_INT
2577 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2578 operands[2] = GEN_INT (31);
2582 (define_insn "*thumb_ashrsi3"
2583 [(set (match_operand:SI 0 "register_operand" "=l,l")
2584 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2585 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2588 [(set_attr "length" "2")]
2591 (define_expand "lshrdi3"
2592 [(set (match_operand:DI 0 "s_register_operand" "")
2593 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2594 (match_operand:SI 2 "reg_or_int_operand" "")))]
2597 if (GET_CODE (operands[2]) == CONST_INT)
2599 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2601 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2604 /* Ideally we shouldn't fail here if we could know that operands[1]
2605 ends up already living in an iwmmxt register. Otherwise it's
2606 cheaper to have the alternate code being generated than moving
2607 values to iwmmxt regs and back. */
2610 else if (!TARGET_REALLY_IWMMXT)
2615 (define_insn "arm_lshrdi3_1bit"
2616 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2617 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2619 (clobber (reg:CC CC_REGNUM))]
2621 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2622 [(set_attr "conds" "clob")
2623 (set_attr "length" "8")]
2626 (define_expand "lshrsi3"
2627 [(set (match_operand:SI 0 "s_register_operand" "")
2628 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2629 (match_operand:SI 2 "arm_rhs_operand" "")))]
2632 if (GET_CODE (operands[2]) == CONST_INT
2633 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2635 emit_insn (gen_movsi (operands[0], const0_rtx));
2641 (define_insn "*thumb_lshrsi3"
2642 [(set (match_operand:SI 0 "register_operand" "=l,l")
2643 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2644 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2647 [(set_attr "length" "2")]
2650 (define_expand "rotlsi3"
2651 [(set (match_operand:SI 0 "s_register_operand" "")
2652 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2653 (match_operand:SI 2 "reg_or_int_operand" "")))]
2656 if (GET_CODE (operands[2]) == CONST_INT)
2657 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2660 rtx reg = gen_reg_rtx (SImode);
2661 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2667 (define_expand "rotrsi3"
2668 [(set (match_operand:SI 0 "s_register_operand" "")
2669 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2670 (match_operand:SI 2 "arm_rhs_operand" "")))]
2675 if (GET_CODE (operands[2]) == CONST_INT
2676 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2677 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2679 else /* TARGET_THUMB */
2681 if (GET_CODE (operands [2]) == CONST_INT)
2682 operands [2] = force_reg (SImode, operands[2]);
2687 (define_insn "*thumb_rotrsi3"
2688 [(set (match_operand:SI 0 "register_operand" "=l")
2689 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2690 (match_operand:SI 2 "register_operand" "l")))]
2693 [(set_attr "length" "2")]
2696 (define_insn "*arm_shiftsi3"
2697 [(set (match_operand:SI 0 "s_register_operand" "=r")
2698 (match_operator:SI 3 "shift_operator"
2699 [(match_operand:SI 1 "s_register_operand" "r")
2700 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2703 [(set_attr "predicable" "yes")
2704 (set_attr "shift" "1")
2705 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2706 (const_string "alu_shift")
2707 (const_string "alu_shift_reg")))]
2710 (define_insn "*shiftsi3_compare0"
2711 [(set (reg:CC_NOOV CC_REGNUM)
2712 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2713 [(match_operand:SI 1 "s_register_operand" "r")
2714 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2716 (set (match_operand:SI 0 "s_register_operand" "=r")
2717 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2719 "mov%?s\\t%0, %1%S3"
2720 [(set_attr "conds" "set")
2721 (set_attr "shift" "1")
2722 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2723 (const_string "alu_shift")
2724 (const_string "alu_shift_reg")))]
2727 (define_insn "*shiftsi3_compare0_scratch"
2728 [(set (reg:CC_NOOV CC_REGNUM)
2729 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2730 [(match_operand:SI 1 "s_register_operand" "r")
2731 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2733 (clobber (match_scratch:SI 0 "=r"))]
2735 "mov%?s\\t%0, %1%S3"
2736 [(set_attr "conds" "set")
2737 (set_attr "shift" "1")]
2740 (define_insn "*notsi_shiftsi"
2741 [(set (match_operand:SI 0 "s_register_operand" "=r")
2742 (not:SI (match_operator:SI 3 "shift_operator"
2743 [(match_operand:SI 1 "s_register_operand" "r")
2744 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2747 [(set_attr "predicable" "yes")
2748 (set_attr "shift" "1")
2749 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2750 (const_string "alu_shift")
2751 (const_string "alu_shift_reg")))]
2754 (define_insn "*notsi_shiftsi_compare0"
2755 [(set (reg:CC_NOOV CC_REGNUM)
2756 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2757 [(match_operand:SI 1 "s_register_operand" "r")
2758 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2760 (set (match_operand:SI 0 "s_register_operand" "=r")
2761 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2763 "mvn%?s\\t%0, %1%S3"
2764 [(set_attr "conds" "set")
2765 (set_attr "shift" "1")
2766 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2767 (const_string "alu_shift")
2768 (const_string "alu_shift_reg")))]
2771 (define_insn "*not_shiftsi_compare0_scratch"
2772 [(set (reg:CC_NOOV CC_REGNUM)
2773 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2774 [(match_operand:SI 1 "s_register_operand" "r")
2775 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2777 (clobber (match_scratch:SI 0 "=r"))]
2779 "mvn%?s\\t%0, %1%S3"
2780 [(set_attr "conds" "set")
2781 (set_attr "shift" "1")
2782 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2783 (const_string "alu_shift")
2784 (const_string "alu_shift_reg")))]
2787 ;; We don't really have extzv, but defining this using shifts helps
2788 ;; to reduce register pressure later on.
2790 (define_expand "extzv"
2792 (ashift:SI (match_operand:SI 1 "register_operand" "")
2793 (match_operand:SI 2 "const_int_operand" "")))
2794 (set (match_operand:SI 0 "register_operand" "")
2795 (lshiftrt:SI (match_dup 4)
2796 (match_operand:SI 3 "const_int_operand" "")))]
2800 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2801 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2803 operands[3] = GEN_INT (rshift);
2807 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2811 operands[2] = GEN_INT (lshift);
2812 operands[4] = gen_reg_rtx (SImode);
2817 ;; Unary arithmetic insns
2819 (define_expand "negdi2"
2821 [(set (match_operand:DI 0 "s_register_operand" "")
2822 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2823 (clobber (reg:CC CC_REGNUM))])]
2828 if (GET_CODE (operands[1]) != REG)
2829 operands[1] = force_reg (SImode, operands[1]);
2834 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2835 ;; The second alternative is to allow the common case of a *full* overlap.
2836 (define_insn "*arm_negdi2"
2837 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2838 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2839 (clobber (reg:CC CC_REGNUM))]
2841 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2842 [(set_attr "conds" "clob")
2843 (set_attr "length" "8")]
2846 (define_insn "*thumb_negdi2"
2847 [(set (match_operand:DI 0 "register_operand" "=&l")
2848 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2849 (clobber (reg:CC CC_REGNUM))]
2851 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2852 [(set_attr "length" "6")]
2855 (define_expand "negsi2"
2856 [(set (match_operand:SI 0 "s_register_operand" "")
2857 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2862 (define_insn "*arm_negsi2"
2863 [(set (match_operand:SI 0 "s_register_operand" "=r")
2864 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2866 "rsb%?\\t%0, %1, #0"
2867 [(set_attr "predicable" "yes")]
2870 (define_insn "*thumb_negsi2"
2871 [(set (match_operand:SI 0 "register_operand" "=l")
2872 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2875 [(set_attr "length" "2")]
2878 (define_expand "negsf2"
2879 [(set (match_operand:SF 0 "s_register_operand" "")
2880 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2881 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2885 (define_expand "negdf2"
2886 [(set (match_operand:DF 0 "s_register_operand" "")
2887 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2888 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2891 ;; abssi2 doesn't really clobber the condition codes if a different register
2892 ;; is being set. To keep things simple, assume during rtl manipulations that
2893 ;; it does, but tell the final scan operator the truth. Similarly for
2896 (define_expand "abssi2"
2898 [(set (match_operand:SI 0 "s_register_operand" "")
2899 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2900 (clobber (reg:CC CC_REGNUM))])]
2904 (define_insn "*arm_abssi2"
2905 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2906 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2907 (clobber (reg:CC CC_REGNUM))]
2910 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2911 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2912 [(set_attr "conds" "clob,*")
2913 (set_attr "shift" "1")
2914 ;; predicable can't be set based on the variant, so left as no
2915 (set_attr "length" "8")]
2918 (define_insn "*neg_abssi2"
2919 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2920 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2921 (clobber (reg:CC CC_REGNUM))]
2924 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2925 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2926 [(set_attr "conds" "clob,*")
2927 (set_attr "shift" "1")
2928 ;; predicable can't be set based on the variant, so left as no
2929 (set_attr "length" "8")]
2932 (define_expand "abssf2"
2933 [(set (match_operand:SF 0 "s_register_operand" "")
2934 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
2935 "TARGET_ARM && TARGET_HARD_FLOAT"
2938 (define_expand "absdf2"
2939 [(set (match_operand:DF 0 "s_register_operand" "")
2940 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
2941 "TARGET_ARM && TARGET_HARD_FLOAT"
2944 (define_expand "sqrtsf2"
2945 [(set (match_operand:SF 0 "s_register_operand" "")
2946 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
2947 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2950 (define_expand "sqrtdf2"
2951 [(set (match_operand:DF 0 "s_register_operand" "")
2952 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
2953 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2956 (define_insn_and_split "one_cmpldi2"
2957 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2958 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2961 "TARGET_ARM && reload_completed"
2962 [(set (match_dup 0) (not:SI (match_dup 1)))
2963 (set (match_dup 2) (not:SI (match_dup 3)))]
2966 operands[2] = gen_highpart (SImode, operands[0]);
2967 operands[0] = gen_lowpart (SImode, operands[0]);
2968 operands[3] = gen_highpart (SImode, operands[1]);
2969 operands[1] = gen_lowpart (SImode, operands[1]);
2971 [(set_attr "length" "8")
2972 (set_attr "predicable" "yes")]
2975 (define_expand "one_cmplsi2"
2976 [(set (match_operand:SI 0 "s_register_operand" "")
2977 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2982 (define_insn "*arm_one_cmplsi2"
2983 [(set (match_operand:SI 0 "s_register_operand" "=r")
2984 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
2987 [(set_attr "predicable" "yes")]
2990 (define_insn "*thumb_one_cmplsi2"
2991 [(set (match_operand:SI 0 "register_operand" "=l")
2992 (not:SI (match_operand:SI 1 "register_operand" "l")))]
2995 [(set_attr "length" "2")]
2998 (define_insn "*notsi_compare0"
2999 [(set (reg:CC_NOOV CC_REGNUM)
3000 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3002 (set (match_operand:SI 0 "s_register_operand" "=r")
3003 (not:SI (match_dup 1)))]
3006 [(set_attr "conds" "set")]
3009 (define_insn "*notsi_compare0_scratch"
3010 [(set (reg:CC_NOOV CC_REGNUM)
3011 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3013 (clobber (match_scratch:SI 0 "=r"))]
3016 [(set_attr "conds" "set")]
3019 ;; Fixed <--> Floating conversion insns
3021 (define_expand "floatsisf2"
3022 [(set (match_operand:SF 0 "s_register_operand" "")
3023 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3024 "TARGET_ARM && TARGET_HARD_FLOAT"
3026 if (TARGET_MAVERICK)
3028 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3033 (define_expand "floatsidf2"
3034 [(set (match_operand:DF 0 "s_register_operand" "")
3035 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3036 "TARGET_ARM && TARGET_HARD_FLOAT"
3038 if (TARGET_MAVERICK)
3040 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3045 (define_expand "fix_truncsfsi2"
3046 [(set (match_operand:SI 0 "s_register_operand" "")
3047 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
3048 "TARGET_ARM && TARGET_HARD_FLOAT"
3050 if (TARGET_MAVERICK)
3052 if (!cirrus_fp_register (operands[0], SImode))
3053 operands[0] = force_reg (SImode, operands[0]);
3054 if (!cirrus_fp_register (operands[1], SFmode))
3055 operands[1] = force_reg (SFmode, operands[0]);
3056 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3061 (define_expand "fix_truncdfsi2"
3062 [(set (match_operand:SI 0 "s_register_operand" "")
3063 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
3064 "TARGET_ARM && TARGET_HARD_FLOAT"
3066 if (TARGET_MAVERICK)
3068 if (!cirrus_fp_register (operands[1], DFmode))
3069 operands[1] = force_reg (DFmode, operands[0]);
3070 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3077 (define_expand "truncdfsf2"
3078 [(set (match_operand:SF 0 "s_register_operand" "")
3080 (match_operand:DF 1 "s_register_operand" "")))]
3081 "TARGET_ARM && TARGET_HARD_FLOAT"
3085 ;; Zero and sign extension instructions.
3087 (define_insn "zero_extendsidi2"
3088 [(set (match_operand:DI 0 "s_register_operand" "=r")
3089 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3092 if (REGNO (operands[1])
3093 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3094 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3095 return \"mov%?\\t%R0, #0\";
3097 [(set_attr "length" "8")
3098 (set_attr "predicable" "yes")]
3101 (define_insn "zero_extendqidi2"
3102 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
3103 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3106 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3107 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3108 [(set_attr "length" "8")
3109 (set_attr "predicable" "yes")
3110 (set_attr "type" "*,load_byte")
3111 (set_attr "pool_range" "*,4092")
3112 (set_attr "neg_pool_range" "*,4084")]
3115 (define_insn "extendsidi2"
3116 [(set (match_operand:DI 0 "s_register_operand" "=r")
3117 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3120 if (REGNO (operands[1])
3121 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3122 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3123 return \"mov%?\\t%R0, %Q0, asr #31\";
3125 [(set_attr "length" "8")
3126 (set_attr "shift" "1")
3127 (set_attr "predicable" "yes")]
3130 (define_expand "zero_extendhisi2"
3132 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3134 (set (match_operand:SI 0 "s_register_operand" "")
3135 (lshiftrt:SI (match_dup 2) (const_int 16)))]
3139 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3141 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3142 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3146 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3148 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3152 if (!s_register_operand (operands[1], HImode))
3153 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3157 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3158 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3162 operands[1] = gen_lowpart (SImode, operands[1]);
3163 operands[2] = gen_reg_rtx (SImode);
3167 (define_insn "*thumb_zero_extendhisi2"
3168 [(set (match_operand:SI 0 "register_operand" "=l")
3169 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3170 "TARGET_THUMB && !arm_arch6"
3172 rtx mem = XEXP (operands[1], 0);
3174 if (GET_CODE (mem) == CONST)
3175 mem = XEXP (mem, 0);
3177 if (GET_CODE (mem) == LABEL_REF)
3178 return \"ldr\\t%0, %1\";
3180 if (GET_CODE (mem) == PLUS)
3182 rtx a = XEXP (mem, 0);
3183 rtx b = XEXP (mem, 1);
3185 /* This can happen due to bugs in reload. */
3186 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3189 ops[0] = operands[0];
3192 output_asm_insn (\"mov %0, %1\", ops);
3194 XEXP (mem, 0) = operands[0];
3197 else if ( GET_CODE (a) == LABEL_REF
3198 && GET_CODE (b) == CONST_INT)
3199 return \"ldr\\t%0, %1\";
3202 return \"ldrh\\t%0, %1\";
3204 [(set_attr "length" "4")
3205 (set_attr "type" "load_byte")
3206 (set_attr "pool_range" "60")]
3209 (define_insn "*thumb_zero_extendhisi2_v6"
3210 [(set (match_operand:SI 0 "register_operand" "=l,l")
3211 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3212 "TARGET_THUMB && arm_arch6"
3216 if (which_alternative == 0)
3217 return \"uxth\\t%0, %1\";
3219 mem = XEXP (operands[1], 0);
3221 if (GET_CODE (mem) == CONST)
3222 mem = XEXP (mem, 0);
3224 if (GET_CODE (mem) == LABEL_REF)
3225 return \"ldr\\t%0, %1\";
3227 if (GET_CODE (mem) == PLUS)
3229 rtx a = XEXP (mem, 0);
3230 rtx b = XEXP (mem, 1);
3232 /* This can happen due to bugs in reload. */
3233 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3236 ops[0] = operands[0];
3239 output_asm_insn (\"mov %0, %1\", ops);
3241 XEXP (mem, 0) = operands[0];
3244 else if ( GET_CODE (a) == LABEL_REF
3245 && GET_CODE (b) == CONST_INT)
3246 return \"ldr\\t%0, %1\";
3249 return \"ldrh\\t%0, %1\";
3251 [(set_attr "length" "2,4")
3252 (set_attr "type" "alu_shift,load_byte")
3253 (set_attr "pool_range" "*,60")]
3256 (define_insn "*arm_zero_extendhisi2"
3257 [(set (match_operand:SI 0 "s_register_operand" "=r")
3258 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3259 "TARGET_ARM && arm_arch4 && !arm_arch6"
3261 [(set_attr "type" "load_byte")
3262 (set_attr "predicable" "yes")
3263 (set_attr "pool_range" "256")
3264 (set_attr "neg_pool_range" "244")]
3267 (define_insn "*arm_zero_extendhisi2_v6"
3268 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3269 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3270 "TARGET_ARM && arm_arch6"
3274 [(set_attr "type" "alu_shift,load_byte")
3275 (set_attr "predicable" "yes")
3276 (set_attr "pool_range" "*,256")
3277 (set_attr "neg_pool_range" "*,244")]
3280 (define_insn "*arm_zero_extendhisi2addsi"
3281 [(set (match_operand:SI 0 "s_register_operand" "=r")
3282 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3283 (match_operand:SI 2 "s_register_operand" "r")))]
3284 "TARGET_ARM && arm_arch6"
3285 "uxtah%?\\t%0, %2, %1"
3286 [(set_attr "type" "alu_shift")
3287 (set_attr "predicable" "yes")]
3291 [(set (match_operand:SI 0 "s_register_operand" "")
3292 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3293 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3294 "TARGET_ARM && (!arm_arch4)"
3295 [(set (match_dup 2) (match_dup 1))
3296 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3298 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3304 [(set (match_operand:SI 0 "s_register_operand" "")
3305 (match_operator:SI 3 "shiftable_operator"
3306 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3307 (match_operand:SI 4 "s_register_operand" "")]))
3308 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3309 "TARGET_ARM && (!arm_arch4)"
3310 [(set (match_dup 2) (match_dup 1))
3313 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3315 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3320 (define_expand "zero_extendqisi2"
3321 [(set (match_operand:SI 0 "s_register_operand" "")
3322 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3325 if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3329 emit_insn (gen_andsi3 (operands[0],
3330 gen_lowpart (SImode, operands[1]),
3333 else /* TARGET_THUMB */
3335 rtx temp = gen_reg_rtx (SImode);
3338 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3339 operands[1] = gen_lowpart (SImode, operands[1]);
3342 ops[1] = operands[1];
3343 ops[2] = GEN_INT (24);
3345 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3346 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3348 ops[0] = operands[0];
3350 ops[2] = GEN_INT (24);
3352 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3353 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3360 (define_insn "*thumb_zero_extendqisi2"
3361 [(set (match_operand:SI 0 "register_operand" "=l")
3362 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3363 "TARGET_THUMB && !arm_arch6"
3365 [(set_attr "length" "2")
3366 (set_attr "type" "load_byte")
3367 (set_attr "pool_range" "32")]
3370 (define_insn "*thumb_zero_extendqisi2_v6"
3371 [(set (match_operand:SI 0 "register_operand" "=l,l")
3372 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3373 "TARGET_THUMB && arm_arch6"
3377 [(set_attr "length" "2,2")
3378 (set_attr "type" "alu_shift,load_byte")
3379 (set_attr "pool_range" "*,32")]
3382 (define_insn "*arm_zero_extendqisi2"
3383 [(set (match_operand:SI 0 "s_register_operand" "=r")
3384 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3385 "TARGET_ARM && !arm_arch6"
3386 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3387 [(set_attr "type" "load_byte")
3388 (set_attr "predicable" "yes")
3389 (set_attr "pool_range" "4096")
3390 (set_attr "neg_pool_range" "4084")]
3393 (define_insn "*arm_zero_extendqisi2_v6"
3394 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3395 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3396 "TARGET_ARM && arm_arch6"
3399 ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3400 [(set_attr "type" "alu_shift,load_byte")
3401 (set_attr "predicable" "yes")
3402 (set_attr "pool_range" "*,4096")
3403 (set_attr "neg_pool_range" "*,4084")]
3406 (define_insn "*arm_zero_extendqisi2addsi"
3407 [(set (match_operand:SI 0 "s_register_operand" "=r")
3408 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3409 (match_operand:SI 2 "s_register_operand" "r")))]
3410 "TARGET_ARM && arm_arch6"
3411 "uxtab%?\\t%0, %2, %1"
3412 [(set_attr "predicable" "yes")
3413 (set_attr "type" "alu_shift")]
3417 [(set (match_operand:SI 0 "s_register_operand" "")
3418 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3419 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3420 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3421 [(set (match_dup 2) (match_dup 1))
3422 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3426 (define_insn "*compareqi_eq0"
3427 [(set (reg:CC_Z CC_REGNUM)
3428 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3432 [(set_attr "conds" "set")]
3435 (define_expand "extendhisi2"
3437 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3439 (set (match_operand:SI 0 "s_register_operand" "")
3440 (ashiftrt:SI (match_dup 2)
3445 if (GET_CODE (operands[1]) == MEM)
3449 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3454 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3455 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3460 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3462 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3466 if (!s_register_operand (operands[1], HImode))
3467 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3472 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3474 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3475 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3480 operands[1] = gen_lowpart (SImode, operands[1]);
3481 operands[2] = gen_reg_rtx (SImode);
3485 (define_insn "thumb_extendhisi2"
3486 [(set (match_operand:SI 0 "register_operand" "=l")
3487 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3488 (clobber (match_scratch:SI 2 "=&l"))]
3489 "TARGET_THUMB && !arm_arch6"
3493 rtx mem = XEXP (operands[1], 0);
3495 /* This code used to try to use 'V', and fix the address only if it was
3496 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3497 range of QImode offsets, and offsettable_address_p does a QImode
3500 if (GET_CODE (mem) == CONST)
3501 mem = XEXP (mem, 0);
3503 if (GET_CODE (mem) == LABEL_REF)
3504 return \"ldr\\t%0, %1\";
3506 if (GET_CODE (mem) == PLUS)
3508 rtx a = XEXP (mem, 0);
3509 rtx b = XEXP (mem, 1);
3511 if (GET_CODE (a) == LABEL_REF
3512 && GET_CODE (b) == CONST_INT)
3513 return \"ldr\\t%0, %1\";
3515 if (GET_CODE (b) == REG)
3516 return \"ldrsh\\t%0, %1\";
3524 ops[2] = const0_rtx;
3527 if (GET_CODE (ops[1]) != REG)
3533 ops[0] = operands[0];
3534 ops[3] = operands[2];
3535 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3538 [(set_attr "length" "4")
3539 (set_attr "type" "load_byte")
3540 (set_attr "pool_range" "1020")]
3543 ;; We used to have an early-clobber on the scratch register here.
3544 ;; However, there's a bug somewhere in reload which means that this
3545 ;; can be partially ignored during spill allocation if the memory
3546 ;; address also needs reloading; this causes an abort later on when
3547 ;; we try to verify the operands. Fortunately, we don't really need
3548 ;; the early-clobber: we can always use operand 0 if operand 2
3549 ;; overlaps the address.
3550 (define_insn "*thumb_extendhisi2_insn_v6"
3551 [(set (match_operand:SI 0 "register_operand" "=l,l")
3552 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3553 (clobber (match_scratch:SI 2 "=X,l"))]
3554 "TARGET_THUMB && arm_arch6"
3560 if (which_alternative == 0)
3561 return \"sxth\\t%0, %1\";
3563 mem = XEXP (operands[1], 0);
3565 /* This code used to try to use 'V', and fix the address only if it was
3566 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3567 range of QImode offsets, and offsettable_address_p does a QImode
3570 if (GET_CODE (mem) == CONST)
3571 mem = XEXP (mem, 0);
3573 if (GET_CODE (mem) == LABEL_REF)
3574 return \"ldr\\t%0, %1\";
3576 if (GET_CODE (mem) == PLUS)
3578 rtx a = XEXP (mem, 0);
3579 rtx b = XEXP (mem, 1);
3581 if (GET_CODE (a) == LABEL_REF
3582 && GET_CODE (b) == CONST_INT)
3583 return \"ldr\\t%0, %1\";
3585 if (GET_CODE (b) == REG)
3586 return \"ldrsh\\t%0, %1\";
3594 ops[2] = const0_rtx;
3597 if (GET_CODE (ops[1]) != REG)
3603 ops[0] = operands[0];
3604 if (reg_mentioned_p (operands[2], ops[1]))
3607 ops[3] = operands[2];
3608 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3611 [(set_attr "length" "2,4")
3612 (set_attr "type" "alu_shift,load_byte")
3613 (set_attr "pool_range" "*,1020")]
3616 (define_expand "extendhisi2_mem"
3617 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3619 (zero_extend:SI (match_dup 7)))
3620 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3621 (set (match_operand:SI 0 "" "")
3622 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3627 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3629 mem1 = gen_rtx_MEM (QImode, addr);
3630 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3631 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3632 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3633 operands[0] = gen_lowpart (SImode, operands[0]);
3635 operands[2] = gen_reg_rtx (SImode);
3636 operands[3] = gen_reg_rtx (SImode);
3637 operands[6] = gen_reg_rtx (SImode);
3640 if (BYTES_BIG_ENDIAN)
3642 operands[4] = operands[2];
3643 operands[5] = operands[3];
3647 operands[4] = operands[3];
3648 operands[5] = operands[2];
3653 (define_insn "*arm_extendhisi2"
3654 [(set (match_operand:SI 0 "s_register_operand" "=r")
3655 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3656 "TARGET_ARM && arm_arch4 && !arm_arch6"
3658 [(set_attr "type" "load_byte")
3659 (set_attr "predicable" "yes")
3660 (set_attr "pool_range" "256")
3661 (set_attr "neg_pool_range" "244")]
3664 (define_insn "*arm_extendhisi2_v6"
3665 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3666 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3667 "TARGET_ARM && arm_arch6"
3671 [(set_attr "type" "alu_shift,load_byte")
3672 (set_attr "predicable" "yes")
3673 (set_attr "pool_range" "*,256")
3674 (set_attr "neg_pool_range" "*,244")]
3677 (define_insn "*arm_extendhisi2addsi"
3678 [(set (match_operand:SI 0 "s_register_operand" "=r")
3679 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3680 (match_operand:SI 2 "s_register_operand" "r")))]
3681 "TARGET_ARM && arm_arch6"
3682 "sxtah%?\\t%0, %2, %1"
3686 [(set (match_operand:SI 0 "s_register_operand" "")
3687 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3688 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3689 "TARGET_ARM && (!arm_arch4)"
3690 [(set (match_dup 2) (match_dup 1))
3691 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3693 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3699 [(set (match_operand:SI 0 "s_register_operand" "")
3700 (match_operator:SI 3 "shiftable_operator"
3701 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3702 (match_operand:SI 4 "s_register_operand" "")]))
3703 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3704 "TARGET_ARM && (!arm_arch4)"
3705 [(set (match_dup 2) (match_dup 1))
3708 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3709 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3714 (define_expand "extendqihi2"
3716 (ashift:SI (match_operand:QI 1 "general_operand" "")
3718 (set (match_operand:HI 0 "s_register_operand" "")
3719 (ashiftrt:SI (match_dup 2)
3724 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3726 emit_insn (gen_rtx_SET (VOIDmode,
3728 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3731 if (!s_register_operand (operands[1], QImode))
3732 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3733 operands[0] = gen_lowpart (SImode, operands[0]);
3734 operands[1] = gen_lowpart (SImode, operands[1]);
3735 operands[2] = gen_reg_rtx (SImode);
3739 (define_insn "*extendqihi_insn"
3740 [(set (match_operand:HI 0 "s_register_operand" "=r")
3741 (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3742 "TARGET_ARM && arm_arch4"
3744 [(set_attr "type" "load_byte")
3745 (set_attr "predicable" "yes")
3746 (set_attr "pool_range" "256")
3747 (set_attr "neg_pool_range" "244")]
3750 (define_expand "extendqisi2"
3752 (ashift:SI (match_operand:QI 1 "general_operand" "")
3754 (set (match_operand:SI 0 "s_register_operand" "")
3755 (ashiftrt:SI (match_dup 2)
3760 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3762 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3763 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3767 if (!s_register_operand (operands[1], QImode))
3768 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3772 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3773 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3777 operands[1] = gen_lowpart (SImode, operands[1]);
3778 operands[2] = gen_reg_rtx (SImode);
3782 (define_insn "*arm_extendqisi"
3783 [(set (match_operand:SI 0 "s_register_operand" "=r")
3784 (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3785 "TARGET_ARM && arm_arch4 && !arm_arch6"
3787 [(set_attr "type" "load_byte")
3788 (set_attr "predicable" "yes")
3789 (set_attr "pool_range" "256")
3790 (set_attr "neg_pool_range" "244")]
3793 (define_insn "*arm_extendqisi_v6"
3794 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3795 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3796 "TARGET_ARM && arm_arch6"
3800 [(set_attr "type" "alu_shift,load_byte")
3801 (set_attr "predicable" "yes")
3802 (set_attr "pool_range" "*,256")
3803 (set_attr "neg_pool_range" "*,244")]
3806 (define_insn "*arm_extendqisi2addsi"
3807 [(set (match_operand:SI 0 "s_register_operand" "=r")
3808 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3809 (match_operand:SI 2 "s_register_operand" "r")))]
3810 "TARGET_ARM && arm_arch6"
3811 "sxtab%?\\t%0, %2, %1"
3812 [(set_attr "type" "alu_shift")
3813 (set_attr "predicable" "yes")]
3816 (define_insn "*thumb_extendqisi2"
3817 [(set (match_operand:SI 0 "register_operand" "=l,l")
3818 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3819 "TARGET_THUMB && !arm_arch6"
3823 rtx mem = XEXP (operands[1], 0);
3825 if (GET_CODE (mem) == CONST)
3826 mem = XEXP (mem, 0);
3828 if (GET_CODE (mem) == LABEL_REF)
3829 return \"ldr\\t%0, %1\";
3831 if (GET_CODE (mem) == PLUS
3832 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3833 return \"ldr\\t%0, %1\";
3835 if (which_alternative == 0)
3836 return \"ldrsb\\t%0, %1\";
3838 ops[0] = operands[0];
3840 if (GET_CODE (mem) == PLUS)
3842 rtx a = XEXP (mem, 0);
3843 rtx b = XEXP (mem, 1);
3848 if (GET_CODE (a) == REG)
3850 if (GET_CODE (b) == REG)
3851 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3852 else if (REGNO (a) == REGNO (ops[0]))
3854 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3855 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3856 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3859 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3861 else if (GET_CODE (b) != REG)
3865 if (REGNO (b) == REGNO (ops[0]))
3867 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3868 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3869 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3872 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3875 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3877 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3878 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3879 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3884 ops[2] = const0_rtx;
3886 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3890 [(set_attr "length" "2,6")
3891 (set_attr "type" "load_byte,load_byte")
3892 (set_attr "pool_range" "32,32")]
3895 (define_insn "*thumb_extendqisi2_v6"
3896 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3897 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3898 "TARGET_THUMB && arm_arch6"
3904 if (which_alternative == 0)
3905 return \"sxtb\\t%0, %1\";
3907 mem = XEXP (operands[1], 0);
3909 if (GET_CODE (mem) == CONST)
3910 mem = XEXP (mem, 0);
3912 if (GET_CODE (mem) == LABEL_REF)
3913 return \"ldr\\t%0, %1\";
3915 if (GET_CODE (mem) == PLUS
3916 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3917 return \"ldr\\t%0, %1\";
3919 if (which_alternative == 0)
3920 return \"ldrsb\\t%0, %1\";
3922 ops[0] = operands[0];
3924 if (GET_CODE (mem) == PLUS)
3926 rtx a = XEXP (mem, 0);
3927 rtx b = XEXP (mem, 1);
3932 if (GET_CODE (a) == REG)
3934 if (GET_CODE (b) == REG)
3935 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3936 else if (REGNO (a) == REGNO (ops[0]))
3938 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3939 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3942 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3944 else if (GET_CODE (b) != REG)
3948 if (REGNO (b) == REGNO (ops[0]))
3950 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3951 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3954 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3957 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3959 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3960 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3965 ops[2] = const0_rtx;
3967 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3971 [(set_attr "length" "2,2,4")
3972 (set_attr "type" "alu_shift,load_byte,load_byte")
3973 (set_attr "pool_range" "*,32,32")]
3976 (define_expand "extendsfdf2"
3977 [(set (match_operand:DF 0 "s_register_operand" "")
3978 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
3979 "TARGET_ARM && TARGET_HARD_FLOAT"
3983 ;; Move insns (including loads and stores)
3985 ;; XXX Just some ideas about movti.
3986 ;; I don't think these are a good idea on the arm, there just aren't enough
3988 ;;(define_expand "loadti"
3989 ;; [(set (match_operand:TI 0 "s_register_operand" "")
3990 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
3993 ;;(define_expand "storeti"
3994 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3995 ;; (match_operand:TI 1 "s_register_operand" ""))]
3998 ;;(define_expand "movti"
3999 ;; [(set (match_operand:TI 0 "general_operand" "")
4000 ;; (match_operand:TI 1 "general_operand" ""))]
4006 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4007 ;; operands[1] = copy_to_reg (operands[1]);
4008 ;; if (GET_CODE (operands[0]) == MEM)
4009 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4010 ;; else if (GET_CODE (operands[1]) == MEM)
4011 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4015 ;; emit_insn (insn);
4019 ;; Recognize garbage generated above.
4022 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4023 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4027 ;; register mem = (which_alternative < 3);
4028 ;; register const char *template;
4030 ;; operands[mem] = XEXP (operands[mem], 0);
4031 ;; switch (which_alternative)
4033 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4034 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4035 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4036 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4037 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4038 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
4040 ;; output_asm_insn (template, operands);
4044 (define_expand "movdi"
4045 [(set (match_operand:DI 0 "general_operand" "")
4046 (match_operand:DI 1 "general_operand" ""))]
4051 if (!no_new_pseudos)
4053 if (GET_CODE (operands[0]) != REG)
4054 operands[1] = force_reg (DImode, operands[1]);
4060 (define_insn "*arm_movdi"
4061 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r ,m")
4062 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
4064 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4067 return (output_move_double (operands));
4069 [(set_attr "length" "8")
4070 (set_attr "type" "*,load2,store2")
4071 (set_attr "pool_range" "*,1020,*")
4072 (set_attr "neg_pool_range" "*,1008,*")]
4075 ;; We can't actually do base+index doubleword loads if the index and
4076 ;; destination overlap. Split here so that we at least have chance to
4079 [(set (match_operand:DI 0 "s_register_operand" "")
4080 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4081 (match_operand:SI 2 "s_register_operand" ""))))]
4083 && reg_overlap_mentioned_p (operands[0], operands[1])
4084 && reg_overlap_mentioned_p (operands[0], operands[2])"
4086 (plus:SI (match_dup 1)
4089 (mem:DI (match_dup 4)))]
4091 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4095 ;;; ??? This should have alternatives for constants.
4096 ;;; ??? This was originally identical to the movdf_insn pattern.
4097 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4098 ;;; thumb_reorg with a memory reference.
4099 (define_insn "*thumb_movdi_insn"
4100 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4101 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
4103 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4104 && ( register_operand (operands[0], DImode)
4105 || register_operand (operands[1], DImode))"
4108 switch (which_alternative)
4112 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4113 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4114 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4116 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4118 operands[1] = GEN_INT (- INTVAL (operands[1]));
4119 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4121 return \"ldmia\\t%1, {%0, %H0}\";
4123 return \"stmia\\t%0, {%1, %H1}\";
4125 return thumb_load_double_from_address (operands);
4127 operands[2] = gen_rtx_MEM (SImode,
4128 plus_constant (XEXP (operands[0], 0), 4));
4129 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4132 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4133 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4134 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4137 [(set_attr "length" "4,4,6,2,2,6,4,4")
4138 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4139 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4142 (define_expand "movsi"
4143 [(set (match_operand:SI 0 "general_operand" "")
4144 (match_operand:SI 1 "general_operand" ""))]
4149 /* Everything except mem = const or mem = mem can be done easily. */
4150 if (GET_CODE (operands[0]) == MEM)
4151 operands[1] = force_reg (SImode, operands[1]);
4152 if (arm_general_register_operand (operands[0], SImode)
4153 && GET_CODE (operands[1]) == CONST_INT
4154 && !(const_ok_for_arm (INTVAL (operands[1]))
4155 || const_ok_for_arm (~INTVAL (operands[1]))))
4157 arm_split_constant (SET, SImode, NULL_RTX,
4158 INTVAL (operands[1]), operands[0], NULL_RTX,
4160 : preserve_subexpressions_p ()));
4164 else /* TARGET_THUMB.... */
4166 if (!no_new_pseudos)
4168 if (GET_CODE (operands[0]) != REG)
4169 operands[1] = force_reg (SImode, operands[1]);
4174 && (CONSTANT_P (operands[1])
4175 || symbol_mentioned_p (operands[1])
4176 || label_mentioned_p (operands[1])))
4177 operands[1] = legitimize_pic_address (operands[1], SImode,
4178 (no_new_pseudos ? operands[0] : 0));
4182 (define_insn "*arm_movsi_insn"
4183 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4184 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
4185 "TARGET_ARM && ! TARGET_IWMMXT
4186 && !(TARGET_HARD_FLOAT && TARGET_VFP)
4187 && ( register_operand (operands[0], SImode)
4188 || register_operand (operands[1], SImode))"
4194 [(set_attr "type" "*,*,load1,store1")
4195 (set_attr "predicable" "yes")
4196 (set_attr "pool_range" "*,*,4096,*")
4197 (set_attr "neg_pool_range" "*,*,4084,*")]
4201 [(set (match_operand:SI 0 "arm_general_register_operand" "")
4202 (match_operand:SI 1 "const_int_operand" ""))]
4204 && (!(const_ok_for_arm (INTVAL (operands[1]))
4205 || const_ok_for_arm (~INTVAL (operands[1]))))"
4206 [(clobber (const_int 0))]
4208 arm_split_constant (SET, SImode, NULL_RTX,
4209 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4214 (define_insn "*thumb_movsi_insn"
4215 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4216 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
4218 && ( register_operand (operands[0], SImode)
4219 || register_operand (operands[1], SImode))"
4230 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4231 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4232 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4236 [(set (match_operand:SI 0 "register_operand" "")
4237 (match_operand:SI 1 "const_int_operand" ""))]
4238 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4239 [(set (match_dup 0) (match_dup 1))
4240 (set (match_dup 0) (neg:SI (match_dup 0)))]
4241 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4245 [(set (match_operand:SI 0 "register_operand" "")
4246 (match_operand:SI 1 "const_int_operand" ""))]
4247 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4248 [(set (match_dup 0) (match_dup 1))
4249 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4252 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4253 unsigned HOST_WIDE_INT mask = 0xff;
4256 for (i = 0; i < 25; i++)
4257 if ((val & (mask << i)) == val)
4260 /* Shouldn't happen, but we don't want to split if the shift is zero. */
4264 operands[1] = GEN_INT (val >> i);
4265 operands[2] = GEN_INT (i);
4269 ;; When generating pic, we need to load the symbol offset into a register.
4270 ;; So that the optimizer does not confuse this with a normal symbol load
4271 ;; we use an unspec. The offset will be loaded from a constant pool entry,
4272 ;; since that is the only type of relocation we can use.
4274 ;; The rather odd constraints on the following are to force reload to leave
4275 ;; the insn alone, and to force the minipool generation pass to then move
4276 ;; the GOT symbol to memory.
4278 (define_insn "pic_load_addr_arm"
4279 [(set (match_operand:SI 0 "s_register_operand" "=r")
4280 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4281 "TARGET_ARM && flag_pic"
4283 [(set_attr "type" "load1")
4284 (set (attr "pool_range") (const_int 4096))
4285 (set (attr "neg_pool_range") (const_int 4084))]
4288 (define_insn "pic_load_addr_thumb"
4289 [(set (match_operand:SI 0 "s_register_operand" "=l")
4290 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4291 "TARGET_THUMB && flag_pic"
4293 [(set_attr "type" "load1")
4294 (set (attr "pool_range") (const_int 1024))]
4297 ;; This variant is used for AOF assembly, since it needs to mention the
4298 ;; pic register in the rtl.
4299 (define_expand "pic_load_addr_based"
4300 [(set (match_operand:SI 0 "s_register_operand" "")
4301 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4302 "TARGET_ARM && flag_pic"
4303 "operands[2] = pic_offset_table_rtx;"
4306 (define_insn "*pic_load_addr_based_insn"
4307 [(set (match_operand:SI 0 "s_register_operand" "=r")
4308 (unspec:SI [(match_operand 1 "" "")
4309 (match_operand 2 "s_register_operand" "r")]
4311 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4313 #ifdef AOF_ASSEMBLER
4314 operands[1] = aof_pic_entry (operands[1]);
4316 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4319 [(set_attr "type" "load1")
4320 (set (attr "pool_range")
4321 (if_then_else (eq_attr "is_thumb" "yes")
4324 (set (attr "neg_pool_range")
4325 (if_then_else (eq_attr "is_thumb" "yes")
4330 (define_insn "pic_add_dot_plus_four"
4331 [(set (match_operand:SI 0 "register_operand" "+r")
4332 (unspec:SI [(plus:SI (match_dup 0)
4333 (const (plus:SI (pc) (const_int 4))))]
4335 (use (label_ref (match_operand 1 "" "")))]
4336 "TARGET_THUMB && flag_pic"
4338 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4339 CODE_LABEL_NUMBER (operands[1]));
4340 return \"add\\t%0, %|pc\";
4342 [(set_attr "length" "2")]
4345 (define_insn "pic_add_dot_plus_eight"
4346 [(set (match_operand:SI 0 "register_operand" "+r")
4347 (unspec:SI [(plus:SI (match_dup 0)
4348 (const (plus:SI (pc) (const_int 8))))]
4350 (use (label_ref (match_operand 1 "" "")))]
4351 "TARGET_ARM && flag_pic"
4353 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4354 CODE_LABEL_NUMBER (operands[1]));
4355 return \"add%?\\t%0, %|pc, %0\";
4357 [(set_attr "predicable" "yes")]
4360 (define_expand "builtin_setjmp_receiver"
4361 [(label_ref (match_operand 0 "" ""))]
4365 arm_finalize_pic (0);
4369 ;; If copying one reg to another we can set the condition codes according to
4370 ;; its value. Such a move is common after a return from subroutine and the
4371 ;; result is being tested against zero.
4373 (define_insn "*movsi_compare0"
4374 [(set (reg:CC CC_REGNUM)
4375 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4377 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4382 sub%?s\\t%0, %1, #0"
4383 [(set_attr "conds" "set")]
4386 ;; Subroutine to store a half word from a register into memory.
4387 ;; Operand 0 is the source register (HImode)
4388 ;; Operand 1 is the destination address in a register (SImode)
4390 ;; In both this routine and the next, we must be careful not to spill
4391 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4392 ;; can generate unrecognizable rtl.
4394 (define_expand "storehi"
4395 [;; store the low byte
4396 (set (match_operand 1 "" "") (match_dup 3))
4397 ;; extract the high byte
4399 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4400 ;; store the high byte
4401 (set (match_dup 4) (match_dup 5))]
4405 rtx op1 = operands[1];
4406 rtx addr = XEXP (op1, 0);
4407 enum rtx_code code = GET_CODE (addr);
4409 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4411 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4413 operands[4] = adjust_address (op1, QImode, 1);
4414 operands[1] = adjust_address (operands[1], QImode, 0);
4415 operands[3] = gen_lowpart (QImode, operands[0]);
4416 operands[0] = gen_lowpart (SImode, operands[0]);
4417 operands[2] = gen_reg_rtx (SImode);
4418 operands[5] = gen_lowpart (QImode, operands[2]);
4422 (define_expand "storehi_bigend"
4423 [(set (match_dup 4) (match_dup 3))
4425 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4426 (set (match_operand 1 "" "") (match_dup 5))]
4430 rtx op1 = operands[1];
4431 rtx addr = XEXP (op1, 0);
4432 enum rtx_code code = GET_CODE (addr);
4434 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4436 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4438 operands[4] = adjust_address (op1, QImode, 1);
4439 operands[1] = adjust_address (operands[1], QImode, 0);
4440 operands[3] = gen_lowpart (QImode, operands[0]);
4441 operands[0] = gen_lowpart (SImode, operands[0]);
4442 operands[2] = gen_reg_rtx (SImode);
4443 operands[5] = gen_lowpart (QImode, operands[2]);
4447 ;; Subroutine to store a half word integer constant into memory.
4448 (define_expand "storeinthi"
4449 [(set (match_operand 0 "" "")
4450 (match_operand 1 "" ""))
4451 (set (match_dup 3) (match_dup 2))]
4455 HOST_WIDE_INT value = INTVAL (operands[1]);
4456 rtx addr = XEXP (operands[0], 0);
4457 rtx op0 = operands[0];
4458 enum rtx_code code = GET_CODE (addr);
4460 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4462 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4464 operands[1] = gen_reg_rtx (SImode);
4465 if (BYTES_BIG_ENDIAN)
4467 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4468 if ((value & 255) == ((value >> 8) & 255))
4469 operands[2] = operands[1];
4472 operands[2] = gen_reg_rtx (SImode);
4473 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4478 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4479 if ((value & 255) == ((value >> 8) & 255))
4480 operands[2] = operands[1];
4483 operands[2] = gen_reg_rtx (SImode);
4484 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4488 operands[3] = adjust_address (op0, QImode, 1);
4489 operands[0] = adjust_address (operands[0], QImode, 0);
4490 operands[2] = gen_lowpart (QImode, operands[2]);
4491 operands[1] = gen_lowpart (QImode, operands[1]);
4495 (define_expand "storehi_single_op"
4496 [(set (match_operand:HI 0 "memory_operand" "")
4497 (match_operand:HI 1 "general_operand" ""))]
4498 "TARGET_ARM && arm_arch4"
4500 if (!s_register_operand (operands[1], HImode))
4501 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4505 (define_expand "movhi"
4506 [(set (match_operand:HI 0 "general_operand" "")
4507 (match_operand:HI 1 "general_operand" ""))]
4512 if (!no_new_pseudos)
4514 if (GET_CODE (operands[0]) == MEM)
4518 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4521 if (GET_CODE (operands[1]) == CONST_INT)
4522 emit_insn (gen_storeinthi (operands[0], operands[1]));
4525 if (GET_CODE (operands[1]) == MEM)
4526 operands[1] = force_reg (HImode, operands[1]);
4527 if (BYTES_BIG_ENDIAN)
4528 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4530 emit_insn (gen_storehi (operands[1], operands[0]));
4534 /* Sign extend a constant, and keep it in an SImode reg. */
4535 else if (GET_CODE (operands[1]) == CONST_INT)
4537 rtx reg = gen_reg_rtx (SImode);
4538 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4540 /* If the constant is already valid, leave it alone. */
4541 if (!const_ok_for_arm (val))
4543 /* If setting all the top bits will make the constant
4544 loadable in a single instruction, then set them.
4545 Otherwise, sign extend the number. */
4547 if (const_ok_for_arm (~(val | ~0xffff)))
4549 else if (val & 0x8000)
4553 emit_insn (gen_movsi (reg, GEN_INT (val)));
4554 operands[1] = gen_lowpart (HImode, reg);
4556 else if (arm_arch4 && !no_new_pseudos && optimize > 0
4557 && GET_CODE (operands[1]) == MEM)
4559 rtx reg = gen_reg_rtx (SImode);
4561 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4562 operands[1] = gen_lowpart (HImode, reg);
4564 else if (!arm_arch4)
4566 if (GET_CODE (operands[1]) == MEM)
4569 rtx offset = const0_rtx;
4570 rtx reg = gen_reg_rtx (SImode);
4572 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4573 || (GET_CODE (base) == PLUS
4574 && (GET_CODE (offset = XEXP (base, 1))
4576 && ((INTVAL(offset) & 1) != 1)
4577 && GET_CODE (base = XEXP (base, 0)) == REG))
4578 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4580 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4583 new = gen_rtx_MEM (SImode,
4584 plus_constant (base, new_offset));
4585 MEM_COPY_ATTRIBUTES (new, operands[1]);
4586 emit_insn (gen_movsi (reg, new));
4587 if (((INTVAL (offset) & 2) != 0)
4588 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4590 rtx reg2 = gen_reg_rtx (SImode);
4592 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4597 emit_insn (gen_movhi_bytes (reg, operands[1]));
4599 operands[1] = gen_lowpart (HImode, reg);
4603 /* Handle loading a large integer during reload. */
4604 else if (GET_CODE (operands[1]) == CONST_INT
4605 && !const_ok_for_arm (INTVAL (operands[1]))
4606 && !const_ok_for_arm (~INTVAL (operands[1])))
4608 /* Writing a constant to memory needs a scratch, which should
4609 be handled with SECONDARY_RELOADs. */
4610 if (GET_CODE (operands[0]) != REG)
4613 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4614 emit_insn (gen_movsi (operands[0], operands[1]));
4618 else /* TARGET_THUMB */
4620 if (!no_new_pseudos)
4622 if (GET_CODE (operands[0]) != REG)
4623 operands[1] = force_reg (HImode, operands[1]);
4625 /* ??? We shouldn't really get invalid addresses here, but this can
4626 happen if we are passed a SP (never OK for HImode/QImode) or
4627 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4628 HImode/QImode) relative address. */
4629 /* ??? This should perhaps be fixed elsewhere, for instance, in
4630 fixup_stack_1, by checking for other kinds of invalid addresses,
4631 e.g. a bare reference to a virtual register. This may confuse the
4632 alpha though, which must handle this case differently. */
4633 if (GET_CODE (operands[0]) == MEM
4634 && !memory_address_p (GET_MODE (operands[0]),
4635 XEXP (operands[0], 0)))
4637 = replace_equiv_address (operands[0],
4638 copy_to_reg (XEXP (operands[0], 0)));
4640 if (GET_CODE (operands[1]) == MEM
4641 && !memory_address_p (GET_MODE (operands[1]),
4642 XEXP (operands[1], 0)))
4644 = replace_equiv_address (operands[1],
4645 copy_to_reg (XEXP (operands[1], 0)));
4647 /* Handle loading a large integer during reload. */
4648 else if (GET_CODE (operands[1]) == CONST_INT
4649 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4651 /* Writing a constant to memory needs a scratch, which should
4652 be handled with SECONDARY_RELOADs. */
4653 if (GET_CODE (operands[0]) != REG)
4656 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4657 emit_insn (gen_movsi (operands[0], operands[1]));
4664 (define_insn "*thumb_movhi_insn"
4665 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4666 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
4668 && ( register_operand (operands[0], HImode)
4669 || register_operand (operands[1], HImode))"
4671 switch (which_alternative)
4673 case 0: return \"add %0, %1, #0\";
4674 case 2: return \"strh %1, %0\";
4675 case 3: return \"mov %0, %1\";
4676 case 4: return \"mov %0, %1\";
4677 case 5: return \"mov %0, %1\";
4680 /* The stack pointer can end up being taken as an index register.
4681 Catch this case here and deal with it. */
4682 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4683 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4684 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4687 ops[0] = operands[0];
4688 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4690 output_asm_insn (\"mov %0, %1\", ops);
4692 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4695 return \"ldrh %0, %1\";
4697 [(set_attr "length" "2,4,2,2,2,2")
4698 (set_attr "type" "*,load1,store1,*,*,*")]
4702 (define_expand "movhi_bytes"
4703 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4705 (zero_extend:SI (match_dup 6)))
4706 (set (match_operand:SI 0 "" "")
4707 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4712 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4714 mem1 = gen_rtx_MEM (QImode, addr);
4715 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4716 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4717 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4718 operands[0] = gen_lowpart (SImode, operands[0]);
4720 operands[2] = gen_reg_rtx (SImode);
4721 operands[3] = gen_reg_rtx (SImode);
4724 if (BYTES_BIG_ENDIAN)
4726 operands[4] = operands[2];
4727 operands[5] = operands[3];
4731 operands[4] = operands[3];
4732 operands[5] = operands[2];
4737 (define_expand "movhi_bigend"
4739 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4742 (ashiftrt:SI (match_dup 2) (const_int 16)))
4743 (set (match_operand:HI 0 "s_register_operand" "")
4747 operands[2] = gen_reg_rtx (SImode);
4748 operands[3] = gen_reg_rtx (SImode);
4749 operands[4] = gen_lowpart (HImode, operands[3]);
4753 ;; Pattern to recognize insn generated default case above
4754 (define_insn "*movhi_insn_arch4"
4755 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4756 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4759 && (GET_CODE (operands[1]) != CONST_INT
4760 || const_ok_for_arm (INTVAL (operands[1]))
4761 || const_ok_for_arm (~INTVAL (operands[1])))"
4763 mov%?\\t%0, %1\\t%@ movhi
4764 mvn%?\\t%0, #%B1\\t%@ movhi
4765 str%?h\\t%1, %0\\t%@ movhi
4766 ldr%?h\\t%0, %1\\t%@ movhi"
4767 [(set_attr "type" "*,*,store1,load1")
4768 (set_attr "predicable" "yes")
4769 (set_attr "pool_range" "*,*,*,256")
4770 (set_attr "neg_pool_range" "*,*,*,244")]
4773 (define_insn "*movhi_bytes"
4774 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4775 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4778 mov%?\\t%0, %1\\t%@ movhi
4779 mvn%?\\t%0, #%B1\\t%@ movhi"
4780 [(set_attr "predicable" "yes")]
4783 (define_insn "thumb_movhi_clobber"
4784 [(set (match_operand:HI 0 "memory_operand" "=m")
4785 (match_operand:HI 1 "register_operand" "l"))
4786 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4792 ;; We use a DImode scratch because we may occasionally need an additional
4793 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4794 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4795 (define_expand "reload_outhi"
4796 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4797 (match_operand:HI 1 "s_register_operand" "r")
4798 (match_operand:DI 2 "s_register_operand" "=&l")])]
4801 arm_reload_out_hi (operands);
4803 thumb_reload_out_hi (operands);
4808 (define_expand "reload_inhi"
4809 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4810 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4811 (match_operand:DI 2 "s_register_operand" "=&r")])]
4815 arm_reload_in_hi (operands);
4817 thumb_reload_out_hi (operands);
4821 (define_expand "movqi"
4822 [(set (match_operand:QI 0 "general_operand" "")
4823 (match_operand:QI 1 "general_operand" ""))]
4828 /* Everything except mem = const or mem = mem can be done easily */
4830 if (!no_new_pseudos)
4832 if (GET_CODE (operands[1]) == CONST_INT)
4834 rtx reg = gen_reg_rtx (SImode);
4836 emit_insn (gen_movsi (reg, operands[1]));
4837 operands[1] = gen_lowpart (QImode, reg);
4839 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4841 rtx reg = gen_reg_rtx (SImode);
4843 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4844 operands[1] = gen_lowpart (QImode, reg);
4846 if (GET_CODE (operands[0]) == MEM)
4847 operands[1] = force_reg (QImode, operands[1]);
4850 else /* TARGET_THUMB */
4852 if (!no_new_pseudos)
4854 if (GET_CODE (operands[0]) != REG)
4855 operands[1] = force_reg (QImode, operands[1]);
4857 /* ??? We shouldn't really get invalid addresses here, but this can
4858 happen if we are passed a SP (never OK for HImode/QImode) or
4859 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4860 HImode/QImode) relative address. */
4861 /* ??? This should perhaps be fixed elsewhere, for instance, in
4862 fixup_stack_1, by checking for other kinds of invalid addresses,
4863 e.g. a bare reference to a virtual register. This may confuse the
4864 alpha though, which must handle this case differently. */
4865 if (GET_CODE (operands[0]) == MEM
4866 && !memory_address_p (GET_MODE (operands[0]),
4867 XEXP (operands[0], 0)))
4869 = replace_equiv_address (operands[0],
4870 copy_to_reg (XEXP (operands[0], 0)));
4871 if (GET_CODE (operands[1]) == MEM
4872 && !memory_address_p (GET_MODE (operands[1]),
4873 XEXP (operands[1], 0)))
4875 = replace_equiv_address (operands[1],
4876 copy_to_reg (XEXP (operands[1], 0)));
4878 /* Handle loading a large integer during reload. */
4879 else if (GET_CODE (operands[1]) == CONST_INT
4880 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4882 /* Writing a constant to memory needs a scratch, which should
4883 be handled with SECONDARY_RELOADs. */
4884 if (GET_CODE (operands[0]) != REG)
4887 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4888 emit_insn (gen_movsi (operands[0], operands[1]));
4896 (define_insn "*arm_movqi_insn"
4897 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4898 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4900 && ( register_operand (operands[0], QImode)
4901 || register_operand (operands[1], QImode))"
4907 [(set_attr "type" "*,*,load1,store1")
4908 (set_attr "predicable" "yes")]
4911 (define_insn "*thumb_movqi_insn"
4912 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4913 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
4915 && ( register_operand (operands[0], QImode)
4916 || register_operand (operands[1], QImode))"
4924 [(set_attr "length" "2")
4925 (set_attr "type" "*,load1,store1,*,*,*")
4926 (set_attr "pool_range" "*,32,*,*,*,*")]
4929 (define_expand "movsf"
4930 [(set (match_operand:SF 0 "general_operand" "")
4931 (match_operand:SF 1 "general_operand" ""))]
4936 if (GET_CODE (operands[0]) == MEM)
4937 operands[1] = force_reg (SFmode, operands[1]);
4939 else /* TARGET_THUMB */
4941 if (!no_new_pseudos)
4943 if (GET_CODE (operands[0]) != REG)
4944 operands[1] = force_reg (SFmode, operands[1]);
4951 [(set (match_operand:SF 0 "nonimmediate_operand" "")
4952 (match_operand:SF 1 "immediate_operand" ""))]
4954 && !(TARGET_HARD_FLOAT && TARGET_FPA)
4956 && GET_CODE (operands[1]) == CONST_DOUBLE"
4957 [(set (match_dup 2) (match_dup 3))]
4959 operands[2] = gen_lowpart (SImode, operands[0]);
4960 operands[3] = gen_lowpart (SImode, operands[1]);
4961 if (operands[2] == 0 || operands[3] == 0)
4966 (define_insn "*arm_movsf_soft_insn"
4967 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4968 (match_operand:SF 1 "general_operand" "r,mE,r"))]
4970 && TARGET_SOFT_FLOAT
4971 && (GET_CODE (operands[0]) != MEM
4972 || register_operand (operands[1], SFmode))"
4975 ldr%?\\t%0, %1\\t%@ float
4976 str%?\\t%1, %0\\t%@ float"
4977 [(set_attr "length" "4,4,4")
4978 (set_attr "predicable" "yes")
4979 (set_attr "type" "*,load1,store1")
4980 (set_attr "pool_range" "*,4096,*")
4981 (set_attr "neg_pool_range" "*,4084,*")]
4984 ;;; ??? This should have alternatives for constants.
4985 (define_insn "*thumb_movsf_insn"
4986 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4987 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
4989 && ( register_operand (operands[0], SFmode)
4990 || register_operand (operands[1], SFmode))"
4999 [(set_attr "length" "2")
5000 (set_attr "type" "*,load1,store1,load1,store1,*,*")
5001 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5004 (define_expand "movdf"
5005 [(set (match_operand:DF 0 "general_operand" "")
5006 (match_operand:DF 1 "general_operand" ""))]
5011 if (GET_CODE (operands[0]) == MEM)
5012 operands[1] = force_reg (DFmode, operands[1]);
5014 else /* TARGET_THUMB */
5016 if (!no_new_pseudos)
5018 if (GET_CODE (operands[0]) != REG)
5019 operands[1] = force_reg (DFmode, operands[1]);
5025 ;; Reloading a df mode value stored in integer regs to memory can require a
5027 (define_expand "reload_outdf"
5028 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5029 (match_operand:DF 1 "s_register_operand" "r")
5030 (match_operand:SI 2 "s_register_operand" "=&r")]
5034 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5037 operands[2] = XEXP (operands[0], 0);
5038 else if (code == POST_INC || code == PRE_DEC)
5040 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5041 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5042 emit_insn (gen_movdi (operands[0], operands[1]));
5045 else if (code == PRE_INC)
5047 rtx reg = XEXP (XEXP (operands[0], 0), 0);
5049 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5052 else if (code == POST_DEC)
5053 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5055 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5056 XEXP (XEXP (operands[0], 0), 1)));
5058 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5061 if (code == POST_DEC)
5062 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5068 (define_insn "*movdf_soft_insn"
5069 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5070 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5071 "TARGET_ARM && TARGET_SOFT_FLOAT
5073 "* return output_move_double (operands);"
5074 [(set_attr "length" "8,8,8")
5075 (set_attr "type" "*,load2,store2")
5076 (set_attr "pool_range" "1020")
5077 (set_attr "neg_pool_range" "1008")]
5080 ;;; ??? This should have alternatives for constants.
5081 ;;; ??? This was originally identical to the movdi_insn pattern.
5082 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5083 ;;; thumb_reorg with a memory reference.
5084 (define_insn "*thumb_movdf_insn"
5085 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5086 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
5088 && ( register_operand (operands[0], DFmode)
5089 || register_operand (operands[1], DFmode))"
5091 switch (which_alternative)
5095 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5096 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5097 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5099 return \"ldmia\\t%1, {%0, %H0}\";
5101 return \"stmia\\t%0, {%1, %H1}\";
5103 return thumb_load_double_from_address (operands);
5105 operands[2] = gen_rtx_MEM (SImode,
5106 plus_constant (XEXP (operands[0], 0), 4));
5107 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5110 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5111 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5112 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5115 [(set_attr "length" "4,2,2,6,4,4")
5116 (set_attr "type" "*,load2,store2,load2,store2,*")
5117 (set_attr "pool_range" "*,*,*,1020,*,*")]
5121 (define_expand "movv2si"
5122 [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5123 (match_operand:V2SI 1 "general_operand" ""))]
5124 "TARGET_REALLY_IWMMXT"
5128 (define_expand "movv4hi"
5129 [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5130 (match_operand:V4HI 1 "general_operand" ""))]
5131 "TARGET_REALLY_IWMMXT"
5135 (define_expand "movv8qi"
5136 [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5137 (match_operand:V8QI 1 "general_operand" ""))]
5138 "TARGET_REALLY_IWMMXT"
5143 ;; load- and store-multiple insns
5144 ;; The arm can load/store any set of registers, provided that they are in
5145 ;; ascending order; but that is beyond GCC so stick with what it knows.
5147 (define_expand "load_multiple"
5148 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5149 (match_operand:SI 1 "" ""))
5150 (use (match_operand:SI 2 "" ""))])]
5153 /* Support only fixed point registers. */
5154 if (GET_CODE (operands[2]) != CONST_INT
5155 || INTVAL (operands[2]) > 14
5156 || INTVAL (operands[2]) < 2
5157 || GET_CODE (operands[1]) != MEM
5158 || GET_CODE (operands[0]) != REG
5159 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5160 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5164 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5165 force_reg (SImode, XEXP (operands[1], 0)),
5166 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5167 MEM_IN_STRUCT_P(operands[1]),
5168 MEM_SCALAR_P (operands[1]));
5172 ;; Load multiple with write-back
5174 (define_insn "*ldmsi_postinc4"
5175 [(match_parallel 0 "load_multiple_operation"
5176 [(set (match_operand:SI 1 "s_register_operand" "=r")
5177 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5179 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5180 (mem:SI (match_dup 2)))
5181 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5182 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5183 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5184 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5185 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5186 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5187 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5188 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5189 [(set_attr "type" "load4")
5190 (set_attr "predicable" "yes")]
5193 (define_insn "*ldmsi_postinc3"
5194 [(match_parallel 0 "load_multiple_operation"
5195 [(set (match_operand:SI 1 "s_register_operand" "=r")
5196 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5198 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5199 (mem:SI (match_dup 2)))
5200 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5201 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5202 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5203 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5204 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5205 "ldm%?ia\\t%1!, {%3, %4, %5}"
5206 [(set_attr "type" "load3")
5207 (set_attr "predicable" "yes")]
5210 (define_insn "*ldmsi_postinc2"
5211 [(match_parallel 0 "load_multiple_operation"
5212 [(set (match_operand:SI 1 "s_register_operand" "=r")
5213 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5215 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5216 (mem:SI (match_dup 2)))
5217 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5218 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5219 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5220 "ldm%?ia\\t%1!, {%3, %4}"
5221 [(set_attr "type" "load2")
5222 (set_attr "predicable" "yes")]
5225 ;; Ordinary load multiple
5227 (define_insn "*ldmsi4"
5228 [(match_parallel 0 "load_multiple_operation"
5229 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5230 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5231 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5232 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5233 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5234 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5235 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5236 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5237 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5238 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5239 [(set_attr "type" "load4")
5240 (set_attr "predicable" "yes")]
5243 (define_insn "*ldmsi3"
5244 [(match_parallel 0 "load_multiple_operation"
5245 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5246 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5247 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5248 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5249 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5250 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5251 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5252 "ldm%?ia\\t%1, {%2, %3, %4}"
5253 [(set_attr "type" "load3")
5254 (set_attr "predicable" "yes")]
5257 (define_insn "*ldmsi2"
5258 [(match_parallel 0 "load_multiple_operation"
5259 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5260 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5261 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5262 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5263 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5264 "ldm%?ia\\t%1, {%2, %3}"
5265 [(set_attr "type" "load2")
5266 (set_attr "predicable" "yes")]
5269 (define_expand "store_multiple"
5270 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5271 (match_operand:SI 1 "" ""))
5272 (use (match_operand:SI 2 "" ""))])]
5275 /* Support only fixed point registers. */
5276 if (GET_CODE (operands[2]) != CONST_INT
5277 || INTVAL (operands[2]) > 14
5278 || INTVAL (operands[2]) < 2
5279 || GET_CODE (operands[1]) != REG
5280 || GET_CODE (operands[0]) != MEM
5281 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5282 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5286 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5287 force_reg (SImode, XEXP (operands[0], 0)),
5288 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5289 MEM_IN_STRUCT_P(operands[0]),
5290 MEM_SCALAR_P (operands[0]));
5294 ;; Store multiple with write-back
5296 (define_insn "*stmsi_postinc4"
5297 [(match_parallel 0 "store_multiple_operation"
5298 [(set (match_operand:SI 1 "s_register_operand" "=r")
5299 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5301 (set (mem:SI (match_dup 2))
5302 (match_operand:SI 3 "arm_hard_register_operand" ""))
5303 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5304 (match_operand:SI 4 "arm_hard_register_operand" ""))
5305 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5306 (match_operand:SI 5 "arm_hard_register_operand" ""))
5307 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5308 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5309 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5310 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5311 [(set_attr "predicable" "yes")
5312 (set_attr "type" "store4")]
5315 (define_insn "*stmsi_postinc3"
5316 [(match_parallel 0 "store_multiple_operation"
5317 [(set (match_operand:SI 1 "s_register_operand" "=r")
5318 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5320 (set (mem:SI (match_dup 2))
5321 (match_operand:SI 3 "arm_hard_register_operand" ""))
5322 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5323 (match_operand:SI 4 "arm_hard_register_operand" ""))
5324 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5325 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5326 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5327 "stm%?ia\\t%1!, {%3, %4, %5}"
5328 [(set_attr "predicable" "yes")
5329 (set_attr "type" "store3")]
5332 (define_insn "*stmsi_postinc2"
5333 [(match_parallel 0 "store_multiple_operation"
5334 [(set (match_operand:SI 1 "s_register_operand" "=r")
5335 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5337 (set (mem:SI (match_dup 2))
5338 (match_operand:SI 3 "arm_hard_register_operand" ""))
5339 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5340 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5341 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5342 "stm%?ia\\t%1!, {%3, %4}"
5343 [(set_attr "predicable" "yes")
5344 (set_attr "type" "store2")]
5347 ;; Ordinary store multiple
5349 (define_insn "*stmsi4"
5350 [(match_parallel 0 "store_multiple_operation"
5351 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5352 (match_operand:SI 2 "arm_hard_register_operand" ""))
5353 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5354 (match_operand:SI 3 "arm_hard_register_operand" ""))
5355 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5356 (match_operand:SI 4 "arm_hard_register_operand" ""))
5357 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5358 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5359 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5360 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5361 [(set_attr "predicable" "yes")
5362 (set_attr "type" "store4")]
5365 (define_insn "*stmsi3"
5366 [(match_parallel 0 "store_multiple_operation"
5367 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5368 (match_operand:SI 2 "arm_hard_register_operand" ""))
5369 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5370 (match_operand:SI 3 "arm_hard_register_operand" ""))
5371 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5372 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5373 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5374 "stm%?ia\\t%1, {%2, %3, %4}"
5375 [(set_attr "predicable" "yes")
5376 (set_attr "type" "store3")]
5379 (define_insn "*stmsi2"
5380 [(match_parallel 0 "store_multiple_operation"
5381 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5382 (match_operand:SI 2 "arm_hard_register_operand" ""))
5383 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5384 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5385 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5386 "stm%?ia\\t%1, {%2, %3}"
5387 [(set_attr "predicable" "yes")
5388 (set_attr "type" "store2")]
5391 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5392 ;; We could let this apply for blocks of less than this, but it clobbers so
5393 ;; many registers that there is then probably a better way.
5395 (define_expand "movstrqi"
5396 [(match_operand:BLK 0 "general_operand" "")
5397 (match_operand:BLK 1 "general_operand" "")
5398 (match_operand:SI 2 "const_int_operand" "")
5399 (match_operand:SI 3 "const_int_operand" "")]
5404 if (arm_gen_movstrqi (operands))
5408 else /* TARGET_THUMB */
5410 if ( INTVAL (operands[3]) != 4
5411 || INTVAL (operands[2]) > 48)
5414 thumb_expand_movstrqi (operands);
5420 ;; Thumb block-move insns
5422 (define_insn "movmem12b"
5423 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5424 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5425 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5426 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5427 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5428 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5429 (set (match_operand:SI 0 "register_operand" "=l")
5430 (plus:SI (match_dup 2) (const_int 12)))
5431 (set (match_operand:SI 1 "register_operand" "=l")
5432 (plus:SI (match_dup 3) (const_int 12)))
5433 (clobber (match_scratch:SI 4 "=&l"))
5434 (clobber (match_scratch:SI 5 "=&l"))
5435 (clobber (match_scratch:SI 6 "=&l"))]
5437 "* return thumb_output_move_mem_multiple (3, operands);"
5438 [(set_attr "length" "4")
5439 ; This isn't entirely accurate... It loads as well, but in terms of
5440 ; scheduling the following insn it is better to consider it as a store
5441 (set_attr "type" "store3")]
5444 (define_insn "movmem8b"
5445 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5446 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5447 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5448 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5449 (set (match_operand:SI 0 "register_operand" "=l")
5450 (plus:SI (match_dup 2) (const_int 8)))
5451 (set (match_operand:SI 1 "register_operand" "=l")
5452 (plus:SI (match_dup 3) (const_int 8)))
5453 (clobber (match_scratch:SI 4 "=&l"))
5454 (clobber (match_scratch:SI 5 "=&l"))]
5456 "* return thumb_output_move_mem_multiple (2, operands);"
5457 [(set_attr "length" "4")
5458 ; This isn't entirely accurate... It loads as well, but in terms of
5459 ; scheduling the following insn it is better to consider it as a store
5460 (set_attr "type" "store2")]
5465 ;; Compare & branch insns
5466 ;; The range calculations are based as follows:
5467 ;; For forward branches, the address calculation returns the address of
5468 ;; the next instruction. This is 2 beyond the branch instruction.
5469 ;; For backward branches, the address calculation returns the address of
5470 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5471 ;; instruction for the shortest sequence, and 4 before the branch instruction
5472 ;; if we have to jump around an unconditional branch.
5473 ;; To the basic branch range the PC offset must be added (this is +4).
5474 ;; So for forward branches we have
5475 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5476 ;; And for backward branches we have
5477 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5479 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5480 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5482 (define_expand "cbranchsi4"
5483 [(set (pc) (if_then_else
5484 (match_operator 0 "arm_comparison_operator"
5485 [(match_operand:SI 1 "s_register_operand" "")
5486 (match_operand:SI 2 "nonmemory_operand" "")])
5487 (label_ref (match_operand 3 "" ""))
5491 if (thumb_cmpneg_operand (operands[2], SImode))
5493 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5494 operands[3], operands[0]));
5497 if (!thumb_cmp_operand (operands[2], SImode))
5498 operands[2] = force_reg (SImode, operands[2]);
5501 (define_insn "*cbranchsi4_insn"
5502 [(set (pc) (if_then_else
5503 (match_operator 0 "arm_comparison_operator"
5504 [(match_operand:SI 1 "s_register_operand" "l,*h")
5505 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5506 (label_ref (match_operand 3 "" ""))
5510 output_asm_insn (\"cmp\\t%1, %2\", operands);
5512 switch (get_attr_length (insn))
5514 case 4: return \"b%d0\\t%l3\";
5515 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5516 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5519 [(set (attr "far_jump")
5521 (eq_attr "length" "8")
5522 (const_string "yes")
5523 (const_string "no")))
5524 (set (attr "length")
5526 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5527 (le (minus (match_dup 3) (pc)) (const_int 256)))
5530 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5531 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5536 (define_insn "cbranchsi4_scratch"
5537 [(set (pc) (if_then_else
5538 (match_operator 4 "arm_comparison_operator"
5539 [(match_operand:SI 1 "s_register_operand" "l,0")
5540 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5541 (label_ref (match_operand 3 "" ""))
5543 (clobber (match_scratch:SI 0 "=l,l"))]
5546 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5548 switch (get_attr_length (insn))
5550 case 4: return \"b%d4\\t%l3\";
5551 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5552 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5555 [(set (attr "far_jump")
5557 (eq_attr "length" "8")
5558 (const_string "yes")
5559 (const_string "no")))
5560 (set (attr "length")
5562 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5563 (le (minus (match_dup 3) (pc)) (const_int 256)))
5566 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5567 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5571 (define_insn "*movsi_cbranchsi4"
5574 (match_operator 3 "arm_comparison_operator"
5575 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5577 (label_ref (match_operand 2 "" ""))
5579 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5583 if (which_alternative == 0)
5584 output_asm_insn (\"cmp\t%0, #0\", operands);
5585 else if (which_alternative == 1)
5586 output_asm_insn (\"sub\t%0, %1, #0\", operands);
5589 output_asm_insn (\"cmp\t%1, #0\", operands);
5590 if (which_alternative == 2)
5591 output_asm_insn (\"mov\t%0, %1\", operands);
5593 output_asm_insn (\"str\t%1, %0\", operands);
5595 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5597 case 4: return \"b%d3\\t%l2\";
5598 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5599 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5602 [(set (attr "far_jump")
5604 (ior (and (gt (symbol_ref ("which_alternative"))
5606 (eq_attr "length" "8"))
5607 (eq_attr "length" "10"))
5608 (const_string "yes")
5609 (const_string "no")))
5610 (set (attr "length")
5612 (le (symbol_ref ("which_alternative"))
5615 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5616 (le (minus (match_dup 2) (pc)) (const_int 256)))
5619 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5620 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5624 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5625 (le (minus (match_dup 2) (pc)) (const_int 256)))
5628 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5629 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5634 (define_insn "*negated_cbranchsi4"
5637 (match_operator 0 "arm_comparison_operator"
5638 [(match_operand:SI 1 "s_register_operand" "l")
5639 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5640 (label_ref (match_operand 3 "" ""))
5644 output_asm_insn (\"cmn\\t%1, %2\", operands);
5645 switch (get_attr_length (insn))
5647 case 4: return \"b%d0\\t%l3\";
5648 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5649 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5652 [(set (attr "far_jump")
5654 (eq_attr "length" "8")
5655 (const_string "yes")
5656 (const_string "no")))
5657 (set (attr "length")
5659 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5660 (le (minus (match_dup 3) (pc)) (const_int 256)))
5663 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5664 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5669 (define_insn "*tbit_cbranch"
5672 (match_operator 0 "equality_operator"
5673 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5675 (match_operand:SI 2 "const_int_operand" "i"))
5677 (label_ref (match_operand 3 "" ""))
5679 (clobber (match_scratch:SI 4 "=l"))]
5684 op[0] = operands[4];
5685 op[1] = operands[1];
5686 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5688 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5689 switch (get_attr_length (insn))
5691 case 4: return \"b%d0\\t%l3\";
5692 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5693 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5696 [(set (attr "far_jump")
5698 (eq_attr "length" "8")
5699 (const_string "yes")
5700 (const_string "no")))
5701 (set (attr "length")
5703 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5704 (le (minus (match_dup 3) (pc)) (const_int 256)))
5707 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5708 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5713 (define_insn "*tstsi3_cbranch"
5716 (match_operator 3 "equality_operator"
5717 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5718 (match_operand:SI 1 "s_register_operand" "l"))
5720 (label_ref (match_operand 2 "" ""))
5725 output_asm_insn (\"tst\\t%0, %1\", operands);
5726 switch (get_attr_length (insn))
5728 case 4: return \"b%d3\\t%l2\";
5729 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5730 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5733 [(set (attr "far_jump")
5735 (eq_attr "length" "8")
5736 (const_string "yes")
5737 (const_string "no")))
5738 (set (attr "length")
5740 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5741 (le (minus (match_dup 2) (pc)) (const_int 256)))
5744 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5745 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5750 (define_insn "*andsi3_cbranch"
5753 (match_operator 5 "equality_operator"
5754 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5755 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5757 (label_ref (match_operand 4 "" ""))
5759 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5760 (and:SI (match_dup 2) (match_dup 3)))
5761 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5765 if (which_alternative == 0)
5766 output_asm_insn (\"and\\t%0, %3\", operands);
5767 else if (which_alternative == 1)
5769 output_asm_insn (\"and\\t%1, %3\", operands);
5770 output_asm_insn (\"mov\\t%0, %1\", operands);
5774 output_asm_insn (\"and\\t%1, %3\", operands);
5775 output_asm_insn (\"str\\t%1, %0\", operands);
5778 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5780 case 4: return \"b%d5\\t%l4\";
5781 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5782 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5785 [(set (attr "far_jump")
5787 (ior (and (eq (symbol_ref ("which_alternative"))
5789 (eq_attr "length" "8"))
5790 (eq_attr "length" "10"))
5791 (const_string "yes")
5792 (const_string "no")))
5793 (set (attr "length")
5795 (eq (symbol_ref ("which_alternative"))
5798 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5799 (le (minus (match_dup 4) (pc)) (const_int 256)))
5802 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5803 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5807 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5808 (le (minus (match_dup 4) (pc)) (const_int 256)))
5811 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5812 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5817 (define_insn "*orrsi3_cbranch_scratch"
5820 (match_operator 4 "equality_operator"
5821 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
5822 (match_operand:SI 2 "s_register_operand" "l"))
5824 (label_ref (match_operand 3 "" ""))
5826 (clobber (match_scratch:SI 0 "=l"))]
5830 output_asm_insn (\"orr\\t%0, %2\", operands);
5831 switch (get_attr_length (insn))
5833 case 4: return \"b%d4\\t%l3\";
5834 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5835 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5838 [(set (attr "far_jump")
5840 (eq_attr "length" "8")
5841 (const_string "yes")
5842 (const_string "no")))
5843 (set (attr "length")
5845 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5846 (le (minus (match_dup 3) (pc)) (const_int 256)))
5849 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5850 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5855 (define_insn "*orrsi3_cbranch"
5858 (match_operator 5 "equality_operator"
5859 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5860 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5862 (label_ref (match_operand 4 "" ""))
5864 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5865 (ior:SI (match_dup 2) (match_dup 3)))
5866 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5870 if (which_alternative == 0)
5871 output_asm_insn (\"orr\\t%0, %3\", operands);
5872 else if (which_alternative == 1)
5874 output_asm_insn (\"orr\\t%1, %3\", operands);
5875 output_asm_insn (\"mov\\t%0, %1\", operands);
5879 output_asm_insn (\"orr\\t%1, %3\", operands);
5880 output_asm_insn (\"str\\t%1, %0\", operands);
5883 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5885 case 4: return \"b%d5\\t%l4\";
5886 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5887 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5890 [(set (attr "far_jump")
5892 (ior (and (eq (symbol_ref ("which_alternative"))
5894 (eq_attr "length" "8"))
5895 (eq_attr "length" "10"))
5896 (const_string "yes")
5897 (const_string "no")))
5898 (set (attr "length")
5900 (eq (symbol_ref ("which_alternative"))
5903 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5904 (le (minus (match_dup 4) (pc)) (const_int 256)))
5907 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5908 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5912 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5913 (le (minus (match_dup 4) (pc)) (const_int 256)))
5916 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5917 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5922 (define_insn "*xorsi3_cbranch_scratch"
5925 (match_operator 4 "equality_operator"
5926 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
5927 (match_operand:SI 2 "s_register_operand" "l"))
5929 (label_ref (match_operand 3 "" ""))
5931 (clobber (match_scratch:SI 0 "=l"))]
5935 output_asm_insn (\"eor\\t%0, %2\", operands);
5936 switch (get_attr_length (insn))
5938 case 4: return \"b%d4\\t%l3\";
5939 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5940 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5943 [(set (attr "far_jump")
5945 (eq_attr "length" "8")
5946 (const_string "yes")
5947 (const_string "no")))
5948 (set (attr "length")
5950 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5951 (le (minus (match_dup 3) (pc)) (const_int 256)))
5954 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5955 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5960 (define_insn "*xorsi3_cbranch"
5963 (match_operator 5 "equality_operator"
5964 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5965 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5967 (label_ref (match_operand 4 "" ""))
5969 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5970 (xor:SI (match_dup 2) (match_dup 3)))
5971 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5975 if (which_alternative == 0)
5976 output_asm_insn (\"eor\\t%0, %3\", operands);
5977 else if (which_alternative == 1)
5979 output_asm_insn (\"eor\\t%1, %3\", operands);
5980 output_asm_insn (\"mov\\t%0, %1\", operands);
5984 output_asm_insn (\"eor\\t%1, %3\", operands);
5985 output_asm_insn (\"str\\t%1, %0\", operands);
5988 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5990 case 4: return \"b%d5\\t%l4\";
5991 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5992 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5995 [(set (attr "far_jump")
5997 (ior (and (eq (symbol_ref ("which_alternative"))
5999 (eq_attr "length" "8"))
6000 (eq_attr "length" "10"))
6001 (const_string "yes")
6002 (const_string "no")))
6003 (set (attr "length")
6005 (eq (symbol_ref ("which_alternative"))
6008 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6009 (le (minus (match_dup 4) (pc)) (const_int 256)))
6012 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6013 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6017 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6018 (le (minus (match_dup 4) (pc)) (const_int 256)))
6021 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6022 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6027 (define_insn "*bicsi3_cbranch_scratch"
6030 (match_operator 4 "equality_operator"
6031 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6032 (match_operand:SI 1 "s_register_operand" "0"))
6034 (label_ref (match_operand 3 "" ""))
6036 (clobber (match_scratch:SI 0 "=l"))]
6040 output_asm_insn (\"bic\\t%0, %2\", operands);
6041 switch (get_attr_length (insn))
6043 case 4: return \"b%d4\\t%l3\";
6044 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6045 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6048 [(set (attr "far_jump")
6050 (eq_attr "length" "8")
6051 (const_string "yes")
6052 (const_string "no")))
6053 (set (attr "length")
6055 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6056 (le (minus (match_dup 3) (pc)) (const_int 256)))
6059 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6060 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6065 (define_insn "*bicsi3_cbranch"
6068 (match_operator 5 "equality_operator"
6069 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6070 (match_operand:SI 2 "s_register_operand" "0,1,1,1"))
6072 (label_ref (match_operand 4 "" ""))
6074 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6075 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6076 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6080 if (which_alternative == 0)
6081 output_asm_insn (\"bic\\t%0, %3\", operands);
6082 else if (which_alternative == 1)
6084 output_asm_insn (\"bic\\t%1, %3\", operands);
6085 output_asm_insn (\"mov\\t%0, %1\", operands);
6089 output_asm_insn (\"bic\\t%1, %3\", operands);
6090 output_asm_insn (\"str\\t%1, %0\", operands);
6093 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6095 case 4: return \"b%d5\\t%l4\";
6096 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6097 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6100 [(set (attr "far_jump")
6102 (ior (and (eq (symbol_ref ("which_alternative"))
6104 (eq_attr "length" "8"))
6105 (eq_attr "length" "10"))
6106 (const_string "yes")
6107 (const_string "no")))
6108 (set (attr "length")
6110 (eq (symbol_ref ("which_alternative"))
6113 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6114 (le (minus (match_dup 4) (pc)) (const_int 256)))
6117 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6118 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6122 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6123 (le (minus (match_dup 4) (pc)) (const_int 256)))
6126 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6127 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6132 (define_insn "*cbranchne_decr1"
6134 (if_then_else (match_operator 3 "equality_operator"
6135 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6137 (label_ref (match_operand 4 "" ""))
6139 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6140 (plus:SI (match_dup 2) (const_int -1)))
6141 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6146 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6148 VOIDmode, operands[2], const1_rtx);
6149 cond[1] = operands[4];
6151 if (which_alternative == 0)
6152 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6153 else if (which_alternative == 1)
6155 /* We must provide an alternative for a hi reg because reload
6156 cannot handle output reloads on a jump instruction, but we
6157 can't subtract into that. Fortunately a mov from lo to hi
6158 does not clobber the condition codes. */
6159 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6160 output_asm_insn (\"mov\\t%0, %1\", operands);
6164 /* Similarly, but the target is memory. */
6165 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6166 output_asm_insn (\"str\\t%1, %0\", operands);
6169 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6172 output_asm_insn (\"b%d0\\t%l1\", cond);
6175 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6176 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6178 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6179 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6183 [(set (attr "far_jump")
6185 (ior (and (eq (symbol_ref ("which_alternative"))
6187 (eq_attr "length" "8"))
6188 (eq_attr "length" "10"))
6189 (const_string "yes")
6190 (const_string "no")))
6191 (set_attr_alternative "length"
6195 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6196 (le (minus (match_dup 4) (pc)) (const_int 256)))
6199 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6200 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6205 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6206 (le (minus (match_dup 4) (pc)) (const_int 256)))
6209 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6210 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6215 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6216 (le (minus (match_dup 4) (pc)) (const_int 256)))
6219 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6220 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6225 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6226 (le (minus (match_dup 4) (pc)) (const_int 256)))
6229 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6230 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6235 (define_insn "*addsi3_cbranch"
6238 (match_operator 4 "comparison_operator"
6240 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6241 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6243 (label_ref (match_operand 5 "" ""))
6246 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6247 (plus:SI (match_dup 2) (match_dup 3)))
6248 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6250 && (GET_CODE (operands[4]) == EQ
6251 || GET_CODE (operands[4]) == NE
6252 || GET_CODE (operands[4]) == GE
6253 || GET_CODE (operands[4]) == LT)"
6259 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6260 cond[1] = operands[2];
6261 cond[2] = operands[3];
6263 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6264 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6266 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6268 if (which_alternative >= 3
6269 && which_alternative < 4)
6270 output_asm_insn (\"mov\\t%0, %1\", operands);
6271 else if (which_alternative >= 4)
6272 output_asm_insn (\"str\\t%1, %0\", operands);
6274 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6277 return \"b%d4\\t%l5\";
6279 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6281 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6285 [(set (attr "far_jump")
6287 (ior (and (lt (symbol_ref ("which_alternative"))
6289 (eq_attr "length" "8"))
6290 (eq_attr "length" "10"))
6291 (const_string "yes")
6292 (const_string "no")))
6293 (set (attr "length")
6295 (lt (symbol_ref ("which_alternative"))
6298 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6299 (le (minus (match_dup 5) (pc)) (const_int 256)))
6302 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6303 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6307 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6308 (le (minus (match_dup 5) (pc)) (const_int 256)))
6311 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6312 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6317 (define_insn "*addsi3_cbranch_scratch"
6320 (match_operator 3 "comparison_operator"
6322 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6323 (match_operand:SI 2 "reg_or_int_operand" "J,l,I,L"))
6325 (label_ref (match_operand 4 "" ""))
6327 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6329 && (GET_CODE (operands[3]) == EQ
6330 || GET_CODE (operands[3]) == NE
6331 || GET_CODE (operands[3]) == GE
6332 || GET_CODE (operands[3]) == LT)"
6335 switch (which_alternative)
6338 output_asm_insn (\"cmp\t%1, #%n2\", operands);
6341 output_asm_insn (\"cmn\t%1, %2\", operands);
6344 output_asm_insn (\"add\t%0, %1, %2\", operands);
6347 output_asm_insn (\"add\t%0, %0, %2\", operands);
6351 switch (get_attr_length (insn))
6354 return \"b%d3\\t%l4\";
6356 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6358 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6362 [(set (attr "far_jump")
6364 (eq_attr "length" "8")
6365 (const_string "yes")
6366 (const_string "no")))
6367 (set (attr "length")
6369 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6370 (le (minus (match_dup 4) (pc)) (const_int 256)))
6373 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6374 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6379 (define_insn "*subsi3_cbranch"
6382 (match_operator 4 "comparison_operator"
6384 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6385 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6387 (label_ref (match_operand 5 "" ""))
6389 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6390 (minus:SI (match_dup 2) (match_dup 3)))
6391 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6393 && (GET_CODE (operands[4]) == EQ
6394 || GET_CODE (operands[4]) == NE
6395 || GET_CODE (operands[4]) == GE
6396 || GET_CODE (operands[4]) == LT)"
6399 if (which_alternative == 0)
6400 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6401 else if (which_alternative == 1)
6403 /* We must provide an alternative for a hi reg because reload
6404 cannot handle output reloads on a jump instruction, but we
6405 can't subtract into that. Fortunately a mov from lo to hi
6406 does not clobber the condition codes. */
6407 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6408 output_asm_insn (\"mov\\t%0, %1\", operands);
6412 /* Similarly, but the target is memory. */
6413 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6414 output_asm_insn (\"str\\t%1, %0\", operands);
6417 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6420 return \"b%d4\\t%l5\";
6422 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6424 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6428 [(set (attr "far_jump")
6430 (ior (and (eq (symbol_ref ("which_alternative"))
6432 (eq_attr "length" "8"))
6433 (eq_attr "length" "10"))
6434 (const_string "yes")
6435 (const_string "no")))
6436 (set (attr "length")
6438 (eq (symbol_ref ("which_alternative"))
6441 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6442 (le (minus (match_dup 5) (pc)) (const_int 256)))
6445 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6446 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6450 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6451 (le (minus (match_dup 5) (pc)) (const_int 256)))
6454 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6455 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6460 (define_insn "*subsi3_cbranch_scratch"
6463 (match_operator 0 "arm_comparison_operator"
6464 [(minus:SI (match_operand:SI 1 "register_operand" "l")
6465 (match_operand:SI 2 "nonmemory_operand" "l"))
6467 (label_ref (match_operand 3 "" ""))
6470 && (GET_CODE (operands[0]) == EQ
6471 || GET_CODE (operands[0]) == NE
6472 || GET_CODE (operands[0]) == GE
6473 || GET_CODE (operands[0]) == LT)"
6475 output_asm_insn (\"cmp\\t%1, %2\", operands);
6476 switch (get_attr_length (insn))
6478 case 4: return \"b%d0\\t%l3\";
6479 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6480 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6483 [(set (attr "far_jump")
6485 (eq_attr "length" "8")
6486 (const_string "yes")
6487 (const_string "no")))
6488 (set (attr "length")
6490 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6491 (le (minus (match_dup 3) (pc)) (const_int 256)))
6494 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6495 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6500 ;; Comparison and test insns
6502 (define_expand "cmpsi"
6503 [(match_operand:SI 0 "s_register_operand" "")
6504 (match_operand:SI 1 "arm_add_operand" "")]
6507 arm_compare_op0 = operands[0];
6508 arm_compare_op1 = operands[1];
6513 (define_expand "cmpsf"
6514 [(match_operand:SF 0 "s_register_operand" "")
6515 (match_operand:SF 1 "arm_float_compare_operand" "")]
6516 "TARGET_ARM && TARGET_HARD_FLOAT"
6518 arm_compare_op0 = operands[0];
6519 arm_compare_op1 = operands[1];
6524 (define_expand "cmpdf"
6525 [(match_operand:DF 0 "s_register_operand" "")
6526 (match_operand:DF 1 "arm_float_compare_operand" "")]
6527 "TARGET_ARM && TARGET_HARD_FLOAT"
6529 arm_compare_op0 = operands[0];
6530 arm_compare_op1 = operands[1];
6535 (define_insn "*arm_cmpsi_insn"
6536 [(set (reg:CC CC_REGNUM)
6537 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6538 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
6543 [(set_attr "conds" "set")]
6546 (define_insn "*cmpsi_shiftsi"
6547 [(set (reg:CC CC_REGNUM)
6548 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6549 (match_operator:SI 3 "shift_operator"
6550 [(match_operand:SI 1 "s_register_operand" "r")
6551 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
6554 [(set_attr "conds" "set")
6555 (set_attr "shift" "1")
6556 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6557 (const_string "alu_shift")
6558 (const_string "alu_shift_reg")))]
6561 (define_insn "*cmpsi_shiftsi_swp"
6562 [(set (reg:CC_SWP CC_REGNUM)
6563 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6564 [(match_operand:SI 1 "s_register_operand" "r")
6565 (match_operand:SI 2 "reg_or_int_operand" "rM")])
6566 (match_operand:SI 0 "s_register_operand" "r")))]
6569 [(set_attr "conds" "set")
6570 (set_attr "shift" "1")
6571 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6572 (const_string "alu_shift")
6573 (const_string "alu_shift_reg")))]
6576 (define_insn "*cmpsi_neg_shiftsi"
6577 [(set (reg:CC CC_REGNUM)
6578 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6579 (neg:SI (match_operator:SI 3 "shift_operator"
6580 [(match_operand:SI 1 "s_register_operand" "r")
6581 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
6584 [(set_attr "conds" "set")
6585 (set_attr "shift" "1")
6586 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6587 (const_string "alu_shift")
6588 (const_string "alu_shift_reg")))]
6591 ;; Cirrus SF compare instruction
6592 (define_insn "*cirrus_cmpsf"
6593 [(set (reg:CCFP CC_REGNUM)
6594 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6595 (match_operand:SF 1 "cirrus_fp_register" "v")))]
6596 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6597 "cfcmps%?\\tr15, %V0, %V1"
6598 [(set_attr "type" "mav_farith")
6599 (set_attr "cirrus" "compare")]
6602 ;; Cirrus DF compare instruction
6603 (define_insn "*cirrus_cmpdf"
6604 [(set (reg:CCFP CC_REGNUM)
6605 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6606 (match_operand:DF 1 "cirrus_fp_register" "v")))]
6607 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6608 "cfcmpd%?\\tr15, %V0, %V1"
6609 [(set_attr "type" "mav_farith")
6610 (set_attr "cirrus" "compare")]
6613 ;; Cirrus DI compare instruction
6614 (define_expand "cmpdi"
6615 [(match_operand:DI 0 "cirrus_fp_register" "")
6616 (match_operand:DI 1 "cirrus_fp_register" "")]
6617 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6619 arm_compare_op0 = operands[0];
6620 arm_compare_op1 = operands[1];
6624 (define_insn "*cirrus_cmpdi"
6625 [(set (reg:CC CC_REGNUM)
6626 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6627 (match_operand:DI 1 "cirrus_fp_register" "v")))]
6628 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6629 "cfcmp64%?\\tr15, %V0, %V1"
6630 [(set_attr "type" "mav_farith")
6631 (set_attr "cirrus" "compare")]
6634 ; This insn allows redundant compares to be removed by cse, nothing should
6635 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6636 ; is deleted later on. The match_dup will match the mode here, so that
6637 ; mode changes of the condition codes aren't lost by this even though we don't
6638 ; specify what they are.
6640 (define_insn "*deleted_compare"
6641 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6643 "\\t%@ deleted compare"
6644 [(set_attr "conds" "set")
6645 (set_attr "length" "0")]
6649 ;; Conditional branch insns
6651 (define_expand "beq"
6653 (if_then_else (eq (match_dup 1) (const_int 0))
6654 (label_ref (match_operand 0 "" ""))
6657 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6660 (define_expand "bne"
6662 (if_then_else (ne (match_dup 1) (const_int 0))
6663 (label_ref (match_operand 0 "" ""))
6666 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6669 (define_expand "bgt"
6671 (if_then_else (gt (match_dup 1) (const_int 0))
6672 (label_ref (match_operand 0 "" ""))
6675 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6678 (define_expand "ble"
6680 (if_then_else (le (match_dup 1) (const_int 0))
6681 (label_ref (match_operand 0 "" ""))
6684 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6687 (define_expand "bge"
6689 (if_then_else (ge (match_dup 1) (const_int 0))
6690 (label_ref (match_operand 0 "" ""))
6693 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6696 (define_expand "blt"
6698 (if_then_else (lt (match_dup 1) (const_int 0))
6699 (label_ref (match_operand 0 "" ""))
6702 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6705 (define_expand "bgtu"
6707 (if_then_else (gtu (match_dup 1) (const_int 0))
6708 (label_ref (match_operand 0 "" ""))
6711 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6714 (define_expand "bleu"
6716 (if_then_else (leu (match_dup 1) (const_int 0))
6717 (label_ref (match_operand 0 "" ""))
6720 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6723 (define_expand "bgeu"
6725 (if_then_else (geu (match_dup 1) (const_int 0))
6726 (label_ref (match_operand 0 "" ""))
6729 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6732 (define_expand "bltu"
6734 (if_then_else (ltu (match_dup 1) (const_int 0))
6735 (label_ref (match_operand 0 "" ""))
6738 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6741 (define_expand "bunordered"
6743 (if_then_else (unordered (match_dup 1) (const_int 0))
6744 (label_ref (match_operand 0 "" ""))
6746 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6747 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6751 (define_expand "bordered"
6753 (if_then_else (ordered (match_dup 1) (const_int 0))
6754 (label_ref (match_operand 0 "" ""))
6756 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6757 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6761 (define_expand "bungt"
6763 (if_then_else (ungt (match_dup 1) (const_int 0))
6764 (label_ref (match_operand 0 "" ""))
6766 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6767 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6770 (define_expand "bunlt"
6772 (if_then_else (unlt (match_dup 1) (const_int 0))
6773 (label_ref (match_operand 0 "" ""))
6775 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6776 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6779 (define_expand "bunge"
6781 (if_then_else (unge (match_dup 1) (const_int 0))
6782 (label_ref (match_operand 0 "" ""))
6784 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6785 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6788 (define_expand "bunle"
6790 (if_then_else (unle (match_dup 1) (const_int 0))
6791 (label_ref (match_operand 0 "" ""))
6793 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6794 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6797 ;; The following two patterns need two branch instructions, since there is
6798 ;; no single instruction that will handle all cases.
6799 (define_expand "buneq"
6801 (if_then_else (uneq (match_dup 1) (const_int 0))
6802 (label_ref (match_operand 0 "" ""))
6804 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6805 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6808 (define_expand "bltgt"
6810 (if_then_else (ltgt (match_dup 1) (const_int 0))
6811 (label_ref (match_operand 0 "" ""))
6813 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6814 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6818 ;; Patterns to match conditional branch insns.
6821 ; Special pattern to match UNEQ.
6822 (define_insn "*arm_buneq"
6824 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6825 (label_ref (match_operand 0 "" ""))
6827 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6829 if (arm_ccfsm_state != 0)
6832 return \"bvs\\t%l0\;beq\\t%l0\";
6834 [(set_attr "conds" "jump_clob")
6835 (set_attr "length" "8")]
6838 ; Special pattern to match LTGT.
6839 (define_insn "*arm_bltgt"
6841 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6842 (label_ref (match_operand 0 "" ""))
6844 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6846 if (arm_ccfsm_state != 0)
6849 return \"bmi\\t%l0\;bgt\\t%l0\";
6851 [(set_attr "conds" "jump_clob")
6852 (set_attr "length" "8")]
6855 (define_insn "*arm_cond_branch"
6857 (if_then_else (match_operator 1 "arm_comparison_operator"
6858 [(match_operand 2 "cc_register" "") (const_int 0)])
6859 (label_ref (match_operand 0 "" ""))
6863 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6865 arm_ccfsm_state += 2;
6868 return \"b%d1\\t%l0\";
6870 [(set_attr "conds" "use")
6871 (set_attr "type" "branch")]
6874 ; Special pattern to match reversed UNEQ.
6875 (define_insn "*arm_buneq_reversed"
6877 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6879 (label_ref (match_operand 0 "" ""))))]
6880 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6882 if (arm_ccfsm_state != 0)
6885 return \"bmi\\t%l0\;bgt\\t%l0\";
6887 [(set_attr "conds" "jump_clob")
6888 (set_attr "length" "8")]
6891 ; Special pattern to match reversed LTGT.
6892 (define_insn "*arm_bltgt_reversed"
6894 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6896 (label_ref (match_operand 0 "" ""))))]
6897 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6899 if (arm_ccfsm_state != 0)
6902 return \"bvs\\t%l0\;beq\\t%l0\";
6904 [(set_attr "conds" "jump_clob")
6905 (set_attr "length" "8")]
6908 (define_insn "*arm_cond_branch_reversed"
6910 (if_then_else (match_operator 1 "arm_comparison_operator"
6911 [(match_operand 2 "cc_register" "") (const_int 0)])
6913 (label_ref (match_operand 0 "" ""))))]
6916 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6918 arm_ccfsm_state += 2;
6921 return \"b%D1\\t%l0\";
6923 [(set_attr "conds" "use")
6924 (set_attr "type" "branch")]
6931 (define_expand "seq"
6932 [(set (match_operand:SI 0 "s_register_operand" "")
6933 (eq:SI (match_dup 1) (const_int 0)))]
6935 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6938 (define_expand "sne"
6939 [(set (match_operand:SI 0 "s_register_operand" "")
6940 (ne:SI (match_dup 1) (const_int 0)))]
6942 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6945 (define_expand "sgt"
6946 [(set (match_operand:SI 0 "s_register_operand" "")
6947 (gt:SI (match_dup 1) (const_int 0)))]
6949 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6952 (define_expand "sle"
6953 [(set (match_operand:SI 0 "s_register_operand" "")
6954 (le:SI (match_dup 1) (const_int 0)))]
6956 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6959 (define_expand "sge"
6960 [(set (match_operand:SI 0 "s_register_operand" "")
6961 (ge:SI (match_dup 1) (const_int 0)))]
6963 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6966 (define_expand "slt"
6967 [(set (match_operand:SI 0 "s_register_operand" "")
6968 (lt:SI (match_dup 1) (const_int 0)))]
6970 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6973 (define_expand "sgtu"
6974 [(set (match_operand:SI 0 "s_register_operand" "")
6975 (gtu:SI (match_dup 1) (const_int 0)))]
6977 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6980 (define_expand "sleu"
6981 [(set (match_operand:SI 0 "s_register_operand" "")
6982 (leu:SI (match_dup 1) (const_int 0)))]
6984 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6987 (define_expand "sgeu"
6988 [(set (match_operand:SI 0 "s_register_operand" "")
6989 (geu:SI (match_dup 1) (const_int 0)))]
6991 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6994 (define_expand "sltu"
6995 [(set (match_operand:SI 0 "s_register_operand" "")
6996 (ltu:SI (match_dup 1) (const_int 0)))]
6998 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7001 (define_expand "sunordered"
7002 [(set (match_operand:SI 0 "s_register_operand" "")
7003 (unordered:SI (match_dup 1) (const_int 0)))]
7004 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7005 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7009 (define_expand "sordered"
7010 [(set (match_operand:SI 0 "s_register_operand" "")
7011 (ordered:SI (match_dup 1) (const_int 0)))]
7012 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7013 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7017 (define_expand "sungt"
7018 [(set (match_operand:SI 0 "s_register_operand" "")
7019 (ungt:SI (match_dup 1) (const_int 0)))]
7020 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7021 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7025 (define_expand "sunge"
7026 [(set (match_operand:SI 0 "s_register_operand" "")
7027 (unge:SI (match_dup 1) (const_int 0)))]
7028 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7029 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7033 (define_expand "sunlt"
7034 [(set (match_operand:SI 0 "s_register_operand" "")
7035 (unlt:SI (match_dup 1) (const_int 0)))]
7036 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7037 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7041 (define_expand "sunle"
7042 [(set (match_operand:SI 0 "s_register_operand" "")
7043 (unle:SI (match_dup 1) (const_int 0)))]
7044 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7045 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7049 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7050 ;;; simple ARM instructions.
7052 ; (define_expand "suneq"
7053 ; [(set (match_operand:SI 0 "s_register_operand" "")
7054 ; (uneq:SI (match_dup 1) (const_int 0)))]
7055 ; "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7059 ; (define_expand "sltgt"
7060 ; [(set (match_operand:SI 0 "s_register_operand" "")
7061 ; (ltgt:SI (match_dup 1) (const_int 0)))]
7062 ; "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7066 (define_insn "*mov_scc"
7067 [(set (match_operand:SI 0 "s_register_operand" "=r")
7068 (match_operator:SI 1 "arm_comparison_operator"
7069 [(match_operand 2 "cc_register" "") (const_int 0)]))]
7071 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7072 [(set_attr "conds" "use")
7073 (set_attr "length" "8")]
7076 (define_insn "*mov_negscc"
7077 [(set (match_operand:SI 0 "s_register_operand" "=r")
7078 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7079 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7081 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7082 [(set_attr "conds" "use")
7083 (set_attr "length" "8")]
7086 (define_insn "*mov_notscc"
7087 [(set (match_operand:SI 0 "s_register_operand" "=r")
7088 (not:SI (match_operator:SI 1 "arm_comparison_operator"
7089 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7091 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7092 [(set_attr "conds" "use")
7093 (set_attr "length" "8")]
7097 ;; Conditional move insns
7099 (define_expand "movsicc"
7100 [(set (match_operand:SI 0 "s_register_operand" "")
7101 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7102 (match_operand:SI 2 "arm_not_operand" "")
7103 (match_operand:SI 3 "arm_not_operand" "")))]
7107 enum rtx_code code = GET_CODE (operands[1]);
7110 if (code == UNEQ || code == LTGT)
7113 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7114 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7118 (define_expand "movsfcc"
7119 [(set (match_operand:SF 0 "s_register_operand" "")
7120 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7121 (match_operand:SF 2 "s_register_operand" "")
7122 (match_operand:SF 3 "nonmemory_operand" "")))]
7126 enum rtx_code code = GET_CODE (operands[1]);
7129 if (code == UNEQ || code == LTGT)
7132 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
7133 Otherwise, ensure it is a valid FP add operand */
7134 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7135 || (!arm_float_add_operand (operands[3], SFmode)))
7136 operands[3] = force_reg (SFmode, operands[3]);
7138 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7139 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7143 (define_expand "movdfcc"
7144 [(set (match_operand:DF 0 "s_register_operand" "")
7145 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7146 (match_operand:DF 2 "s_register_operand" "")
7147 (match_operand:DF 3 "arm_float_add_operand" "")))]
7148 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7151 enum rtx_code code = GET_CODE (operands[1]);
7154 if (code == UNEQ || code == LTGT)
7157 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7158 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7162 (define_insn "*movsicc_insn"
7163 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7165 (match_operator 3 "arm_comparison_operator"
7166 [(match_operand 4 "cc_register" "") (const_int 0)])
7167 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7168 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7175 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7176 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7177 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7178 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7179 [(set_attr "length" "4,4,4,4,8,8,8,8")
7180 (set_attr "conds" "use")]
7183 (define_insn "*movsfcc_soft_insn"
7184 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7185 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7186 [(match_operand 4 "cc_register" "") (const_int 0)])
7187 (match_operand:SF 1 "s_register_operand" "0,r")
7188 (match_operand:SF 2 "s_register_operand" "r,0")))]
7189 "TARGET_ARM && TARGET_SOFT_FLOAT"
7193 [(set_attr "conds" "use")]
7197 ;; Jump and linkage insns
7199 (define_expand "jump"
7201 (label_ref (match_operand 0 "" "")))]
7206 (define_insn "*arm_jump"
7208 (label_ref (match_operand 0 "" "")))]
7212 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7214 arm_ccfsm_state += 2;
7217 return \"b%?\\t%l0\";
7220 [(set_attr "predicable" "yes")]
7223 (define_insn "*thumb_jump"
7225 (label_ref (match_operand 0 "" "")))]
7228 if (get_attr_length (insn) == 2)
7230 return \"bl\\t%l0\\t%@ far jump\";
7232 [(set (attr "far_jump")
7234 (eq_attr "length" "4")
7235 (const_string "yes")
7236 (const_string "no")))
7237 (set (attr "length")
7239 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7240 (le (minus (match_dup 0) (pc)) (const_int 2048)))
7245 (define_expand "call"
7246 [(parallel [(call (match_operand 0 "memory_operand" "")
7247 (match_operand 1 "general_operand" ""))
7248 (use (match_operand 2 "" ""))
7249 (clobber (reg:SI LR_REGNUM))])]
7255 /* In an untyped call, we can get NULL for operand 2. */
7256 if (operands[2] == NULL_RTX)
7257 operands[2] = const0_rtx;
7259 /* This is to decide if we should generate indirect calls by loading the
7260 32 bit address of the callee into a register before performing the
7261 branch and link. operand[2] encodes the long_call/short_call
7262 attribute of the function being called. This attribute is set whenever
7263 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7264 is used, and the short_call attribute can also be set if function is
7265 declared as static or if it has already been defined in the current
7266 compilation unit. See arm.c and arm.h for info about this. The third
7267 parameter to arm_is_longcall_p is used to tell it which pattern
7269 callee = XEXP (operands[0], 0);
7271 if (GET_CODE (callee) != REG
7272 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7273 XEXP (operands[0], 0) = force_reg (Pmode, callee);
7277 (define_insn "*call_reg"
7278 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7279 (match_operand 1 "" ""))
7280 (use (match_operand 2 "" ""))
7281 (clobber (reg:SI LR_REGNUM))]
7284 return output_call (operands);
7286 ;; length is worst case, normally it is only two
7287 [(set_attr "length" "12")
7288 (set_attr "type" "call")]
7291 (define_insn "*call_mem"
7292 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7293 (match_operand 1 "" ""))
7294 (use (match_operand 2 "" ""))
7295 (clobber (reg:SI LR_REGNUM))]
7298 return output_call_mem (operands);
7300 [(set_attr "length" "12")
7301 (set_attr "type" "call")]
7304 (define_insn "*call_indirect"
7305 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7306 (match_operand 1 "" ""))
7307 (use (match_operand 2 "" ""))
7308 (clobber (reg:SI LR_REGNUM))]
7312 if (TARGET_CALLER_INTERWORKING)
7313 return \"bl\\t%__interwork_call_via_%0\";
7315 return \"bl\\t%__call_via_%0\";
7317 [(set_attr "type" "call")]
7320 (define_insn "*call_value_indirect"
7321 [(set (match_operand 0 "" "")
7322 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7323 (match_operand 2 "" "")))
7324 (use (match_operand 3 "" ""))
7325 (clobber (reg:SI LR_REGNUM))]
7329 if (TARGET_CALLER_INTERWORKING)
7330 return \"bl\\t%__interwork_call_via_%1\";
7332 return \"bl\\t%__call_via_%1\";
7334 [(set_attr "type" "call")]
7337 (define_expand "call_value"
7338 [(parallel [(set (match_operand 0 "" "")
7339 (call (match_operand 1 "memory_operand" "")
7340 (match_operand 2 "general_operand" "")))
7341 (use (match_operand 3 "" ""))
7342 (clobber (reg:SI LR_REGNUM))])]
7346 rtx callee = XEXP (operands[1], 0);
7348 /* In an untyped call, we can get NULL for operand 2. */
7349 if (operands[3] == 0)
7350 operands[3] = const0_rtx;
7352 /* See the comment in define_expand \"call\". */
7353 if (GET_CODE (callee) != REG
7354 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7355 XEXP (operands[1], 0) = force_reg (Pmode, callee);
7359 (define_insn "*call_value_reg"
7360 [(set (match_operand 0 "" "")
7361 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7362 (match_operand 2 "" "")))
7363 (use (match_operand 3 "" ""))
7364 (clobber (reg:SI LR_REGNUM))]
7367 return output_call (&operands[1]);
7369 [(set_attr "length" "12")
7370 (set_attr "type" "call")]
7373 (define_insn "*call_value_mem"
7374 [(set (match_operand 0 "" "")
7375 (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7376 (match_operand 2 "" "")))
7377 (use (match_operand 3 "" ""))
7378 (clobber (reg:SI LR_REGNUM))]
7379 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7381 return output_call_mem (&operands[1]);
7383 [(set_attr "length" "12")
7384 (set_attr "type" "call")]
7387 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7388 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7390 (define_insn "*call_symbol"
7391 [(call (mem:SI (match_operand:SI 0 "" ""))
7392 (match_operand 1 "" ""))
7393 (use (match_operand 2 "" ""))
7394 (clobber (reg:SI LR_REGNUM))]
7396 && (GET_CODE (operands[0]) == SYMBOL_REF)
7397 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7400 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7402 [(set_attr "type" "call")]
7405 (define_insn "*call_value_symbol"
7406 [(set (match_operand 0 "s_register_operand" "")
7407 (call (mem:SI (match_operand:SI 1 "" ""))
7408 (match_operand:SI 2 "" "")))
7409 (use (match_operand 3 "" ""))
7410 (clobber (reg:SI LR_REGNUM))]
7412 && (GET_CODE (operands[1]) == SYMBOL_REF)
7413 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7416 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7418 [(set_attr "type" "call")]
7421 (define_insn "*call_insn"
7422 [(call (mem:SI (match_operand:SI 0 "" ""))
7423 (match_operand:SI 1 "" ""))
7424 (use (match_operand 2 "" ""))
7425 (clobber (reg:SI LR_REGNUM))]
7427 && GET_CODE (operands[0]) == SYMBOL_REF
7428 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7430 [(set_attr "length" "4")
7431 (set_attr "type" "call")]
7434 (define_insn "*call_value_insn"
7435 [(set (match_operand 0 "register_operand" "")
7436 (call (mem:SI (match_operand 1 "" ""))
7437 (match_operand 2 "" "")))
7438 (use (match_operand 3 "" ""))
7439 (clobber (reg:SI LR_REGNUM))]
7441 && GET_CODE (operands[1]) == SYMBOL_REF
7442 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7444 [(set_attr "length" "4")
7445 (set_attr "type" "call")]
7448 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7449 (define_expand "sibcall"
7450 [(parallel [(call (match_operand 0 "memory_operand" "")
7451 (match_operand 1 "general_operand" ""))
7453 (use (match_operand 2 "" ""))])]
7457 if (operands[2] == NULL_RTX)
7458 operands[2] = const0_rtx;
7462 (define_expand "sibcall_value"
7463 [(parallel [(set (match_operand 0 "register_operand" "")
7464 (call (match_operand 1 "memory_operand" "")
7465 (match_operand 2 "general_operand" "")))
7467 (use (match_operand 3 "" ""))])]
7471 if (operands[3] == NULL_RTX)
7472 operands[3] = const0_rtx;
7476 (define_insn "*sibcall_insn"
7477 [(call (mem:SI (match_operand:SI 0 "" "X"))
7478 (match_operand 1 "" ""))
7480 (use (match_operand 2 "" ""))]
7481 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7483 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7485 [(set_attr "type" "call")]
7488 (define_insn "*sibcall_value_insn"
7489 [(set (match_operand 0 "s_register_operand" "")
7490 (call (mem:SI (match_operand:SI 1 "" "X"))
7491 (match_operand 2 "" "")))
7493 (use (match_operand 3 "" ""))]
7494 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7496 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7498 [(set_attr "type" "call")]
7501 ;; Often the return insn will be the same as loading from memory, so set attr
7502 (define_insn "return"
7504 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7507 if (arm_ccfsm_state == 2)
7509 arm_ccfsm_state += 2;
7512 return output_return_instruction (const_true_rtx, TRUE, FALSE);
7514 [(set_attr "type" "load1")
7515 (set_attr "length" "12")
7516 (set_attr "predicable" "yes")]
7519 (define_insn "*cond_return"
7521 (if_then_else (match_operator 0 "arm_comparison_operator"
7522 [(match_operand 1 "cc_register" "") (const_int 0)])
7525 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7528 if (arm_ccfsm_state == 2)
7530 arm_ccfsm_state += 2;
7533 return output_return_instruction (operands[0], TRUE, FALSE);
7535 [(set_attr "conds" "use")
7536 (set_attr "length" "12")
7537 (set_attr "type" "load1")]
7540 (define_insn "*cond_return_inverted"
7542 (if_then_else (match_operator 0 "arm_comparison_operator"
7543 [(match_operand 1 "cc_register" "") (const_int 0)])
7546 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7549 if (arm_ccfsm_state == 2)
7551 arm_ccfsm_state += 2;
7554 return output_return_instruction (operands[0], TRUE, TRUE);
7556 [(set_attr "conds" "use")
7557 (set_attr "type" "load1")]
7560 ;; Generate a sequence of instructions to determine if the processor is
7561 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7564 (define_expand "return_addr_mask"
7566 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7568 (set (match_operand:SI 0 "s_register_operand" "")
7569 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7571 (const_int 67108860)))] ; 0x03fffffc
7574 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7577 (define_insn "*check_arch2"
7578 [(set (match_operand:CC_NOOV 0 "cc_register" "")
7579 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7582 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7583 [(set_attr "length" "8")
7584 (set_attr "conds" "set")]
7587 ;; Call subroutine returning any type.
7589 (define_expand "untyped_call"
7590 [(parallel [(call (match_operand 0 "" "")
7592 (match_operand 1 "" "")
7593 (match_operand 2 "" "")])]
7599 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
7601 for (i = 0; i < XVECLEN (operands[2], 0); i++)
7603 rtx set = XVECEXP (operands[2], 0, i);
7605 emit_move_insn (SET_DEST (set), SET_SRC (set));
7608 /* The optimizer does not know that the call sets the function value
7609 registers we stored in the result block. We avoid problems by
7610 claiming that all hard registers are used and clobbered at this
7612 emit_insn (gen_blockage ());
7618 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7619 ;; all of memory. This blocks insns from being moved across this point.
7621 (define_insn "blockage"
7622 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7625 [(set_attr "length" "0")
7626 (set_attr "type" "block")]
7629 (define_expand "casesi"
7630 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
7631 (match_operand:SI 1 "const_int_operand" "") ; lower bound
7632 (match_operand:SI 2 "const_int_operand" "") ; total range
7633 (match_operand:SI 3 "" "") ; table label
7634 (match_operand:SI 4 "" "")] ; Out of range label
7639 if (operands[1] != const0_rtx)
7641 reg = gen_reg_rtx (SImode);
7643 emit_insn (gen_addsi3 (reg, operands[0],
7644 GEN_INT (-INTVAL (operands[1]))));
7648 if (!const_ok_for_arm (INTVAL (operands[2])))
7649 operands[2] = force_reg (SImode, operands[2]);
7651 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7657 ;; The USE in this pattern is needed to tell flow analysis that this is
7658 ;; a CASESI insn. It has no other purpose.
7659 (define_insn "casesi_internal"
7660 [(parallel [(set (pc)
7662 (leu (match_operand:SI 0 "s_register_operand" "r")
7663 (match_operand:SI 1 "arm_rhs_operand" "rI"))
7664 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7665 (label_ref (match_operand 2 "" ""))))
7666 (label_ref (match_operand 3 "" ""))))
7667 (clobber (reg:CC CC_REGNUM))
7668 (use (label_ref (match_dup 2)))])]
7672 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
7673 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
7675 [(set_attr "conds" "clob")
7676 (set_attr "length" "12")]
7679 (define_expand "indirect_jump"
7681 (match_operand:SI 0 "s_register_operand" ""))]
7686 (define_insn "*arm_indirect_jump"
7688 (match_operand:SI 0 "s_register_operand" "r"))]
7690 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
7691 [(set_attr "predicable" "yes")]
7694 ;; Although not supported by the define_expand above,
7695 ;; cse/combine may generate this form.
7696 (define_insn "*load_indirect_jump"
7698 (match_operand:SI 0 "memory_operand" "m"))]
7700 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
7701 [(set_attr "type" "load1")
7702 (set_attr "pool_range" "4096")
7703 (set_attr "neg_pool_range" "4084")
7704 (set_attr "predicable" "yes")]
7707 (define_insn "*thumb_indirect_jump"
7709 (match_operand:SI 0 "register_operand" "l*r"))]
7712 [(set_attr "conds" "clob")
7713 (set_attr "length" "2")]
7724 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
7725 return \"mov\\tr8, r8\";
7727 [(set (attr "length")
7728 (if_then_else (eq_attr "is_thumb" "yes")
7734 ;; Patterns to allow combination of arithmetic, cond code and shifts
7736 (define_insn "*arith_shiftsi"
7737 [(set (match_operand:SI 0 "s_register_operand" "=r")
7738 (match_operator:SI 1 "shiftable_operator"
7739 [(match_operator:SI 3 "shift_operator"
7740 [(match_operand:SI 4 "s_register_operand" "r")
7741 (match_operand:SI 5 "reg_or_int_operand" "rI")])
7742 (match_operand:SI 2 "s_register_operand" "r")]))]
7744 "%i1%?\\t%0, %2, %4%S3"
7745 [(set_attr "predicable" "yes")
7746 (set_attr "shift" "4")
7747 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7748 (const_string "alu_shift")
7749 (const_string "alu_shift_reg")))]
7753 [(set (match_operand:SI 0 "s_register_operand" "")
7754 (match_operator:SI 1 "shiftable_operator"
7755 [(match_operator:SI 2 "shiftable_operator"
7756 [(match_operator:SI 3 "shift_operator"
7757 [(match_operand:SI 4 "s_register_operand" "")
7758 (match_operand:SI 5 "reg_or_int_operand" "")])
7759 (match_operand:SI 6 "s_register_operand" "")])
7760 (match_operand:SI 7 "arm_rhs_operand" "")]))
7761 (clobber (match_operand:SI 8 "s_register_operand" ""))]
7764 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7767 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
7770 (define_insn "*arith_shiftsi_compare0"
7771 [(set (reg:CC_NOOV CC_REGNUM)
7772 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7773 [(match_operator:SI 3 "shift_operator"
7774 [(match_operand:SI 4 "s_register_operand" "r")
7775 (match_operand:SI 5 "reg_or_int_operand" "rI")])
7776 (match_operand:SI 2 "s_register_operand" "r")])
7778 (set (match_operand:SI 0 "s_register_operand" "=r")
7779 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7782 "%i1%?s\\t%0, %2, %4%S3"
7783 [(set_attr "conds" "set")
7784 (set_attr "shift" "4")
7785 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7786 (const_string "alu_shift")
7787 (const_string "alu_shift_reg")))]
7790 (define_insn "*arith_shiftsi_compare0_scratch"
7791 [(set (reg:CC_NOOV CC_REGNUM)
7792 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7793 [(match_operator:SI 3 "shift_operator"
7794 [(match_operand:SI 4 "s_register_operand" "r")
7795 (match_operand:SI 5 "reg_or_int_operand" "rI")])
7796 (match_operand:SI 2 "s_register_operand" "r")])
7798 (clobber (match_scratch:SI 0 "=r"))]
7800 "%i1%?s\\t%0, %2, %4%S3"
7801 [(set_attr "conds" "set")
7802 (set_attr "shift" "4")
7803 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7804 (const_string "alu_shift")
7805 (const_string "alu_shift_reg")))]
7808 (define_insn "*sub_shiftsi"
7809 [(set (match_operand:SI 0 "s_register_operand" "=r")
7810 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7811 (match_operator:SI 2 "shift_operator"
7812 [(match_operand:SI 3 "s_register_operand" "r")
7813 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7815 "sub%?\\t%0, %1, %3%S2"
7816 [(set_attr "predicable" "yes")
7817 (set_attr "shift" "3")
7818 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7819 (const_string "alu_shift")
7820 (const_string "alu_shift_reg")))]
7823 (define_insn "*sub_shiftsi_compare0"
7824 [(set (reg:CC_NOOV CC_REGNUM)
7826 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7827 (match_operator:SI 2 "shift_operator"
7828 [(match_operand:SI 3 "s_register_operand" "r")
7829 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7831 (set (match_operand:SI 0 "s_register_operand" "=r")
7832 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7835 "sub%?s\\t%0, %1, %3%S2"
7836 [(set_attr "conds" "set")
7837 (set_attr "shift" "3")
7838 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7839 (const_string "alu_shift")
7840 (const_string "alu_shift_reg")))]
7843 (define_insn "*sub_shiftsi_compare0_scratch"
7844 [(set (reg:CC_NOOV CC_REGNUM)
7846 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7847 (match_operator:SI 2 "shift_operator"
7848 [(match_operand:SI 3 "s_register_operand" "r")
7849 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7851 (clobber (match_scratch:SI 0 "=r"))]
7853 "sub%?s\\t%0, %1, %3%S2"
7854 [(set_attr "conds" "set")
7855 (set_attr "shift" "3")
7856 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7857 (const_string "alu_shift")
7858 (const_string "alu_shift_reg")))]
7863 (define_insn "*and_scc"
7864 [(set (match_operand:SI 0 "s_register_operand" "=r")
7865 (and:SI (match_operator:SI 1 "arm_comparison_operator"
7866 [(match_operand 3 "cc_register" "") (const_int 0)])
7867 (match_operand:SI 2 "s_register_operand" "r")))]
7869 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7870 [(set_attr "conds" "use")
7871 (set_attr "length" "8")]
7874 (define_insn "*ior_scc"
7875 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7876 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
7877 [(match_operand 3 "cc_register" "") (const_int 0)])
7878 (match_operand:SI 1 "s_register_operand" "0,?r")))]
7882 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7883 [(set_attr "conds" "use")
7884 (set_attr "length" "4,8")]
7887 (define_insn "*compare_scc"
7888 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7889 (match_operator:SI 1 "arm_comparison_operator"
7890 [(match_operand:SI 2 "s_register_operand" "r,r")
7891 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7892 (clobber (reg:CC CC_REGNUM))]
7895 if (operands[3] == const0_rtx)
7897 if (GET_CODE (operands[1]) == LT)
7898 return \"mov\\t%0, %2, lsr #31\";
7900 if (GET_CODE (operands[1]) == GE)
7901 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7903 if (GET_CODE (operands[1]) == EQ)
7904 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
7907 if (GET_CODE (operands[1]) == NE)
7909 if (which_alternative == 1)
7910 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7911 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7913 if (which_alternative == 1)
7914 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7916 output_asm_insn (\"cmp\\t%2, %3\", operands);
7917 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7919 [(set_attr "conds" "clob")
7920 (set_attr "length" "12")]
7923 (define_insn "*cond_move"
7924 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7925 (if_then_else:SI (match_operator 3 "equality_operator"
7926 [(match_operator 4 "arm_comparison_operator"
7927 [(match_operand 5 "cc_register" "") (const_int 0)])
7929 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7930 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7933 if (GET_CODE (operands[3]) == NE)
7935 if (which_alternative != 1)
7936 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7937 if (which_alternative != 0)
7938 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7941 if (which_alternative != 0)
7942 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7943 if (which_alternative != 1)
7944 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7947 [(set_attr "conds" "use")
7948 (set_attr "length" "4,4,8")]
7951 (define_insn "*cond_arith"
7952 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7953 (match_operator:SI 5 "shiftable_operator"
7954 [(match_operator:SI 4 "arm_comparison_operator"
7955 [(match_operand:SI 2 "s_register_operand" "r,r")
7956 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7957 (match_operand:SI 1 "s_register_operand" "0,?r")]))
7958 (clobber (reg:CC CC_REGNUM))]
7961 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7962 return \"%i5\\t%0, %1, %2, lsr #31\";
7964 output_asm_insn (\"cmp\\t%2, %3\", operands);
7965 if (GET_CODE (operands[5]) == AND)
7966 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7967 else if (GET_CODE (operands[5]) == MINUS)
7968 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7969 else if (which_alternative != 0)
7970 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7971 return \"%i5%d4\\t%0, %1, #1\";
7973 [(set_attr "conds" "clob")
7974 (set_attr "length" "12")]
7977 (define_insn "*cond_sub"
7978 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7979 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7980 (match_operator:SI 4 "arm_comparison_operator"
7981 [(match_operand:SI 2 "s_register_operand" "r,r")
7982 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7983 (clobber (reg:CC CC_REGNUM))]
7986 output_asm_insn (\"cmp\\t%2, %3\", operands);
7987 if (which_alternative != 0)
7988 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7989 return \"sub%d4\\t%0, %1, #1\";
7991 [(set_attr "conds" "clob")
7992 (set_attr "length" "8,12")]
7995 (define_insn "*cmp_ite0"
7996 [(set (match_operand 6 "dominant_cc_register" "")
7999 (match_operator 4 "arm_comparison_operator"
8000 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8001 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8002 (match_operator:SI 5 "arm_comparison_operator"
8003 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8004 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8010 static const char * const opcodes[4][2] =
8012 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8013 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8014 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8015 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8016 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8017 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8018 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8019 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8022 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8024 return opcodes[which_alternative][swap];
8026 [(set_attr "conds" "set")
8027 (set_attr "length" "8")]
8030 (define_insn "*cmp_ite1"
8031 [(set (match_operand 6 "dominant_cc_register" "")
8034 (match_operator 4 "arm_comparison_operator"
8035 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8036 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8037 (match_operator:SI 5 "arm_comparison_operator"
8038 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8039 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8045 static const char * const opcodes[4][2] =
8047 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8048 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8049 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8050 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8051 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8052 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8053 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8054 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8057 comparison_dominates_p (GET_CODE (operands[5]),
8058 reverse_condition (GET_CODE (operands[4])));
8060 return opcodes[which_alternative][swap];
8062 [(set_attr "conds" "set")
8063 (set_attr "length" "8")]
8066 (define_insn "*cmp_and"
8067 [(set (match_operand 6 "dominant_cc_register" "")
8070 (match_operator 4 "arm_comparison_operator"
8071 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8072 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8073 (match_operator:SI 5 "arm_comparison_operator"
8074 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8075 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8080 static const char *const opcodes[4][2] =
8082 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8083 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8084 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8085 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8086 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8087 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8088 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8089 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8092 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8094 return opcodes[which_alternative][swap];
8096 [(set_attr "conds" "set")
8097 (set_attr "predicable" "no")
8098 (set_attr "length" "8")]
8101 (define_insn "*cmp_ior"
8102 [(set (match_operand 6 "dominant_cc_register" "")
8105 (match_operator 4 "arm_comparison_operator"
8106 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8107 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8108 (match_operator:SI 5 "arm_comparison_operator"
8109 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8110 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8115 static const char *const opcodes[4][2] =
8117 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8118 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8119 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8120 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8121 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8122 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8123 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8124 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8127 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8129 return opcodes[which_alternative][swap];
8132 [(set_attr "conds" "set")
8133 (set_attr "length" "8")]
8136 (define_insn_and_split "*ior_scc_scc"
8137 [(set (match_operand:SI 0 "s_register_operand" "=r")
8138 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8139 [(match_operand:SI 1 "s_register_operand" "r")
8140 (match_operand:SI 2 "arm_add_operand" "rIL")])
8141 (match_operator:SI 6 "arm_comparison_operator"
8142 [(match_operand:SI 4 "s_register_operand" "r")
8143 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8144 (clobber (reg:CC CC_REGNUM))]
8146 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8149 "TARGET_ARM && reload_completed"
8153 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8154 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8156 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8158 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8161 [(set_attr "conds" "clob")
8162 (set_attr "length" "16")])
8164 ; If the above pattern is followed by a CMP insn, then the compare is
8165 ; redundant, since we can rework the conditional instruction that follows.
8166 (define_insn_and_split "*ior_scc_scc_cmp"
8167 [(set (match_operand 0 "dominant_cc_register" "")
8168 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8169 [(match_operand:SI 1 "s_register_operand" "r")
8170 (match_operand:SI 2 "arm_add_operand" "rIL")])
8171 (match_operator:SI 6 "arm_comparison_operator"
8172 [(match_operand:SI 4 "s_register_operand" "r")
8173 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8175 (set (match_operand:SI 7 "s_register_operand" "=r")
8176 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8177 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8180 "TARGET_ARM && reload_completed"
8184 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8185 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8187 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8189 [(set_attr "conds" "set")
8190 (set_attr "length" "16")])
8192 (define_insn_and_split "*and_scc_scc"
8193 [(set (match_operand:SI 0 "s_register_operand" "=r")
8194 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8195 [(match_operand:SI 1 "s_register_operand" "r")
8196 (match_operand:SI 2 "arm_add_operand" "rIL")])
8197 (match_operator:SI 6 "arm_comparison_operator"
8198 [(match_operand:SI 4 "s_register_operand" "r")
8199 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8200 (clobber (reg:CC CC_REGNUM))]
8202 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8205 "TARGET_ARM && reload_completed
8206 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8211 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8212 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8214 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8216 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8219 [(set_attr "conds" "clob")
8220 (set_attr "length" "16")])
8222 ; If the above pattern is followed by a CMP insn, then the compare is
8223 ; redundant, since we can rework the conditional instruction that follows.
8224 (define_insn_and_split "*and_scc_scc_cmp"
8225 [(set (match_operand 0 "dominant_cc_register" "")
8226 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8227 [(match_operand:SI 1 "s_register_operand" "r")
8228 (match_operand:SI 2 "arm_add_operand" "rIL")])
8229 (match_operator:SI 6 "arm_comparison_operator"
8230 [(match_operand:SI 4 "s_register_operand" "r")
8231 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8233 (set (match_operand:SI 7 "s_register_operand" "=r")
8234 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8235 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8238 "TARGET_ARM && reload_completed"
8242 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8243 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8245 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8247 [(set_attr "conds" "set")
8248 (set_attr "length" "16")])
8250 ;; If there is no dominance in the comparison, then we can still save an
8251 ;; instruction in the AND case, since we can know that the second compare
8252 ;; need only zero the value if false (if true, then the value is already
8254 (define_insn_and_split "*and_scc_scc_nodom"
8255 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8256 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8257 [(match_operand:SI 1 "s_register_operand" "r,r,0")
8258 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8259 (match_operator:SI 6 "arm_comparison_operator"
8260 [(match_operand:SI 4 "s_register_operand" "r,r,r")
8261 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8262 (clobber (reg:CC CC_REGNUM))]
8264 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8267 "TARGET_ARM && reload_completed"
8268 [(parallel [(set (match_dup 0)
8269 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8270 (clobber (reg:CC CC_REGNUM))])
8271 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8273 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8276 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8277 operands[4], operands[5]),
8279 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8281 [(set_attr "conds" "clob")
8282 (set_attr "length" "20")])
8285 [(set (reg:CC_NOOV CC_REGNUM)
8286 (compare:CC_NOOV (ior:SI
8287 (and:SI (match_operand:SI 0 "s_register_operand" "")
8289 (match_operator:SI 1 "comparison_operator"
8290 [(match_operand:SI 2 "s_register_operand" "")
8291 (match_operand:SI 3 "arm_add_operand" "")]))
8293 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8296 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8298 (set (reg:CC_NOOV CC_REGNUM)
8299 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8304 [(set (reg:CC_NOOV CC_REGNUM)
8305 (compare:CC_NOOV (ior:SI
8306 (match_operator:SI 1 "comparison_operator"
8307 [(match_operand:SI 2 "s_register_operand" "")
8308 (match_operand:SI 3 "arm_add_operand" "")])
8309 (and:SI (match_operand:SI 0 "s_register_operand" "")
8312 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8315 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8317 (set (reg:CC_NOOV CC_REGNUM)
8318 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8322 (define_insn "*negscc"
8323 [(set (match_operand:SI 0 "s_register_operand" "=r")
8324 (neg:SI (match_operator 3 "arm_comparison_operator"
8325 [(match_operand:SI 1 "s_register_operand" "r")
8326 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8327 (clobber (reg:CC CC_REGNUM))]
8330 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8331 return \"mov\\t%0, %1, asr #31\";
8333 if (GET_CODE (operands[3]) == NE)
8334 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8336 if (GET_CODE (operands[3]) == GT)
8337 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8339 output_asm_insn (\"cmp\\t%1, %2\", operands);
8340 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8341 return \"mvn%d3\\t%0, #0\";
8343 [(set_attr "conds" "clob")
8344 (set_attr "length" "12")]
8347 (define_insn "movcond"
8348 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8350 (match_operator 5 "arm_comparison_operator"
8351 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8352 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8353 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8354 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8355 (clobber (reg:CC CC_REGNUM))]
8358 if (GET_CODE (operands[5]) == LT
8359 && (operands[4] == const0_rtx))
8361 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8363 if (operands[2] == const0_rtx)
8364 return \"and\\t%0, %1, %3, asr #31\";
8365 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8367 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8369 if (operands[1] == const0_rtx)
8370 return \"bic\\t%0, %2, %3, asr #31\";
8371 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8373 /* The only case that falls through to here is when both ops 1 & 2
8377 if (GET_CODE (operands[5]) == GE
8378 && (operands[4] == const0_rtx))
8380 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8382 if (operands[2] == const0_rtx)
8383 return \"bic\\t%0, %1, %3, asr #31\";
8384 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8386 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8388 if (operands[1] == const0_rtx)
8389 return \"and\\t%0, %2, %3, asr #31\";
8390 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8392 /* The only case that falls through to here is when both ops 1 & 2
8395 if (GET_CODE (operands[4]) == CONST_INT
8396 && !const_ok_for_arm (INTVAL (operands[4])))
8397 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8399 output_asm_insn (\"cmp\\t%3, %4\", operands);
8400 if (which_alternative != 0)
8401 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8402 if (which_alternative != 1)
8403 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8406 [(set_attr "conds" "clob")
8407 (set_attr "length" "8,8,12")]
8410 (define_insn "*ifcompare_plus_move"
8411 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8412 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8413 [(match_operand:SI 4 "s_register_operand" "r,r")
8414 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8416 (match_operand:SI 2 "s_register_operand" "r,r")
8417 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8418 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8419 (clobber (reg:CC CC_REGNUM))]
8422 [(set_attr "conds" "clob")
8423 (set_attr "length" "8,12")]
8426 (define_insn "*if_plus_move"
8427 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8429 (match_operator 4 "arm_comparison_operator"
8430 [(match_operand 5 "cc_register" "") (const_int 0)])
8432 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8433 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8434 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8438 sub%d4\\t%0, %2, #%n3
8439 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8440 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8441 [(set_attr "conds" "use")
8442 (set_attr "length" "4,4,8,8")
8443 (set_attr "type" "*,*,*,*")]
8446 (define_insn "*ifcompare_move_plus"
8447 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8448 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8449 [(match_operand:SI 4 "s_register_operand" "r,r")
8450 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8451 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8453 (match_operand:SI 2 "s_register_operand" "r,r")
8454 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8455 (clobber (reg:CC CC_REGNUM))]
8458 [(set_attr "conds" "clob")
8459 (set_attr "length" "8,12")]
8462 (define_insn "*if_move_plus"
8463 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8465 (match_operator 4 "arm_comparison_operator"
8466 [(match_operand 5 "cc_register" "") (const_int 0)])
8467 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8469 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8470 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8474 sub%D4\\t%0, %2, #%n3
8475 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8476 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8477 [(set_attr "conds" "use")
8478 (set_attr "length" "4,4,8,8")
8479 (set_attr "type" "*,*,*,*")]
8482 (define_insn "*ifcompare_arith_arith"
8483 [(set (match_operand:SI 0 "s_register_operand" "=r")
8484 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8485 [(match_operand:SI 5 "s_register_operand" "r")
8486 (match_operand:SI 6 "arm_add_operand" "rIL")])
8487 (match_operator:SI 8 "shiftable_operator"
8488 [(match_operand:SI 1 "s_register_operand" "r")
8489 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8490 (match_operator:SI 7 "shiftable_operator"
8491 [(match_operand:SI 3 "s_register_operand" "r")
8492 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8493 (clobber (reg:CC CC_REGNUM))]
8496 [(set_attr "conds" "clob")
8497 (set_attr "length" "12")]
8500 (define_insn "*if_arith_arith"
8501 [(set (match_operand:SI 0 "s_register_operand" "=r")
8502 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8503 [(match_operand 8 "cc_register" "") (const_int 0)])
8504 (match_operator:SI 6 "shiftable_operator"
8505 [(match_operand:SI 1 "s_register_operand" "r")
8506 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8507 (match_operator:SI 7 "shiftable_operator"
8508 [(match_operand:SI 3 "s_register_operand" "r")
8509 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8511 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8512 [(set_attr "conds" "use")
8513 (set_attr "length" "8")]
8516 (define_insn "*ifcompare_arith_move"
8517 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8518 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8519 [(match_operand:SI 2 "s_register_operand" "r,r")
8520 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8521 (match_operator:SI 7 "shiftable_operator"
8522 [(match_operand:SI 4 "s_register_operand" "r,r")
8523 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8524 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8525 (clobber (reg:CC CC_REGNUM))]
8528 /* If we have an operation where (op x 0) is the identity operation and
8529 the conditional operator is LT or GE and we are comparing against zero and
8530 everything is in registers then we can do this in two instructions. */
8531 if (operands[3] == const0_rtx
8532 && GET_CODE (operands[7]) != AND
8533 && GET_CODE (operands[5]) == REG
8534 && GET_CODE (operands[1]) == REG
8535 && REGNO (operands[1]) == REGNO (operands[4])
8536 && REGNO (operands[4]) != REGNO (operands[0]))
8538 if (GET_CODE (operands[6]) == LT)
8539 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8540 else if (GET_CODE (operands[6]) == GE)
8541 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8543 if (GET_CODE (operands[3]) == CONST_INT
8544 && !const_ok_for_arm (INTVAL (operands[3])))
8545 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8547 output_asm_insn (\"cmp\\t%2, %3\", operands);
8548 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8549 if (which_alternative != 0)
8550 return \"mov%D6\\t%0, %1\";
8553 [(set_attr "conds" "clob")
8554 (set_attr "length" "8,12")]
8557 (define_insn "*if_arith_move"
8558 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8559 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8560 [(match_operand 6 "cc_register" "") (const_int 0)])
8561 (match_operator:SI 5 "shiftable_operator"
8562 [(match_operand:SI 2 "s_register_operand" "r,r")
8563 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8564 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8568 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8569 [(set_attr "conds" "use")
8570 (set_attr "length" "4,8")
8571 (set_attr "type" "*,*")]
8574 (define_insn "*ifcompare_move_arith"
8575 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8576 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8577 [(match_operand:SI 4 "s_register_operand" "r,r")
8578 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8579 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8580 (match_operator:SI 7 "shiftable_operator"
8581 [(match_operand:SI 2 "s_register_operand" "r,r")
8582 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8583 (clobber (reg:CC CC_REGNUM))]
8586 /* If we have an operation where (op x 0) is the identity operation and
8587 the conditional operator is LT or GE and we are comparing against zero and
8588 everything is in registers then we can do this in two instructions */
8589 if (operands[5] == const0_rtx
8590 && GET_CODE (operands[7]) != AND
8591 && GET_CODE (operands[3]) == REG
8592 && GET_CODE (operands[1]) == REG
8593 && REGNO (operands[1]) == REGNO (operands[2])
8594 && REGNO (operands[2]) != REGNO (operands[0]))
8596 if (GET_CODE (operands[6]) == GE)
8597 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8598 else if (GET_CODE (operands[6]) == LT)
8599 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8602 if (GET_CODE (operands[5]) == CONST_INT
8603 && !const_ok_for_arm (INTVAL (operands[5])))
8604 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8606 output_asm_insn (\"cmp\\t%4, %5\", operands);
8608 if (which_alternative != 0)
8609 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8610 return \"%I7%D6\\t%0, %2, %3\";
8612 [(set_attr "conds" "clob")
8613 (set_attr "length" "8,12")]
8616 (define_insn "*if_move_arith"
8617 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8619 (match_operator 4 "arm_comparison_operator"
8620 [(match_operand 6 "cc_register" "") (const_int 0)])
8621 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8622 (match_operator:SI 5 "shiftable_operator"
8623 [(match_operand:SI 2 "s_register_operand" "r,r")
8624 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8628 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8629 [(set_attr "conds" "use")
8630 (set_attr "length" "4,8")
8631 (set_attr "type" "*,*")]
8634 (define_insn "*ifcompare_move_not"
8635 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8637 (match_operator 5 "arm_comparison_operator"
8638 [(match_operand:SI 3 "s_register_operand" "r,r")
8639 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8640 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8642 (match_operand:SI 2 "s_register_operand" "r,r"))))
8643 (clobber (reg:CC CC_REGNUM))]
8646 [(set_attr "conds" "clob")
8647 (set_attr "length" "8,12")]
8650 (define_insn "*if_move_not"
8651 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8653 (match_operator 4 "arm_comparison_operator"
8654 [(match_operand 3 "cc_register" "") (const_int 0)])
8655 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8656 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8660 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8661 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8662 [(set_attr "conds" "use")
8663 (set_attr "length" "4,8,8")]
8666 (define_insn "*ifcompare_not_move"
8667 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8669 (match_operator 5 "arm_comparison_operator"
8670 [(match_operand:SI 3 "s_register_operand" "r,r")
8671 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8673 (match_operand:SI 2 "s_register_operand" "r,r"))
8674 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8675 (clobber (reg:CC CC_REGNUM))]
8678 [(set_attr "conds" "clob")
8679 (set_attr "length" "8,12")]
8682 (define_insn "*if_not_move"
8683 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8685 (match_operator 4 "arm_comparison_operator"
8686 [(match_operand 3 "cc_register" "") (const_int 0)])
8687 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8688 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8692 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
8693 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8694 [(set_attr "conds" "use")
8695 (set_attr "length" "4,8,8")]
8698 (define_insn "*ifcompare_shift_move"
8699 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8701 (match_operator 6 "arm_comparison_operator"
8702 [(match_operand:SI 4 "s_register_operand" "r,r")
8703 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8704 (match_operator:SI 7 "shift_operator"
8705 [(match_operand:SI 2 "s_register_operand" "r,r")
8706 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
8707 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8708 (clobber (reg:CC CC_REGNUM))]
8711 [(set_attr "conds" "clob")
8712 (set_attr "length" "8,12")]
8715 (define_insn "*if_shift_move"
8716 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8718 (match_operator 5 "arm_comparison_operator"
8719 [(match_operand 6 "cc_register" "") (const_int 0)])
8720 (match_operator:SI 4 "shift_operator"
8721 [(match_operand:SI 2 "s_register_operand" "r,r,r")
8722 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
8723 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8727 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
8728 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8729 [(set_attr "conds" "use")
8730 (set_attr "shift" "2")
8731 (set_attr "length" "4,8,8")
8732 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8733 (const_string "alu_shift")
8734 (const_string "alu_shift_reg")))]
8737 (define_insn "*ifcompare_move_shift"
8738 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8740 (match_operator 6 "arm_comparison_operator"
8741 [(match_operand:SI 4 "s_register_operand" "r,r")
8742 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8743 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8744 (match_operator:SI 7 "shift_operator"
8745 [(match_operand:SI 2 "s_register_operand" "r,r")
8746 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
8747 (clobber (reg:CC CC_REGNUM))]
8750 [(set_attr "conds" "clob")
8751 (set_attr "length" "8,12")]
8754 (define_insn "*if_move_shift"
8755 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8757 (match_operator 5 "arm_comparison_operator"
8758 [(match_operand 6 "cc_register" "") (const_int 0)])
8759 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8760 (match_operator:SI 4 "shift_operator"
8761 [(match_operand:SI 2 "s_register_operand" "r,r,r")
8762 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
8766 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
8767 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8768 [(set_attr "conds" "use")
8769 (set_attr "shift" "2")
8770 (set_attr "length" "4,8,8")
8771 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8772 (const_string "alu_shift")
8773 (const_string "alu_shift_reg")))]
8776 (define_insn "*ifcompare_shift_shift"
8777 [(set (match_operand:SI 0 "s_register_operand" "=r")
8779 (match_operator 7 "arm_comparison_operator"
8780 [(match_operand:SI 5 "s_register_operand" "r")
8781 (match_operand:SI 6 "arm_add_operand" "rIL")])
8782 (match_operator:SI 8 "shift_operator"
8783 [(match_operand:SI 1 "s_register_operand" "r")
8784 (match_operand:SI 2 "arm_rhs_operand" "rM")])
8785 (match_operator:SI 9 "shift_operator"
8786 [(match_operand:SI 3 "s_register_operand" "r")
8787 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
8788 (clobber (reg:CC CC_REGNUM))]
8791 [(set_attr "conds" "clob")
8792 (set_attr "length" "12")]
8795 (define_insn "*if_shift_shift"
8796 [(set (match_operand:SI 0 "s_register_operand" "=r")
8798 (match_operator 5 "arm_comparison_operator"
8799 [(match_operand 8 "cc_register" "") (const_int 0)])
8800 (match_operator:SI 6 "shift_operator"
8801 [(match_operand:SI 1 "s_register_operand" "r")
8802 (match_operand:SI 2 "arm_rhs_operand" "rM")])
8803 (match_operator:SI 7 "shift_operator"
8804 [(match_operand:SI 3 "s_register_operand" "r")
8805 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
8807 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8808 [(set_attr "conds" "use")
8809 (set_attr "shift" "1")
8810 (set_attr "length" "8")
8811 (set (attr "type") (if_then_else
8812 (and (match_operand 2 "const_int_operand" "")
8813 (match_operand 4 "const_int_operand" ""))
8814 (const_string "alu_shift")
8815 (const_string "alu_shift_reg")))]
8818 (define_insn "*ifcompare_not_arith"
8819 [(set (match_operand:SI 0 "s_register_operand" "=r")
8821 (match_operator 6 "arm_comparison_operator"
8822 [(match_operand:SI 4 "s_register_operand" "r")
8823 (match_operand:SI 5 "arm_add_operand" "rIL")])
8824 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8825 (match_operator:SI 7 "shiftable_operator"
8826 [(match_operand:SI 2 "s_register_operand" "r")
8827 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
8828 (clobber (reg:CC CC_REGNUM))]
8831 [(set_attr "conds" "clob")
8832 (set_attr "length" "12")]
8835 (define_insn "*if_not_arith"
8836 [(set (match_operand:SI 0 "s_register_operand" "=r")
8838 (match_operator 5 "arm_comparison_operator"
8839 [(match_operand 4 "cc_register" "") (const_int 0)])
8840 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8841 (match_operator:SI 6 "shiftable_operator"
8842 [(match_operand:SI 2 "s_register_operand" "r")
8843 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
8845 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8846 [(set_attr "conds" "use")
8847 (set_attr "length" "8")]
8850 (define_insn "*ifcompare_arith_not"
8851 [(set (match_operand:SI 0 "s_register_operand" "=r")
8853 (match_operator 6 "arm_comparison_operator"
8854 [(match_operand:SI 4 "s_register_operand" "r")
8855 (match_operand:SI 5 "arm_add_operand" "rIL")])
8856 (match_operator:SI 7 "shiftable_operator"
8857 [(match_operand:SI 2 "s_register_operand" "r")
8858 (match_operand:SI 3 "arm_rhs_operand" "rI")])
8859 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
8860 (clobber (reg:CC CC_REGNUM))]
8863 [(set_attr "conds" "clob")
8864 (set_attr "length" "12")]
8867 (define_insn "*if_arith_not"
8868 [(set (match_operand:SI 0 "s_register_operand" "=r")
8870 (match_operator 5 "arm_comparison_operator"
8871 [(match_operand 4 "cc_register" "") (const_int 0)])
8872 (match_operator:SI 6 "shiftable_operator"
8873 [(match_operand:SI 2 "s_register_operand" "r")
8874 (match_operand:SI 3 "arm_rhs_operand" "rI")])
8875 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
8877 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8878 [(set_attr "conds" "use")
8879 (set_attr "length" "8")]
8882 (define_insn "*ifcompare_neg_move"
8883 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8885 (match_operator 5 "arm_comparison_operator"
8886 [(match_operand:SI 3 "s_register_operand" "r,r")
8887 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8888 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
8889 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8890 (clobber (reg:CC CC_REGNUM))]
8893 [(set_attr "conds" "clob")
8894 (set_attr "length" "8,12")]
8897 (define_insn "*if_neg_move"
8898 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8900 (match_operator 4 "arm_comparison_operator"
8901 [(match_operand 3 "cc_register" "") (const_int 0)])
8902 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8903 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8907 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
8908 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8909 [(set_attr "conds" "use")
8910 (set_attr "length" "4,8,8")]
8913 (define_insn "*ifcompare_move_neg"
8914 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8916 (match_operator 5 "arm_comparison_operator"
8917 [(match_operand:SI 3 "s_register_operand" "r,r")
8918 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8919 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8920 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
8921 (clobber (reg:CC CC_REGNUM))]
8924 [(set_attr "conds" "clob")
8925 (set_attr "length" "8,12")]
8928 (define_insn "*if_move_neg"
8929 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8931 (match_operator 4 "arm_comparison_operator"
8932 [(match_operand 3 "cc_register" "") (const_int 0)])
8933 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8934 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8938 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
8939 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
8940 [(set_attr "conds" "use")
8941 (set_attr "length" "4,8,8")]
8944 (define_insn "*arith_adjacentmem"
8945 [(set (match_operand:SI 0 "s_register_operand" "=r")
8946 (match_operator:SI 1 "shiftable_operator"
8947 [(match_operand:SI 2 "memory_operand" "m")
8948 (match_operand:SI 3 "memory_operand" "m")]))
8949 (clobber (match_scratch:SI 4 "=r"))]
8950 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
8955 int val1 = 0, val2 = 0;
8957 if (REGNO (operands[0]) > REGNO (operands[4]))
8959 ldm[1] = operands[4];
8960 ldm[2] = operands[0];
8964 ldm[1] = operands[0];
8965 ldm[2] = operands[4];
8967 if (GET_CODE (XEXP (operands[2], 0)) != REG)
8968 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
8969 if (GET_CODE (XEXP (operands[3], 0)) != REG)
8970 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
8971 arith[0] = operands[0];
8972 arith[3] = operands[1];
8986 ldm[0] = ops[0] = operands[4];
8987 ops[1] = XEXP (XEXP (operands[2], 0), 0);
8988 ops[2] = XEXP (XEXP (operands[2], 0), 1);
8989 output_add_immediate (ops);
8991 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8993 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8997 ldm[0] = XEXP (operands[3], 0);
8999 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9001 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9005 ldm[0] = XEXP (operands[2], 0);
9007 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9009 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9011 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9014 [(set_attr "length" "12")
9015 (set_attr "predicable" "yes")
9016 (set_attr "type" "load1")]
9019 ;; the arm can support extended pre-inc instructions
9021 ;; In all these cases, we use operands 0 and 1 for the register being
9022 ;; incremented because those are the operands that local-alloc will
9023 ;; tie and these are the pair most likely to be tieable (and the ones
9024 ;; that will benefit the most).
9026 ;; We reject the frame pointer if it occurs anywhere in these patterns since
9027 ;; elimination will cause too many headaches.
9029 (define_insn "*strqi_preinc"
9030 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9031 (match_operand:SI 2 "index_operand" "rJ")))
9032 (match_operand:QI 3 "s_register_operand" "r"))
9033 (set (match_operand:SI 0 "s_register_operand" "=r")
9034 (plus:SI (match_dup 1) (match_dup 2)))]
9036 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9037 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9038 && (GET_CODE (operands[2]) != REG
9039 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9040 "str%?b\\t%3, [%0, %2]!"
9041 [(set_attr "type" "store1")
9042 (set_attr "predicable" "yes")]
9045 (define_insn "*strqi_predec"
9046 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9047 (match_operand:SI 2 "s_register_operand" "r")))
9048 (match_operand:QI 3 "s_register_operand" "r"))
9049 (set (match_operand:SI 0 "s_register_operand" "=r")
9050 (minus:SI (match_dup 1) (match_dup 2)))]
9052 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9053 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9054 && (GET_CODE (operands[2]) != REG
9055 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9056 "str%?b\\t%3, [%0, -%2]!"
9057 [(set_attr "type" "store1")
9058 (set_attr "predicable" "yes")]
9061 (define_insn "*loadqi_preinc"
9062 [(set (match_operand:QI 3 "s_register_operand" "=r")
9063 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9064 (match_operand:SI 2 "index_operand" "rJ"))))
9065 (set (match_operand:SI 0 "s_register_operand" "=r")
9066 (plus:SI (match_dup 1) (match_dup 2)))]
9068 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9069 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9070 && (GET_CODE (operands[2]) != REG
9071 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9072 "ldr%?b\\t%3, [%0, %2]!"
9073 [(set_attr "type" "load_byte")
9074 (set_attr "predicable" "yes")]
9077 (define_insn "*loadqi_predec"
9078 [(set (match_operand:QI 3 "s_register_operand" "=r")
9079 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9080 (match_operand:SI 2 "s_register_operand" "r"))))
9081 (set (match_operand:SI 0 "s_register_operand" "=r")
9082 (minus:SI (match_dup 1) (match_dup 2)))]
9084 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9085 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9086 && (GET_CODE (operands[2]) != REG
9087 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9088 "ldr%?b\\t%3, [%0, -%2]!"
9089 [(set_attr "type" "load_byte")
9090 (set_attr "predicable" "yes")]
9093 (define_insn "*loadqisi_preinc"
9094 [(set (match_operand:SI 3 "s_register_operand" "=r")
9096 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9097 (match_operand:SI 2 "index_operand" "rJ")))))
9098 (set (match_operand:SI 0 "s_register_operand" "=r")
9099 (plus:SI (match_dup 1) (match_dup 2)))]
9101 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9102 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9103 && (GET_CODE (operands[2]) != REG
9104 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9105 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
9106 [(set_attr "type" "load_byte")
9107 (set_attr "predicable" "yes")]
9110 (define_insn "*loadqisi_predec"
9111 [(set (match_operand:SI 3 "s_register_operand" "=r")
9113 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9114 (match_operand:SI 2 "s_register_operand" "r")))))
9115 (set (match_operand:SI 0 "s_register_operand" "=r")
9116 (minus:SI (match_dup 1) (match_dup 2)))]
9118 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9119 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9120 && (GET_CODE (operands[2]) != REG
9121 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9122 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
9123 [(set_attr "type" "load_byte")
9124 (set_attr "predicable" "yes")]
9127 (define_insn "*strsi_preinc"
9128 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9129 (match_operand:SI 2 "index_operand" "rJ")))
9130 (match_operand:SI 3 "s_register_operand" "r"))
9131 (set (match_operand:SI 0 "s_register_operand" "=r")
9132 (plus:SI (match_dup 1) (match_dup 2)))]
9134 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9135 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9136 && (GET_CODE (operands[2]) != REG
9137 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9138 "str%?\\t%3, [%0, %2]!"
9139 [(set_attr "type" "store1")
9140 (set_attr "predicable" "yes")]
9143 (define_insn "*strsi_predec"
9144 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9145 (match_operand:SI 2 "s_register_operand" "r")))
9146 (match_operand:SI 3 "s_register_operand" "r"))
9147 (set (match_operand:SI 0 "s_register_operand" "=r")
9148 (minus:SI (match_dup 1) (match_dup 2)))]
9150 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9151 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9152 && (GET_CODE (operands[2]) != REG
9153 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9154 "str%?\\t%3, [%0, -%2]!"
9155 [(set_attr "type" "store1")
9156 (set_attr "predicable" "yes")]
9159 (define_insn "*loadsi_preinc"
9160 [(set (match_operand:SI 3 "s_register_operand" "=r")
9161 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9162 (match_operand:SI 2 "index_operand" "rJ"))))
9163 (set (match_operand:SI 0 "s_register_operand" "=r")
9164 (plus:SI (match_dup 1) (match_dup 2)))]
9166 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9167 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9168 && (GET_CODE (operands[2]) != REG
9169 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9170 "ldr%?\\t%3, [%0, %2]!"
9171 [(set_attr "type" "load1")
9172 (set_attr "predicable" "yes")]
9175 (define_insn "*loadsi_predec"
9176 [(set (match_operand:SI 3 "s_register_operand" "=r")
9177 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9178 (match_operand:SI 2 "s_register_operand" "r"))))
9179 (set (match_operand:SI 0 "s_register_operand" "=r")
9180 (minus:SI (match_dup 1) (match_dup 2)))]
9182 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9183 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9184 && (GET_CODE (operands[2]) != REG
9185 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9186 "ldr%?\\t%3, [%0, -%2]!"
9187 [(set_attr "type" "load1")
9188 (set_attr "predicable" "yes")]
9191 (define_insn "*strqi_shiftpreinc"
9192 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9193 [(match_operand:SI 3 "s_register_operand" "r")
9194 (match_operand:SI 4 "const_shift_operand" "n")])
9195 (match_operand:SI 1 "s_register_operand" "0")))
9196 (match_operand:QI 5 "s_register_operand" "r"))
9197 (set (match_operand:SI 0 "s_register_operand" "=r")
9198 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9201 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9202 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9203 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9204 "str%?b\\t%5, [%0, %3%S2]!"
9205 [(set_attr "type" "store1")
9206 (set_attr "predicable" "yes")]
9209 (define_insn "*strqi_shiftpredec"
9210 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9211 (match_operator:SI 2 "shift_operator"
9212 [(match_operand:SI 3 "s_register_operand" "r")
9213 (match_operand:SI 4 "const_shift_operand" "n")])))
9214 (match_operand:QI 5 "s_register_operand" "r"))
9215 (set (match_operand:SI 0 "s_register_operand" "=r")
9216 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9219 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9220 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9221 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9222 "str%?b\\t%5, [%0, -%3%S2]!"
9223 [(set_attr "type" "store1")
9224 (set_attr "predicable" "yes")]
9227 (define_insn "*loadqi_shiftpreinc"
9228 [(set (match_operand:QI 5 "s_register_operand" "=r")
9229 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9230 [(match_operand:SI 3 "s_register_operand" "r")
9231 (match_operand:SI 4 "const_shift_operand" "n")])
9232 (match_operand:SI 1 "s_register_operand" "0"))))
9233 (set (match_operand:SI 0 "s_register_operand" "=r")
9234 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9237 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9238 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9239 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9240 "ldr%?b\\t%5, [%0, %3%S2]!"
9241 [(set_attr "type" "load_byte")
9242 (set_attr "predicable" "yes")]
9245 (define_insn "*loadqi_shiftpredec"
9246 [(set (match_operand:QI 5 "s_register_operand" "=r")
9247 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9248 (match_operator:SI 2 "shift_operator"
9249 [(match_operand:SI 3 "s_register_operand" "r")
9250 (match_operand:SI 4 "const_shift_operand" "n")]))))
9251 (set (match_operand:SI 0 "s_register_operand" "=r")
9252 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9255 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9256 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9257 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9258 "ldr%?b\\t%5, [%0, -%3%S2]!"
9259 [(set_attr "type" "load_byte")
9260 (set_attr "predicable" "yes")]
9263 (define_insn "*strsi_shiftpreinc"
9264 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9265 [(match_operand:SI 3 "s_register_operand" "r")
9266 (match_operand:SI 4 "const_shift_operand" "n")])
9267 (match_operand:SI 1 "s_register_operand" "0")))
9268 (match_operand:SI 5 "s_register_operand" "r"))
9269 (set (match_operand:SI 0 "s_register_operand" "=r")
9270 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9273 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9274 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9275 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9276 "str%?\\t%5, [%0, %3%S2]!"
9277 [(set_attr "type" "store1")
9278 (set_attr "predicable" "yes")]
9281 (define_insn "*strsi_shiftpredec"
9282 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9283 (match_operator:SI 2 "shift_operator"
9284 [(match_operand:SI 3 "s_register_operand" "r")
9285 (match_operand:SI 4 "const_shift_operand" "n")])))
9286 (match_operand:SI 5 "s_register_operand" "r"))
9287 (set (match_operand:SI 0 "s_register_operand" "=r")
9288 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9291 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9292 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9293 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9294 "str%?\\t%5, [%0, -%3%S2]!"
9295 [(set_attr "type" "store1")
9296 (set_attr "predicable" "yes")]
9299 (define_insn "*loadsi_shiftpreinc"
9300 [(set (match_operand:SI 5 "s_register_operand" "=r")
9301 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9302 [(match_operand:SI 3 "s_register_operand" "r")
9303 (match_operand:SI 4 "const_shift_operand" "n")])
9304 (match_operand:SI 1 "s_register_operand" "0"))))
9305 (set (match_operand:SI 0 "s_register_operand" "=r")
9306 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9309 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9310 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9311 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9312 "ldr%?\\t%5, [%0, %3%S2]!"
9313 [(set_attr "type" "load1")
9314 (set_attr "predicable" "yes")]
9317 (define_insn "*loadsi_shiftpredec"
9318 [(set (match_operand:SI 5 "s_register_operand" "=r")
9319 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9320 (match_operator:SI 2 "shift_operator"
9321 [(match_operand:SI 3 "s_register_operand" "r")
9322 (match_operand:SI 4 "const_shift_operand" "n")]))))
9323 (set (match_operand:SI 0 "s_register_operand" "=r")
9324 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9327 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9328 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9329 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9330 "ldr%?\\t%5, [%0, -%3%S2]!"
9331 [(set_attr "type" "load1")
9332 (set_attr "predicable" "yes")])
9334 ; It can also support extended post-inc expressions, but combine doesn't
9336 ; It doesn't seem worth adding peepholes for anything but the most common
9337 ; cases since, unlike combine, the increment must immediately follow the load
9338 ; for this pattern to match.
9339 ; We must watch to see that the source/destination register isn't also the
9340 ; same as the base address register, and that if the index is a register,
9341 ; that it is not the same as the base address register. In such cases the
9342 ; instruction that we would generate would have UNPREDICTABLE behavior so
9346 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9347 (match_operand:QI 2 "s_register_operand" "r"))
9349 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9351 && (REGNO (operands[2]) != REGNO (operands[0]))
9352 && (GET_CODE (operands[1]) != REG
9353 || (REGNO (operands[1]) != REGNO (operands[0])))"
9354 "str%?b\\t%2, [%0], %1"
9358 [(set (match_operand:QI 0 "s_register_operand" "=r")
9359 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9361 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9363 && REGNO (operands[0]) != REGNO(operands[1])
9364 && (GET_CODE (operands[2]) != REG
9365 || REGNO(operands[0]) != REGNO (operands[2]))"
9366 "ldr%?b\\t%0, [%1], %2"
9370 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9371 (match_operand:SI 2 "s_register_operand" "r"))
9373 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9375 && (REGNO (operands[2]) != REGNO (operands[0]))
9376 && (GET_CODE (operands[1]) != REG
9377 || (REGNO (operands[1]) != REGNO (operands[0])))"
9378 "str%?\\t%2, [%0], %1"
9382 [(set (match_operand:SI 0 "s_register_operand" "=r")
9383 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9385 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9387 && REGNO (operands[0]) != REGNO(operands[1])
9388 && (GET_CODE (operands[2]) != REG
9389 || REGNO(operands[0]) != REGNO (operands[2]))"
9390 "ldr%?\\t%0, [%1], %2"
9394 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9395 (match_operand:SI 1 "index_operand" "rJ")))
9396 (match_operand:QI 2 "s_register_operand" "r"))
9397 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9399 && (REGNO (operands[2]) != REGNO (operands[0]))
9400 && (GET_CODE (operands[1]) != REG
9401 || (REGNO (operands[1]) != REGNO (operands[0])))"
9402 "str%?b\\t%2, [%0, %1]!"
9406 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9407 [(match_operand:SI 0 "s_register_operand" "r")
9408 (match_operand:SI 1 "const_int_operand" "n")])
9409 (match_operand:SI 2 "s_register_operand" "+r")))
9410 (match_operand:QI 3 "s_register_operand" "r"))
9411 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9414 && (REGNO (operands[3]) != REGNO (operands[2]))
9415 && (REGNO (operands[0]) != REGNO (operands[2]))"
9416 "str%?b\\t%3, [%2, %0%S4]!"
9419 ; This pattern is never tried by combine, so do it as a peephole
9422 [(set (match_operand:SI 0 "arm_general_register_operand" "")
9423 (match_operand:SI 1 "arm_general_register_operand" ""))
9424 (set (reg:CC CC_REGNUM)
9425 (compare:CC (match_dup 1) (const_int 0)))]
9427 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9428 (set (match_dup 0) (match_dup 1))])]
9432 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9433 ; reversed, check that the memory references aren't volatile.
9436 [(set (match_operand:SI 0 "s_register_operand" "=r")
9437 (match_operand:SI 4 "memory_operand" "m"))
9438 (set (match_operand:SI 1 "s_register_operand" "=r")
9439 (match_operand:SI 5 "memory_operand" "m"))
9440 (set (match_operand:SI 2 "s_register_operand" "=r")
9441 (match_operand:SI 6 "memory_operand" "m"))
9442 (set (match_operand:SI 3 "s_register_operand" "=r")
9443 (match_operand:SI 7 "memory_operand" "m"))]
9444 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9446 return emit_ldm_seq (operands, 4);
9451 [(set (match_operand:SI 0 "s_register_operand" "=r")
9452 (match_operand:SI 3 "memory_operand" "m"))
9453 (set (match_operand:SI 1 "s_register_operand" "=r")
9454 (match_operand:SI 4 "memory_operand" "m"))
9455 (set (match_operand:SI 2 "s_register_operand" "=r")
9456 (match_operand:SI 5 "memory_operand" "m"))]
9457 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9459 return emit_ldm_seq (operands, 3);
9464 [(set (match_operand:SI 0 "s_register_operand" "=r")
9465 (match_operand:SI 2 "memory_operand" "m"))
9466 (set (match_operand:SI 1 "s_register_operand" "=r")
9467 (match_operand:SI 3 "memory_operand" "m"))]
9468 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9470 return emit_ldm_seq (operands, 2);
9475 [(set (match_operand:SI 4 "memory_operand" "=m")
9476 (match_operand:SI 0 "s_register_operand" "r"))
9477 (set (match_operand:SI 5 "memory_operand" "=m")
9478 (match_operand:SI 1 "s_register_operand" "r"))
9479 (set (match_operand:SI 6 "memory_operand" "=m")
9480 (match_operand:SI 2 "s_register_operand" "r"))
9481 (set (match_operand:SI 7 "memory_operand" "=m")
9482 (match_operand:SI 3 "s_register_operand" "r"))]
9483 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9485 return emit_stm_seq (operands, 4);
9490 [(set (match_operand:SI 3 "memory_operand" "=m")
9491 (match_operand:SI 0 "s_register_operand" "r"))
9492 (set (match_operand:SI 4 "memory_operand" "=m")
9493 (match_operand:SI 1 "s_register_operand" "r"))
9494 (set (match_operand:SI 5 "memory_operand" "=m")
9495 (match_operand:SI 2 "s_register_operand" "r"))]
9496 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9498 return emit_stm_seq (operands, 3);
9503 [(set (match_operand:SI 2 "memory_operand" "=m")
9504 (match_operand:SI 0 "s_register_operand" "r"))
9505 (set (match_operand:SI 3 "memory_operand" "=m")
9506 (match_operand:SI 1 "s_register_operand" "r"))]
9507 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9509 return emit_stm_seq (operands, 2);
9514 [(set (match_operand:SI 0 "s_register_operand" "")
9515 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9517 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9518 [(match_operand:SI 3 "s_register_operand" "")
9519 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9520 (clobber (match_operand:SI 5 "s_register_operand" ""))]
9522 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9523 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9528 ;; This split can be used because CC_Z mode implies that the following
9529 ;; branch will be an equality, or an unsigned inequality, so the sign
9530 ;; extension is not needed.
9533 [(set (reg:CC_Z CC_REGNUM)
9535 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9537 (match_operand 1 "const_int_operand" "")))
9538 (clobber (match_scratch:SI 2 ""))]
9540 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9541 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9542 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9543 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9545 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9549 (define_expand "prologue"
9550 [(clobber (const_int 0))]
9553 arm_expand_prologue ();
9555 thumb_expand_prologue ();
9560 (define_expand "epilogue"
9561 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9565 thumb_expand_epilogue ();
9566 else if (USE_RETURN_INSN (FALSE))
9568 emit_jump_insn (gen_return ());
9571 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9573 gen_rtx_RETURN (VOIDmode)),
9579 ;; Note - although unspec_volatile's USE all hard registers,
9580 ;; USEs are ignored after relaod has completed. Thus we need
9581 ;; to add an unspec of the link register to ensure that flow
9582 ;; does not think that it is unused by the sibcall branch that
9583 ;; will replace the standard function epilogue.
9584 (define_insn "sibcall_epilogue"
9585 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9586 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9589 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9590 return output_return_instruction (const_true_rtx, FALSE, FALSE);
9591 return arm_output_epilogue (next_nonnote_insn (insn));
9593 ;; Length is absolute worst case
9594 [(set_attr "length" "44")
9595 (set_attr "type" "block")
9596 ;; We don't clobber the conditions, but the potential length of this
9597 ;; operation is sufficient to make conditionalizing the sequence
9598 ;; unlikely to be profitable.
9599 (set_attr "conds" "clob")]
9602 (define_insn "*epilogue_insns"
9603 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9607 return arm_output_epilogue (NULL);
9608 else /* TARGET_THUMB */
9609 return thumb_unexpanded_epilogue ();
9611 ; Length is absolute worst case
9612 [(set_attr "length" "44")
9613 (set_attr "type" "block")
9614 ;; We don't clobber the conditions, but the potential length of this
9615 ;; operation is sufficient to make conditionalizing the sequence
9616 ;; unlikely to be profitable.
9617 (set_attr "conds" "clob")]
9620 (define_expand "eh_epilogue"
9621 [(use (match_operand:SI 0 "register_operand" ""))
9622 (use (match_operand:SI 1 "register_operand" ""))
9623 (use (match_operand:SI 2 "register_operand" ""))]
9627 cfun->machine->eh_epilogue_sp_ofs = operands[1];
9628 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9630 rtx ra = gen_rtx_REG (Pmode, 2);
9632 emit_move_insn (ra, operands[2]);
9635 /* This is a hack -- we may have crystalized the function type too
9637 cfun->machine->func_type = 0;
9641 ;; This split is only used during output to reduce the number of patterns
9642 ;; that need assembler instructions adding to them. We allowed the setting
9643 ;; of the conditions to be implicit during rtl generation so that
9644 ;; the conditional compare patterns would work. However this conflicts to
9645 ;; some extent with the conditional data operations, so we have to split them
9649 [(set (match_operand:SI 0 "s_register_operand" "")
9650 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9651 [(match_operand 2 "" "") (match_operand 3 "" "")])
9653 (match_operand 4 "" "")))
9654 (clobber (reg:CC CC_REGNUM))]
9655 "TARGET_ARM && reload_completed"
9656 [(set (match_dup 5) (match_dup 6))
9657 (cond_exec (match_dup 7)
9658 (set (match_dup 0) (match_dup 4)))]
9661 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9662 operands[2], operands[3]);
9663 enum rtx_code rc = GET_CODE (operands[1]);
9665 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9666 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9667 if (mode == CCFPmode || mode == CCFPEmode)
9668 rc = reverse_condition_maybe_unordered (rc);
9670 rc = reverse_condition (rc);
9672 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9677 [(set (match_operand:SI 0 "s_register_operand" "")
9678 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9679 [(match_operand 2 "" "") (match_operand 3 "" "")])
9680 (match_operand 4 "" "")
9682 (clobber (reg:CC CC_REGNUM))]
9683 "TARGET_ARM && reload_completed"
9684 [(set (match_dup 5) (match_dup 6))
9685 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9686 (set (match_dup 0) (match_dup 4)))]
9689 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9690 operands[2], operands[3]);
9692 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9693 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9698 [(set (match_operand:SI 0 "s_register_operand" "")
9699 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9700 [(match_operand 2 "" "") (match_operand 3 "" "")])
9701 (match_operand 4 "" "")
9702 (match_operand 5 "" "")))
9703 (clobber (reg:CC CC_REGNUM))]
9704 "TARGET_ARM && reload_completed"
9705 [(set (match_dup 6) (match_dup 7))
9706 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9707 (set (match_dup 0) (match_dup 4)))
9708 (cond_exec (match_dup 8)
9709 (set (match_dup 0) (match_dup 5)))]
9712 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9713 operands[2], operands[3]);
9714 enum rtx_code rc = GET_CODE (operands[1]);
9716 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9717 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9718 if (mode == CCFPmode || mode == CCFPEmode)
9719 rc = reverse_condition_maybe_unordered (rc);
9721 rc = reverse_condition (rc);
9723 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9728 [(set (match_operand:SI 0 "s_register_operand" "")
9729 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9730 [(match_operand:SI 2 "s_register_operand" "")
9731 (match_operand:SI 3 "arm_add_operand" "")])
9732 (match_operand:SI 4 "arm_rhs_operand" "")
9734 (match_operand:SI 5 "s_register_operand" ""))))
9735 (clobber (reg:CC CC_REGNUM))]
9736 "TARGET_ARM && reload_completed"
9737 [(set (match_dup 6) (match_dup 7))
9738 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9739 (set (match_dup 0) (match_dup 4)))
9740 (cond_exec (match_dup 8)
9741 (set (match_dup 0) (not:SI (match_dup 5))))]
9744 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9745 operands[2], operands[3]);
9746 enum rtx_code rc = GET_CODE (operands[1]);
9748 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9749 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9750 if (mode == CCFPmode || mode == CCFPEmode)
9751 rc = reverse_condition_maybe_unordered (rc);
9753 rc = reverse_condition (rc);
9755 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9759 (define_insn "*cond_move_not"
9760 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9761 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9762 [(match_operand 3 "cc_register" "") (const_int 0)])
9763 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9765 (match_operand:SI 2 "s_register_operand" "r,r"))))]
9769 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9770 [(set_attr "conds" "use")
9771 (set_attr "length" "4,8")]
9774 ;; The next two patterns occur when an AND operation is followed by a
9775 ;; scc insn sequence
9777 (define_insn "*sign_extract_onebit"
9778 [(set (match_operand:SI 0 "s_register_operand" "=r")
9779 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9781 (match_operand:SI 2 "const_int_operand" "n")))
9782 (clobber (reg:CC CC_REGNUM))]
9785 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9786 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9787 return \"mvnne\\t%0, #0\";
9789 [(set_attr "conds" "clob")
9790 (set_attr "length" "8")]
9793 (define_insn "*not_signextract_onebit"
9794 [(set (match_operand:SI 0 "s_register_operand" "=r")
9796 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9798 (match_operand:SI 2 "const_int_operand" "n"))))
9799 (clobber (reg:CC CC_REGNUM))]
9802 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9803 output_asm_insn (\"tst\\t%1, %2\", operands);
9804 output_asm_insn (\"mvneq\\t%0, #0\", operands);
9805 return \"movne\\t%0, #0\";
9807 [(set_attr "conds" "clob")
9808 (set_attr "length" "12")]
9811 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
9812 ;; expressions. For simplicity, the first register is also in the unspec
9814 (define_insn "*push_multi"
9815 [(match_parallel 2 "multi_register_push"
9816 [(set (match_operand:BLK 0 "memory_operand" "=m")
9817 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9818 UNSPEC_PUSH_MULT))])]
9822 int num_saves = XVECLEN (operands[2], 0);
9824 /* For the StrongARM at least it is faster to
9825 use STR to store only a single register. */
9827 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9833 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9835 for (i = 1; i < num_saves; i++)
9837 strcat (pattern, \", %|\");
9839 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9842 strcat (pattern, \"}\");
9843 output_asm_insn (pattern, operands);
9848 [(set_attr "type" "store4")]
9851 (define_insn "stack_tie"
9852 [(set (mem:BLK (scratch))
9853 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9854 (match_operand:SI 1 "s_register_operand" "r")]
9858 [(set_attr "length" "0")]
9861 ;; Similarly for the floating point registers
9862 (define_insn "*push_fp_multi"
9863 [(match_parallel 2 "multi_register_push"
9864 [(set (match_operand:BLK 0 "memory_operand" "=m")
9865 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9866 UNSPEC_PUSH_MULT))])]
9867 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
9872 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9873 output_asm_insn (pattern, operands);
9876 [(set_attr "type" "f_store")]
9879 ;; Special patterns for dealing with the constant pool
9881 (define_insn "align_4"
9882 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9885 assemble_align (32);
9890 (define_insn "align_8"
9891 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
9894 assemble_align (64);
9899 (define_insn "consttable_end"
9900 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9903 making_const_table = FALSE;
9908 (define_insn "consttable_1"
9909 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9912 making_const_table = TRUE;
9913 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9917 [(set_attr "length" "4")]
9920 (define_insn "consttable_2"
9921 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9924 making_const_table = TRUE;
9925 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9929 [(set_attr "length" "4")]
9932 (define_insn "consttable_4"
9933 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9937 making_const_table = TRUE;
9938 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9943 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9944 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9948 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9953 [(set_attr "length" "4")]
9956 (define_insn "consttable_8"
9957 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9961 making_const_table = TRUE;
9962 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9967 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9968 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9972 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9977 [(set_attr "length" "8")]
9980 ;; Miscellaneous Thumb patterns
9982 (define_expand "tablejump"
9983 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
9984 (use (label_ref (match_operand 1 "" "")))])]
9989 /* Hopefully, CSE will eliminate this copy. */
9990 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
9991 rtx reg2 = gen_reg_rtx (SImode);
9993 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
9999 (define_insn "*thumb_tablejump"
10000 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10001 (use (label_ref (match_operand 1 "" "")))]
10004 [(set_attr "length" "2")]
10007 ;; V5 Instructions,
10009 (define_insn "clzsi2"
10010 [(set (match_operand:SI 0 "s_register_operand" "=r")
10011 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10012 "TARGET_ARM && arm_arch5"
10014 [(set_attr "predicable" "yes")])
10016 (define_expand "ffssi2"
10017 [(set (match_operand:SI 0 "s_register_operand" "")
10018 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10019 "TARGET_ARM && arm_arch5"
10024 t1 = gen_reg_rtx (SImode);
10025 t2 = gen_reg_rtx (SImode);
10026 t3 = gen_reg_rtx (SImode);
10028 emit_insn (gen_negsi2 (t1, operands[1]));
10029 emit_insn (gen_andsi3 (t2, operands[1], t1));
10030 emit_insn (gen_clzsi2 (t3, t2));
10031 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10036 (define_expand "ctzsi2"
10037 [(set (match_operand:SI 0 "s_register_operand" "")
10038 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10039 "TARGET_ARM && arm_arch5"
10044 t1 = gen_reg_rtx (SImode);
10045 t2 = gen_reg_rtx (SImode);
10046 t3 = gen_reg_rtx (SImode);
10048 emit_insn (gen_negsi2 (t1, operands[1]));
10049 emit_insn (gen_andsi3 (t2, operands[1], t1));
10050 emit_insn (gen_clzsi2 (t3, t2));
10051 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10056 ;; V5E instructions.
10058 (define_insn "prefetch"
10059 [(prefetch (match_operand:SI 0 "address_operand" "p")
10060 (match_operand:SI 1 "" "")
10061 (match_operand:SI 2 "" ""))]
10062 "TARGET_ARM && arm_arch5e"
10065 ;; General predication pattern
10068 [(match_operator 0 "arm_comparison_operator"
10069 [(match_operand 1 "cc_register" "")
10075 (define_insn "prologue_use"
10076 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10078 "%@ %0 needed for prologue"
10081 ;; Load the FPA co-processor patterns
10083 ;; Load the Maverick co-processor patterns
10084 (include "cirrus.md")
10085 ;; Load the Intel Wireless Multimedia Extension patterns
10086 (include "iwmmxt.md")
10087 ;; Load the VFP co-processor patterns