1 ;;- Machine description for ARM for GNU compiler
2 ;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;; 2001, 2002, 2003 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.
81 ;; UNSPEC_VOLATILE Usage:
84 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
86 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
87 ; instruction epilogue sequence that isn't expanded
88 ; into normal RTL. Used for both normal and sibcall
90 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
91 ; for inlined constants.
92 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
94 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
96 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
98 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
100 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
105 ;;---------------------------------------------------------------------------
108 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
109 ; generating ARM code. This is used to control the length of some insn
110 ; patterns that share the same RTL in both ARM and Thumb code.
111 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
113 ; PROG_MODE attribute is used to determine whether condition codes are
114 ; clobbered by a call insn: they are if in prog32 mode. This is controlled
115 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
116 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
118 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
119 ; scheduling decisions for the load unit and the multiplier.
120 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
122 ;; Operand number of an input operand that is shifted. Zero if the
123 ;; given instruction does not shift one of its input operands.
124 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_is_xscale")))
125 (define_attr "shift" "" (const_int 0))
127 ; Floating Point Unit. If we only have floating point emulation, then there
128 ; is no point in scheduling the floating point insns. (Well, for best
129 ; performance we should try and group them together).
130 (define_attr "fpu" "softfpa,fpa,fpe2,fpe3,maverick"
131 (const (symbol_ref "arm_fpu_attr")))
133 ; LENGTH of an instruction (in bytes)
134 (define_attr "length" "" (const_int 4))
136 ; POOL_RANGE is how far away from a constant pool entry that this insn
137 ; can be placed. If the distance is zero, then this insn will never
138 ; reference the pool.
139 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
140 ; before its address.
141 (define_attr "pool_range" "" (const_int 0))
142 (define_attr "neg_pool_range" "" (const_int 0))
144 ; An assembler sequence may clobber the condition codes without us knowing.
145 ; If such an insn references the pool, then we have no way of knowing how,
146 ; so use the most conservative value for pool_range.
147 (define_asm_attributes
148 [(set_attr "conds" "clob")
149 (set_attr "length" "4")
150 (set_attr "pool_range" "250")])
152 ; TYPE attribute is used to detect floating point instructions which, if
153 ; running on a co-processor can run in parallel with other, basic instructions
154 ; If write-buffer scheduling is enabled then it can also be used in the
155 ; scheduling of writes.
157 ; Classification of each insn
158 ; normal any data instruction that doesn't hit memory or fp regs
159 ; mult a multiply instruction
160 ; block blockage insn, this blocks all functional units
161 ; float a floating point arithmetic operation (subject to expansion)
162 ; fdivd DFmode floating point division
163 ; fdivs SFmode floating point division
164 ; fmul Floating point multiply
165 ; ffmul Fast floating point multiply
166 ; farith Floating point arithmetic (4 cycle)
167 ; ffarith Fast floating point arithmetic (2 cycle)
168 ; float_em a floating point arithmetic operation that is normally emulated
169 ; even on a machine with an fpa.
170 ; f_load a floating point load from memory
171 ; f_store a floating point store to memory
172 ; f_mem_r a transfer of a floating point register to a real reg via mem
173 ; r_mem_f the reverse of f_mem_r
174 ; f_2_r fast transfer float to arm (no memory needed)
175 ; r_2_f fast transfer arm to float
176 ; call a subroutine call
177 ; load any load from memory
178 ; store1 store 1 word to memory from arm registers
179 ; store2 store 2 words
180 ; store3 store 3 words
181 ; store4 store 4 words
182 ; Additions for Cirrus Maverick co-processor:
183 ; mav_farith Floating point arithmetic (4 cycle)
184 ; mav_dmult Double multiplies (7 cycle)
187 "normal,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,call,load,store1,store2,store3,store4,mav_farith,mav_dmult"
188 (const_string "normal"))
190 ; Load scheduling, set from the arm_ld_sched variable
191 ; initialized by arm_override_options()
192 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
194 ; condition codes: this one is used by final_prescan_insn to speed up
195 ; conditionalizing instructions. It saves having to scan the rtl to see if
196 ; it uses or alters the condition codes.
198 ; USE means that the condition codes are used by the insn in the process of
199 ; outputting code, this means (at present) that we can't use the insn in
202 ; SET means that the purpose of the insn is to set the condition codes in a
203 ; well defined manner.
205 ; CLOB means that the condition codes are altered in an undefined manner, if
206 ; they are altered at all
208 ; JUMP_CLOB is used when the condition cannot be represented by a single
209 ; instruction (UNEQ and LTGT). These cannot be predicated.
211 ; NOCOND means that the condition codes are neither altered nor affect the
212 ; output of this insn
214 (define_attr "conds" "use,set,clob,jump_clob,nocond"
215 (if_then_else (eq_attr "type" "call")
216 (if_then_else (eq_attr "prog_mode" "prog32")
217 (const_string "clob") (const_string "nocond"))
218 (const_string "nocond")))
220 ; Predicable means that the insn can be conditionally executed based on
221 ; an automatically added predicate (additional patterns are generated by
222 ; gen...). We default to 'no' because no Thumb patterns match this rule
223 ; and not all ARM patterns do.
224 (define_attr "predicable" "no,yes" (const_string "no"))
226 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
227 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
228 ; suffer blockages enough to warrent modelling this (and it can adversely
229 ; affect the schedule).
230 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
232 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
233 ; to stall the processor. Used with model_wbuf above.
234 (define_attr "write_conflict" "no,yes"
235 (if_then_else (eq_attr "type"
236 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
238 (const_string "no")))
240 ; Classify the insns into those that take one cycle and those that take more
241 ; than one on the main cpu execution unit.
242 (define_attr "core_cycles" "single,multi"
243 (if_then_else (eq_attr "type"
244 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
245 (const_string "single")
246 (const_string "multi")))
248 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
249 ;; distant label. Only applicable to Thumb code.
250 (define_attr "far_jump" "yes,no" (const_string "no"))
252 ;; (define_function_unit {name} {num-units} {n-users} {test}
253 ;; {ready-delay} {issue-delay} [{conflict-list}])
255 ;;--------------------------------------------------------------------
257 ;;--------------------------------------------------------------------
258 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
260 ; The write buffer on some of the arm6 processors is hard to model exactly.
261 ; There is room in the buffer for up to two addresses and up to eight words
262 ; of memory, but the two needn't be split evenly. When writing the two
263 ; addresses are fully pipelined. However, a read from memory that is not
264 ; currently in the cache will block until the writes have completed.
265 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
266 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
267 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
268 ; cycle to add as well.
270 (define_function_unit "write_buf" 1 2
271 (and (eq_attr "model_wbuf" "yes")
272 (eq_attr "type" "store1,r_mem_f")) 5 3)
273 (define_function_unit "write_buf" 1 2
274 (and (eq_attr "model_wbuf" "yes")
275 (eq_attr "type" "store2")) 7 4)
276 (define_function_unit "write_buf" 1 2
277 (and (eq_attr "model_wbuf" "yes")
278 (eq_attr "type" "store3")) 9 5)
279 (define_function_unit "write_buf" 1 2
280 (and (eq_attr "model_wbuf" "yes")
281 (eq_attr "type" "store4")) 11 6)
283 ;;--------------------------------------------------------------------
284 ;; Write blockage unit
285 ;;--------------------------------------------------------------------
286 ; The write_blockage unit models (partially), the fact that reads will stall
287 ; until the write buffer empties.
288 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
289 ; so we don't model them here
290 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
291 (eq_attr "type" "store1")) 5 5
292 [(eq_attr "write_conflict" "yes")])
293 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
294 (eq_attr "type" "store2")) 7 7
295 [(eq_attr "write_conflict" "yes")])
296 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
297 (eq_attr "type" "store3")) 9 9
298 [(eq_attr "write_conflict" "yes")])
299 (define_function_unit "write_blockage" 1 0
300 (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
301 [(eq_attr "write_conflict" "yes")])
302 (define_function_unit "write_blockage" 1 0
303 (and (eq_attr "model_wbuf" "yes")
304 (eq_attr "write_conflict" "yes")) 1 1)
306 ;;--------------------------------------------------------------------
308 ;;--------------------------------------------------------------------
309 ; Everything must spend at least one cycle in the core unit
310 (define_function_unit "core" 1 0 (eq_attr "core_cycles" "single") 1 1)
312 (define_function_unit "core" 1 0
313 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
315 (define_function_unit "core" 1 0
316 (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
318 ;; We do not need to conditionalize the define_function_unit immediately
319 ;; above. This one will be ignored for anything other than xscale
320 ;; compiles and for xscale compiles it provides a larger delay
321 ;; and the scheduler will DTRT.
322 ;; FIXME: this test needs to be revamped to not depend on this feature
325 (define_function_unit "core" 1 0
326 (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
327 (eq_attr "is_xscale" "yes"))
330 (define_function_unit "core" 1 0
331 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
333 (define_function_unit "core" 1 0
334 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
336 (define_function_unit "core" 1 0
337 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
339 (define_function_unit "core" 1 0
340 (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
342 (define_function_unit "core" 1 0
343 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
345 (define_function_unit "core" 1 0
346 (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
348 (define_function_unit "core" 1 0
349 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
350 (eq_attr "type" "mult")) 4 4)
352 (define_function_unit "core" 1 0
353 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
354 (eq_attr "type" "mult")) 3 2)
356 (define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
358 (define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
360 (define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
362 (define_function_unit "core" 1 0
363 (and (eq_attr "core_cycles" "multi")
364 (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
366 ;;---------------------------------------------------------------------------
371 ;; Note: For DImode insns, there is normally no reason why operands should
372 ;; not be in the same register, what we don't want is for something being
373 ;; written to partially overlap something that is an input.
374 ;; Cirrus 64bit additions should not be split because we have a native
375 ;; 64bit addition instructions.
377 (define_expand "adddi3"
379 [(set (match_operand:DI 0 "s_register_operand" "")
380 (plus:DI (match_operand:DI 1 "s_register_operand" "")
381 (match_operand:DI 2 "s_register_operand" "")))
382 (clobber (reg:CC CC_REGNUM))])]
387 if (!cirrus_fp_register (operands[0], DImode))
388 operands[0] = force_reg (DImode, operands[0]);
389 if (!cirrus_fp_register (operands[1], DImode))
390 operands[1] = force_reg (DImode, operands[1]);
391 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
397 if (GET_CODE (operands[1]) != REG)
398 operands[1] = force_reg (SImode, operands[1]);
399 if (GET_CODE (operands[2]) != REG)
400 operands[2] = force_reg (SImode, operands[2]);
405 (define_insn "*thumb_adddi3"
406 [(set (match_operand:DI 0 "register_operand" "=l")
407 (plus:DI (match_operand:DI 1 "register_operand" "%0")
408 (match_operand:DI 2 "register_operand" "l")))
409 (clobber (reg:CC CC_REGNUM))
412 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
413 [(set_attr "length" "4")]
416 (define_insn_and_split "*arm_adddi3"
417 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
418 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
419 (match_operand:DI 2 "s_register_operand" "r, 0")))
420 (clobber (reg:CC CC_REGNUM))]
421 "TARGET_ARM && !TARGET_CIRRUS"
423 "TARGET_ARM && reload_completed"
424 [(parallel [(set (reg:CC_C CC_REGNUM)
425 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
427 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
428 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
429 (plus:SI (match_dup 4) (match_dup 5))))]
432 operands[3] = gen_highpart (SImode, operands[0]);
433 operands[0] = gen_lowpart (SImode, operands[0]);
434 operands[4] = gen_highpart (SImode, operands[1]);
435 operands[1] = gen_lowpart (SImode, operands[1]);
436 operands[5] = gen_highpart (SImode, operands[2]);
437 operands[2] = gen_lowpart (SImode, operands[2]);
439 [(set_attr "conds" "clob")
440 (set_attr "length" "8")]
443 (define_insn_and_split "*adddi_sesidi_di"
444 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
445 (plus:DI (sign_extend:DI
446 (match_operand:SI 2 "s_register_operand" "r,r"))
447 (match_operand:DI 1 "s_register_operand" "r,0")))
448 (clobber (reg:CC CC_REGNUM))]
449 "TARGET_ARM && !TARGET_CIRRUS"
451 "TARGET_ARM && reload_completed"
452 [(parallel [(set (reg:CC_C CC_REGNUM)
453 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
455 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
456 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
457 (plus:SI (ashiftrt:SI (match_dup 2)
462 operands[3] = gen_highpart (SImode, operands[0]);
463 operands[0] = gen_lowpart (SImode, operands[0]);
464 operands[4] = gen_highpart (SImode, operands[1]);
465 operands[1] = gen_lowpart (SImode, operands[1]);
466 operands[2] = gen_lowpart (SImode, operands[2]);
468 [(set_attr "conds" "clob")
469 (set_attr "length" "8")]
472 (define_insn_and_split "*adddi_zesidi_di"
473 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
474 (plus:DI (zero_extend:DI
475 (match_operand:SI 2 "s_register_operand" "r,r"))
476 (match_operand:DI 1 "s_register_operand" "r,0")))
477 (clobber (reg:CC CC_REGNUM))]
478 "TARGET_ARM && !TARGET_CIRRUS"
480 "TARGET_ARM && reload_completed"
481 [(parallel [(set (reg:CC_C CC_REGNUM)
482 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
484 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
485 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
486 (plus:SI (match_dup 4) (const_int 0))))]
489 operands[3] = gen_highpart (SImode, operands[0]);
490 operands[0] = gen_lowpart (SImode, operands[0]);
491 operands[4] = gen_highpart (SImode, operands[1]);
492 operands[1] = gen_lowpart (SImode, operands[1]);
493 operands[2] = gen_lowpart (SImode, operands[2]);
495 [(set_attr "conds" "clob")
496 (set_attr "length" "8")]
499 (define_expand "addsi3"
500 [(set (match_operand:SI 0 "s_register_operand" "")
501 (plus:SI (match_operand:SI 1 "s_register_operand" "")
502 (match_operand:SI 2 "reg_or_int_operand" "")))]
505 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
507 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
509 (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
515 ; If there is a scratch available, this will be faster than synthesising the
518 [(match_scratch:SI 3 "r")
519 (set (match_operand:SI 0 "s_register_operand" "")
520 (plus:SI (match_operand:SI 1 "s_register_operand" "")
521 (match_operand:SI 2 "const_int_operand" "")))]
523 !(const_ok_for_arm (INTVAL (operands[2]))
524 || const_ok_for_arm (-INTVAL (operands[2])))
525 && const_ok_for_arm (~INTVAL (operands[2]))"
526 [(set (match_dup 3) (match_dup 2))
527 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
531 (define_insn_and_split "*arm_addsi3"
532 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
533 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
534 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
541 GET_CODE (operands[2]) == CONST_INT
542 && !(const_ok_for_arm (INTVAL (operands[2]))
543 || const_ok_for_arm (-INTVAL (operands[2])))"
544 [(clobber (const_int 0))]
546 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
550 [(set_attr "length" "4,4,16")
551 (set_attr "predicable" "yes")]
554 ;; Register group 'k' is a single register group containing only the stack
555 ;; register. Trying to reload it will always fail catastrophically,
556 ;; so never allow those alternatives to match if reloading is needed.
558 (define_insn "*thumb_addsi3"
559 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
560 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
561 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
564 static const char * const asms[] =
566 \"add\\t%0, %0, %2\",
567 \"sub\\t%0, %0, #%n2\",
568 \"add\\t%0, %1, %2\",
569 \"add\\t%0, %0, %2\",
570 \"add\\t%0, %0, %2\",
571 \"add\\t%0, %1, %2\",
574 if ((which_alternative == 2 || which_alternative == 6)
575 && GET_CODE (operands[2]) == CONST_INT
576 && INTVAL (operands[2]) < 0)
577 return \"sub\\t%0, %1, #%n2\";
578 return asms[which_alternative];
580 [(set_attr "length" "2")]
583 ;; Reloading and elimination of the frame pointer can
584 ;; sometimes cause this optimization to be missed.
586 [(set (match_operand:SI 0 "register_operand" "")
587 (match_operand:SI 1 "const_int_operand" ""))
589 (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
591 && REGNO (operands[2]) == STACK_POINTER_REGNUM
592 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
593 && (INTVAL (operands[1]) & 3) == 0"
594 [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
598 (define_insn "*addsi3_compare0"
599 [(set (reg:CC_NOOV CC_REGNUM)
601 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
602 (match_operand:SI 2 "arm_add_operand" "rI,L"))
604 (set (match_operand:SI 0 "s_register_operand" "=r,r")
605 (plus:SI (match_dup 1) (match_dup 2)))]
609 sub%?s\\t%0, %1, #%n2"
610 [(set_attr "conds" "set")]
613 (define_insn "*addsi3_compare0_scratch"
614 [(set (reg:CC_NOOV CC_REGNUM)
616 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
617 (match_operand:SI 1 "arm_add_operand" "rI,L"))
623 [(set_attr "conds" "set")]
626 ;; These patterns are the same ones as the two regular addsi3_compare0
627 ;; patterns, except we write them slightly different - the combiner
628 ;; tends to generate them this way.
629 (define_insn "*addsi3_compare0_for_combiner"
630 [(set (reg:CC CC_REGNUM)
632 (match_operand:SI 1 "s_register_operand" "r,r")
633 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
634 (set (match_operand:SI 0 "s_register_operand" "=r,r")
635 (plus:SI (match_dup 1) (match_dup 2)))]
639 sub%?s\\t%0, %1, #%n2"
640 [(set_attr "conds" "set")]
643 (define_insn "*addsi3_compare0_scratch_for_combiner"
644 [(set (reg:CC CC_REGNUM)
646 (match_operand:SI 0 "s_register_operand" "r,r")
647 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
652 [(set_attr "conds" "set")]
655 ;; The next four insns work because they compare the result with one of
656 ;; the operands, and we know that the use of the condition code is
657 ;; either GEU or LTU, so we can use the carry flag from the addition
658 ;; instead of doing the compare a second time.
659 (define_insn "*addsi3_compare_op1"
660 [(set (reg:CC_C CC_REGNUM)
662 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
663 (match_operand:SI 2 "arm_add_operand" "rI,L"))
665 (set (match_operand:SI 0 "s_register_operand" "=r,r")
666 (plus:SI (match_dup 1) (match_dup 2)))]
670 sub%?s\\t%0, %1, #%n2"
671 [(set_attr "conds" "set")]
674 (define_insn "*addsi3_compare_op2"
675 [(set (reg:CC_C CC_REGNUM)
677 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
678 (match_operand:SI 2 "arm_add_operand" "rI,L"))
680 (set (match_operand:SI 0 "s_register_operand" "=r,r")
681 (plus:SI (match_dup 1) (match_dup 2)))]
685 sub%?s\\t%0, %1, #%n2"
686 [(set_attr "conds" "set")]
689 (define_insn "*compare_addsi2_op0"
690 [(set (reg:CC_C CC_REGNUM)
692 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
693 (match_operand:SI 1 "arm_add_operand" "rI,L"))
699 [(set_attr "conds" "set")]
702 (define_insn "*compare_addsi2_op1"
703 [(set (reg:CC_C CC_REGNUM)
705 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
706 (match_operand:SI 1 "arm_add_operand" "rI,L"))
712 [(set_attr "conds" "set")]
715 (define_insn "*addsi3_carryin"
716 [(set (match_operand:SI 0 "s_register_operand" "=r")
717 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
718 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
719 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
722 [(set_attr "conds" "use")]
725 (define_insn "*addsi3_carryin_shift"
726 [(set (match_operand:SI 0 "s_register_operand" "")
727 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
729 (match_operator:SI 2 "shift_operator"
730 [(match_operand:SI 3 "s_register_operand" "")
731 (match_operand:SI 4 "reg_or_int_operand" "")])
732 (match_operand:SI 1 "s_register_operand" ""))))]
734 "adc%?\\t%0, %1, %3%S2"
735 [(set_attr "conds" "use")]
738 (define_insn "*addsi3_carryin_alt1"
739 [(set (match_operand:SI 0 "s_register_operand" "=r")
740 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
741 (match_operand:SI 2 "arm_rhs_operand" "rI"))
742 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
745 [(set_attr "conds" "use")]
748 (define_insn "*addsi3_carryin_alt2"
749 [(set (match_operand:SI 0 "s_register_operand" "=r")
750 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
751 (match_operand:SI 1 "s_register_operand" "r"))
752 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
755 [(set_attr "conds" "use")]
758 (define_insn "*addsi3_carryin_alt3"
759 [(set (match_operand:SI 0 "s_register_operand" "=r")
760 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
761 (match_operand:SI 2 "arm_rhs_operand" "rI"))
762 (match_operand:SI 1 "s_register_operand" "r")))]
765 [(set_attr "conds" "use")]
768 (define_insn "incscc"
769 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
770 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
771 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
772 (match_operand:SI 1 "s_register_operand" "0,?r")))]
776 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
777 [(set_attr "conds" "use")
778 (set_attr "length" "4,8")]
781 (define_expand "addsf3"
782 [(set (match_operand:SF 0 "s_register_operand" "")
783 (plus:SF (match_operand:SF 1 "s_register_operand" "")
784 (match_operand:SF 2 "fpa_add_operand" "")))]
785 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
788 && !cirrus_fp_register (operands[2], SFmode))
789 operands[2] = force_reg (SFmode, operands[2]);
792 (define_expand "adddf3"
793 [(set (match_operand:DF 0 "s_register_operand" "")
794 (plus:DF (match_operand:DF 1 "s_register_operand" "")
795 (match_operand:DF 2 "fpa_add_operand" "")))]
796 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
799 && !cirrus_fp_register (operands[2], DFmode))
800 operands[2] = force_reg (DFmode, operands[2]);
803 (define_expand "subdi3"
805 [(set (match_operand:DI 0 "s_register_operand" "")
806 (minus:DI (match_operand:DI 1 "s_register_operand" "")
807 (match_operand:DI 2 "s_register_operand" "")))
808 (clobber (reg:CC CC_REGNUM))])]
813 && cirrus_fp_register (operands[0], DImode)
814 && cirrus_fp_register (operands[1], DImode))
816 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
822 if (GET_CODE (operands[1]) != REG)
823 operands[1] = force_reg (SImode, operands[1]);
824 if (GET_CODE (operands[2]) != REG)
825 operands[2] = force_reg (SImode, operands[2]);
830 (define_insn "*arm_subdi3"
831 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
832 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
833 (match_operand:DI 2 "s_register_operand" "r,0,0")))
834 (clobber (reg:CC CC_REGNUM))]
836 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
837 [(set_attr "conds" "clob")
838 (set_attr "length" "8")]
841 (define_insn "*thumb_subdi3"
842 [(set (match_operand:DI 0 "register_operand" "=l")
843 (minus:DI (match_operand:DI 1 "register_operand" "0")
844 (match_operand:DI 2 "register_operand" "l")))
845 (clobber (reg:CC CC_REGNUM))]
847 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
848 [(set_attr "length" "4")]
851 (define_insn "*subdi_di_zesidi"
852 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
853 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
855 (match_operand:SI 2 "s_register_operand" "r,r"))))
856 (clobber (reg:CC CC_REGNUM))]
858 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
859 [(set_attr "conds" "clob")
860 (set_attr "length" "8")]
863 (define_insn "*subdi_di_sesidi"
864 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
865 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
867 (match_operand:SI 2 "s_register_operand" "r,r"))))
868 (clobber (reg:CC CC_REGNUM))]
870 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
871 [(set_attr "conds" "clob")
872 (set_attr "length" "8")]
875 (define_insn "*subdi_zesidi_di"
876 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
877 (minus:DI (zero_extend:DI
878 (match_operand:SI 2 "s_register_operand" "r,r"))
879 (match_operand:DI 1 "s_register_operand" "?r,0")))
880 (clobber (reg:CC CC_REGNUM))]
882 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
883 [(set_attr "conds" "clob")
884 (set_attr "length" "8")]
887 (define_insn "*subdi_sesidi_di"
888 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
889 (minus:DI (sign_extend:DI
890 (match_operand:SI 2 "s_register_operand" "r,r"))
891 (match_operand:DI 1 "s_register_operand" "?r,0")))
892 (clobber (reg:CC CC_REGNUM))]
894 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
895 [(set_attr "conds" "clob")
896 (set_attr "length" "8")]
899 (define_insn "*subdi_zesidi_zesidi"
900 [(set (match_operand:DI 0 "s_register_operand" "=r")
901 (minus:DI (zero_extend:DI
902 (match_operand:SI 1 "s_register_operand" "r"))
904 (match_operand:SI 2 "s_register_operand" "r"))))
905 (clobber (reg:CC CC_REGNUM))]
907 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
908 [(set_attr "conds" "clob")
909 (set_attr "length" "8")]
912 (define_expand "subsi3"
913 [(set (match_operand:SI 0 "s_register_operand" "")
914 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
915 (match_operand:SI 2 "s_register_operand" "")))]
918 if (GET_CODE (operands[1]) == CONST_INT)
922 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
925 : preserve_subexpressions_p ()));
928 else /* TARGET_THUMB */
929 operands[1] = force_reg (SImode, operands[1]);
934 (define_insn "*thumb_subsi3_insn"
935 [(set (match_operand:SI 0 "register_operand" "=l")
936 (minus:SI (match_operand:SI 1 "register_operand" "l")
937 (match_operand:SI 2 "register_operand" "l")))]
940 [(set_attr "length" "2")]
943 (define_insn_and_split "*arm_subsi3_insn"
944 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
945 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
946 (match_operand:SI 2 "s_register_operand" "r,r")))]
952 && GET_CODE (operands[1]) == CONST_INT
953 && !const_ok_for_arm (INTVAL (operands[1]))"
954 [(clobber (const_int 0))]
956 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
960 [(set_attr "length" "4,16")
961 (set_attr "predicable" "yes")]
965 [(match_scratch:SI 3 "r")
966 (set (match_operand:SI 0 "s_register_operand" "")
967 (minus:SI (match_operand:SI 1 "const_int_operand" "")
968 (match_operand:SI 2 "s_register_operand" "")))]
970 && !const_ok_for_arm (INTVAL (operands[1]))
971 && const_ok_for_arm (~INTVAL (operands[1]))"
972 [(set (match_dup 3) (match_dup 1))
973 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
977 (define_insn "*subsi3_compare0"
978 [(set (reg:CC_NOOV CC_REGNUM)
980 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
981 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
983 (set (match_operand:SI 0 "s_register_operand" "=r,r")
984 (minus:SI (match_dup 1) (match_dup 2)))]
989 [(set_attr "conds" "set")]
992 (define_insn "decscc"
993 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
994 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
995 (match_operator:SI 2 "arm_comparison_operator"
996 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1000 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1001 [(set_attr "conds" "use")
1002 (set_attr "length" "*,8")]
1005 (define_expand "subsf3"
1006 [(set (match_operand:SF 0 "s_register_operand" "")
1007 (minus:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1008 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1009 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1013 if (!cirrus_fp_register (operands[1], SFmode))
1014 operands[1] = force_reg (SFmode, operands[1]);
1015 if (!cirrus_fp_register (operands[2], SFmode))
1016 operands[2] = force_reg (SFmode, operands[2]);
1020 (define_expand "subdf3"
1021 [(set (match_operand:DF 0 "s_register_operand" "")
1022 (minus:DF (match_operand:DF 1 "fpa_rhs_operand" "")
1023 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1024 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1028 if (!cirrus_fp_register (operands[1], DFmode))
1029 operands[1] = force_reg (DFmode, operands[1]);
1030 if (!cirrus_fp_register (operands[2], DFmode))
1031 operands[2] = force_reg (DFmode, operands[2]);
1036 ;; Multiplication insns
1038 (define_expand "mulsi3"
1039 [(set (match_operand:SI 0 "s_register_operand" "")
1040 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1041 (match_operand:SI 1 "s_register_operand" "")))]
1046 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1047 (define_insn "*arm_mulsi3"
1048 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1049 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1050 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1052 "mul%?\\t%0, %2, %1"
1053 [(set_attr "type" "mult")
1054 (set_attr "predicable" "yes")]
1057 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1058 ; 1 and 2; are the same, because reload will make operand 0 match
1059 ; operand 1 without realizing that this conflicts with operand 2. We fix
1060 ; this by adding another alternative to match this case, and then `reload'
1061 ; it ourselves. This alternative must come first.
1062 (define_insn "*thumb_mulsi3"
1063 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1064 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1065 (match_operand:SI 2 "register_operand" "l,l,l")))]
1068 if (which_alternative < 2)
1069 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1071 return \"mul\\t%0, %0, %2\";
1073 [(set_attr "length" "4,4,2")
1074 (set_attr "type" "mult")]
1077 (define_insn "*mulsi3_compare0"
1078 [(set (reg:CC_NOOV CC_REGNUM)
1079 (compare:CC_NOOV (mult:SI
1080 (match_operand:SI 2 "s_register_operand" "r,r")
1081 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1083 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1084 (mult:SI (match_dup 2) (match_dup 1)))]
1085 "TARGET_ARM && !arm_is_xscale"
1086 "mul%?s\\t%0, %2, %1"
1087 [(set_attr "conds" "set")
1088 (set_attr "type" "mult")]
1091 (define_insn "*mulsi_compare0_scratch"
1092 [(set (reg:CC_NOOV CC_REGNUM)
1093 (compare:CC_NOOV (mult:SI
1094 (match_operand:SI 2 "s_register_operand" "r,r")
1095 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1097 (clobber (match_scratch:SI 0 "=&r,&r"))]
1098 "TARGET_ARM && !arm_is_xscale"
1099 "mul%?s\\t%0, %2, %1"
1100 [(set_attr "conds" "set")
1101 (set_attr "type" "mult")]
1104 ;; Unnamed templates to match MLA instruction.
1106 (define_insn "*mulsi3addsi"
1107 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1109 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1110 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1111 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1113 "mla%?\\t%0, %2, %1, %3"
1114 [(set_attr "type" "mult")
1115 (set_attr "predicable" "yes")]
1118 (define_insn "*mulsi3addsi_compare0"
1119 [(set (reg:CC_NOOV CC_REGNUM)
1122 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1123 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1124 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1126 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1127 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1129 "TARGET_ARM && !arm_is_xscale"
1130 "mla%?s\\t%0, %2, %1, %3"
1131 [(set_attr "conds" "set")
1132 (set_attr "type" "mult")]
1135 (define_insn "*mulsi3addsi_compare0_scratch"
1136 [(set (reg:CC_NOOV CC_REGNUM)
1139 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1140 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1141 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1143 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1144 "TARGET_ARM && !arm_is_xscale"
1145 "mla%?s\\t%0, %2, %1, %3"
1146 [(set_attr "conds" "set")
1147 (set_attr "type" "mult")]
1150 ;; Unnamed template to match long long multiply-accumlate (smlal)
1152 (define_insn "*mulsidi3adddi"
1153 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1156 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1157 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1158 (match_operand:DI 1 "s_register_operand" "0")))]
1159 "TARGET_ARM && arm_fast_multiply"
1160 "smlal%?\\t%Q0, %R0, %3, %2"
1161 [(set_attr "type" "mult")
1162 (set_attr "predicable" "yes")]
1165 (define_insn "mulsidi3"
1166 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1168 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1169 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1170 "TARGET_ARM && arm_fast_multiply"
1171 "smull%?\\t%Q0, %R0, %1, %2"
1172 [(set_attr "type" "mult")
1173 (set_attr "predicable" "yes")]
1176 (define_insn "umulsidi3"
1177 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1179 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1180 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1181 "TARGET_ARM && arm_fast_multiply"
1182 "umull%?\\t%Q0, %R0, %1, %2"
1183 [(set_attr "type" "mult")
1184 (set_attr "predicable" "yes")]
1187 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1189 (define_insn "*umulsidi3adddi"
1190 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1193 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1194 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1195 (match_operand:DI 1 "s_register_operand" "0")))]
1196 "TARGET_ARM && arm_fast_multiply"
1197 "umlal%?\\t%Q0, %R0, %3, %2"
1198 [(set_attr "type" "mult")
1199 (set_attr "predicable" "yes")]
1202 (define_insn "smulsi3_highpart"
1203 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1207 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1208 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1210 (clobber (match_scratch:SI 3 "=&r,&r"))]
1211 "TARGET_ARM && arm_fast_multiply"
1212 "smull%?\\t%3, %0, %2, %1"
1213 [(set_attr "type" "mult")
1214 (set_attr "predicable" "yes")]
1217 (define_insn "umulsi3_highpart"
1218 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1222 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1223 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1225 (clobber (match_scratch:SI 3 "=&r,&r"))]
1226 "TARGET_ARM && arm_fast_multiply"
1227 "umull%?\\t%3, %0, %2, %1"
1228 [(set_attr "type" "mult")
1229 (set_attr "predicable" "yes")]
1232 (define_insn "mulhisi3"
1233 [(set (match_operand:SI 0 "s_register_operand" "=r")
1234 (mult:SI (sign_extend:SI
1235 (match_operand:HI 1 "s_register_operand" "%r"))
1237 (match_operand:HI 2 "s_register_operand" "r"))))]
1238 "TARGET_ARM && arm_arch5e"
1239 "smulbb%?\\t%0, %1, %2"
1240 [(set_attr "type" "mult")
1241 (set_attr "predicable" "yes")]
1244 (define_insn "*mulhisi3tb"
1245 [(set (match_operand:SI 0 "s_register_operand" "=r")
1246 (mult:SI (ashiftrt:SI
1247 (match_operand:SI 1 "s_register_operand" "r")
1250 (match_operand:HI 2 "s_register_operand" "r"))))]
1251 "TARGET_ARM && arm_arch5e"
1252 "smultb%?\\t%0, %1, %2"
1253 [(set_attr "type" "mult")
1254 (set_attr "predicable" "yes")]
1257 (define_insn "*mulhisi3bt"
1258 [(set (match_operand:SI 0 "s_register_operand" "=r")
1259 (mult:SI (sign_extend:SI
1260 (match_operand:HI 1 "s_register_operand" "r"))
1262 (match_operand:SI 2 "s_register_operand" "r")
1264 "TARGET_ARM && arm_arch5e"
1265 "smulbt%?\\t%0, %1, %2"
1266 [(set_attr "type" "mult")
1267 (set_attr "predicable" "yes")]
1270 (define_insn "*mulhisi3tt"
1271 [(set (match_operand:SI 0 "s_register_operand" "=r")
1272 (mult:SI (ashiftrt:SI
1273 (match_operand:SI 1 "s_register_operand" "r")
1276 (match_operand:SI 2 "s_register_operand" "r")
1278 "TARGET_ARM && arm_arch5e"
1279 "smultt%?\\t%0, %1, %2"
1280 [(set_attr "type" "mult")
1281 (set_attr "predicable" "yes")]
1284 (define_insn "*mulhisi3addsi"
1285 [(set (match_operand:SI 0 "s_register_operand" "=r")
1286 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1287 (mult:SI (sign_extend:SI
1288 (match_operand:HI 2 "s_register_operand" "%r"))
1290 (match_operand:HI 3 "s_register_operand" "r")))))]
1291 "TARGET_ARM && arm_arch5e"
1292 "smlabb%?\\t%0, %2, %3, %1"
1293 [(set_attr "type" "mult")
1294 (set_attr "predicable" "yes")]
1297 (define_insn "*mulhidi3adddi"
1298 [(set (match_operand:DI 0 "s_register_operand" "=r")
1300 (match_operand:DI 1 "s_register_operand" "0")
1301 (mult:DI (sign_extend:DI
1302 (match_operand:HI 2 "s_register_operand" "%r"))
1304 (match_operand:HI 3 "s_register_operand" "r")))))]
1305 "TARGET_ARM && arm_arch5e"
1306 "smlalbb%?\\t%Q0, %R0, %2, %3"
1307 [(set_attr "type" "mult")
1308 (set_attr "predicable" "yes")])
1310 (define_expand "mulsf3"
1311 [(set (match_operand:SF 0 "s_register_operand" "")
1312 (mult:SF (match_operand:SF 1 "s_register_operand" "")
1313 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1314 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1317 && !cirrus_fp_register (operands[2], SFmode))
1318 operands[2] = force_reg (SFmode, operands[2]);
1321 (define_expand "muldf3"
1322 [(set (match_operand:DF 0 "s_register_operand" "")
1323 (mult:DF (match_operand:DF 1 "s_register_operand" "")
1324 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1325 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1328 && !cirrus_fp_register (operands[2], DFmode))
1329 operands[2] = force_reg (DFmode, operands[2]);
1334 (define_expand "divsf3"
1335 [(set (match_operand:SF 0 "s_register_operand" "")
1336 (div:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1337 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1338 "TARGET_ARM && TARGET_HARD_FLOAT"
1341 (define_expand "divdf3"
1342 [(set (match_operand:DF 0 "s_register_operand" "")
1343 (div:DF (match_operand:DF 1 "fpa_rhs_operand" "")
1344 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1345 "TARGET_ARM && TARGET_HARD_FLOAT"
1350 (define_expand "modsf3"
1351 [(set (match_operand:SF 0 "s_register_operand" "")
1352 (mod:SF (match_operand:SF 1 "s_register_operand" "")
1353 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1354 "TARGET_ARM && TARGET_HARD_FLOAT"
1357 (define_expand "moddf3"
1358 [(set (match_operand:DF 0 "s_register_operand" "")
1359 (mod:DF (match_operand:DF 1 "s_register_operand" "")
1360 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1361 "TARGET_ARM && TARGET_HARD_FLOAT"
1364 ;; Boolean and,ior,xor insns
1366 ;; Split up double word logical operations
1368 ;; Split up simple DImode logical operations. Simply perform the logical
1369 ;; operation on the upper and lower halves of the registers.
1371 [(set (match_operand:DI 0 "s_register_operand" "")
1372 (match_operator:DI 6 "logical_binary_operator"
1373 [(match_operand:DI 1 "s_register_operand" "")
1374 (match_operand:DI 2 "s_register_operand" "")]))]
1375 "TARGET_ARM && reload_completed"
1376 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1377 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1380 operands[3] = gen_highpart (SImode, operands[0]);
1381 operands[0] = gen_lowpart (SImode, operands[0]);
1382 operands[4] = gen_highpart (SImode, operands[1]);
1383 operands[1] = gen_lowpart (SImode, operands[1]);
1384 operands[5] = gen_highpart (SImode, operands[2]);
1385 operands[2] = gen_lowpart (SImode, operands[2]);
1390 [(set (match_operand:DI 0 "s_register_operand" "")
1391 (match_operator:DI 6 "logical_binary_operator"
1392 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1393 (match_operand:DI 1 "s_register_operand" "")]))]
1394 "TARGET_ARM && reload_completed"
1395 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1396 (set (match_dup 3) (match_op_dup:SI 6
1397 [(ashiftrt:SI (match_dup 2) (const_int 31))
1401 operands[3] = gen_highpart (SImode, operands[0]);
1402 operands[0] = gen_lowpart (SImode, operands[0]);
1403 operands[4] = gen_highpart (SImode, operands[1]);
1404 operands[1] = gen_lowpart (SImode, operands[1]);
1405 operands[5] = gen_highpart (SImode, operands[2]);
1406 operands[2] = gen_lowpart (SImode, operands[2]);
1410 ;; The zero extend of operand 2 means we can just copy the high part of
1411 ;; operand1 into operand0.
1413 [(set (match_operand:DI 0 "s_register_operand" "")
1415 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1416 (match_operand:DI 1 "s_register_operand" "")))]
1417 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1418 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1419 (set (match_dup 3) (match_dup 4))]
1422 operands[4] = gen_highpart (SImode, operands[1]);
1423 operands[3] = gen_highpart (SImode, operands[0]);
1424 operands[0] = gen_lowpart (SImode, operands[0]);
1425 operands[1] = gen_lowpart (SImode, operands[1]);
1429 ;; The zero extend of operand 2 means we can just copy the high part of
1430 ;; operand1 into operand0.
1432 [(set (match_operand:DI 0 "s_register_operand" "")
1434 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1435 (match_operand:DI 1 "s_register_operand" "")))]
1436 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1437 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1438 (set (match_dup 3) (match_dup 4))]
1441 operands[4] = gen_highpart (SImode, operands[1]);
1442 operands[3] = gen_highpart (SImode, operands[0]);
1443 operands[0] = gen_lowpart (SImode, operands[0]);
1444 operands[1] = gen_lowpart (SImode, operands[1]);
1448 (define_insn "anddi3"
1449 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1450 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1451 (match_operand:DI 2 "s_register_operand" "r,r")))]
1454 [(set_attr "length" "8")]
1457 (define_insn_and_split "*anddi_zesidi_di"
1458 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1459 (and:DI (zero_extend:DI
1460 (match_operand:SI 2 "s_register_operand" "r,r"))
1461 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1464 "TARGET_ARM && reload_completed"
1465 ; The zero extend of operand 2 clears the high word of the output
1467 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1468 (set (match_dup 3) (const_int 0))]
1471 operands[3] = gen_highpart (SImode, operands[0]);
1472 operands[0] = gen_lowpart (SImode, operands[0]);
1473 operands[1] = gen_lowpart (SImode, operands[1]);
1475 [(set_attr "length" "8")]
1478 (define_insn "*anddi_sesdi_di"
1479 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1480 (and:DI (sign_extend:DI
1481 (match_operand:SI 2 "s_register_operand" "r,r"))
1482 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1485 [(set_attr "length" "8")]
1488 (define_expand "andsi3"
1489 [(set (match_operand:SI 0 "s_register_operand" "")
1490 (and:SI (match_operand:SI 1 "s_register_operand" "")
1491 (match_operand:SI 2 "reg_or_int_operand" "")))]
1496 if (GET_CODE (operands[2]) == CONST_INT)
1498 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1501 ? 0 : preserve_subexpressions_p ()));
1505 else /* TARGET_THUMB */
1507 if (GET_CODE (operands[2]) != CONST_INT)
1508 operands[2] = force_reg (SImode, operands[2]);
1513 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1515 operands[2] = force_reg (SImode,
1516 GEN_INT (~INTVAL (operands[2])));
1518 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1523 for (i = 9; i <= 31; i++)
1525 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1527 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1531 else if ((((HOST_WIDE_INT) 1) << i) - 1
1532 == ~INTVAL (operands[2]))
1534 rtx shift = GEN_INT (i);
1535 rtx reg = gen_reg_rtx (SImode);
1537 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1538 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1544 operands[2] = force_reg (SImode, operands[2]);
1550 (define_insn_and_split "*arm_andsi3_insn"
1551 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1552 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1553 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1557 bic%?\\t%0, %1, #%B2
1560 && GET_CODE (operands[2]) == CONST_INT
1561 && !(const_ok_for_arm (INTVAL (operands[2]))
1562 || const_ok_for_arm (~INTVAL (operands[2])))"
1563 [(clobber (const_int 0))]
1565 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1569 [(set_attr "length" "4,4,16")
1570 (set_attr "predicable" "yes")]
1573 (define_insn "*thumb_andsi3_insn"
1574 [(set (match_operand:SI 0 "register_operand" "=l")
1575 (and:SI (match_operand:SI 1 "register_operand" "%0")
1576 (match_operand:SI 2 "register_operand" "l")))]
1579 [(set_attr "length" "2")]
1582 (define_insn "*andsi3_compare0"
1583 [(set (reg:CC_NOOV CC_REGNUM)
1585 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1586 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1588 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1589 (and:SI (match_dup 1) (match_dup 2)))]
1593 bic%?s\\t%0, %1, #%B2"
1594 [(set_attr "conds" "set")]
1597 (define_insn "*andsi3_compare0_scratch"
1598 [(set (reg:CC_NOOV CC_REGNUM)
1600 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1601 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1603 (clobber (match_scratch:SI 2 "=X,r"))]
1607 bic%?s\\t%2, %0, #%B1"
1608 [(set_attr "conds" "set")]
1611 (define_insn "*zeroextractsi_compare0_scratch"
1612 [(set (reg:CC_NOOV CC_REGNUM)
1613 (compare:CC_NOOV (zero_extract:SI
1614 (match_operand:SI 0 "s_register_operand" "r")
1615 (match_operand 1 "const_int_operand" "n")
1616 (match_operand 2 "const_int_operand" "n"))
1619 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1620 && INTVAL (operands[1]) > 0
1621 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1622 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1624 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1625 << INTVAL (operands[2]));
1626 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1629 [(set_attr "conds" "set")]
1632 (define_insn "*ne_zeroextractsi"
1633 [(set (match_operand:SI 0 "s_register_operand" "=r")
1634 (ne:SI (zero_extract:SI
1635 (match_operand:SI 1 "s_register_operand" "r")
1636 (match_operand:SI 2 "const_int_operand" "n")
1637 (match_operand:SI 3 "const_int_operand" "n"))
1639 (clobber (reg:CC CC_REGNUM))]
1641 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1642 && INTVAL (operands[2]) > 0
1643 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1644 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1646 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1647 << INTVAL (operands[3]));
1648 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1649 return \"movne\\t%0, #1\";
1651 [(set_attr "conds" "clob")
1652 (set_attr "length" "8")]
1655 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1656 ;;; represented by the bitfield, then this will produce incorrect results.
1657 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1658 ;;; which have a real bit-field insert instruction, the truncation happens
1659 ;;; in the bit-field insert instruction itself. Since arm does not have a
1660 ;;; bit-field insert instruction, we would have to emit code here to truncate
1661 ;;; the value before we insert. This loses some of the advantage of having
1662 ;;; this insv pattern, so this pattern needs to be reevalutated.
1664 (define_expand "insv"
1665 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1666 (match_operand:SI 1 "general_operand" "")
1667 (match_operand:SI 2 "general_operand" ""))
1668 (match_operand:SI 3 "reg_or_int_operand" ""))]
1672 int start_bit = INTVAL (operands[2]);
1673 int width = INTVAL (operands[1]);
1674 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1675 rtx target, subtarget;
1677 target = operands[0];
1678 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1679 subreg as the final target. */
1680 if (GET_CODE (target) == SUBREG)
1682 subtarget = gen_reg_rtx (SImode);
1683 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1684 < GET_MODE_SIZE (SImode))
1685 target = SUBREG_REG (target);
1690 if (GET_CODE (operands[3]) == CONST_INT)
1692 /* Since we are inserting a known constant, we may be able to
1693 reduce the number of bits that we have to clear so that
1694 the mask becomes simple. */
1695 /* ??? This code does not check to see if the new mask is actually
1696 simpler. It may not be. */
1697 rtx op1 = gen_reg_rtx (SImode);
1698 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1699 start of this pattern. */
1700 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1701 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1703 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1704 emit_insn (gen_iorsi3 (subtarget, op1,
1705 GEN_INT (op3_value << start_bit)));
1707 else if (start_bit == 0
1708 && !(const_ok_for_arm (mask)
1709 || const_ok_for_arm (~mask)))
1711 /* A Trick, since we are setting the bottom bits in the word,
1712 we can shift operand[3] up, operand[0] down, OR them together
1713 and rotate the result back again. This takes 3 insns, and
1714 the third might be mergable into another op. */
1715 /* The shift up copes with the possibility that operand[3] is
1716 wider than the bitfield. */
1717 rtx op0 = gen_reg_rtx (SImode);
1718 rtx op1 = gen_reg_rtx (SImode);
1720 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1721 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1722 emit_insn (gen_iorsi3 (op1, op1, op0));
1723 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1725 else if ((width + start_bit == 32)
1726 && !(const_ok_for_arm (mask)
1727 || const_ok_for_arm (~mask)))
1729 /* Similar trick, but slightly less efficient. */
1731 rtx op0 = gen_reg_rtx (SImode);
1732 rtx op1 = gen_reg_rtx (SImode);
1734 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1735 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1736 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1737 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1741 rtx op0 = GEN_INT (mask);
1742 rtx op1 = gen_reg_rtx (SImode);
1743 rtx op2 = gen_reg_rtx (SImode);
1745 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1747 rtx tmp = gen_reg_rtx (SImode);
1749 emit_insn (gen_movsi (tmp, op0));
1753 /* Mask out any bits in operand[3] that are not needed. */
1754 emit_insn (gen_andsi3 (op1, operands[3], op0));
1756 if (GET_CODE (op0) == CONST_INT
1757 && (const_ok_for_arm (mask << start_bit)
1758 || const_ok_for_arm (~(mask << start_bit))))
1760 op0 = GEN_INT (~(mask << start_bit));
1761 emit_insn (gen_andsi3 (op2, operands[0], op0));
1765 if (GET_CODE (op0) == CONST_INT)
1767 rtx tmp = gen_reg_rtx (SImode);
1769 emit_insn (gen_movsi (tmp, op0));
1774 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1776 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1780 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1782 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1785 if (subtarget != target)
1787 /* If TARGET is still a SUBREG, then it must be wider than a word,
1788 so we must be careful only to set the subword we were asked to. */
1789 if (GET_CODE (target) == SUBREG)
1790 emit_move_insn (target, subtarget);
1792 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1799 ; constants for op 2 will never be given to these patterns.
1800 (define_insn_and_split "*anddi_notdi_di"
1801 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1802 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1803 (match_operand:DI 2 "s_register_operand" "0,r")))]
1806 "TARGET_ARM && reload_completed"
1807 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1808 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1811 operands[3] = gen_highpart (SImode, operands[0]);
1812 operands[0] = gen_lowpart (SImode, operands[0]);
1813 operands[4] = gen_highpart (SImode, operands[1]);
1814 operands[1] = gen_lowpart (SImode, operands[1]);
1815 operands[5] = gen_highpart (SImode, operands[2]);
1816 operands[2] = gen_lowpart (SImode, operands[2]);
1818 [(set_attr "length" "8")
1819 (set_attr "predicable" "yes")]
1822 (define_insn_and_split "*anddi_notzesidi_di"
1823 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1824 (and:DI (not:DI (zero_extend:DI
1825 (match_operand:SI 2 "s_register_operand" "r,r")))
1826 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1829 bic%?\\t%Q0, %Q1, %2
1831 ; (not (zero_extend ...)) allows us to just copy the high word from
1832 ; operand1 to operand0.
1835 && operands[0] != operands[1]"
1836 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1837 (set (match_dup 3) (match_dup 4))]
1840 operands[3] = gen_highpart (SImode, operands[0]);
1841 operands[0] = gen_lowpart (SImode, operands[0]);
1842 operands[4] = gen_highpart (SImode, operands[1]);
1843 operands[1] = gen_lowpart (SImode, operands[1]);
1845 [(set_attr "length" "4,8")
1846 (set_attr "predicable" "yes")]
1849 (define_insn_and_split "*anddi_notsesidi_di"
1850 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1851 (and:DI (not:DI (sign_extend:DI
1852 (match_operand:SI 2 "s_register_operand" "r,r")))
1853 (match_operand:DI 1 "s_register_operand" "0,r")))]
1856 "TARGET_ARM && reload_completed"
1857 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1858 (set (match_dup 3) (and:SI (not:SI
1859 (ashiftrt:SI (match_dup 2) (const_int 31)))
1863 operands[3] = gen_highpart (SImode, operands[0]);
1864 operands[0] = gen_lowpart (SImode, operands[0]);
1865 operands[4] = gen_highpart (SImode, operands[1]);
1866 operands[1] = gen_lowpart (SImode, operands[1]);
1868 [(set_attr "length" "8")
1869 (set_attr "predicable" "yes")]
1872 (define_insn "andsi_notsi_si"
1873 [(set (match_operand:SI 0 "s_register_operand" "=r")
1874 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1875 (match_operand:SI 1 "s_register_operand" "r")))]
1877 "bic%?\\t%0, %1, %2"
1878 [(set_attr "predicable" "yes")]
1881 (define_insn "bicsi3"
1882 [(set (match_operand:SI 0 "register_operand" "=l")
1883 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
1884 (match_operand:SI 2 "register_operand" "0")))]
1887 [(set_attr "length" "2")]
1890 (define_insn "andsi_not_shiftsi_si"
1891 [(set (match_operand:SI 0 "s_register_operand" "=r")
1892 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
1893 [(match_operand:SI 2 "s_register_operand" "r")
1894 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
1895 (match_operand:SI 1 "s_register_operand" "r")))]
1897 "bic%?\\t%0, %1, %2%S4"
1898 [(set_attr "predicable" "yes")
1899 (set_attr "shift" "2")
1903 (define_insn "*andsi_notsi_si_compare0"
1904 [(set (reg:CC_NOOV CC_REGNUM)
1906 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1907 (match_operand:SI 1 "s_register_operand" "r"))
1909 (set (match_operand:SI 0 "s_register_operand" "=r")
1910 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
1912 "bic%?s\\t%0, %1, %2"
1913 [(set_attr "conds" "set")]
1916 (define_insn "*andsi_notsi_si_compare0_scratch"
1917 [(set (reg:CC_NOOV CC_REGNUM)
1919 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1920 (match_operand:SI 1 "s_register_operand" "r"))
1922 (clobber (match_scratch:SI 0 "=r"))]
1924 "bic%?s\\t%0, %1, %2"
1925 [(set_attr "conds" "set")]
1928 (define_insn "iordi3"
1929 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1930 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1931 (match_operand:DI 2 "s_register_operand" "r,r")))]
1934 [(set_attr "length" "8")
1935 (set_attr "predicable" "yes")]
1938 (define_insn "*iordi_zesidi_di"
1939 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1940 (ior:DI (zero_extend:DI
1941 (match_operand:SI 2 "s_register_operand" "r,r"))
1942 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1945 orr%?\\t%Q0, %Q1, %2
1947 [(set_attr "length" "4,8")
1948 (set_attr "predicable" "yes")]
1951 (define_insn "*iordi_sesidi_di"
1952 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1953 (ior:DI (sign_extend:DI
1954 (match_operand:SI 2 "s_register_operand" "r,r"))
1955 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1958 [(set_attr "length" "8")
1959 (set_attr "predicable" "yes")]
1962 (define_expand "iorsi3"
1963 [(set (match_operand:SI 0 "s_register_operand" "")
1964 (ior:SI (match_operand:SI 1 "s_register_operand" "")
1965 (match_operand:SI 2 "reg_or_int_operand" "")))]
1968 if (GET_CODE (operands[2]) == CONST_INT)
1972 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1975 ? 0 : preserve_subexpressions_p ()));
1978 else /* TARGET_THUMB */
1979 operands [2] = force_reg (SImode, operands [2]);
1984 (define_insn_and_split "*arm_iorsi3"
1985 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1986 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
1987 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
1993 && GET_CODE (operands[2]) == CONST_INT
1994 && !const_ok_for_arm (INTVAL (operands[2]))"
1995 [(clobber (const_int 0))]
1997 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2001 [(set_attr "length" "4,16")
2002 (set_attr "predicable" "yes")]
2005 (define_insn "*thumb_iorsi3"
2006 [(set (match_operand:SI 0 "register_operand" "=l")
2007 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2008 (match_operand:SI 2 "register_operand" "l")))]
2011 [(set_attr "length" "2")]
2015 [(match_scratch:SI 3 "r")
2016 (set (match_operand:SI 0 "s_register_operand" "")
2017 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2018 (match_operand:SI 2 "const_int_operand" "")))]
2020 && !const_ok_for_arm (INTVAL (operands[2]))
2021 && const_ok_for_arm (~INTVAL (operands[2]))"
2022 [(set (match_dup 3) (match_dup 2))
2023 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2027 (define_insn "*iorsi3_compare0"
2028 [(set (reg:CC_NOOV CC_REGNUM)
2029 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2030 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2032 (set (match_operand:SI 0 "s_register_operand" "=r")
2033 (ior:SI (match_dup 1) (match_dup 2)))]
2035 "orr%?s\\t%0, %1, %2"
2036 [(set_attr "conds" "set")]
2039 (define_insn "*iorsi3_compare0_scratch"
2040 [(set (reg:CC_NOOV CC_REGNUM)
2041 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2042 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2044 (clobber (match_scratch:SI 0 "=r"))]
2046 "orr%?s\\t%0, %1, %2"
2047 [(set_attr "conds" "set")]
2050 (define_insn "xordi3"
2051 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2052 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2053 (match_operand:DI 2 "s_register_operand" "r,r")))]
2056 [(set_attr "length" "8")
2057 (set_attr "predicable" "yes")]
2060 (define_insn "*xordi_zesidi_di"
2061 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2062 (xor:DI (zero_extend:DI
2063 (match_operand:SI 2 "s_register_operand" "r,r"))
2064 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2067 eor%?\\t%Q0, %Q1, %2
2069 [(set_attr "length" "4,8")
2070 (set_attr "predicable" "yes")]
2073 (define_insn "*xordi_sesidi_di"
2074 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2075 (xor:DI (sign_extend:DI
2076 (match_operand:SI 2 "s_register_operand" "r,r"))
2077 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2080 [(set_attr "length" "8")
2081 (set_attr "predicable" "yes")]
2084 (define_expand "xorsi3"
2085 [(set (match_operand:SI 0 "s_register_operand" "")
2086 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2087 (match_operand:SI 2 "arm_rhs_operand" "")))]
2090 if (GET_CODE (operands[2]) == CONST_INT)
2091 operands[2] = force_reg (SImode, operands[2]);
2095 (define_insn "*arm_xorsi3"
2096 [(set (match_operand:SI 0 "s_register_operand" "=r")
2097 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2098 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2100 "eor%?\\t%0, %1, %2"
2101 [(set_attr "predicable" "yes")]
2104 (define_insn "*thumb_xorsi3"
2105 [(set (match_operand:SI 0 "register_operand" "=l")
2106 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2107 (match_operand:SI 2 "register_operand" "l")))]
2110 [(set_attr "length" "2")]
2113 (define_insn "*xorsi3_compare0"
2114 [(set (reg:CC_NOOV CC_REGNUM)
2115 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2116 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2118 (set (match_operand:SI 0 "s_register_operand" "=r")
2119 (xor:SI (match_dup 1) (match_dup 2)))]
2121 "eor%?s\\t%0, %1, %2"
2122 [(set_attr "conds" "set")]
2125 (define_insn "*xorsi3_compare0_scratch"
2126 [(set (reg:CC_NOOV CC_REGNUM)
2127 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2128 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2132 [(set_attr "conds" "set")]
2135 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2136 ; (NOT D) we can sometimes merge the final NOT into one of the following
2140 [(set (match_operand:SI 0 "s_register_operand" "")
2141 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2142 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2143 (match_operand:SI 3 "arm_rhs_operand" "")))
2144 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2146 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2147 (not:SI (match_dup 3))))
2148 (set (match_dup 0) (not:SI (match_dup 4)))]
2152 (define_insn "*andsi_iorsi3_notsi"
2153 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2154 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2155 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2156 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2158 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2159 [(set_attr "length" "8")
2160 (set_attr "predicable" "yes")]
2165 ;; Minimum and maximum insns
2167 (define_insn "smaxsi3"
2168 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2169 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2170 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2171 (clobber (reg:CC CC_REGNUM))]
2174 cmp\\t%1, %2\;movlt\\t%0, %2
2175 cmp\\t%1, %2\;movge\\t%0, %1
2176 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2177 [(set_attr "conds" "clob")
2178 (set_attr "length" "8,8,12")]
2181 (define_insn "sminsi3"
2182 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2183 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2184 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2185 (clobber (reg:CC CC_REGNUM))]
2188 cmp\\t%1, %2\;movge\\t%0, %2
2189 cmp\\t%1, %2\;movlt\\t%0, %1
2190 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2191 [(set_attr "conds" "clob")
2192 (set_attr "length" "8,8,12")]
2195 (define_insn "umaxsi3"
2196 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2197 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2198 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2199 (clobber (reg:CC CC_REGNUM))]
2202 cmp\\t%1, %2\;movcc\\t%0, %2
2203 cmp\\t%1, %2\;movcs\\t%0, %1
2204 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2205 [(set_attr "conds" "clob")
2206 (set_attr "length" "8,8,12")]
2209 (define_insn "uminsi3"
2210 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2211 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2212 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2213 (clobber (reg:CC CC_REGNUM))]
2216 cmp\\t%1, %2\;movcs\\t%0, %2
2217 cmp\\t%1, %2\;movcc\\t%0, %1
2218 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2219 [(set_attr "conds" "clob")
2220 (set_attr "length" "8,8,12")]
2223 (define_insn "*store_minmaxsi"
2224 [(set (match_operand:SI 0 "memory_operand" "=m")
2225 (match_operator:SI 3 "minmax_operator"
2226 [(match_operand:SI 1 "s_register_operand" "r")
2227 (match_operand:SI 2 "s_register_operand" "r")]))
2228 (clobber (reg:CC CC_REGNUM))]
2231 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2233 output_asm_insn (\"cmp\\t%1, %2\", operands);
2234 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2235 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2238 [(set_attr "conds" "clob")
2239 (set_attr "length" "12")
2240 (set_attr "type" "store1")]
2243 ; Reject the frame pointer in operand[1], since reloading this after
2244 ; it has been eliminated can cause carnage.
2245 (define_insn "*minmax_arithsi"
2246 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2247 (match_operator:SI 4 "shiftable_operator"
2248 [(match_operator:SI 5 "minmax_operator"
2249 [(match_operand:SI 2 "s_register_operand" "r,r")
2250 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2251 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2252 (clobber (reg:CC CC_REGNUM))]
2254 && (GET_CODE (operands[1]) != REG
2255 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2256 && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2259 enum rtx_code code = GET_CODE (operands[4]);
2261 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2263 output_asm_insn (\"cmp\\t%2, %3\", operands);
2264 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2265 if (which_alternative != 0 || operands[3] != const0_rtx
2266 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2267 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2270 [(set_attr "conds" "clob")
2271 (set_attr "length" "12")]
2275 ;; Shift and rotation insns
2277 (define_expand "ashlsi3"
2278 [(set (match_operand:SI 0 "s_register_operand" "")
2279 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2280 (match_operand:SI 2 "arm_rhs_operand" "")))]
2283 if (GET_CODE (operands[2]) == CONST_INT
2284 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2286 emit_insn (gen_movsi (operands[0], const0_rtx));
2292 (define_insn "*thumb_ashlsi3"
2293 [(set (match_operand:SI 0 "register_operand" "=l,l")
2294 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2295 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2298 [(set_attr "length" "2")]
2301 (define_expand "ashrsi3"
2302 [(set (match_operand:SI 0 "s_register_operand" "")
2303 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2304 (match_operand:SI 2 "arm_rhs_operand" "")))]
2307 if (GET_CODE (operands[2]) == CONST_INT
2308 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2309 operands[2] = GEN_INT (31);
2313 (define_insn "*thumb_ashrsi3"
2314 [(set (match_operand:SI 0 "register_operand" "=l,l")
2315 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2316 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2319 [(set_attr "length" "2")]
2322 (define_expand "lshrsi3"
2323 [(set (match_operand:SI 0 "s_register_operand" "")
2324 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2325 (match_operand:SI 2 "arm_rhs_operand" "")))]
2328 if (GET_CODE (operands[2]) == CONST_INT
2329 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2331 emit_insn (gen_movsi (operands[0], const0_rtx));
2337 (define_insn "*thumb_lshrsi3"
2338 [(set (match_operand:SI 0 "register_operand" "=l,l")
2339 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2340 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2343 [(set_attr "length" "2")]
2346 (define_expand "rotlsi3"
2347 [(set (match_operand:SI 0 "s_register_operand" "")
2348 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2349 (match_operand:SI 2 "reg_or_int_operand" "")))]
2352 if (GET_CODE (operands[2]) == CONST_INT)
2353 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2356 rtx reg = gen_reg_rtx (SImode);
2357 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2363 (define_expand "rotrsi3"
2364 [(set (match_operand:SI 0 "s_register_operand" "")
2365 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2366 (match_operand:SI 2 "arm_rhs_operand" "")))]
2371 if (GET_CODE (operands[2]) == CONST_INT
2372 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2373 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2375 else /* TARGET_THUMB */
2377 if (GET_CODE (operands [2]) == CONST_INT)
2378 operands [2] = force_reg (SImode, operands[2]);
2383 (define_insn "*thumb_rotrsi3"
2384 [(set (match_operand:SI 0 "register_operand" "=l")
2385 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2386 (match_operand:SI 2 "register_operand" "l")))]
2389 [(set_attr "length" "2")]
2392 (define_expand "ashldi3"
2393 [(set (match_operand:DI 0 "s_register_operand" "")
2394 (ashift:DI (match_operand:DI 1 "general_operand" "")
2395 (match_operand:SI 2 "general_operand" "")))]
2396 "TARGET_ARM && (TARGET_CIRRUS)"
2398 if (! s_register_operand (operands[1], DImode))
2399 operands[1] = copy_to_mode_reg (DImode, operands[1]);
2400 if (! s_register_operand (operands[2], SImode))
2401 operands[2] = copy_to_mode_reg (SImode, operands[2]);
2405 (define_insn "*arm_shiftsi3"
2406 [(set (match_operand:SI 0 "s_register_operand" "=r")
2407 (match_operator:SI 3 "shift_operator"
2408 [(match_operand:SI 1 "s_register_operand" "r")
2409 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2412 [(set_attr "predicable" "yes")
2413 (set_attr "shift" "1")
2417 (define_insn "*shiftsi3_compare0"
2418 [(set (reg:CC_NOOV CC_REGNUM)
2419 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2420 [(match_operand:SI 1 "s_register_operand" "r")
2421 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2423 (set (match_operand:SI 0 "s_register_operand" "=r")
2424 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2426 "mov%?s\\t%0, %1%S3"
2427 [(set_attr "conds" "set")
2428 (set_attr "shift" "1")
2432 (define_insn "*shiftsi3_compare0_scratch"
2433 [(set (reg:CC_NOOV CC_REGNUM)
2434 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2435 [(match_operand:SI 1 "s_register_operand" "r")
2436 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2438 (clobber (match_scratch:SI 0 "=r"))]
2440 "mov%?s\\t%0, %1%S3"
2441 [(set_attr "conds" "set")
2442 (set_attr "shift" "1")
2446 (define_insn "*notsi_shiftsi"
2447 [(set (match_operand:SI 0 "s_register_operand" "=r")
2448 (not:SI (match_operator:SI 3 "shift_operator"
2449 [(match_operand:SI 1 "s_register_operand" "r")
2450 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2453 [(set_attr "predicable" "yes")
2454 (set_attr "shift" "1")
2458 (define_insn "*notsi_shiftsi_compare0"
2459 [(set (reg:CC_NOOV CC_REGNUM)
2460 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2461 [(match_operand:SI 1 "s_register_operand" "r")
2462 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2464 (set (match_operand:SI 0 "s_register_operand" "=r")
2465 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2467 "mvn%?s\\t%0, %1%S3"
2468 [(set_attr "conds" "set")
2469 (set_attr "shift" "1")
2473 (define_insn "*not_shiftsi_compare0_scratch"
2474 [(set (reg:CC_NOOV CC_REGNUM)
2475 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2476 [(match_operand:SI 1 "s_register_operand" "r")
2477 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2479 (clobber (match_scratch:SI 0 "=r"))]
2481 "mvn%?s\\t%0, %1%S3"
2482 [(set_attr "conds" "set")
2483 (set_attr "shift" "1")
2487 ;; We don't really have extzv, but defining this using shifts helps
2488 ;; to reduce register pressure later on.
2490 (define_expand "extzv"
2492 (ashift:SI (match_operand:SI 1 "register_operand" "")
2493 (match_operand:SI 2 "const_int_operand" "")))
2494 (set (match_operand:SI 0 "register_operand" "")
2495 (lshiftrt:SI (match_dup 4)
2496 (match_operand:SI 3 "const_int_operand" "")))]
2500 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2501 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2503 operands[3] = GEN_INT (rshift);
2507 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2511 operands[2] = GEN_INT (lshift);
2512 operands[4] = gen_reg_rtx (SImode);
2517 ;; Unary arithmetic insns
2519 (define_expand "negdi2"
2521 [(set (match_operand:DI 0 "s_register_operand" "")
2522 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2523 (clobber (reg:CC CC_REGNUM))])]
2528 if (GET_CODE (operands[1]) != REG)
2529 operands[1] = force_reg (SImode, operands[1]);
2534 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2535 ;; The second alternative is to allow the common case of a *full* overlap.
2536 (define_insn "*arm_negdi2"
2537 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2538 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2539 (clobber (reg:CC CC_REGNUM))]
2541 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2542 [(set_attr "conds" "clob")
2543 (set_attr "length" "8")]
2546 (define_insn "*thumb_negdi2"
2547 [(set (match_operand:DI 0 "register_operand" "=&l")
2548 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2549 (clobber (reg:CC CC_REGNUM))]
2551 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2552 [(set_attr "length" "6")]
2555 (define_expand "negsi2"
2556 [(set (match_operand:SI 0 "s_register_operand" "")
2557 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2562 (define_insn "*arm_negsi2"
2563 [(set (match_operand:SI 0 "s_register_operand" "=r")
2564 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2566 "rsb%?\\t%0, %1, #0"
2567 [(set_attr "predicable" "yes")]
2570 (define_insn "*thumb_negsi2"
2571 [(set (match_operand:SI 0 "register_operand" "=l")
2572 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2575 [(set_attr "length" "2")]
2578 (define_expand "negsf2"
2579 [(set (match_operand:SF 0 "s_register_operand" "")
2580 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2581 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2585 (define_expand "negdf2"
2586 [(set (match_operand:DF 0 "s_register_operand" "")
2587 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2588 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2591 ;; abssi2 doesn't really clobber the condition codes if a different register
2592 ;; is being set. To keep things simple, assume during rtl manipulations that
2593 ;; it does, but tell the final scan operator the truth. Similarly for
2596 (define_expand "abssi2"
2598 [(set (match_operand:SI 0 "s_register_operand" "")
2599 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2600 (clobber (reg:CC CC_REGNUM))])]
2604 (define_insn "*arm_abssi2"
2605 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2606 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2607 (clobber (reg:CC CC_REGNUM))]
2610 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2611 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2612 [(set_attr "conds" "clob,*")
2613 (set_attr "shift" "1")
2614 ;; predicable can't be set based on the variant, so left as no
2615 (set_attr "length" "8")]
2618 (define_insn "*neg_abssi2"
2619 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2620 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2621 (clobber (reg:CC CC_REGNUM))]
2624 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2625 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2626 [(set_attr "conds" "clob,*")
2627 (set_attr "shift" "1")
2628 ;; predicable can't be set based on the variant, so left as no
2629 (set_attr "length" "8")]
2632 (define_expand "abssf2"
2633 [(set (match_operand:SF 0 "s_register_operand" "")
2634 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
2635 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2638 (define_expand "absdf2"
2639 [(set (match_operand:DF 0 "s_register_operand" "")
2640 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
2641 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2644 (define_expand "sqrtsf2"
2645 [(set (match_operand:SF 0 "s_register_operand" "")
2646 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
2647 "TARGET_ARM && TARGET_HARD_FLOAT"
2650 (define_expand "sqrtdf2"
2651 [(set (match_operand:DF 0 "s_register_operand" "")
2652 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
2653 "TARGET_ARM && TARGET_HARD_FLOAT"
2656 (define_insn_and_split "one_cmpldi2"
2657 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2658 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2661 "TARGET_ARM && reload_completed"
2662 [(set (match_dup 0) (not:SI (match_dup 1)))
2663 (set (match_dup 2) (not:SI (match_dup 3)))]
2666 operands[2] = gen_highpart (SImode, operands[0]);
2667 operands[0] = gen_lowpart (SImode, operands[0]);
2668 operands[3] = gen_highpart (SImode, operands[1]);
2669 operands[1] = gen_lowpart (SImode, operands[1]);
2671 [(set_attr "length" "8")
2672 (set_attr "predicable" "yes")]
2675 (define_expand "one_cmplsi2"
2676 [(set (match_operand:SI 0 "s_register_operand" "")
2677 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2682 (define_insn "*arm_one_cmplsi2"
2683 [(set (match_operand:SI 0 "s_register_operand" "=r")
2684 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
2687 [(set_attr "predicable" "yes")]
2690 (define_insn "*thumb_one_cmplsi2"
2691 [(set (match_operand:SI 0 "register_operand" "=l")
2692 (not:SI (match_operand:SI 1 "register_operand" "l")))]
2695 [(set_attr "length" "2")]
2698 (define_insn "*notsi_compare0"
2699 [(set (reg:CC_NOOV CC_REGNUM)
2700 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2702 (set (match_operand:SI 0 "s_register_operand" "=r")
2703 (not:SI (match_dup 1)))]
2706 [(set_attr "conds" "set")]
2709 (define_insn "*notsi_compare0_scratch"
2710 [(set (reg:CC_NOOV CC_REGNUM)
2711 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2713 (clobber (match_scratch:SI 0 "=r"))]
2716 [(set_attr "conds" "set")]
2719 ;; Fixed <--> Floating conversion insns
2721 (define_expand "floatsisf2"
2722 [(set (match_operand:SF 0 "s_register_operand" "")
2723 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
2724 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2728 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
2733 (define_expand "floatsidf2"
2734 [(set (match_operand:DF 0 "s_register_operand" "")
2735 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
2736 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2740 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
2745 (define_expand "fix_truncsfsi2"
2746 [(set (match_operand:SI 0 "s_register_operand" "")
2747 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
2748 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2752 if (!cirrus_fp_register (operands[0], SImode))
2753 operands[0] = force_reg (SImode, operands[0]);
2754 if (!cirrus_fp_register (operands[1], SFmode))
2755 operands[1] = force_reg (SFmode, operands[0]);
2756 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
2761 (define_expand "fix_truncdfsi2"
2762 [(set (match_operand:SI 0 "s_register_operand" "")
2763 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
2764 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2768 if (!cirrus_fp_register (operands[1], DFmode))
2769 operands[1] = force_reg (DFmode, operands[0]);
2770 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
2777 (define_expand "truncdfsf2"
2778 [(set (match_operand:SF 0 "s_register_operand" "")
2780 (match_operand:DF 1 "s_register_operand" "")))]
2781 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2785 ;; Zero and sign extension instructions.
2787 (define_insn "zero_extendsidi2"
2788 [(set (match_operand:DI 0 "s_register_operand" "=r")
2789 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2792 if (REGNO (operands[1])
2793 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2794 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2795 return \"mov%?\\t%R0, #0\";
2797 [(set_attr "length" "8")
2798 (set_attr "predicable" "yes")]
2801 (define_insn "zero_extendqidi2"
2802 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
2803 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2806 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
2807 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
2808 [(set_attr "length" "8")
2809 (set_attr "predicable" "yes")
2810 (set_attr "type" "*,load")
2811 (set_attr "pool_range" "*,4092")
2812 (set_attr "neg_pool_range" "*,4084")]
2815 (define_insn "extendsidi2"
2816 [(set (match_operand:DI 0 "s_register_operand" "=r")
2817 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2820 if (REGNO (operands[1])
2821 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2822 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2823 return \"mov%?\\t%R0, %Q0, asr #31\";
2825 [(set_attr "length" "8")
2826 (set_attr "shift" "1")
2827 (set_attr "predicable" "yes")]
2830 (define_expand "zero_extendhisi2"
2832 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2834 (set (match_operand:SI 0 "s_register_operand" "")
2835 (lshiftrt:SI (match_dup 2) (const_int 16)))]
2841 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2843 /* Note: We do not have to worry about TARGET_MMU_TRAPS
2844 here because the insn below will generate an LDRH instruction
2845 rather than an LDR instruction, so we cannot get an unaligned
2847 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2848 gen_rtx_ZERO_EXTEND (SImode,
2852 if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
2854 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
2857 if (!s_register_operand (operands[1], HImode))
2858 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2859 operands[1] = gen_lowpart (SImode, operands[1]);
2860 operands[2] = gen_reg_rtx (SImode);
2862 else /* TARGET_THUMB */
2864 if (GET_CODE (operands[1]) == MEM)
2868 tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
2869 tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
2876 if (!s_register_operand (operands[1], HImode))
2877 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2878 operands[1] = gen_lowpart (SImode, operands[1]);
2879 operands[2] = gen_reg_rtx (SImode);
2881 ops[0] = operands[2];
2882 ops[1] = operands[1];
2883 ops[2] = GEN_INT (16);
2885 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
2886 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
2888 ops[0] = operands[0];
2889 ops[1] = operands[2];
2890 ops[2] = GEN_INT (16);
2892 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
2893 gen_rtx_LSHIFTRT (SImode, ops[1],
2901 (define_insn "*thumb_zero_extendhisi2"
2902 [(set (match_operand:SI 0 "register_operand" "=l")
2903 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2906 rtx mem = XEXP (operands[1], 0);
2908 if (GET_CODE (mem) == CONST)
2909 mem = XEXP (mem, 0);
2911 if (GET_CODE (mem) == LABEL_REF)
2912 return \"ldr\\t%0, %1\";
2914 if (GET_CODE (mem) == PLUS)
2916 rtx a = XEXP (mem, 0);
2917 rtx b = XEXP (mem, 1);
2919 /* This can happen due to bugs in reload. */
2920 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
2923 ops[0] = operands[0];
2926 output_asm_insn (\"mov %0, %1\", ops);
2928 XEXP (mem, 0) = operands[0];
2931 else if ( GET_CODE (a) == LABEL_REF
2932 && GET_CODE (b) == CONST_INT)
2933 return \"ldr\\t%0, %1\";
2936 return \"ldrh\\t%0, %1\";
2938 [(set_attr "length" "4")
2939 (set_attr "type" "load")
2940 (set_attr "pool_range" "60")]
2943 (define_insn "*arm_zero_extendhisi2"
2944 [(set (match_operand:SI 0 "s_register_operand" "=r")
2945 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2946 "TARGET_ARM && arm_arch4"
2948 [(set_attr "type" "load")
2949 (set_attr "predicable" "yes")
2950 (set_attr "pool_range" "256")
2951 (set_attr "neg_pool_range" "244")]
2955 [(set (match_operand:SI 0 "s_register_operand" "")
2956 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2957 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2958 "TARGET_ARM && (!arm_arch4)"
2959 [(set (match_dup 2) (match_dup 1))
2960 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
2962 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
2968 [(set (match_operand:SI 0 "s_register_operand" "")
2969 (match_operator:SI 3 "shiftable_operator"
2970 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2971 (match_operand:SI 4 "s_register_operand" "")]))
2972 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2973 "TARGET_ARM && (!arm_arch4)"
2974 [(set (match_dup 2) (match_dup 1))
2977 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2979 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
2984 (define_expand "zero_extendqisi2"
2985 [(set (match_operand:SI 0 "s_register_operand" "")
2986 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
2989 if (GET_CODE (operands[1]) != MEM)
2993 emit_insn (gen_andsi3 (operands[0],
2994 gen_lowpart (SImode, operands[1]),
2997 else /* TARGET_THUMB */
2999 rtx temp = gen_reg_rtx (SImode);
3002 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3003 operands[1] = gen_lowpart (SImode, operands[1]);
3006 ops[1] = operands[1];
3007 ops[2] = GEN_INT (24);
3009 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3010 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3012 ops[0] = operands[0];
3014 ops[2] = GEN_INT (24);
3016 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3017 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3024 (define_insn "*thumb_zero_extendqisi2"
3025 [(set (match_operand:SI 0 "register_operand" "=l")
3026 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3029 [(set_attr "length" "2")
3030 (set_attr "type" "load")
3031 (set_attr "pool_range" "32")]
3034 (define_insn "*arm_zero_extendqisi2"
3035 [(set (match_operand:SI 0 "s_register_operand" "=r")
3036 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3038 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3039 [(set_attr "type" "load")
3040 (set_attr "predicable" "yes")
3041 (set_attr "pool_range" "4096")
3042 (set_attr "neg_pool_range" "4084")]
3046 [(set (match_operand:SI 0 "s_register_operand" "")
3047 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3048 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3049 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3050 [(set (match_dup 2) (match_dup 1))
3051 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3055 (define_insn "*compareqi_eq0"
3056 [(set (reg:CC_Z CC_REGNUM)
3057 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3061 [(set_attr "conds" "set")]
3064 (define_expand "extendhisi2"
3066 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3068 (set (match_operand:SI 0 "s_register_operand" "")
3069 (ashiftrt:SI (match_dup 2)
3074 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3076 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3077 here because the insn below will generate an LDRH instruction
3078 rather than an LDR instruction, so we cannot get an unaligned
3080 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3081 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3085 if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3087 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3090 if (!s_register_operand (operands[1], HImode))
3091 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3092 operands[1] = gen_lowpart (SImode, operands[1]);
3093 operands[2] = gen_reg_rtx (SImode);
3099 ops[0] = operands[2];
3100 ops[1] = operands[1];
3101 ops[2] = GEN_INT (16);
3103 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3104 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3106 ops[0] = operands[0];
3107 ops[1] = operands[2];
3108 ops[2] = GEN_INT (16);
3110 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3111 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3118 (define_insn "*thumb_extendhisi2_insn"
3119 [(set (match_operand:SI 0 "register_operand" "=l")
3120 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3121 (clobber (match_scratch:SI 2 "=&l"))]
3126 rtx mem = XEXP (operands[1], 0);
3128 /* This code used to try to use 'V', and fix the address only if it was
3129 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3130 range of QImode offsets, and offsettable_address_p does a QImode
3133 if (GET_CODE (mem) == CONST)
3134 mem = XEXP (mem, 0);
3136 if (GET_CODE (mem) == LABEL_REF)
3137 return \"ldr\\t%0, %1\";
3139 if (GET_CODE (mem) == PLUS)
3141 rtx a = XEXP (mem, 0);
3142 rtx b = XEXP (mem, 1);
3144 if (GET_CODE (a) == LABEL_REF
3145 && GET_CODE (b) == CONST_INT)
3146 return \"ldr\\t%0, %1\";
3148 if (GET_CODE (b) == REG)
3149 return \"ldrsh\\t%0, %1\";
3157 ops[2] = const0_rtx;
3160 if (GET_CODE (ops[1]) != REG)
3166 ops[0] = operands[0];
3167 ops[3] = operands[2];
3168 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3171 [(set_attr "length" "4")
3172 (set_attr "type" "load")
3173 (set_attr "pool_range" "1020")]
3176 (define_expand "extendhisi2_mem"
3177 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3179 (zero_extend:SI (match_dup 7)))
3180 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3181 (set (match_operand:SI 0 "" "")
3182 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3187 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3189 mem1 = gen_rtx_MEM (QImode, addr);
3190 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3191 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3192 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3193 operands[0] = gen_lowpart (SImode, operands[0]);
3195 operands[2] = gen_reg_rtx (SImode);
3196 operands[3] = gen_reg_rtx (SImode);
3197 operands[6] = gen_reg_rtx (SImode);
3200 if (BYTES_BIG_ENDIAN)
3202 operands[4] = operands[2];
3203 operands[5] = operands[3];
3207 operands[4] = operands[3];
3208 operands[5] = operands[2];
3213 (define_insn "*arm_extendhisi_insn"
3214 [(set (match_operand:SI 0 "s_register_operand" "=r")
3215 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3216 "TARGET_ARM && arm_arch4"
3218 [(set_attr "type" "load")
3219 (set_attr "predicable" "yes")
3220 (set_attr "pool_range" "256")
3221 (set_attr "neg_pool_range" "244")]
3225 [(set (match_operand:SI 0 "s_register_operand" "")
3226 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3227 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3228 "TARGET_ARM && (!arm_arch4)"
3229 [(set (match_dup 2) (match_dup 1))
3230 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3232 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3238 [(set (match_operand:SI 0 "s_register_operand" "")
3239 (match_operator:SI 3 "shiftable_operator"
3240 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3241 (match_operand:SI 4 "s_register_operand" "")]))
3242 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3243 "TARGET_ARM && (!arm_arch4)"
3244 [(set (match_dup 2) (match_dup 1))
3247 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3248 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3253 (define_expand "extendqihi2"
3255 (ashift:SI (match_operand:QI 1 "general_operand" "")
3257 (set (match_operand:HI 0 "s_register_operand" "")
3258 (ashiftrt:SI (match_dup 2)
3263 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3265 emit_insn (gen_rtx_SET (VOIDmode,
3267 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3270 if (!s_register_operand (operands[1], QImode))
3271 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3272 operands[0] = gen_lowpart (SImode, operands[0]);
3273 operands[1] = gen_lowpart (SImode, operands[1]);
3274 operands[2] = gen_reg_rtx (SImode);
3278 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3279 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3280 (define_insn "*extendqihi_insn"
3281 [(set (match_operand:HI 0 "s_register_operand" "=r")
3282 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3283 "TARGET_ARM && arm_arch4"
3285 /* If the address is invalid, this will split the instruction into two. */
3286 if (bad_signed_byte_operand (operands[1], VOIDmode))
3288 return \"ldr%?sb\\t%0, %1\";
3290 [(set_attr "type" "load")
3291 (set_attr "predicable" "yes")
3292 (set_attr "length" "8")
3293 (set_attr "pool_range" "256")
3294 (set_attr "neg_pool_range" "244")]
3298 [(set (match_operand:HI 0 "s_register_operand" "")
3299 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3300 "TARGET_ARM && arm_arch4 && reload_completed"
3301 [(set (match_dup 3) (match_dup 1))
3302 (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3305 HOST_WIDE_INT offset;
3307 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3308 operands[2] = gen_rtx_MEM (QImode, operands[3]);
3309 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3310 operands[1] = XEXP (operands[1], 0);
3311 if (GET_CODE (operands[1]) == PLUS
3312 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3313 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3314 || const_ok_for_arm (-offset)))
3316 HOST_WIDE_INT low = (offset > 0
3317 ? (offset & 0xff) : -((-offset) & 0xff));
3318 XEXP (operands[2], 0) = plus_constant (operands[3], low);
3319 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3321 /* Ensure the sum is in correct canonical form */
3322 else if (GET_CODE (operands[1]) == PLUS
3323 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3324 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3325 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3326 XEXP (operands[1], 1),
3327 XEXP (operands[1], 0));
3331 (define_expand "extendqisi2"
3333 (ashift:SI (match_operand:QI 1 "general_operand" "")
3335 (set (match_operand:SI 0 "s_register_operand" "")
3336 (ashiftrt:SI (match_dup 2)
3341 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3343 emit_insn (gen_rtx_SET (VOIDmode,
3345 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3348 if (!s_register_operand (operands[1], QImode))
3349 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3350 operands[1] = gen_lowpart (SImode, operands[1]);
3351 operands[2] = gen_reg_rtx (SImode);
3357 ops[0] = operands[2];
3358 ops[1] = operands[1];
3359 ops[2] = GEN_INT (24);
3361 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3362 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3364 ops[0] = operands[0];
3365 ops[1] = operands[2];
3366 ops[2] = GEN_INT (24);
3368 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3369 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3376 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3377 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3378 (define_insn "*arm_extendqisi_insn"
3379 [(set (match_operand:SI 0 "s_register_operand" "=r")
3380 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3381 "TARGET_ARM && arm_arch4"
3383 /* If the address is invalid, this will split the instruction into two. */
3384 if (bad_signed_byte_operand (operands[1], VOIDmode))
3386 return \"ldr%?sb\\t%0, %1\";
3388 [(set_attr "type" "load")
3389 (set_attr "predicable" "yes")
3390 (set_attr "length" "8")
3391 (set_attr "pool_range" "256")
3392 (set_attr "neg_pool_range" "244")]
3396 [(set (match_operand:SI 0 "s_register_operand" "")
3397 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3398 "TARGET_ARM && arm_arch4 && reload_completed"
3399 [(set (match_dup 0) (match_dup 1))
3400 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3403 HOST_WIDE_INT offset;
3405 operands[2] = gen_rtx_MEM (QImode, operands[0]);
3406 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3407 operands[1] = XEXP (operands[1], 0);
3408 if (GET_CODE (operands[1]) == PLUS
3409 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3410 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3411 || const_ok_for_arm (-offset)))
3413 HOST_WIDE_INT low = (offset > 0
3414 ? (offset & 0xff) : -((-offset) & 0xff));
3415 XEXP (operands[2], 0) = plus_constant (operands[0], low);
3416 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3418 /* Ensure the sum is in correct canonical form */
3419 else if (GET_CODE (operands[1]) == PLUS
3420 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3421 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3422 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3423 XEXP (operands[1], 1),
3424 XEXP (operands[1], 0));
3428 (define_insn "*thumb_extendqisi2_insn"
3429 [(set (match_operand:SI 0 "register_operand" "=l,l")
3430 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3435 rtx mem = XEXP (operands[1], 0);
3437 if (GET_CODE (mem) == CONST)
3438 mem = XEXP (mem, 0);
3440 if (GET_CODE (mem) == LABEL_REF)
3441 return \"ldr\\t%0, %1\";
3443 if (GET_CODE (mem) == PLUS
3444 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3445 return \"ldr\\t%0, %1\";
3447 if (which_alternative == 0)
3448 return \"ldrsb\\t%0, %1\";
3450 ops[0] = operands[0];
3452 if (GET_CODE (mem) == PLUS)
3454 rtx a = XEXP (mem, 0);
3455 rtx b = XEXP (mem, 1);
3460 if (GET_CODE (a) == REG)
3462 if (GET_CODE (b) == REG)
3463 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3464 else if (REGNO (a) == REGNO (ops[0]))
3466 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3467 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3468 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3471 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3473 else if (GET_CODE (b) != REG)
3477 if (REGNO (b) == REGNO (ops[0]))
3479 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3480 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3481 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3484 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3487 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3489 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3490 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3491 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3496 ops[2] = const0_rtx;
3498 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3502 [(set_attr "length" "2,6")
3503 (set_attr "type" "load,load")
3504 (set_attr "pool_range" "32,32")]
3507 (define_expand "extendsfdf2"
3508 [(set (match_operand:DF 0 "s_register_operand" "")
3509 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
3510 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3514 ;; Move insns (including loads and stores)
3516 ;; XXX Just some ideas about movti.
3517 ;; I don't think these are a good idea on the arm, there just aren't enough
3519 ;;(define_expand "loadti"
3520 ;; [(set (match_operand:TI 0 "s_register_operand" "")
3521 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
3524 ;;(define_expand "storeti"
3525 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3526 ;; (match_operand:TI 1 "s_register_operand" ""))]
3529 ;;(define_expand "movti"
3530 ;; [(set (match_operand:TI 0 "general_operand" "")
3531 ;; (match_operand:TI 1 "general_operand" ""))]
3537 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3538 ;; operands[1] = copy_to_reg (operands[1]);
3539 ;; if (GET_CODE (operands[0]) == MEM)
3540 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3541 ;; else if (GET_CODE (operands[1]) == MEM)
3542 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3546 ;; emit_insn (insn);
3550 ;; Recognize garbage generated above.
3553 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3554 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3558 ;; register mem = (which_alternative < 3);
3559 ;; register const char *template;
3561 ;; operands[mem] = XEXP (operands[mem], 0);
3562 ;; switch (which_alternative)
3564 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3565 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
3566 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
3567 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
3568 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
3569 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
3571 ;; output_asm_insn (template, operands);
3575 (define_expand "movdi"
3576 [(set (match_operand:DI 0 "general_operand" "")
3577 (match_operand:DI 1 "general_operand" ""))]
3582 if (!no_new_pseudos)
3584 if (GET_CODE (operands[0]) != REG)
3585 operands[1] = force_reg (DImode, operands[1]);
3591 (define_insn "*arm_movdi"
3592 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3593 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
3594 "TARGET_ARM && !TARGET_CIRRUS"
3596 return (output_move_double (operands));
3598 [(set_attr "length" "8")
3599 (set_attr "type" "*,load,store2")
3600 (set_attr "pool_range" "*,1020,*")
3601 (set_attr "neg_pool_range" "*,1008,*")]
3604 ;;; ??? This should have alternatives for constants.
3605 ;;; ??? This was originally identical to the movdf_insn pattern.
3606 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3607 ;;; thumb_reorg with a memory reference.
3608 (define_insn "*thumb_movdi_insn"
3609 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3610 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
3613 && ( register_operand (operands[0], DImode)
3614 || register_operand (operands[1], DImode))"
3617 switch (which_alternative)
3621 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3622 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
3623 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
3625 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3627 operands[1] = GEN_INT (- INTVAL (operands[1]));
3628 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3630 return \"ldmia\\t%1, {%0, %H0}\";
3632 return \"stmia\\t%0, {%1, %H1}\";
3634 return thumb_load_double_from_address (operands);
3636 operands[2] = gen_rtx (MEM, SImode,
3637 plus_constant (XEXP (operands[0], 0), 4));
3638 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3641 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3642 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
3643 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
3646 [(set_attr "length" "4,4,6,2,2,6,4,4")
3647 (set_attr "type" "*,*,*,load,store2,load,store2,*")
3648 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
3651 (define_expand "movsi"
3652 [(set (match_operand:SI 0 "general_operand" "")
3653 (match_operand:SI 1 "general_operand" ""))]
3658 /* Everything except mem = const or mem = mem can be done easily */
3659 if (GET_CODE (operands[0]) == MEM)
3660 operands[1] = force_reg (SImode, operands[1]);
3661 if (GET_CODE (operands[1]) == CONST_INT
3662 && !(const_ok_for_arm (INTVAL (operands[1]))
3663 || const_ok_for_arm (~INTVAL (operands[1]))))
3665 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3668 : preserve_subexpressions_p ()));
3672 else /* TARGET_THUMB.... */
3674 if (!no_new_pseudos)
3676 if (GET_CODE (operands[0]) != REG)
3677 operands[1] = force_reg (SImode, operands[1]);
3682 && (CONSTANT_P (operands[1])
3683 || symbol_mentioned_p (operands[1])
3684 || label_mentioned_p (operands[1])))
3685 operands[1] = legitimize_pic_address (operands[1], SImode,
3686 (no_new_pseudos ? operands[0] : 0));
3690 (define_insn "*arm_movsi_insn"
3691 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
3692 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
3694 && ( register_operand (operands[0], SImode)
3695 || register_operand (operands[1], SImode))"
3701 [(set_attr "type" "*,*,load,store1")
3702 (set_attr "predicable" "yes")
3703 (set_attr "pool_range" "*,*,4096,*")
3704 (set_attr "neg_pool_range" "*,*,4084,*")]
3708 [(set (match_operand:SI 0 "s_register_operand" "")
3709 (match_operand:SI 1 "const_int_operand" ""))]
3711 && (!(const_ok_for_arm (INTVAL (operands[1]))
3712 || const_ok_for_arm (~INTVAL (operands[1]))))"
3713 [(clobber (const_int 0))]
3715 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3721 (define_insn "*thumb_movsi_insn"
3722 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
3723 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
3725 && ( register_operand (operands[0], SImode)
3726 || register_operand (operands[1], SImode))"
3737 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
3738 (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
3739 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
3743 [(set (match_operand:SI 0 "register_operand" "")
3744 (match_operand:SI 1 "const_int_operand" ""))]
3745 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
3746 [(set (match_dup 0) (match_dup 1))
3747 (set (match_dup 0) (neg:SI (match_dup 0)))]
3748 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
3752 [(set (match_operand:SI 0 "register_operand" "")
3753 (match_operand:SI 1 "const_int_operand" ""))]
3754 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
3755 [(set (match_dup 0) (match_dup 1))
3756 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
3759 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
3760 unsigned HOST_WIDE_INT mask = 0xff;
3763 for (i = 0; i < 25; i++)
3764 if ((val & (mask << i)) == val)
3767 /* Shouldn't happen, but we don't want to split if the shift is zero. */
3771 operands[1] = GEN_INT (val >> i);
3772 operands[2] = GEN_INT (i);
3776 ;; When generating pic, we need to load the symbol offset into a register.
3777 ;; So that the optimizer does not confuse this with a normal symbol load
3778 ;; we use an unspec. The offset will be loaded from a constant pool entry,
3779 ;; since that is the only type of relocation we can use.
3781 ;; The rather odd constraints on the following are to force reload to leave
3782 ;; the insn alone, and to force the minipool generation pass to then move
3783 ;; the GOT symbol to memory.
3785 (define_insn "pic_load_addr_arm"
3786 [(set (match_operand:SI 0 "s_register_operand" "=r")
3787 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3788 "TARGET_ARM && flag_pic"
3790 [(set_attr "type" "load")
3791 (set (attr "pool_range") (const_int 4096))
3792 (set (attr "neg_pool_range") (const_int 4084))]
3795 (define_insn "pic_load_addr_thumb"
3796 [(set (match_operand:SI 0 "s_register_operand" "=l")
3797 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3798 "TARGET_THUMB && flag_pic"
3800 [(set_attr "type" "load")
3801 (set (attr "pool_range") (const_int 1024))]
3804 ;; This variant is used for AOF assembly, since it needs to mention the
3805 ;; pic register in the rtl.
3806 (define_expand "pic_load_addr_based"
3807 [(set (match_operand:SI 0 "s_register_operand" "")
3808 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
3809 "TARGET_ARM && flag_pic"
3810 "operands[2] = pic_offset_table_rtx;"
3813 (define_insn "*pic_load_addr_based_insn"
3814 [(set (match_operand:SI 0 "s_register_operand" "=r")
3815 (unspec:SI [(match_operand 1 "" "")
3816 (match_operand 2 "s_register_operand" "r")]
3818 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
3820 #ifdef AOF_ASSEMBLER
3821 operands[1] = aof_pic_entry (operands[1]);
3823 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
3826 [(set_attr "type" "load")
3827 (set (attr "pool_range")
3828 (if_then_else (eq_attr "is_thumb" "yes")
3831 (set (attr "neg_pool_range")
3832 (if_then_else (eq_attr "is_thumb" "yes")
3837 (define_insn "pic_add_dot_plus_four"
3838 [(set (match_operand:SI 0 "register_operand" "+r")
3839 (unspec:SI [(plus:SI (match_dup 0)
3840 (const (plus:SI (pc) (const_int 4))))]
3842 (use (label_ref (match_operand 1 "" "")))]
3843 "TARGET_THUMB && flag_pic"
3845 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3846 CODE_LABEL_NUMBER (operands[1]));
3847 return \"add\\t%0, %|pc\";
3849 [(set_attr "length" "2")]
3852 (define_insn "pic_add_dot_plus_eight"
3853 [(set (match_operand:SI 0 "register_operand" "+r")
3854 (unspec:SI [(plus:SI (match_dup 0)
3855 (const (plus:SI (pc) (const_int 8))))]
3857 (use (label_ref (match_operand 1 "" "")))]
3858 "TARGET_ARM && flag_pic"
3860 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3861 CODE_LABEL_NUMBER (operands[1]));
3862 return \"add%?\\t%0, %|pc, %0\";
3864 [(set_attr "predicable" "yes")]
3867 (define_expand "builtin_setjmp_receiver"
3868 [(label_ref (match_operand 0 "" ""))]
3872 arm_finalize_pic (0);
3876 ;; If copying one reg to another we can set the condition codes according to
3877 ;; its value. Such a move is common after a return from subroutine and the
3878 ;; result is being tested against zero.
3880 (define_insn "*movsi_compare0"
3881 [(set (reg:CC CC_REGNUM)
3882 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
3884 (set (match_operand:SI 0 "s_register_operand" "=r,r")
3889 sub%?s\\t%0, %1, #0"
3890 [(set_attr "conds" "set")]
3893 ;; Subroutine to store a half word from a register into memory.
3894 ;; Operand 0 is the source register (HImode)
3895 ;; Operand 1 is the destination address in a register (SImode)
3897 ;; In both this routine and the next, we must be careful not to spill
3898 ;; a memory address of reg+large_const into a separate PLUS insn, since this
3899 ;; can generate unrecognizable rtl.
3901 (define_expand "storehi"
3902 [;; store the low byte
3903 (set (match_operand 1 "" "") (match_dup 3))
3904 ;; extract the high byte
3906 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
3907 ;; store the high byte
3908 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
3912 rtx op1 = operands[1];
3913 rtx addr = XEXP (op1, 0);
3914 enum rtx_code code = GET_CODE (addr);
3916 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
3918 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
3920 operands[4] = adjust_address (op1, QImode, 1);
3921 operands[1] = adjust_address (operands[1], QImode, 0);
3922 operands[3] = gen_lowpart (QImode, operands[0]);
3923 operands[0] = gen_lowpart (SImode, operands[0]);
3924 operands[2] = gen_reg_rtx (SImode);
3928 (define_expand "storehi_bigend"
3929 [(set (match_dup 4) (match_dup 3))
3931 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
3932 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 3))]
3936 rtx op1 = operands[1];
3937 rtx addr = XEXP (op1, 0);
3938 enum rtx_code code = GET_CODE (addr);
3940 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
3942 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
3944 operands[4] = adjust_address (op1, QImode, 1);
3945 operands[1] = adjust_address (operands[1], QImode, 0);
3946 operands[3] = gen_lowpart (QImode, operands[0]);
3947 operands[0] = gen_lowpart (SImode, operands[0]);
3948 operands[2] = gen_reg_rtx (SImode);
3952 ;; Subroutine to store a half word integer constant into memory.
3953 (define_expand "storeinthi"
3954 [(set (match_operand 0 "" "")
3955 (subreg:QI (match_operand 1 "" "") 0))
3956 (set (match_dup 3) (match_dup 2))]
3960 HOST_WIDE_INT value = INTVAL (operands[1]);
3961 rtx addr = XEXP (operands[0], 0);
3962 rtx op0 = operands[0];
3963 enum rtx_code code = GET_CODE (addr);
3965 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
3967 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
3969 operands[1] = gen_reg_rtx (SImode);
3970 if (BYTES_BIG_ENDIAN)
3972 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
3973 if ((value & 255) == ((value >> 8) & 255))
3974 operands[2] = operands[1];
3977 operands[2] = gen_reg_rtx (SImode);
3978 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
3983 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
3984 if ((value & 255) == ((value >> 8) & 255))
3985 operands[2] = operands[1];
3988 operands[2] = gen_reg_rtx (SImode);
3989 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
3993 operands[3] = adjust_address (op0, QImode, 1);
3994 operands[0] = adjust_address (operands[0], QImode, 0);
3995 operands[2] = gen_lowpart (QImode, operands[2]);
3999 (define_expand "storehi_single_op"
4000 [(set (match_operand:HI 0 "memory_operand" "")
4001 (match_operand:HI 1 "general_operand" ""))]
4002 "TARGET_ARM && arm_arch4"
4004 if (!s_register_operand (operands[1], HImode))
4005 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4009 (define_expand "movhi"
4010 [(set (match_operand:HI 0 "general_operand" "")
4011 (match_operand:HI 1 "general_operand" ""))]
4016 if (!no_new_pseudos)
4018 if (GET_CODE (operands[0]) == MEM)
4022 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4025 if (GET_CODE (operands[1]) == CONST_INT)
4026 emit_insn (gen_storeinthi (operands[0], operands[1]));
4029 if (GET_CODE (operands[1]) == MEM)
4030 operands[1] = force_reg (HImode, operands[1]);
4031 if (BYTES_BIG_ENDIAN)
4032 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4034 emit_insn (gen_storehi (operands[1], operands[0]));
4038 /* Sign extend a constant, and keep it in an SImode reg. */
4039 else if (GET_CODE (operands[1]) == CONST_INT)
4041 rtx reg = gen_reg_rtx (SImode);
4042 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4044 /* If the constant is already valid, leave it alone. */
4045 if (!const_ok_for_arm (val))
4047 /* If setting all the top bits will make the constant
4048 loadable in a single instruction, then set them.
4049 Otherwise, sign extend the number. */
4051 if (const_ok_for_arm (~(val | ~0xffff)))
4053 else if (val & 0x8000)
4057 emit_insn (gen_movsi (reg, GEN_INT (val)));
4058 operands[1] = gen_lowpart (HImode, reg);
4060 else if (arm_arch4 && !no_new_pseudos && optimize > 0
4061 && GET_CODE (operands[1]) == MEM)
4063 rtx reg = gen_reg_rtx (SImode);
4065 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4066 operands[1] = gen_lowpart (HImode, reg);
4068 else if (!arm_arch4)
4070 /* Note: We do not have to worry about TARGET_MMU_TRAPS
4071 for v4 and up architectures because LDRH instructions will
4072 be used to access the HI values, and these cannot generate
4073 unaligned word access faults in the MMU. */
4074 if (GET_CODE (operands[1]) == MEM)
4076 if (TARGET_MMU_TRAPS)
4079 rtx offset = const0_rtx;
4080 rtx reg = gen_reg_rtx (SImode);
4082 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4083 || (GET_CODE (base) == PLUS
4084 && (GET_CODE (offset = XEXP (base, 1))
4086 && ((INTVAL(offset) & 1) != 1)
4087 && GET_CODE (base = XEXP (base, 0)) == REG))
4088 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4090 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4093 new = gen_rtx_MEM (SImode,
4094 plus_constant (base, new_offset));
4095 MEM_COPY_ATTRIBUTES (new, operands[1]);
4096 emit_insn (gen_movsi (reg, new));
4097 if (((INTVAL (offset) & 2) != 0)
4098 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4100 rtx reg2 = gen_reg_rtx (SImode);
4102 emit_insn (gen_lshrsi3 (reg2, reg,
4108 emit_insn (gen_movhi_bytes (reg, operands[1]));
4110 operands[1] = gen_lowpart (HImode, reg);
4112 else if (BYTES_BIG_ENDIAN)
4115 rtx offset = const0_rtx;
4117 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4118 || (GET_CODE (base) == PLUS
4119 && (GET_CODE (offset = XEXP (base, 1))
4121 && GET_CODE (base = XEXP (base, 0)) == REG))
4122 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4124 rtx reg = gen_reg_rtx (SImode);
4127 if ((INTVAL (offset) & 2) == 2)
4129 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4130 new = gen_rtx_MEM (SImode,
4131 plus_constant (base,
4133 MEM_COPY_ATTRIBUTES (new, operands[1]);
4134 emit_insn (gen_movsi (reg, new));
4138 new = gen_rtx_MEM (SImode,
4139 XEXP (operands[1], 0));
4140 MEM_COPY_ATTRIBUTES (new, operands[1]);
4141 emit_insn (gen_rotated_loadsi (reg, new));
4144 operands[1] = gen_lowpart (HImode, reg);
4148 emit_insn (gen_movhi_bigend (operands[0],
4156 /* Handle loading a large integer during reload */
4157 else if (GET_CODE (operands[1]) == CONST_INT
4158 && !const_ok_for_arm (INTVAL (operands[1]))
4159 && !const_ok_for_arm (~INTVAL (operands[1])))
4161 /* Writing a constant to memory needs a scratch, which should
4162 be handled with SECONDARY_RELOADs. */
4163 if (GET_CODE (operands[0]) != REG)
4166 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4167 emit_insn (gen_movsi (operands[0], operands[1]));
4171 else /* TARGET_THUMB */
4173 if (!no_new_pseudos)
4175 if (GET_CODE (operands[0]) != REG)
4176 operands[1] = force_reg (HImode, operands[1]);
4178 /* ??? We shouldn't really get invalid addresses here, but this can
4179 happen if we are passed a SP (never OK for HImode/QImode) or
4180 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4181 HImode/QImode) relative address. */
4182 /* ??? This should perhaps be fixed elsewhere, for instance, in
4183 fixup_stack_1, by checking for other kinds of invalid addresses,
4184 e.g. a bare reference to a virtual register. This may confuse the
4185 alpha though, which must handle this case differently. */
4186 if (GET_CODE (operands[0]) == MEM
4187 && !memory_address_p (GET_MODE (operands[0]),
4188 XEXP (operands[0], 0)))
4190 = replace_equiv_address (operands[0],
4191 copy_to_reg (XEXP (operands[0], 0)));
4193 if (GET_CODE (operands[1]) == MEM
4194 && !memory_address_p (GET_MODE (operands[1]),
4195 XEXP (operands[1], 0)))
4197 = replace_equiv_address (operands[1],
4198 copy_to_reg (XEXP (operands[1], 0)));
4200 /* Handle loading a large integer during reload */
4201 else if (GET_CODE (operands[1]) == CONST_INT
4202 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4204 /* Writing a constant to memory needs a scratch, which should
4205 be handled with SECONDARY_RELOADs. */
4206 if (GET_CODE (operands[0]) != REG)
4209 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4210 emit_insn (gen_movsi (operands[0], operands[1]));
4217 (define_insn "*thumb_movhi_insn"
4218 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4219 (match_operand:HI 1 "general_operand" "l,mn,l,*h,*r,I"))]
4221 && ( register_operand (operands[0], HImode)
4222 || register_operand (operands[1], HImode))"
4224 switch (which_alternative)
4226 case 0: return \"add %0, %1, #0\";
4227 case 2: return \"strh %1, %0\";
4228 case 3: return \"mov %0, %1\";
4229 case 4: return \"mov %0, %1\";
4230 case 5: return \"mov %0, %1\";
4233 /* The stack pointer can end up being taken as an index register.
4234 Catch this case here and deal with it. */
4235 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4236 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4237 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4240 ops[0] = operands[0];
4241 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4243 output_asm_insn (\"mov %0, %1\", ops);
4245 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4248 return \"ldrh %0, %1\";
4250 [(set_attr "length" "2,4,2,2,2,2")
4251 (set_attr "type" "*,load,store1,*,*,*")
4252 (set_attr "pool_range" "*,64,*,*,*,*")]
4256 (define_insn "rotated_loadsi"
4257 [(set (match_operand:SI 0 "s_register_operand" "=r")
4258 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4260 "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4265 ops[0] = operands[0];
4266 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4267 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4270 [(set_attr "type" "load")
4271 (set_attr "predicable" "yes")]
4274 (define_expand "movhi_bytes"
4275 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4277 (zero_extend:SI (match_dup 6)))
4278 (set (match_operand:SI 0 "" "")
4279 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4284 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4286 mem1 = gen_rtx_MEM (QImode, addr);
4287 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4288 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4289 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4290 operands[0] = gen_lowpart (SImode, operands[0]);
4292 operands[2] = gen_reg_rtx (SImode);
4293 operands[3] = gen_reg_rtx (SImode);
4296 if (BYTES_BIG_ENDIAN)
4298 operands[4] = operands[2];
4299 operands[5] = operands[3];
4303 operands[4] = operands[3];
4304 operands[5] = operands[2];
4309 (define_expand "movhi_bigend"
4311 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4314 (ashiftrt:SI (match_dup 2) (const_int 16)))
4315 (set (match_operand:HI 0 "s_register_operand" "")
4316 (subreg:HI (match_dup 3) 0))]
4319 operands[2] = gen_reg_rtx (SImode);
4320 operands[3] = gen_reg_rtx (SImode);
4324 ;; Pattern to recognize insn generated default case above
4325 (define_insn "*movhi_insn_arch4"
4326 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4327 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4330 && (GET_CODE (operands[1]) != CONST_INT
4331 || const_ok_for_arm (INTVAL (operands[1]))
4332 || const_ok_for_arm (~INTVAL (operands[1])))"
4334 mov%?\\t%0, %1\\t%@ movhi
4335 mvn%?\\t%0, #%B1\\t%@ movhi
4336 str%?h\\t%1, %0\\t%@ movhi
4337 ldr%?h\\t%0, %1\\t%@ movhi"
4338 [(set_attr "type" "*,*,store1,load")
4339 (set_attr "predicable" "yes")
4340 (set_attr "pool_range" "*,*,*,256")
4341 (set_attr "neg_pool_range" "*,*,*,244")]
4344 (define_insn "*movhi_insn_littleend"
4345 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4346 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4349 && !BYTES_BIG_ENDIAN
4350 && !TARGET_MMU_TRAPS
4351 && (GET_CODE (operands[1]) != CONST_INT
4352 || const_ok_for_arm (INTVAL (operands[1]))
4353 || const_ok_for_arm (~INTVAL (operands[1])))"
4355 mov%?\\t%0, %1\\t%@ movhi
4356 mvn%?\\t%0, #%B1\\t%@ movhi
4357 ldr%?\\t%0, %1\\t%@ movhi"
4358 [(set_attr "type" "*,*,load")
4359 (set_attr "predicable" "yes")
4360 (set_attr "pool_range" "4096")
4361 (set_attr "neg_pool_range" "4084")]
4364 (define_insn "*movhi_insn_bigend"
4365 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4366 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4370 && !TARGET_MMU_TRAPS
4371 && (GET_CODE (operands[1]) != CONST_INT
4372 || const_ok_for_arm (INTVAL (operands[1]))
4373 || const_ok_for_arm (~INTVAL (operands[1])))"
4375 mov%?\\t%0, %1\\t%@ movhi
4376 mvn%?\\t%0, #%B1\\t%@ movhi
4377 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4378 [(set_attr "type" "*,*,load")
4379 (set_attr "predicable" "yes")
4380 (set_attr "length" "4,4,8")
4381 (set_attr "pool_range" "*,*,4092")
4382 (set_attr "neg_pool_range" "*,*,4084")]
4385 (define_insn "*loadhi_si_bigend"
4386 [(set (match_operand:SI 0 "s_register_operand" "=r")
4387 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
4391 && !TARGET_MMU_TRAPS"
4392 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4393 [(set_attr "type" "load")
4394 (set_attr "predicable" "yes")
4395 (set_attr "pool_range" "4096")
4396 (set_attr "neg_pool_range" "4084")]
4399 (define_insn "*movhi_bytes"
4400 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4401 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4402 "TARGET_ARM && TARGET_MMU_TRAPS"
4404 mov%?\\t%0, %1\\t%@ movhi
4405 mvn%?\\t%0, #%B1\\t%@ movhi"
4406 [(set_attr "predicable" "yes")]
4409 (define_insn "thumb_movhi_clobber"
4410 [(set (match_operand:HI 0 "memory_operand" "=m")
4411 (match_operand:HI 1 "register_operand" "l"))
4412 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4418 ;; We use a DImode scratch because we may occasionally need an additional
4419 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4420 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4421 (define_expand "reload_outhi"
4422 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4423 (match_operand:HI 1 "s_register_operand" "r")
4424 (match_operand:DI 2 "s_register_operand" "=&l")])]
4427 arm_reload_out_hi (operands);
4429 thumb_reload_out_hi (operands);
4434 (define_expand "reload_inhi"
4435 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4436 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4437 (match_operand:DI 2 "s_register_operand" "=&r")])]
4438 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4441 arm_reload_in_hi (operands);
4443 thumb_reload_out_hi (operands);
4447 (define_expand "movqi"
4448 [(set (match_operand:QI 0 "general_operand" "")
4449 (match_operand:QI 1 "general_operand" ""))]
4454 /* Everything except mem = const or mem = mem can be done easily */
4456 if (!no_new_pseudos)
4458 if (GET_CODE (operands[1]) == CONST_INT)
4460 rtx reg = gen_reg_rtx (SImode);
4462 emit_insn (gen_movsi (reg, operands[1]));
4463 operands[1] = gen_lowpart (QImode, reg);
4465 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4467 rtx reg = gen_reg_rtx (SImode);
4469 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4470 operands[1] = gen_lowpart (QImode, reg);
4472 if (GET_CODE (operands[0]) == MEM)
4473 operands[1] = force_reg (QImode, operands[1]);
4476 else /* TARGET_THUMB */
4478 if (!no_new_pseudos)
4480 if (GET_CODE (operands[0]) != REG)
4481 operands[1] = force_reg (QImode, operands[1]);
4483 /* ??? We shouldn't really get invalid addresses here, but this can
4484 happen if we are passed a SP (never OK for HImode/QImode) or
4485 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4486 HImode/QImode) relative address. */
4487 /* ??? This should perhaps be fixed elsewhere, for instance, in
4488 fixup_stack_1, by checking for other kinds of invalid addresses,
4489 e.g. a bare reference to a virtual register. This may confuse the
4490 alpha though, which must handle this case differently. */
4491 if (GET_CODE (operands[0]) == MEM
4492 && !memory_address_p (GET_MODE (operands[0]),
4493 XEXP (operands[0], 0)))
4495 = replace_equiv_address (operands[0],
4496 copy_to_reg (XEXP (operands[0], 0)));
4497 if (GET_CODE (operands[1]) == MEM
4498 && !memory_address_p (GET_MODE (operands[1]),
4499 XEXP (operands[1], 0)))
4501 = replace_equiv_address (operands[1],
4502 copy_to_reg (XEXP (operands[1], 0)));
4504 /* Handle loading a large integer during reload */
4505 else if (GET_CODE (operands[1]) == CONST_INT
4506 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4508 /* Writing a constant to memory needs a scratch, which should
4509 be handled with SECONDARY_RELOADs. */
4510 if (GET_CODE (operands[0]) != REG)
4513 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4514 emit_insn (gen_movsi (operands[0], operands[1]));
4522 (define_insn "*arm_movqi_insn"
4523 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4524 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4526 && ( register_operand (operands[0], QImode)
4527 || register_operand (operands[1], QImode))"
4533 [(set_attr "type" "*,*,load,store1")
4534 (set_attr "predicable" "yes")]
4537 (define_insn "*thumb_movqi_insn"
4538 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4539 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
4541 && ( register_operand (operands[0], QImode)
4542 || register_operand (operands[1], QImode))"
4550 [(set_attr "length" "2")
4551 (set_attr "type" "*,load,store1,*,*,*")
4552 (set_attr "pool_range" "*,32,*,*,*,*")]
4555 (define_expand "movsf"
4556 [(set (match_operand:SF 0 "general_operand" "")
4557 (match_operand:SF 1 "general_operand" ""))]
4562 if (GET_CODE (operands[0]) == MEM)
4563 operands[1] = force_reg (SFmode, operands[1]);
4565 else /* TARGET_THUMB */
4567 if (!no_new_pseudos)
4569 if (GET_CODE (operands[0]) != REG)
4570 operands[1] = force_reg (SFmode, operands[1]);
4577 [(set (match_operand:SF 0 "nonimmediate_operand" "")
4578 (match_operand:SF 1 "immediate_operand" ""))]
4580 && !TARGET_HARD_FLOAT
4582 && GET_CODE (operands[1]) == CONST_DOUBLE"
4583 [(set (match_dup 2) (match_dup 3))]
4585 operands[2] = gen_lowpart (SImode, operands[0]);
4586 operands[3] = gen_lowpart (SImode, operands[1]);
4587 if (operands[2] == 0 || operands[3] == 0)
4592 (define_insn "*arm_movsf_soft_insn"
4593 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4594 (match_operand:SF 1 "general_operand" "r,mE,r"))]
4597 && TARGET_SOFT_FLOAT
4598 && (GET_CODE (operands[0]) != MEM
4599 || register_operand (operands[1], SFmode))"
4602 ldr%?\\t%0, %1\\t%@ float
4603 str%?\\t%1, %0\\t%@ float"
4604 [(set_attr "length" "4,4,4")
4605 (set_attr "predicable" "yes")
4606 (set_attr "type" "*,load,store1")
4607 (set_attr "pool_range" "*,4096,*")
4608 (set_attr "neg_pool_range" "*,4084,*")]
4611 ;;; ??? This should have alternatives for constants.
4612 (define_insn "*thumb_movsf_insn"
4613 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4614 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
4616 && ( register_operand (operands[0], SFmode)
4617 || register_operand (operands[1], SFmode))"
4626 [(set_attr "length" "2")
4627 (set_attr "type" "*,load,store1,load,store1,*,*")
4628 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
4631 (define_expand "movdf"
4632 [(set (match_operand:DF 0 "general_operand" "")
4633 (match_operand:DF 1 "general_operand" ""))]
4638 if (GET_CODE (operands[0]) == MEM)
4639 operands[1] = force_reg (DFmode, operands[1]);
4641 else /* TARGET_THUMB */
4643 if (!no_new_pseudos)
4645 if (GET_CODE (operands[0]) != REG)
4646 operands[1] = force_reg (DFmode, operands[1]);
4652 ;; Reloading a df mode value stored in integer regs to memory can require a
4654 (define_expand "reload_outdf"
4655 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
4656 (match_operand:DF 1 "s_register_operand" "r")
4657 (match_operand:SI 2 "s_register_operand" "=&r")]
4661 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
4664 operands[2] = XEXP (operands[0], 0);
4665 else if (code == POST_INC || code == PRE_DEC)
4667 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
4668 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
4669 emit_insn (gen_movdi (operands[0], operands[1]));
4672 else if (code == PRE_INC)
4674 rtx reg = XEXP (XEXP (operands[0], 0), 0);
4676 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
4679 else if (code == POST_DEC)
4680 operands[2] = XEXP (XEXP (operands[0], 0), 0);
4682 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
4683 XEXP (XEXP (operands[0], 0), 1)));
4685 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
4688 if (code == POST_DEC)
4689 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
4695 (define_insn "*movdf_soft_insn"
4696 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
4697 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
4698 "TARGET_ARM && TARGET_SOFT_FLOAT
4701 "* return output_move_double (operands);"
4702 [(set_attr "length" "8,8,8")
4703 (set_attr "type" "*,load,store2")
4704 (set_attr "pool_range" "1020")
4705 (set_attr "neg_pool_range" "1008")]
4708 ;;; ??? This should have alternatives for constants.
4709 ;;; ??? This was originally identical to the movdi_insn pattern.
4710 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
4711 ;;; thumb_reorg with a memory reference.
4712 (define_insn "*thumb_movdf_insn"
4713 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
4714 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
4716 && ( register_operand (operands[0], DFmode)
4717 || register_operand (operands[1], DFmode))"
4719 switch (which_alternative)
4723 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4724 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4725 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4727 return \"ldmia\\t%1, {%0, %H0}\";
4729 return \"stmia\\t%0, {%1, %H1}\";
4731 return thumb_load_double_from_address (operands);
4733 operands[2] = gen_rtx (MEM, SImode,
4734 plus_constant (XEXP (operands[0], 0), 4));
4735 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4738 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4739 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4740 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4743 [(set_attr "length" "4,2,2,6,4,4")
4744 (set_attr "type" "*,load,store2,load,store2,*")
4745 (set_attr "pool_range" "*,*,*,1020,*,*")]
4749 ;; load- and store-multiple insns
4750 ;; The arm can load/store any set of registers, provided that they are in
4751 ;; ascending order; but that is beyond GCC so stick with what it knows.
4753 (define_expand "load_multiple"
4754 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
4755 (match_operand:SI 1 "" ""))
4756 (use (match_operand:SI 2 "" ""))])]
4759 /* Support only fixed point registers. */
4760 if (GET_CODE (operands[2]) != CONST_INT
4761 || INTVAL (operands[2]) > 14
4762 || INTVAL (operands[2]) < 2
4763 || GET_CODE (operands[1]) != MEM
4764 || GET_CODE (operands[0]) != REG
4765 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
4766 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
4770 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
4771 force_reg (SImode, XEXP (operands[1], 0)),
4772 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
4773 MEM_IN_STRUCT_P(operands[1]),
4774 MEM_SCALAR_P (operands[1]));
4778 ;; Load multiple with write-back
4780 (define_insn "*ldmsi_postinc4"
4781 [(match_parallel 0 "load_multiple_operation"
4782 [(set (match_operand:SI 1 "s_register_operand" "=r")
4783 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4785 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4786 (mem:SI (match_dup 2)))
4787 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4788 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
4789 (set (match_operand:SI 5 "arm_hard_register_operand" "")
4790 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
4791 (set (match_operand:SI 6 "arm_hard_register_operand" "")
4792 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
4793 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
4794 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
4795 [(set_attr "type" "load")
4796 (set_attr "predicable" "yes")]
4799 (define_insn "*ldmsi_postinc3"
4800 [(match_parallel 0 "load_multiple_operation"
4801 [(set (match_operand:SI 1 "s_register_operand" "=r")
4802 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4804 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4805 (mem:SI (match_dup 2)))
4806 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4807 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
4808 (set (match_operand:SI 5 "arm_hard_register_operand" "")
4809 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
4810 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4811 "ldm%?ia\\t%1!, {%3, %4, %5}"
4812 [(set_attr "type" "load")
4813 (set_attr "predicable" "yes")]
4816 (define_insn "*ldmsi_postinc2"
4817 [(match_parallel 0 "load_multiple_operation"
4818 [(set (match_operand:SI 1 "s_register_operand" "=r")
4819 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4821 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4822 (mem:SI (match_dup 2)))
4823 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4824 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
4825 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4826 "ldm%?ia\\t%1!, {%3, %4}"
4827 [(set_attr "type" "load")
4828 (set_attr "predicable" "yes")]
4831 ;; Ordinary load multiple
4833 (define_insn "*ldmsi4"
4834 [(match_parallel 0 "load_multiple_operation"
4835 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4836 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4837 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4838 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
4839 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4840 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
4841 (set (match_operand:SI 5 "arm_hard_register_operand" "")
4842 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
4843 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4844 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
4845 [(set_attr "type" "load")
4846 (set_attr "predicable" "yes")]
4849 (define_insn "*ldmsi3"
4850 [(match_parallel 0 "load_multiple_operation"
4851 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4852 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4853 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4854 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
4855 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4856 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
4857 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4858 "ldm%?ia\\t%1, {%2, %3, %4}"
4859 [(set_attr "type" "load")
4860 (set_attr "predicable" "yes")]
4863 (define_insn "*ldmsi2"
4864 [(match_parallel 0 "load_multiple_operation"
4865 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4866 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4867 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4868 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
4869 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
4870 "ldm%?ia\\t%1, {%2, %3}"
4871 [(set_attr "type" "load")
4872 (set_attr "predicable" "yes")]
4875 (define_expand "store_multiple"
4876 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
4877 (match_operand:SI 1 "" ""))
4878 (use (match_operand:SI 2 "" ""))])]
4881 /* Support only fixed point registers */
4882 if (GET_CODE (operands[2]) != CONST_INT
4883 || INTVAL (operands[2]) > 14
4884 || INTVAL (operands[2]) < 2
4885 || GET_CODE (operands[1]) != REG
4886 || GET_CODE (operands[0]) != MEM
4887 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
4888 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
4892 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
4893 force_reg (SImode, XEXP (operands[0], 0)),
4894 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
4895 MEM_IN_STRUCT_P(operands[0]),
4896 MEM_SCALAR_P (operands[0]));
4900 ;; Store multiple with write-back
4902 (define_insn "*stmsi_postinc4"
4903 [(match_parallel 0 "store_multiple_operation"
4904 [(set (match_operand:SI 1 "s_register_operand" "=r")
4905 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4907 (set (mem:SI (match_dup 2))
4908 (match_operand:SI 3 "arm_hard_register_operand" ""))
4909 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
4910 (match_operand:SI 4 "arm_hard_register_operand" ""))
4911 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
4912 (match_operand:SI 5 "arm_hard_register_operand" ""))
4913 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
4914 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
4915 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
4916 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
4917 [(set_attr "predicable" "yes")
4918 (set_attr "type" "store4")]
4921 (define_insn "*stmsi_postinc3"
4922 [(match_parallel 0 "store_multiple_operation"
4923 [(set (match_operand:SI 1 "s_register_operand" "=r")
4924 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4926 (set (mem:SI (match_dup 2))
4927 (match_operand:SI 3 "arm_hard_register_operand" ""))
4928 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
4929 (match_operand:SI 4 "arm_hard_register_operand" ""))
4930 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
4931 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
4932 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4933 "stm%?ia\\t%1!, {%3, %4, %5}"
4934 [(set_attr "predicable" "yes")
4935 (set_attr "type" "store3")]
4938 (define_insn "*stmsi_postinc2"
4939 [(match_parallel 0 "store_multiple_operation"
4940 [(set (match_operand:SI 1 "s_register_operand" "=r")
4941 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4943 (set (mem:SI (match_dup 2))
4944 (match_operand:SI 3 "arm_hard_register_operand" ""))
4945 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
4946 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
4947 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4948 "stm%?ia\\t%1!, {%3, %4}"
4949 [(set_attr "predicable" "yes")
4950 (set_attr "type" "store2")]
4953 ;; Ordinary store multiple
4955 (define_insn "*stmsi4"
4956 [(match_parallel 0 "store_multiple_operation"
4957 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
4958 (match_operand:SI 2 "arm_hard_register_operand" ""))
4959 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
4960 (match_operand:SI 3 "arm_hard_register_operand" ""))
4961 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
4962 (match_operand:SI 4 "arm_hard_register_operand" ""))
4963 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
4964 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
4965 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4966 "stm%?ia\\t%1, {%2, %3, %4, %5}"
4967 [(set_attr "predicable" "yes")
4968 (set_attr "type" "store4")]
4971 (define_insn "*stmsi3"
4972 [(match_parallel 0 "store_multiple_operation"
4973 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
4974 (match_operand:SI 2 "arm_hard_register_operand" ""))
4975 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
4976 (match_operand:SI 3 "arm_hard_register_operand" ""))
4977 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
4978 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
4979 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4980 "stm%?ia\\t%1, {%2, %3, %4}"
4981 [(set_attr "predicable" "yes")
4982 (set_attr "type" "store3")]
4985 (define_insn "*stmsi2"
4986 [(match_parallel 0 "store_multiple_operation"
4987 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
4988 (match_operand:SI 2 "arm_hard_register_operand" ""))
4989 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
4990 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
4991 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
4992 "stm%?ia\\t%1, {%2, %3}"
4993 [(set_attr "predicable" "yes")
4994 (set_attr "type" "store2")]
4997 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
4998 ;; We could let this apply for blocks of less than this, but it clobbers so
4999 ;; many registers that there is then probably a better way.
5001 (define_expand "movstrqi"
5002 [(match_operand:BLK 0 "general_operand" "")
5003 (match_operand:BLK 1 "general_operand" "")
5004 (match_operand:SI 2 "const_int_operand" "")
5005 (match_operand:SI 3 "const_int_operand" "")]
5010 if (arm_gen_movstrqi (operands))
5014 else /* TARGET_THUMB */
5016 if ( INTVAL (operands[3]) != 4
5017 || INTVAL (operands[2]) > 48)
5020 thumb_expand_movstrqi (operands);
5026 ;; Thumb block-move insns
5028 (define_insn "movmem12b"
5029 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5030 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5031 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5032 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5033 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5034 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5035 (set (match_operand:SI 0 "register_operand" "=l")
5036 (plus:SI (match_dup 2) (const_int 12)))
5037 (set (match_operand:SI 1 "register_operand" "=l")
5038 (plus:SI (match_dup 3) (const_int 12)))
5039 (clobber (match_scratch:SI 4 "=&l"))
5040 (clobber (match_scratch:SI 5 "=&l"))
5041 (clobber (match_scratch:SI 6 "=&l"))]
5043 "* return thumb_output_move_mem_multiple (3, operands);"
5044 [(set_attr "length" "4")
5045 ; This isn't entirely accurate... It loads as well, but in terms of
5046 ; scheduling the following insn it is better to consider it as a store
5047 (set_attr "type" "store3")]
5050 (define_insn "movmem8b"
5051 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5052 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5053 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5054 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5055 (set (match_operand:SI 0 "register_operand" "=l")
5056 (plus:SI (match_dup 2) (const_int 8)))
5057 (set (match_operand:SI 1 "register_operand" "=l")
5058 (plus:SI (match_dup 3) (const_int 8)))
5059 (clobber (match_scratch:SI 4 "=&l"))
5060 (clobber (match_scratch:SI 5 "=&l"))]
5062 "* return thumb_output_move_mem_multiple (2, operands);"
5063 [(set_attr "length" "4")
5064 ; This isn't entirely accurate... It loads as well, but in terms of
5065 ; scheduling the following insn it is better to consider it as a store
5066 (set_attr "type" "store2")]
5071 ;; Compare & branch insns
5072 ;; The range calcualations are based as follows:
5073 ;; For forward branches, the address calculation returns the address of
5074 ;; the next instruction. This is 2 beyond the branch instruction.
5075 ;; For backward branches, the address calculation returns the address of
5076 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5077 ;; instruction for the shortest sequence, and 4 before the branch instruction
5078 ;; if we have to jump around an unconditional branch.
5079 ;; To the basic branch range the PC offset must be added (this is +4).
5080 ;; So for forward branches we have
5081 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5082 ;; And for backward branches we have
5083 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5085 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5086 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5088 (define_insn "cbranchsi4"
5091 (match_operator 0 "arm_comparison_operator"
5092 [(match_operand:SI 1 "register_operand" "l,r")
5093 (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5094 (label_ref (match_operand 3 "" ""))
5098 output_asm_insn (\"cmp\\t%1, %2\", operands);
5099 switch (get_attr_length (insn))
5101 case 4: return \"b%d0\\t%l3\";
5102 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5103 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5106 [(set (attr "far_jump")
5108 (eq_attr "length" "8")
5109 (const_string "yes")
5110 (const_string "no")))
5111 (set (attr "length")
5113 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5114 (le (minus (match_dup 3) (pc)) (const_int 256)))
5117 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5118 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5123 (define_insn "*negated_cbranchsi4"
5126 (match_operator 0 "arm_comparison_operator"
5127 [(match_operand:SI 1 "register_operand" "l")
5128 (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5129 (label_ref (match_operand 3 "" ""))
5133 output_asm_insn (\"cmn\\t%1, %2\", operands);
5134 switch (get_attr_length (insn))
5136 case 4: return \"b%d0\\t%l3\";
5137 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5138 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5141 [(set (attr "far_jump")
5143 (eq_attr "length" "8")
5144 (const_string "yes")
5145 (const_string "no")))
5146 (set (attr "length")
5148 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5149 (le (minus (match_dup 3) (pc)) (const_int 256)))
5152 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5153 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5159 ;; Comparison and test insns
5161 (define_expand "cmpsi"
5162 [(match_operand:SI 0 "s_register_operand" "")
5163 (match_operand:SI 1 "arm_add_operand" "")]
5166 arm_compare_op0 = operands[0];
5167 arm_compare_op1 = operands[1];
5172 (define_expand "cmpsf"
5173 [(match_operand:SF 0 "s_register_operand" "")
5174 (match_operand:SF 1 "fpa_rhs_operand" "")]
5175 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5177 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
5178 operands[1] = force_reg (SFmode, operands[1]);
5180 arm_compare_op0 = operands[0];
5181 arm_compare_op1 = operands[1];
5186 (define_expand "cmpdf"
5187 [(match_operand:DF 0 "s_register_operand" "")
5188 (match_operand:DF 1 "fpa_rhs_operand" "")]
5189 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5191 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
5192 operands[1] = force_reg (DFmode, operands[1]);
5194 arm_compare_op0 = operands[0];
5195 arm_compare_op1 = operands[1];
5200 (define_insn "*arm_cmpsi_insn"
5201 [(set (reg:CC CC_REGNUM)
5202 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5203 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
5208 [(set_attr "conds" "set")]
5211 (define_insn "*cmpsi_shiftsi"
5212 [(set (reg:CC CC_REGNUM)
5213 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5214 (match_operator:SI 3 "shift_operator"
5215 [(match_operand:SI 1 "s_register_operand" "r")
5216 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
5219 [(set_attr "conds" "set")
5220 (set_attr "shift" "1")
5224 (define_insn "*cmpsi_shiftsi_swp"
5225 [(set (reg:CC_SWP CC_REGNUM)
5226 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5227 [(match_operand:SI 1 "s_register_operand" "r")
5228 (match_operand:SI 2 "reg_or_int_operand" "rM")])
5229 (match_operand:SI 0 "s_register_operand" "r")))]
5232 [(set_attr "conds" "set")
5233 (set_attr "shift" "1")
5237 (define_insn "*cmpsi_neg_shiftsi"
5238 [(set (reg:CC CC_REGNUM)
5239 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5240 (neg:SI (match_operator:SI 3 "shift_operator"
5241 [(match_operand:SI 1 "s_register_operand" "r")
5242 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5245 [(set_attr "conds" "set")
5246 (set_attr "shift" "1")
5250 ;; Cirrus SF compare instruction
5251 (define_insn "*cirrus_cmpsf"
5252 [(set (reg:CCFP CC_REGNUM)
5253 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
5254 (match_operand:SF 1 "cirrus_fp_register" "v")))]
5255 "TARGET_ARM && TARGET_CIRRUS"
5256 "cfcmps%?\\tr15, %V0, %V1"
5257 [(set_attr "type" "mav_farith")
5258 (set_attr "cirrus" "compare")]
5261 ;; Cirrus DF compare instruction
5262 (define_insn "*cirrus_cmpdf"
5263 [(set (reg:CCFP CC_REGNUM)
5264 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
5265 (match_operand:DF 1 "cirrus_fp_register" "v")))]
5266 "TARGET_ARM && TARGET_CIRRUS"
5267 "cfcmpd%?\\tr15, %V0, %V1"
5268 [(set_attr "type" "mav_farith")
5269 (set_attr "cirrus" "compare")]
5272 ;; Cirrus DI compare instruction
5273 (define_expand "cmpdi"
5274 [(match_operand:DI 0 "cirrus_fp_register" "")
5275 (match_operand:DI 1 "cirrus_fp_register" "")]
5276 "TARGET_ARM && TARGET_CIRRUS"
5278 arm_compare_op0 = operands[0];
5279 arm_compare_op1 = operands[1];
5283 (define_insn "*cirrus_cmpdi"
5284 [(set (reg:CC CC_REGNUM)
5285 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
5286 (match_operand:DI 1 "cirrus_fp_register" "v")))]
5287 "TARGET_ARM && TARGET_CIRRUS"
5288 "cfcmp64%?\\tr15, %V0, %V1"
5289 [(set_attr "type" "mav_farith")
5290 (set_attr "cirrus" "compare")]
5293 ; This insn allows redundant compares to be removed by cse, nothing should
5294 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5295 ; is deleted later on. The match_dup will match the mode here, so that
5296 ; mode changes of the condition codes aren't lost by this even though we don't
5297 ; specify what they are.
5299 (define_insn "*deleted_compare"
5300 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5302 "\\t%@ deleted compare"
5303 [(set_attr "conds" "set")
5304 (set_attr "length" "0")]
5308 ;; Conditional branch insns
5310 (define_expand "beq"
5312 (if_then_else (eq (match_dup 1) (const_int 0))
5313 (label_ref (match_operand 0 "" ""))
5316 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5319 (define_expand "bne"
5321 (if_then_else (ne (match_dup 1) (const_int 0))
5322 (label_ref (match_operand 0 "" ""))
5325 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5328 (define_expand "bgt"
5330 (if_then_else (gt (match_dup 1) (const_int 0))
5331 (label_ref (match_operand 0 "" ""))
5334 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5337 (define_expand "ble"
5339 (if_then_else (le (match_dup 1) (const_int 0))
5340 (label_ref (match_operand 0 "" ""))
5343 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5346 (define_expand "bge"
5348 (if_then_else (ge (match_dup 1) (const_int 0))
5349 (label_ref (match_operand 0 "" ""))
5352 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5355 (define_expand "blt"
5357 (if_then_else (lt (match_dup 1) (const_int 0))
5358 (label_ref (match_operand 0 "" ""))
5361 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5364 (define_expand "bgtu"
5366 (if_then_else (gtu (match_dup 1) (const_int 0))
5367 (label_ref (match_operand 0 "" ""))
5370 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5373 (define_expand "bleu"
5375 (if_then_else (leu (match_dup 1) (const_int 0))
5376 (label_ref (match_operand 0 "" ""))
5379 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5382 (define_expand "bgeu"
5384 (if_then_else (geu (match_dup 1) (const_int 0))
5385 (label_ref (match_operand 0 "" ""))
5388 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5391 (define_expand "bltu"
5393 (if_then_else (ltu (match_dup 1) (const_int 0))
5394 (label_ref (match_operand 0 "" ""))
5397 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5400 (define_expand "bunordered"
5402 (if_then_else (unordered (match_dup 1) (const_int 0))
5403 (label_ref (match_operand 0 "" ""))
5405 "TARGET_ARM && TARGET_HARD_FLOAT"
5406 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5410 (define_expand "bordered"
5412 (if_then_else (ordered (match_dup 1) (const_int 0))
5413 (label_ref (match_operand 0 "" ""))
5415 "TARGET_ARM && TARGET_HARD_FLOAT"
5416 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5420 (define_expand "bungt"
5422 (if_then_else (ungt (match_dup 1) (const_int 0))
5423 (label_ref (match_operand 0 "" ""))
5425 "TARGET_ARM && TARGET_HARD_FLOAT"
5426 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5429 (define_expand "bunlt"
5431 (if_then_else (unlt (match_dup 1) (const_int 0))
5432 (label_ref (match_operand 0 "" ""))
5434 "TARGET_ARM && TARGET_HARD_FLOAT"
5435 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5438 (define_expand "bunge"
5440 (if_then_else (unge (match_dup 1) (const_int 0))
5441 (label_ref (match_operand 0 "" ""))
5443 "TARGET_ARM && TARGET_HARD_FLOAT"
5444 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5447 (define_expand "bunle"
5449 (if_then_else (unle (match_dup 1) (const_int 0))
5450 (label_ref (match_operand 0 "" ""))
5452 "TARGET_ARM && TARGET_HARD_FLOAT"
5453 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5456 ;; The following two patterns need two branch instructions, since there is
5457 ;; no single instruction that will handle all cases.
5458 (define_expand "buneq"
5460 (if_then_else (uneq (match_dup 1) (const_int 0))
5461 (label_ref (match_operand 0 "" ""))
5463 "TARGET_ARM && TARGET_HARD_FLOAT"
5464 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
5467 (define_expand "bltgt"
5469 (if_then_else (ltgt (match_dup 1) (const_int 0))
5470 (label_ref (match_operand 0 "" ""))
5472 "TARGET_ARM && TARGET_HARD_FLOAT"
5473 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
5477 ;; Patterns to match conditional branch insns.
5480 ; Special pattern to match UNEQ.
5481 (define_insn "*arm_buneq"
5483 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5484 (label_ref (match_operand 0 "" ""))
5486 "TARGET_ARM && TARGET_HARD_FLOAT"
5488 if (arm_ccfsm_state != 0)
5491 return \"bvs\\t%l0\;beq\\t%l0\";
5493 [(set_attr "conds" "jump_clob")
5494 (set_attr "length" "8")]
5497 ; Special pattern to match LTGT.
5498 (define_insn "*arm_bltgt"
5500 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5501 (label_ref (match_operand 0 "" ""))
5503 "TARGET_ARM && TARGET_HARD_FLOAT"
5505 if (arm_ccfsm_state != 0)
5508 return \"bmi\\t%l0\;bgt\\t%l0\";
5510 [(set_attr "conds" "jump_clob")
5511 (set_attr "length" "8")]
5514 (define_insn "*arm_cond_branch"
5516 (if_then_else (match_operator 1 "arm_comparison_operator"
5517 [(match_operand 2 "cc_register" "") (const_int 0)])
5518 (label_ref (match_operand 0 "" ""))
5522 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5524 arm_ccfsm_state += 2;
5527 return \"b%d1\\t%l0\";
5529 [(set_attr "conds" "use")]
5532 ; Special pattern to match reversed UNEQ.
5533 (define_insn "*arm_buneq_reversed"
5535 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5537 (label_ref (match_operand 0 "" ""))))]
5538 "TARGET_ARM && TARGET_HARD_FLOAT"
5540 if (arm_ccfsm_state != 0)
5543 return \"bmi\\t%l0\;bgt\\t%l0\";
5545 [(set_attr "conds" "jump_clob")
5546 (set_attr "length" "8")]
5549 ; Special pattern to match reversed LTGT.
5550 (define_insn "*arm_bltgt_reversed"
5552 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5554 (label_ref (match_operand 0 "" ""))))]
5555 "TARGET_ARM && TARGET_HARD_FLOAT"
5557 if (arm_ccfsm_state != 0)
5560 return \"bvs\\t%l0\;beq\\t%l0\";
5562 [(set_attr "conds" "jump_clob")
5563 (set_attr "length" "8")]
5566 (define_insn "*arm_cond_branch_reversed"
5568 (if_then_else (match_operator 1 "arm_comparison_operator"
5569 [(match_operand 2 "cc_register" "") (const_int 0)])
5571 (label_ref (match_operand 0 "" ""))))]
5574 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5576 arm_ccfsm_state += 2;
5579 return \"b%D1\\t%l0\";
5581 [(set_attr "conds" "use")]
5588 (define_expand "seq"
5589 [(set (match_operand:SI 0 "s_register_operand" "")
5590 (eq:SI (match_dup 1) (const_int 0)))]
5592 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5595 (define_expand "sne"
5596 [(set (match_operand:SI 0 "s_register_operand" "")
5597 (ne:SI (match_dup 1) (const_int 0)))]
5599 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5602 (define_expand "sgt"
5603 [(set (match_operand:SI 0 "s_register_operand" "")
5604 (gt:SI (match_dup 1) (const_int 0)))]
5606 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5609 (define_expand "sle"
5610 [(set (match_operand:SI 0 "s_register_operand" "")
5611 (le:SI (match_dup 1) (const_int 0)))]
5613 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5616 (define_expand "sge"
5617 [(set (match_operand:SI 0 "s_register_operand" "")
5618 (ge:SI (match_dup 1) (const_int 0)))]
5620 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5623 (define_expand "slt"
5624 [(set (match_operand:SI 0 "s_register_operand" "")
5625 (lt:SI (match_dup 1) (const_int 0)))]
5627 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5630 (define_expand "sgtu"
5631 [(set (match_operand:SI 0 "s_register_operand" "")
5632 (gtu:SI (match_dup 1) (const_int 0)))]
5634 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5637 (define_expand "sleu"
5638 [(set (match_operand:SI 0 "s_register_operand" "")
5639 (leu:SI (match_dup 1) (const_int 0)))]
5641 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5644 (define_expand "sgeu"
5645 [(set (match_operand:SI 0 "s_register_operand" "")
5646 (geu:SI (match_dup 1) (const_int 0)))]
5648 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5651 (define_expand "sltu"
5652 [(set (match_operand:SI 0 "s_register_operand" "")
5653 (ltu:SI (match_dup 1) (const_int 0)))]
5655 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5658 (define_expand "sunordered"
5659 [(set (match_operand:SI 0 "s_register_operand" "")
5660 (unordered:SI (match_dup 1) (const_int 0)))]
5661 "TARGET_ARM && TARGET_HARD_FLOAT"
5662 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5666 (define_expand "sordered"
5667 [(set (match_operand:SI 0 "s_register_operand" "")
5668 (ordered:SI (match_dup 1) (const_int 0)))]
5669 "TARGET_ARM && TARGET_HARD_FLOAT"
5670 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5674 (define_expand "sungt"
5675 [(set (match_operand:SI 0 "s_register_operand" "")
5676 (ungt:SI (match_dup 1) (const_int 0)))]
5677 "TARGET_ARM && TARGET_HARD_FLOAT"
5678 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
5682 (define_expand "sunge"
5683 [(set (match_operand:SI 0 "s_register_operand" "")
5684 (unge:SI (match_dup 1) (const_int 0)))]
5685 "TARGET_ARM && TARGET_HARD_FLOAT"
5686 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
5690 (define_expand "sunlt"
5691 [(set (match_operand:SI 0 "s_register_operand" "")
5692 (unlt:SI (match_dup 1) (const_int 0)))]
5693 "TARGET_ARM && TARGET_HARD_FLOAT"
5694 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
5698 (define_expand "sunle"
5699 [(set (match_operand:SI 0 "s_register_operand" "")
5700 (unle:SI (match_dup 1) (const_int 0)))]
5701 "TARGET_ARM && TARGET_HARD_FLOAT"
5702 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
5706 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
5707 ;;; simple ARM instructions.
5709 ; (define_expand "suneq"
5710 ; [(set (match_operand:SI 0 "s_register_operand" "")
5711 ; (uneq:SI (match_dup 1) (const_int 0)))]
5712 ; "TARGET_ARM && TARGET_HARD_FLOAT"
5716 ; (define_expand "sltgt"
5717 ; [(set (match_operand:SI 0 "s_register_operand" "")
5718 ; (ltgt:SI (match_dup 1) (const_int 0)))]
5719 ; "TARGET_ARM && TARGET_HARD_FLOAT"
5723 (define_insn "*mov_scc"
5724 [(set (match_operand:SI 0 "s_register_operand" "=r")
5725 (match_operator:SI 1 "arm_comparison_operator"
5726 [(match_operand 2 "cc_register" "") (const_int 0)]))]
5728 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
5729 [(set_attr "conds" "use")
5730 (set_attr "length" "8")]
5733 (define_insn "*mov_negscc"
5734 [(set (match_operand:SI 0 "s_register_operand" "=r")
5735 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
5736 [(match_operand 2 "cc_register" "") (const_int 0)])))]
5738 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
5739 [(set_attr "conds" "use")
5740 (set_attr "length" "8")]
5743 (define_insn "*mov_notscc"
5744 [(set (match_operand:SI 0 "s_register_operand" "=r")
5745 (not:SI (match_operator:SI 1 "arm_comparison_operator"
5746 [(match_operand 2 "cc_register" "") (const_int 0)])))]
5748 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
5749 [(set_attr "conds" "use")
5750 (set_attr "length" "8")]
5754 ;; Conditional move insns
5756 (define_expand "movsicc"
5757 [(set (match_operand:SI 0 "s_register_operand" "")
5758 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
5759 (match_operand:SI 2 "arm_not_operand" "")
5760 (match_operand:SI 3 "arm_not_operand" "")))]
5764 enum rtx_code code = GET_CODE (operands[1]);
5767 if (code == UNEQ || code == LTGT)
5770 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
5771 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
5775 (define_expand "movsfcc"
5776 [(set (match_operand:SF 0 "s_register_operand" "")
5777 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
5778 (match_operand:SF 2 "s_register_operand" "")
5779 (match_operand:SF 3 "nonmemory_operand" "")))]
5783 enum rtx_code code = GET_CODE (operands[1]);
5786 if (code == UNEQ || code == LTGT)
5789 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
5790 Otherwise, ensure it is a valid FP add operand */
5791 if ((!TARGET_HARD_FLOAT)
5792 || (!fpa_add_operand (operands[3], SFmode)))
5793 operands[3] = force_reg (SFmode, operands[3]);
5795 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
5796 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
5800 (define_expand "movdfcc"
5801 [(set (match_operand:DF 0 "s_register_operand" "")
5802 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
5803 (match_operand:DF 2 "s_register_operand" "")
5804 (match_operand:DF 3 "fpa_add_operand" "")))]
5805 "TARGET_ARM && TARGET_HARD_FLOAT"
5808 enum rtx_code code = GET_CODE (operands[1]);
5811 if (code == UNEQ || code == LTGT)
5814 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
5815 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
5819 (define_insn "*movsicc_insn"
5820 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
5822 (match_operator 3 "arm_comparison_operator"
5823 [(match_operand 4 "cc_register" "") (const_int 0)])
5824 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
5825 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
5832 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
5833 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
5834 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
5835 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
5836 [(set_attr "length" "4,4,4,4,8,8,8,8")
5837 (set_attr "conds" "use")]
5840 (define_insn "*movsfcc_soft_insn"
5841 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
5842 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
5843 [(match_operand 4 "cc_register" "") (const_int 0)])
5844 (match_operand:SF 1 "s_register_operand" "0,r")
5845 (match_operand:SF 2 "s_register_operand" "r,0")))]
5846 "TARGET_ARM && TARGET_SOFT_FLOAT"
5850 [(set_attr "conds" "use")]
5854 ;; Jump and linkage insns
5856 (define_expand "jump"
5858 (label_ref (match_operand 0 "" "")))]
5863 (define_insn "*arm_jump"
5865 (label_ref (match_operand 0 "" "")))]
5869 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5871 arm_ccfsm_state += 2;
5874 return \"b%?\\t%l0\";
5877 [(set_attr "predicable" "yes")]
5880 (define_insn "*thumb_jump"
5882 (label_ref (match_operand 0 "" "")))]
5885 if (get_attr_length (insn) == 2)
5887 return \"bl\\t%l0\\t%@ far jump\";
5889 [(set (attr "far_jump")
5891 (eq_attr "length" "4")
5892 (const_string "yes")
5893 (const_string "no")))
5894 (set (attr "length")
5896 (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
5897 (le (minus (match_dup 0) (pc)) (const_int 2044)))
5902 (define_expand "call"
5903 [(parallel [(call (match_operand 0 "memory_operand" "")
5904 (match_operand 1 "general_operand" ""))
5905 (use (match_operand 2 "" ""))
5906 (clobber (reg:SI LR_REGNUM))])]
5912 /* In an untyped call, we can get NULL for operand 2. */
5913 if (operands[2] == NULL_RTX)
5914 operands[2] = const0_rtx;
5916 /* This is to decide if we should generate indirect calls by loading the
5917 32 bit address of the callee into a register before performing the
5918 branch and link. operand[2] encodes the long_call/short_call
5919 attribute of the function being called. This attribute is set whenever
5920 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
5921 is used, and the short_call attribute can also be set if function is
5922 declared as static or if it has already been defined in the current
5923 compilation unit. See arm.c and arm.h for info about this. The third
5924 parameter to arm_is_longcall_p is used to tell it which pattern
5926 callee = XEXP (operands[0], 0);
5928 if (GET_CODE (callee) != REG
5929 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
5930 XEXP (operands[0], 0) = force_reg (Pmode, callee);
5934 (define_insn "*call_reg"
5935 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
5936 (match_operand 1 "" ""))
5937 (use (match_operand 2 "" ""))
5938 (clobber (reg:SI LR_REGNUM))]
5941 return output_call (operands);
5943 ;; length is worst case, normally it is only two
5944 [(set_attr "length" "12")
5945 (set_attr "type" "call")]
5948 (define_insn "*call_mem"
5949 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
5950 (match_operand 1 "" ""))
5951 (use (match_operand 2 "" ""))
5952 (clobber (reg:SI LR_REGNUM))]
5955 return output_call_mem (operands);
5957 [(set_attr "length" "12")
5958 (set_attr "type" "call")]
5961 (define_insn "*call_indirect"
5962 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
5963 (match_operand 1 "" ""))
5964 (use (match_operand 2 "" ""))
5965 (clobber (reg:SI LR_REGNUM))]
5969 if (TARGET_CALLER_INTERWORKING)
5970 return \"bl\\t%__interwork_call_via_%0\";
5972 return \"bl\\t%__call_via_%0\";
5974 [(set_attr "type" "call")]
5977 (define_insn "*call_value_indirect"
5978 [(set (match_operand 0 "" "=l")
5979 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
5980 (match_operand 2 "" "")))
5981 (use (match_operand 3 "" ""))
5982 (clobber (reg:SI LR_REGNUM))]
5986 if (TARGET_CALLER_INTERWORKING)
5987 return \"bl\\t%__interwork_call_via_%1\";
5989 return \"bl\\t%__call_via_%1\";
5991 [(set_attr "type" "call")]
5994 (define_expand "call_value"
5995 [(parallel [(set (match_operand 0 "" "")
5996 (call (match_operand 1 "memory_operand" "")
5997 (match_operand 2 "general_operand" "")))
5998 (use (match_operand 3 "" ""))
5999 (clobber (reg:SI LR_REGNUM))])]
6003 rtx callee = XEXP (operands[1], 0);
6005 /* In an untyped call, we can get NULL for operand 2. */
6006 if (operands[3] == 0)
6007 operands[3] = const0_rtx;
6009 /* See the comment in define_expand \"call\". */
6010 if (GET_CODE (callee) != REG
6011 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6012 XEXP (operands[1], 0) = force_reg (Pmode, callee);
6016 (define_insn "*call_value_reg"
6017 [(set (match_operand 0 "" "=r,f,v")
6018 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r,r"))
6019 (match_operand 2 "" "")))
6020 (use (match_operand 3 "" ""))
6021 (clobber (reg:SI LR_REGNUM))]
6024 return output_call (&operands[1]);
6026 [(set_attr "length" "12")
6027 (set_attr "type" "call")]
6030 (define_insn "*call_value_mem"
6031 [(set (match_operand 0 "" "=r,f,v")
6032 (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m,m"))
6033 (match_operand 2 "" "")))
6034 (use (match_operand 3 "" ""))
6035 (clobber (reg:SI LR_REGNUM))]
6036 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6038 return output_call_mem (&operands[1]);
6040 [(set_attr "length" "12")
6041 (set_attr "type" "call")]
6044 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6045 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6047 (define_insn "*call_symbol"
6048 [(call (mem:SI (match_operand:SI 0 "" "X"))
6049 (match_operand 1 "" ""))
6050 (use (match_operand 2 "" ""))
6051 (clobber (reg:SI LR_REGNUM))]
6053 && (GET_CODE (operands[0]) == SYMBOL_REF)
6054 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6057 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6059 [(set_attr "type" "call")]
6062 (define_insn "*call_value_symbol"
6063 [(set (match_operand 0 "s_register_operand" "=r,f,v")
6064 (call (mem:SI (match_operand:SI 1 "" "X,X,X"))
6065 (match_operand:SI 2 "" "")))
6066 (use (match_operand 3 "" ""))
6067 (clobber (reg:SI LR_REGNUM))]
6069 && (GET_CODE (operands[1]) == SYMBOL_REF)
6070 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6073 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6075 [(set_attr "type" "call")]
6078 (define_insn "*call_insn"
6079 [(call (mem:SI (match_operand:SI 0 "" "X"))
6080 (match_operand:SI 1 "" ""))
6081 (use (match_operand 2 "" ""))
6082 (clobber (reg:SI LR_REGNUM))]
6084 && GET_CODE (operands[0]) == SYMBOL_REF
6085 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6087 [(set_attr "length" "4")
6088 (set_attr "type" "call")]
6091 (define_insn "*call_value_insn"
6092 [(set (match_operand 0 "register_operand" "=l")
6093 (call (mem:SI (match_operand 1 "" "X"))
6094 (match_operand 2 "" "")))
6095 (use (match_operand 3 "" ""))
6096 (clobber (reg:SI LR_REGNUM))]
6098 && GET_CODE (operands[1]) == SYMBOL_REF
6099 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6101 [(set_attr "length" "4")
6102 (set_attr "type" "call")]
6105 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6106 (define_expand "sibcall"
6107 [(parallel [(call (match_operand 0 "memory_operand" "")
6108 (match_operand 1 "general_operand" ""))
6110 (use (match_operand 2 "" ""))])]
6114 if (operands[2] == NULL_RTX)
6115 operands[2] = const0_rtx;
6119 (define_expand "sibcall_value"
6120 [(parallel [(set (match_operand 0 "register_operand" "")
6121 (call (match_operand 1 "memory_operand" "")
6122 (match_operand 2 "general_operand" "")))
6124 (use (match_operand 3 "" ""))])]
6128 if (operands[3] == NULL_RTX)
6129 operands[3] = const0_rtx;
6133 (define_insn "*sibcall_insn"
6134 [(call (mem:SI (match_operand:SI 0 "" "X"))
6135 (match_operand 1 "" ""))
6137 (use (match_operand 2 "" ""))]
6138 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6140 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6142 [(set_attr "type" "call")]
6145 (define_insn "*sibcall_value_insn"
6146 [(set (match_operand 0 "s_register_operand" "=r,f,v")
6147 (call (mem:SI (match_operand:SI 1 "" "X,X,X"))
6148 (match_operand 2 "" "")))
6150 (use (match_operand 3 "" ""))]
6151 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6153 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6155 [(set_attr "type" "call")]
6158 ;; Often the return insn will be the same as loading from memory, so set attr
6159 (define_insn "return"
6161 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6164 if (arm_ccfsm_state == 2)
6166 arm_ccfsm_state += 2;
6169 return output_return_instruction (const_true_rtx, TRUE, FALSE);
6171 [(set_attr "type" "load")
6172 (set_attr "predicable" "yes")]
6175 (define_insn "*cond_return"
6177 (if_then_else (match_operator 0 "arm_comparison_operator"
6178 [(match_operand 1 "cc_register" "") (const_int 0)])
6181 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6184 if (arm_ccfsm_state == 2)
6186 arm_ccfsm_state += 2;
6189 return output_return_instruction (operands[0], TRUE, FALSE);
6191 [(set_attr "conds" "use")
6192 (set_attr "type" "load")]
6195 (define_insn "*cond_return_inverted"
6197 (if_then_else (match_operator 0 "arm_comparison_operator"
6198 [(match_operand 1 "cc_register" "") (const_int 0)])
6201 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6204 if (arm_ccfsm_state == 2)
6206 arm_ccfsm_state += 2;
6209 return output_return_instruction (operands[0], TRUE, TRUE);
6211 [(set_attr "conds" "use")
6212 (set_attr "type" "load")]
6215 ;; Generate a sequence of instructions to determine if the processor is
6216 ;; in 26-bit or 32-bit mode, and return the appropriate return address
6219 (define_expand "return_addr_mask"
6221 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6223 (set (match_operand:SI 0 "s_register_operand" "")
6224 (if_then_else:SI (eq (match_dup 1) (const_int 0))
6226 (const_int 67108860)))] ; 0x03fffffc
6229 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
6232 (define_insn "*check_arch2"
6233 [(set (match_operand:CC_NOOV 0 "cc_register" "")
6234 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6237 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
6238 [(set_attr "length" "8")
6239 (set_attr "conds" "set")]
6242 ;; Call subroutine returning any type.
6244 (define_expand "untyped_call"
6245 [(parallel [(call (match_operand 0 "" "")
6247 (match_operand 1 "" "")
6248 (match_operand 2 "" "")])]
6254 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6256 for (i = 0; i < XVECLEN (operands[2], 0); i++)
6258 rtx set = XVECEXP (operands[2], 0, i);
6260 emit_move_insn (SET_DEST (set), SET_SRC (set));
6263 /* The optimizer does not know that the call sets the function value
6264 registers we stored in the result block. We avoid problems by
6265 claiming that all hard registers are used and clobbered at this
6267 emit_insn (gen_blockage ());
6273 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6274 ;; all of memory. This blocks insns from being moved across this point.
6276 (define_insn "blockage"
6277 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6280 [(set_attr "length" "0")
6281 (set_attr "type" "block")]
6284 (define_expand "casesi"
6285 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6286 (match_operand:SI 1 "const_int_operand" "") ; lower bound
6287 (match_operand:SI 2 "const_int_operand" "") ; total range
6288 (match_operand:SI 3 "" "") ; table label
6289 (match_operand:SI 4 "" "")] ; Out of range label
6294 if (operands[1] != const0_rtx)
6296 reg = gen_reg_rtx (SImode);
6298 emit_insn (gen_addsi3 (reg, operands[0],
6299 GEN_INT (-INTVAL (operands[1]))));
6303 if (!const_ok_for_arm (INTVAL (operands[2])))
6304 operands[2] = force_reg (SImode, operands[2]);
6306 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6312 ;; The USE in this pattern is needed to tell flow analysis that this is
6313 ;; a CASESI insn. It has no other purpose.
6314 (define_insn "casesi_internal"
6315 [(parallel [(set (pc)
6317 (leu (match_operand:SI 0 "s_register_operand" "r")
6318 (match_operand:SI 1 "arm_rhs_operand" "rI"))
6319 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6320 (label_ref (match_operand 2 "" ""))))
6321 (label_ref (match_operand 3 "" ""))))
6322 (clobber (reg:CC CC_REGNUM))
6323 (use (label_ref (match_dup 2)))])]
6327 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6328 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6330 [(set_attr "conds" "clob")
6331 (set_attr "length" "12")]
6334 (define_expand "indirect_jump"
6336 (match_operand:SI 0 "s_register_operand" ""))]
6341 (define_insn "*arm_indirect_jump"
6343 (match_operand:SI 0 "s_register_operand" "r"))]
6345 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6346 [(set_attr "predicable" "yes")]
6349 ;; Although not supported by the define_expand above,
6350 ;; cse/combine may generate this form.
6351 (define_insn "*load_indirect_jump"
6353 (match_operand:SI 0 "memory_operand" "m"))]
6355 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6356 [(set_attr "type" "load")
6357 (set_attr "pool_range" "4096")
6358 (set_attr "neg_pool_range" "4084")
6359 (set_attr "predicable" "yes")]
6362 (define_insn "*thumb_indirect_jump"
6364 (match_operand:SI 0 "register_operand" "l*r"))]
6367 [(set_attr "conds" "clob")
6368 (set_attr "length" "2")]
6379 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6380 return \"mov\\tr8, r8\";
6382 [(set (attr "length")
6383 (if_then_else (eq_attr "is_thumb" "yes")
6389 ;; Patterns to allow combination of arithmetic, cond code and shifts
6391 (define_insn "*arith_shiftsi"
6392 [(set (match_operand:SI 0 "s_register_operand" "=r")
6393 (match_operator:SI 1 "shiftable_operator"
6394 [(match_operator:SI 3 "shift_operator"
6395 [(match_operand:SI 4 "s_register_operand" "r")
6396 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6397 (match_operand:SI 2 "s_register_operand" "r")]))]
6399 "%i1%?\\t%0, %2, %4%S3"
6400 [(set_attr "predicable" "yes")
6401 (set_attr "shift" "4")
6405 (define_insn "*arith_shiftsi_compare0"
6406 [(set (reg:CC_NOOV CC_REGNUM)
6407 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6408 [(match_operator:SI 3 "shift_operator"
6409 [(match_operand:SI 4 "s_register_operand" "r")
6410 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6411 (match_operand:SI 2 "s_register_operand" "r")])
6413 (set (match_operand:SI 0 "s_register_operand" "=r")
6414 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6417 "%i1%?s\\t%0, %2, %4%S3"
6418 [(set_attr "conds" "set")
6419 (set_attr "shift" "4")
6423 (define_insn "*arith_shiftsi_compare0_scratch"
6424 [(set (reg:CC_NOOV CC_REGNUM)
6425 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6426 [(match_operator:SI 3 "shift_operator"
6427 [(match_operand:SI 4 "s_register_operand" "r")
6428 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6429 (match_operand:SI 2 "s_register_operand" "r")])
6431 (clobber (match_scratch:SI 0 "=r"))]
6433 "%i1%?s\\t%0, %2, %4%S3"
6434 [(set_attr "conds" "set")
6435 (set_attr "shift" "4")
6439 (define_insn "*sub_shiftsi"
6440 [(set (match_operand:SI 0 "s_register_operand" "=r")
6441 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6442 (match_operator:SI 2 "shift_operator"
6443 [(match_operand:SI 3 "s_register_operand" "r")
6444 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
6446 "sub%?\\t%0, %1, %3%S2"
6447 [(set_attr "predicable" "yes")
6448 (set_attr "shift" "3")
6452 (define_insn "*sub_shiftsi_compare0"
6453 [(set (reg:CC_NOOV CC_REGNUM)
6455 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6456 (match_operator:SI 2 "shift_operator"
6457 [(match_operand:SI 3 "s_register_operand" "r")
6458 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6460 (set (match_operand:SI 0 "s_register_operand" "=r")
6461 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6464 "sub%?s\\t%0, %1, %3%S2"
6465 [(set_attr "conds" "set")
6466 (set_attr "shift" "3")
6470 (define_insn "*sub_shiftsi_compare0_scratch"
6471 [(set (reg:CC_NOOV CC_REGNUM)
6473 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6474 (match_operator:SI 2 "shift_operator"
6475 [(match_operand:SI 3 "s_register_operand" "r")
6476 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6478 (clobber (match_scratch:SI 0 "=r"))]
6480 "sub%?s\\t%0, %1, %3%S2"
6481 [(set_attr "conds" "set")
6482 (set_attr "shift" "3")
6488 (define_insn "*and_scc"
6489 [(set (match_operand:SI 0 "s_register_operand" "=r")
6490 (and:SI (match_operator:SI 1 "arm_comparison_operator"
6491 [(match_operand 3 "cc_register" "") (const_int 0)])
6492 (match_operand:SI 2 "s_register_operand" "r")))]
6494 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
6495 [(set_attr "conds" "use")
6496 (set_attr "length" "8")]
6499 (define_insn "*ior_scc"
6500 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6501 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
6502 [(match_operand 3 "cc_register" "") (const_int 0)])
6503 (match_operand:SI 1 "s_register_operand" "0,?r")))]
6507 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
6508 [(set_attr "conds" "use")
6509 (set_attr "length" "4,8")]
6512 (define_insn "*compare_scc"
6513 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6514 (match_operator:SI 1 "arm_comparison_operator"
6515 [(match_operand:SI 2 "s_register_operand" "r,r")
6516 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
6517 (clobber (reg:CC CC_REGNUM))]
6520 if (operands[3] == const0_rtx)
6522 if (GET_CODE (operands[1]) == LT)
6523 return \"mov\\t%0, %2, lsr #31\";
6525 if (GET_CODE (operands[1]) == GE)
6526 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
6528 if (GET_CODE (operands[1]) == EQ)
6529 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
6532 if (GET_CODE (operands[1]) == NE)
6534 if (which_alternative == 1)
6535 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
6536 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
6538 if (which_alternative == 1)
6539 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
6541 output_asm_insn (\"cmp\\t%2, %3\", operands);
6542 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
6544 [(set_attr "conds" "clob")
6545 (set_attr "length" "12")]
6548 (define_insn "*cond_move"
6549 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
6550 (if_then_else:SI (match_operator 3 "equality_operator"
6551 [(match_operator 4 "arm_comparison_operator"
6552 [(match_operand 5 "cc_register" "") (const_int 0)])
6554 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
6555 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
6558 if (GET_CODE (operands[3]) == NE)
6560 if (which_alternative != 1)
6561 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
6562 if (which_alternative != 0)
6563 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
6566 if (which_alternative != 0)
6567 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6568 if (which_alternative != 1)
6569 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
6572 [(set_attr "conds" "use")
6573 (set_attr "length" "4,4,8")]
6576 (define_insn "*cond_arith"
6577 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6578 (match_operator:SI 5 "shiftable_operator"
6579 [(match_operator:SI 4 "arm_comparison_operator"
6580 [(match_operand:SI 2 "s_register_operand" "r,r")
6581 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
6582 (match_operand:SI 1 "s_register_operand" "0,?r")]))
6583 (clobber (reg:CC CC_REGNUM))]
6586 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
6587 return \"%i5\\t%0, %1, %2, lsr #31\";
6589 output_asm_insn (\"cmp\\t%2, %3\", operands);
6590 if (GET_CODE (operands[5]) == AND)
6591 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
6592 else if (GET_CODE (operands[5]) == MINUS)
6593 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
6594 else if (which_alternative != 0)
6595 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6596 return \"%i5%d4\\t%0, %1, #1\";
6598 [(set_attr "conds" "clob")
6599 (set_attr "length" "12")]
6602 (define_insn "*cond_sub"
6603 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6604 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
6605 (match_operator:SI 4 "arm_comparison_operator"
6606 [(match_operand:SI 2 "s_register_operand" "r,r")
6607 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
6608 (clobber (reg:CC CC_REGNUM))]
6611 output_asm_insn (\"cmp\\t%2, %3\", operands);
6612 if (which_alternative != 0)
6613 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6614 return \"sub%d4\\t%0, %1, #1\";
6616 [(set_attr "conds" "clob")
6617 (set_attr "length" "8,12")]
6620 (define_insn "*cmp_ite0"
6621 [(set (match_operand 6 "dominant_cc_register" "")
6624 (match_operator 4 "arm_comparison_operator"
6625 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6626 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6627 (match_operator:SI 5 "arm_comparison_operator"
6628 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6629 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
6635 static const char * const opcodes[4][2] =
6637 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
6638 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
6639 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
6640 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
6641 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
6642 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
6643 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
6644 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
6647 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
6649 return opcodes[which_alternative][swap];
6651 [(set_attr "conds" "set")
6652 (set_attr "length" "8")]
6655 (define_insn "*cmp_ite1"
6656 [(set (match_operand 6 "dominant_cc_register" "")
6659 (match_operator 4 "arm_comparison_operator"
6660 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6661 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6662 (match_operator:SI 5 "arm_comparison_operator"
6663 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6664 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
6670 static const char * const opcodes[4][2] =
6672 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
6673 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
6674 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
6675 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
6676 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
6677 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
6678 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
6679 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
6682 comparison_dominates_p (GET_CODE (operands[5]),
6683 reverse_condition (GET_CODE (operands[4])));
6685 return opcodes[which_alternative][swap];
6687 [(set_attr "conds" "set")
6688 (set_attr "length" "8")]
6691 (define_insn "*cmp_and"
6692 [(set (match_operand 6 "dominant_cc_register" "")
6695 (match_operator 4 "arm_comparison_operator"
6696 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6697 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6698 (match_operator:SI 5 "arm_comparison_operator"
6699 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6700 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
6705 static const char *const opcodes[4][2] =
6707 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
6708 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
6709 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
6710 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
6711 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
6712 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
6713 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
6714 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
6717 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
6719 return opcodes[which_alternative][swap];
6721 [(set_attr "conds" "set")
6722 (set_attr "predicable" "no")
6723 (set_attr "length" "8")]
6726 (define_insn "*cmp_ior"
6727 [(set (match_operand 6 "dominant_cc_register" "")
6730 (match_operator 4 "arm_comparison_operator"
6731 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6732 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6733 (match_operator:SI 5 "arm_comparison_operator"
6734 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6735 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
6740 static const char *const opcodes[4][2] =
6742 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
6743 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
6744 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
6745 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
6746 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
6747 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
6748 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
6749 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
6752 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
6754 return opcodes[which_alternative][swap];
6757 [(set_attr "conds" "set")
6758 (set_attr "length" "8")]
6761 (define_insn_and_split "*ior_scc_scc"
6762 [(set (match_operand:SI 0 "s_register_operand" "=r")
6763 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
6764 [(match_operand:SI 1 "s_register_operand" "r")
6765 (match_operand:SI 2 "arm_add_operand" "rIL")])
6766 (match_operator:SI 6 "arm_comparison_operator"
6767 [(match_operand:SI 4 "s_register_operand" "r")
6768 (match_operand:SI 5 "arm_add_operand" "rIL")])))
6769 (clobber (reg:CC CC_REGNUM))]
6771 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
6774 "TARGET_ARM && reload_completed"
6778 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6779 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
6781 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
6783 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
6786 [(set_attr "conds" "clob")
6787 (set_attr "length" "16")])
6789 ; If the above pattern is followed by a CMP insn, then the compare is
6790 ; redundant, since we can rework the conditional instruction that follows.
6791 (define_insn_and_split "*ior_scc_scc_cmp"
6792 [(set (match_operand 0 "dominant_cc_register" "")
6793 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
6794 [(match_operand:SI 1 "s_register_operand" "r")
6795 (match_operand:SI 2 "arm_add_operand" "rIL")])
6796 (match_operator:SI 6 "arm_comparison_operator"
6797 [(match_operand:SI 4 "s_register_operand" "r")
6798 (match_operand:SI 5 "arm_add_operand" "rIL")]))
6800 (set (match_operand:SI 7 "s_register_operand" "=r")
6801 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6802 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
6805 "TARGET_ARM && reload_completed"
6809 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6810 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
6812 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
6814 [(set_attr "conds" "set")
6815 (set_attr "length" "16")])
6817 (define_insn_and_split "*and_scc_scc"
6818 [(set (match_operand:SI 0 "s_register_operand" "=r")
6819 (and:SI (match_operator:SI 3 "arm_comparison_operator"
6820 [(match_operand:SI 1 "s_register_operand" "r")
6821 (match_operand:SI 2 "arm_add_operand" "rIL")])
6822 (match_operator:SI 6 "arm_comparison_operator"
6823 [(match_operand:SI 4 "s_register_operand" "r")
6824 (match_operand:SI 5 "arm_add_operand" "rIL")])))
6825 (clobber (reg:CC CC_REGNUM))]
6827 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
6830 "TARGET_ARM && reload_completed
6831 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
6836 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6837 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
6839 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
6841 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
6844 [(set_attr "conds" "clob")
6845 (set_attr "length" "16")])
6847 ; If the above pattern is followed by a CMP insn, then the compare is
6848 ; redundant, since we can rework the conditional instruction that follows.
6849 (define_insn_and_split "*and_scc_scc_cmp"
6850 [(set (match_operand 0 "dominant_cc_register" "")
6851 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
6852 [(match_operand:SI 1 "s_register_operand" "r")
6853 (match_operand:SI 2 "arm_add_operand" "rIL")])
6854 (match_operator:SI 6 "arm_comparison_operator"
6855 [(match_operand:SI 4 "s_register_operand" "r")
6856 (match_operand:SI 5 "arm_add_operand" "rIL")]))
6858 (set (match_operand:SI 7 "s_register_operand" "=r")
6859 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6860 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
6863 "TARGET_ARM && reload_completed"
6867 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6868 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
6870 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
6872 [(set_attr "conds" "set")
6873 (set_attr "length" "16")])
6875 ;; If there is no dominance in the comparison, then we can still save an
6876 ;; instruction in the AND case, since we can know that the second compare
6877 ;; need only zero the value if false (if true, then the value is already
6879 (define_insn_and_split "*and_scc_scc_nodom"
6880 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
6881 (and:SI (match_operator:SI 3 "arm_comparison_operator"
6882 [(match_operand:SI 1 "s_register_operand" "r,r,0")
6883 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
6884 (match_operator:SI 6 "arm_comparison_operator"
6885 [(match_operand:SI 4 "s_register_operand" "r,r,r")
6886 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
6887 (clobber (reg:CC CC_REGNUM))]
6889 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
6892 "TARGET_ARM && reload_completed"
6893 [(parallel [(set (match_dup 0)
6894 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
6895 (clobber (reg:CC CC_REGNUM))])
6896 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
6898 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
6901 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
6902 operands[4], operands[5]),
6904 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
6906 [(set_attr "conds" "clob")
6907 (set_attr "length" "20")])
6909 (define_insn "*negscc"
6910 [(set (match_operand:SI 0 "s_register_operand" "=r")
6911 (neg:SI (match_operator 3 "arm_comparison_operator"
6912 [(match_operand:SI 1 "s_register_operand" "r")
6913 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
6914 (clobber (reg:CC CC_REGNUM))]
6917 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
6918 return \"mov\\t%0, %1, asr #31\";
6920 if (GET_CODE (operands[3]) == NE)
6921 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
6923 if (GET_CODE (operands[3]) == GT)
6924 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
6926 output_asm_insn (\"cmp\\t%1, %2\", operands);
6927 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
6928 return \"mvn%d3\\t%0, #0\";
6930 [(set_attr "conds" "clob")
6931 (set_attr "length" "12")]
6934 (define_insn "movcond"
6935 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
6937 (match_operator 5 "arm_comparison_operator"
6938 [(match_operand:SI 3 "s_register_operand" "r,r,r")
6939 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
6940 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
6941 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
6942 (clobber (reg:CC CC_REGNUM))]
6945 if (GET_CODE (operands[5]) == LT
6946 && (operands[4] == const0_rtx))
6948 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
6950 if (operands[2] == const0_rtx)
6951 return \"and\\t%0, %1, %3, asr #31\";
6952 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
6954 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
6956 if (operands[1] == const0_rtx)
6957 return \"bic\\t%0, %2, %3, asr #31\";
6958 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
6960 /* The only case that falls through to here is when both ops 1 & 2
6964 if (GET_CODE (operands[5]) == GE
6965 && (operands[4] == const0_rtx))
6967 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
6969 if (operands[2] == const0_rtx)
6970 return \"bic\\t%0, %1, %3, asr #31\";
6971 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
6973 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
6975 if (operands[1] == const0_rtx)
6976 return \"and\\t%0, %2, %3, asr #31\";
6977 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
6979 /* The only case that falls through to here is when both ops 1 & 2
6982 if (GET_CODE (operands[4]) == CONST_INT
6983 && !const_ok_for_arm (INTVAL (operands[4])))
6984 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
6986 output_asm_insn (\"cmp\\t%3, %4\", operands);
6987 if (which_alternative != 0)
6988 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
6989 if (which_alternative != 1)
6990 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
6993 [(set_attr "conds" "clob")
6994 (set_attr "length" "8,8,12")]
6997 (define_insn "*ifcompare_plus_move"
6998 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6999 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7000 [(match_operand:SI 4 "s_register_operand" "r,r")
7001 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7003 (match_operand:SI 2 "s_register_operand" "r,r")
7004 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7005 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7006 (clobber (reg:CC CC_REGNUM))]
7009 [(set_attr "conds" "clob")
7010 (set_attr "length" "8,12")]
7013 (define_insn "*if_plus_move"
7014 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7016 (match_operator 4 "arm_comparison_operator"
7017 [(match_operand 5 "cc_register" "") (const_int 0)])
7019 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7020 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7021 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7025 sub%d4\\t%0, %2, #%n3
7026 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7027 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7028 [(set_attr "conds" "use")
7029 (set_attr "length" "4,4,8,8")
7030 (set_attr "type" "*,*,*,*")]
7033 (define_insn "*ifcompare_move_plus"
7034 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7035 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7036 [(match_operand:SI 4 "s_register_operand" "r,r")
7037 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7038 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7040 (match_operand:SI 2 "s_register_operand" "r,r")
7041 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7042 (clobber (reg:CC CC_REGNUM))]
7045 [(set_attr "conds" "clob")
7046 (set_attr "length" "8,12")]
7049 (define_insn "*if_move_plus"
7050 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7052 (match_operator 4 "arm_comparison_operator"
7053 [(match_operand 5 "cc_register" "") (const_int 0)])
7054 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7056 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7057 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7061 sub%D4\\t%0, %2, #%n3
7062 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7063 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7064 [(set_attr "conds" "use")
7065 (set_attr "length" "4,4,8,8")
7066 (set_attr "type" "*,*,*,*")]
7069 (define_insn "*ifcompare_arith_arith"
7070 [(set (match_operand:SI 0 "s_register_operand" "=r")
7071 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7072 [(match_operand:SI 5 "s_register_operand" "r")
7073 (match_operand:SI 6 "arm_add_operand" "rIL")])
7074 (match_operator:SI 8 "shiftable_operator"
7075 [(match_operand:SI 1 "s_register_operand" "r")
7076 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7077 (match_operator:SI 7 "shiftable_operator"
7078 [(match_operand:SI 3 "s_register_operand" "r")
7079 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7080 (clobber (reg:CC CC_REGNUM))]
7083 [(set_attr "conds" "clob")
7084 (set_attr "length" "12")]
7087 (define_insn "*if_arith_arith"
7088 [(set (match_operand:SI 0 "s_register_operand" "=r")
7089 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7090 [(match_operand 8 "cc_register" "") (const_int 0)])
7091 (match_operator:SI 6 "shiftable_operator"
7092 [(match_operand:SI 1 "s_register_operand" "r")
7093 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7094 (match_operator:SI 7 "shiftable_operator"
7095 [(match_operand:SI 3 "s_register_operand" "r")
7096 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7098 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7099 [(set_attr "conds" "use")
7100 (set_attr "length" "8")]
7103 (define_insn "*ifcompare_arith_move"
7104 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7105 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7106 [(match_operand:SI 2 "s_register_operand" "r,r")
7107 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7108 (match_operator:SI 7 "shiftable_operator"
7109 [(match_operand:SI 4 "s_register_operand" "r,r")
7110 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7111 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7112 (clobber (reg:CC CC_REGNUM))]
7115 /* If we have an operation where (op x 0) is the identity operation and
7116 the conditional operator is LT or GE and we are comparing against zero and
7117 everything is in registers then we can do this in two instructions */
7118 if (operands[3] == const0_rtx
7119 && GET_CODE (operands[7]) != AND
7120 && GET_CODE (operands[5]) == REG
7121 && GET_CODE (operands[1]) == REG
7122 && REGNO (operands[1]) == REGNO (operands[4])
7123 && REGNO (operands[4]) != REGNO (operands[0]))
7125 if (GET_CODE (operands[6]) == LT)
7126 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7127 else if (GET_CODE (operands[6]) == GE)
7128 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7130 if (GET_CODE (operands[3]) == CONST_INT
7131 && !const_ok_for_arm (INTVAL (operands[3])))
7132 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7134 output_asm_insn (\"cmp\\t%2, %3\", operands);
7135 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7136 if (which_alternative != 0)
7137 return \"mov%D6\\t%0, %1\";
7140 [(set_attr "conds" "clob")
7141 (set_attr "length" "8,12")]
7144 (define_insn "*if_arith_move"
7145 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7146 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7147 [(match_operand 6 "cc_register" "") (const_int 0)])
7148 (match_operator:SI 5 "shiftable_operator"
7149 [(match_operand:SI 2 "s_register_operand" "r,r")
7150 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7151 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7155 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7156 [(set_attr "conds" "use")
7157 (set_attr "length" "4,8")
7158 (set_attr "type" "*,*")]
7161 (define_insn "*ifcompare_move_arith"
7162 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7163 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7164 [(match_operand:SI 4 "s_register_operand" "r,r")
7165 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7166 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7167 (match_operator:SI 7 "shiftable_operator"
7168 [(match_operand:SI 2 "s_register_operand" "r,r")
7169 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7170 (clobber (reg:CC CC_REGNUM))]
7173 /* If we have an operation where (op x 0) is the identity operation and
7174 the conditional operator is LT or GE and we are comparing against zero and
7175 everything is in registers then we can do this in two instructions */
7176 if (operands[5] == const0_rtx
7177 && GET_CODE (operands[7]) != AND
7178 && GET_CODE (operands[3]) == REG
7179 && GET_CODE (operands[1]) == REG
7180 && REGNO (operands[1]) == REGNO (operands[2])
7181 && REGNO (operands[2]) != REGNO (operands[0]))
7183 if (GET_CODE (operands[6]) == GE)
7184 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7185 else if (GET_CODE (operands[6]) == LT)
7186 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7189 if (GET_CODE (operands[5]) == CONST_INT
7190 && !const_ok_for_arm (INTVAL (operands[5])))
7191 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7193 output_asm_insn (\"cmp\\t%4, %5\", operands);
7195 if (which_alternative != 0)
7196 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7197 return \"%I7%D6\\t%0, %2, %3\";
7199 [(set_attr "conds" "clob")
7200 (set_attr "length" "8,12")]
7203 (define_insn "*if_move_arith"
7204 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7206 (match_operator 4 "arm_comparison_operator"
7207 [(match_operand 6 "cc_register" "") (const_int 0)])
7208 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7209 (match_operator:SI 5 "shiftable_operator"
7210 [(match_operand:SI 2 "s_register_operand" "r,r")
7211 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7215 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7216 [(set_attr "conds" "use")
7217 (set_attr "length" "4,8")
7218 (set_attr "type" "*,*")]
7221 (define_insn "*ifcompare_move_not"
7222 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7224 (match_operator 5 "arm_comparison_operator"
7225 [(match_operand:SI 3 "s_register_operand" "r,r")
7226 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7227 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7229 (match_operand:SI 2 "s_register_operand" "r,r"))))
7230 (clobber (reg:CC CC_REGNUM))]
7233 [(set_attr "conds" "clob")
7234 (set_attr "length" "8,12")]
7237 (define_insn "*if_move_not"
7238 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7240 (match_operator 4 "arm_comparison_operator"
7241 [(match_operand 3 "cc_register" "") (const_int 0)])
7242 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7243 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7247 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7248 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7249 [(set_attr "conds" "use")
7250 (set_attr "length" "4,8,8")]
7253 (define_insn "*ifcompare_not_move"
7254 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7256 (match_operator 5 "arm_comparison_operator"
7257 [(match_operand:SI 3 "s_register_operand" "r,r")
7258 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7260 (match_operand:SI 2 "s_register_operand" "r,r"))
7261 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7262 (clobber (reg:CC CC_REGNUM))]
7265 [(set_attr "conds" "clob")
7266 (set_attr "length" "8,12")]
7269 (define_insn "*if_not_move"
7270 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7272 (match_operator 4 "arm_comparison_operator"
7273 [(match_operand 3 "cc_register" "") (const_int 0)])
7274 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7275 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7279 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7280 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7281 [(set_attr "conds" "use")
7282 (set_attr "length" "4,8,8")]
7285 (define_insn "*ifcompare_shift_move"
7286 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7288 (match_operator 6 "arm_comparison_operator"
7289 [(match_operand:SI 4 "s_register_operand" "r,r")
7290 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7291 (match_operator:SI 7 "shift_operator"
7292 [(match_operand:SI 2 "s_register_operand" "r,r")
7293 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7294 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7295 (clobber (reg:CC CC_REGNUM))]
7298 [(set_attr "conds" "clob")
7299 (set_attr "length" "8,12")]
7302 (define_insn "*if_shift_move"
7303 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7305 (match_operator 5 "arm_comparison_operator"
7306 [(match_operand 6 "cc_register" "") (const_int 0)])
7307 (match_operator:SI 4 "shift_operator"
7308 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7309 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7310 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7314 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7315 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7316 [(set_attr "conds" "use")
7317 (set_attr "shift" "2")
7318 (set_attr "length" "4,8,8")]
7321 (define_insn "*ifcompare_move_shift"
7322 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7324 (match_operator 6 "arm_comparison_operator"
7325 [(match_operand:SI 4 "s_register_operand" "r,r")
7326 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7327 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7328 (match_operator:SI 7 "shift_operator"
7329 [(match_operand:SI 2 "s_register_operand" "r,r")
7330 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7331 (clobber (reg:CC CC_REGNUM))]
7334 [(set_attr "conds" "clob")
7335 (set_attr "length" "8,12")]
7338 (define_insn "*if_move_shift"
7339 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7341 (match_operator 5 "arm_comparison_operator"
7342 [(match_operand 6 "cc_register" "") (const_int 0)])
7343 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7344 (match_operator:SI 4 "shift_operator"
7345 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7346 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7350 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7351 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7352 [(set_attr "conds" "use")
7353 (set_attr "shift" "2")
7354 (set_attr "length" "4,8,8")]
7357 (define_insn "*ifcompare_shift_shift"
7358 [(set (match_operand:SI 0 "s_register_operand" "=r")
7360 (match_operator 7 "arm_comparison_operator"
7361 [(match_operand:SI 5 "s_register_operand" "r")
7362 (match_operand:SI 6 "arm_add_operand" "rIL")])
7363 (match_operator:SI 8 "shift_operator"
7364 [(match_operand:SI 1 "s_register_operand" "r")
7365 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7366 (match_operator:SI 9 "shift_operator"
7367 [(match_operand:SI 3 "s_register_operand" "r")
7368 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7369 (clobber (reg:CC CC_REGNUM))]
7372 [(set_attr "conds" "clob")
7373 (set_attr "length" "12")]
7376 (define_insn "*if_shift_shift"
7377 [(set (match_operand:SI 0 "s_register_operand" "=r")
7379 (match_operator 5 "arm_comparison_operator"
7380 [(match_operand 8 "cc_register" "") (const_int 0)])
7381 (match_operator:SI 6 "shift_operator"
7382 [(match_operand:SI 1 "s_register_operand" "r")
7383 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7384 (match_operator:SI 7 "shift_operator"
7385 [(match_operand:SI 3 "s_register_operand" "r")
7386 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7388 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7389 [(set_attr "conds" "use")
7390 (set_attr "shift" "1")
7391 (set_attr "length" "8")]
7394 (define_insn "*ifcompare_not_arith"
7395 [(set (match_operand:SI 0 "s_register_operand" "=r")
7397 (match_operator 6 "arm_comparison_operator"
7398 [(match_operand:SI 4 "s_register_operand" "r")
7399 (match_operand:SI 5 "arm_add_operand" "rIL")])
7400 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7401 (match_operator:SI 7 "shiftable_operator"
7402 [(match_operand:SI 2 "s_register_operand" "r")
7403 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7404 (clobber (reg:CC CC_REGNUM))]
7407 [(set_attr "conds" "clob")
7408 (set_attr "length" "12")]
7411 (define_insn "*if_not_arith"
7412 [(set (match_operand:SI 0 "s_register_operand" "=r")
7414 (match_operator 5 "arm_comparison_operator"
7415 [(match_operand 4 "cc_register" "") (const_int 0)])
7416 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7417 (match_operator:SI 6 "shiftable_operator"
7418 [(match_operand:SI 2 "s_register_operand" "r")
7419 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7421 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7422 [(set_attr "conds" "use")
7423 (set_attr "length" "8")]
7426 (define_insn "*ifcompare_arith_not"
7427 [(set (match_operand:SI 0 "s_register_operand" "=r")
7429 (match_operator 6 "arm_comparison_operator"
7430 [(match_operand:SI 4 "s_register_operand" "r")
7431 (match_operand:SI 5 "arm_add_operand" "rIL")])
7432 (match_operator:SI 7 "shiftable_operator"
7433 [(match_operand:SI 2 "s_register_operand" "r")
7434 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7435 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7436 (clobber (reg:CC CC_REGNUM))]
7439 [(set_attr "conds" "clob")
7440 (set_attr "length" "12")]
7443 (define_insn "*if_arith_not"
7444 [(set (match_operand:SI 0 "s_register_operand" "=r")
7446 (match_operator 5 "arm_comparison_operator"
7447 [(match_operand 4 "cc_register" "") (const_int 0)])
7448 (match_operator:SI 6 "shiftable_operator"
7449 [(match_operand:SI 2 "s_register_operand" "r")
7450 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7451 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7453 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7454 [(set_attr "conds" "use")
7455 (set_attr "length" "8")]
7458 (define_insn "*ifcompare_neg_move"
7459 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7461 (match_operator 5 "arm_comparison_operator"
7462 [(match_operand:SI 3 "s_register_operand" "r,r")
7463 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7464 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7465 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7466 (clobber (reg:CC CC_REGNUM))]
7469 [(set_attr "conds" "clob")
7470 (set_attr "length" "8,12")]
7473 (define_insn "*if_neg_move"
7474 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7476 (match_operator 4 "arm_comparison_operator"
7477 [(match_operand 3 "cc_register" "") (const_int 0)])
7478 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7479 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7483 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7484 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
7485 [(set_attr "conds" "use")
7486 (set_attr "length" "4,8,8")]
7489 (define_insn "*ifcompare_move_neg"
7490 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7492 (match_operator 5 "arm_comparison_operator"
7493 [(match_operand:SI 3 "s_register_operand" "r,r")
7494 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7495 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7496 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
7497 (clobber (reg:CC CC_REGNUM))]
7500 [(set_attr "conds" "clob")
7501 (set_attr "length" "8,12")]
7504 (define_insn "*if_move_neg"
7505 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7507 (match_operator 4 "arm_comparison_operator"
7508 [(match_operand 3 "cc_register" "") (const_int 0)])
7509 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7510 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7514 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
7515 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
7516 [(set_attr "conds" "use")
7517 (set_attr "length" "4,8,8")]
7520 (define_insn "*arith_adjacentmem"
7521 [(set (match_operand:SI 0 "s_register_operand" "=r")
7522 (match_operator:SI 1 "shiftable_operator"
7523 [(match_operand:SI 2 "memory_operand" "m")
7524 (match_operand:SI 3 "memory_operand" "m")]))
7525 (clobber (match_scratch:SI 4 "=r"))]
7526 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
7531 int val1 = 0, val2 = 0;
7533 if (REGNO (operands[0]) > REGNO (operands[4]))
7535 ldm[1] = operands[4];
7536 ldm[2] = operands[0];
7540 ldm[1] = operands[0];
7541 ldm[2] = operands[4];
7543 if (GET_CODE (XEXP (operands[2], 0)) != REG)
7544 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
7545 if (GET_CODE (XEXP (operands[3], 0)) != REG)
7546 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
7547 arith[0] = operands[0];
7548 arith[3] = operands[1];
7562 ldm[0] = ops[0] = operands[4];
7563 ops[1] = XEXP (XEXP (operands[2], 0), 0);
7564 ops[2] = XEXP (XEXP (operands[2], 0), 1);
7565 output_add_immediate (ops);
7567 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7569 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7573 ldm[0] = XEXP (operands[3], 0);
7575 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7577 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7581 ldm[0] = XEXP (operands[2], 0);
7583 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7585 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7587 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
7590 [(set_attr "length" "12")
7591 (set_attr "predicable" "yes")
7592 (set_attr "type" "load")]
7595 ;; the arm can support extended pre-inc instructions
7597 ;; In all these cases, we use operands 0 and 1 for the register being
7598 ;; incremented because those are the operands that local-alloc will
7599 ;; tie and these are the pair most likely to be tieable (and the ones
7600 ;; that will benefit the most).
7602 ;; We reject the frame pointer if it occurs anywhere in these patterns since
7603 ;; elimination will cause too many headaches.
7605 (define_insn "*strqi_preinc"
7606 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7607 (match_operand:SI 2 "index_operand" "rJ")))
7608 (match_operand:QI 3 "s_register_operand" "r"))
7609 (set (match_operand:SI 0 "s_register_operand" "=r")
7610 (plus:SI (match_dup 1) (match_dup 2)))]
7612 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7613 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7614 && (GET_CODE (operands[2]) != REG
7615 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7616 "str%?b\\t%3, [%0, %2]!"
7617 [(set_attr "type" "store1")
7618 (set_attr "predicable" "yes")]
7621 (define_insn "*strqi_predec"
7622 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7623 (match_operand:SI 2 "s_register_operand" "r")))
7624 (match_operand:QI 3 "s_register_operand" "r"))
7625 (set (match_operand:SI 0 "s_register_operand" "=r")
7626 (minus:SI (match_dup 1) (match_dup 2)))]
7628 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7629 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7630 && (GET_CODE (operands[2]) != REG
7631 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7632 "str%?b\\t%3, [%0, -%2]!"
7633 [(set_attr "type" "store1")
7634 (set_attr "predicable" "yes")]
7637 (define_insn "*loadqi_preinc"
7638 [(set (match_operand:QI 3 "s_register_operand" "=r")
7639 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7640 (match_operand:SI 2 "index_operand" "rJ"))))
7641 (set (match_operand:SI 0 "s_register_operand" "=r")
7642 (plus:SI (match_dup 1) (match_dup 2)))]
7644 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7645 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7646 && (GET_CODE (operands[2]) != REG
7647 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7648 "ldr%?b\\t%3, [%0, %2]!"
7649 [(set_attr "type" "load")
7650 (set_attr "predicable" "yes")]
7653 (define_insn "*loadqi_predec"
7654 [(set (match_operand:QI 3 "s_register_operand" "=r")
7655 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7656 (match_operand:SI 2 "s_register_operand" "r"))))
7657 (set (match_operand:SI 0 "s_register_operand" "=r")
7658 (minus:SI (match_dup 1) (match_dup 2)))]
7660 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7661 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7662 && (GET_CODE (operands[2]) != REG
7663 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7664 "ldr%?b\\t%3, [%0, -%2]!"
7665 [(set_attr "type" "load")
7666 (set_attr "predicable" "yes")]
7669 (define_insn "*loadqisi_preinc"
7670 [(set (match_operand:SI 3 "s_register_operand" "=r")
7672 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7673 (match_operand:SI 2 "index_operand" "rJ")))))
7674 (set (match_operand:SI 0 "s_register_operand" "=r")
7675 (plus:SI (match_dup 1) (match_dup 2)))]
7677 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7678 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7679 && (GET_CODE (operands[2]) != REG
7680 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7681 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
7682 [(set_attr "type" "load")
7683 (set_attr "predicable" "yes")]
7686 (define_insn "*loadqisi_predec"
7687 [(set (match_operand:SI 3 "s_register_operand" "=r")
7689 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7690 (match_operand:SI 2 "s_register_operand" "r")))))
7691 (set (match_operand:SI 0 "s_register_operand" "=r")
7692 (minus:SI (match_dup 1) (match_dup 2)))]
7694 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7695 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7696 && (GET_CODE (operands[2]) != REG
7697 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7698 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
7699 [(set_attr "type" "load")
7700 (set_attr "predicable" "yes")]
7703 (define_insn "*strsi_preinc"
7704 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7705 (match_operand:SI 2 "index_operand" "rJ")))
7706 (match_operand:SI 3 "s_register_operand" "r"))
7707 (set (match_operand:SI 0 "s_register_operand" "=r")
7708 (plus:SI (match_dup 1) (match_dup 2)))]
7710 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7711 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7712 && (GET_CODE (operands[2]) != REG
7713 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7714 "str%?\\t%3, [%0, %2]!"
7715 [(set_attr "type" "store1")
7716 (set_attr "predicable" "yes")]
7719 (define_insn "*strsi_predec"
7720 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7721 (match_operand:SI 2 "s_register_operand" "r")))
7722 (match_operand:SI 3 "s_register_operand" "r"))
7723 (set (match_operand:SI 0 "s_register_operand" "=r")
7724 (minus:SI (match_dup 1) (match_dup 2)))]
7726 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7727 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7728 && (GET_CODE (operands[2]) != REG
7729 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7730 "str%?\\t%3, [%0, -%2]!"
7731 [(set_attr "type" "store1")
7732 (set_attr "predicable" "yes")]
7735 (define_insn "*loadsi_preinc"
7736 [(set (match_operand:SI 3 "s_register_operand" "=r")
7737 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7738 (match_operand:SI 2 "index_operand" "rJ"))))
7739 (set (match_operand:SI 0 "s_register_operand" "=r")
7740 (plus:SI (match_dup 1) (match_dup 2)))]
7742 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7743 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7744 && (GET_CODE (operands[2]) != REG
7745 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7746 "ldr%?\\t%3, [%0, %2]!"
7747 [(set_attr "type" "load")
7748 (set_attr "predicable" "yes")]
7751 (define_insn "*loadsi_predec"
7752 [(set (match_operand:SI 3 "s_register_operand" "=r")
7753 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7754 (match_operand:SI 2 "s_register_operand" "r"))))
7755 (set (match_operand:SI 0 "s_register_operand" "=r")
7756 (minus:SI (match_dup 1) (match_dup 2)))]
7758 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7759 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7760 && (GET_CODE (operands[2]) != REG
7761 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7762 "ldr%?\\t%3, [%0, -%2]!"
7763 [(set_attr "type" "load")
7764 (set_attr "predicable" "yes")]
7767 (define_insn "*loadhi_preinc"
7768 [(set (match_operand:HI 3 "s_register_operand" "=r")
7769 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7770 (match_operand:SI 2 "index_operand" "rJ"))))
7771 (set (match_operand:SI 0 "s_register_operand" "=r")
7772 (plus:SI (match_dup 1) (match_dup 2)))]
7774 && !BYTES_BIG_ENDIAN
7775 && !TARGET_MMU_TRAPS
7777 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7778 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7779 && (GET_CODE (operands[2]) != REG
7780 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7781 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
7782 [(set_attr "type" "load")
7783 (set_attr "predicable" "yes")]
7786 (define_insn "*loadhi_predec"
7787 [(set (match_operand:HI 3 "s_register_operand" "=r")
7788 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7789 (match_operand:SI 2 "s_register_operand" "r"))))
7790 (set (match_operand:SI 0 "s_register_operand" "=r")
7791 (minus:SI (match_dup 1) (match_dup 2)))]
7793 && !BYTES_BIG_ENDIAN
7794 && !TARGET_MMU_TRAPS
7796 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7797 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7798 && (GET_CODE (operands[2]) != REG
7799 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7800 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
7801 [(set_attr "type" "load")
7802 (set_attr "predicable" "yes")]
7805 (define_insn "*strqi_shiftpreinc"
7806 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
7807 [(match_operand:SI 3 "s_register_operand" "r")
7808 (match_operand:SI 4 "const_shift_operand" "n")])
7809 (match_operand:SI 1 "s_register_operand" "0")))
7810 (match_operand:QI 5 "s_register_operand" "r"))
7811 (set (match_operand:SI 0 "s_register_operand" "=r")
7812 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7815 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7816 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7817 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7818 "str%?b\\t%5, [%0, %3%S2]!"
7819 [(set_attr "type" "store1")
7820 (set_attr "predicable" "yes")]
7823 (define_insn "*strqi_shiftpredec"
7824 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7825 (match_operator:SI 2 "shift_operator"
7826 [(match_operand:SI 3 "s_register_operand" "r")
7827 (match_operand:SI 4 "const_shift_operand" "n")])))
7828 (match_operand:QI 5 "s_register_operand" "r"))
7829 (set (match_operand:SI 0 "s_register_operand" "=r")
7830 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7833 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7834 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7835 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7836 "str%?b\\t%5, [%0, -%3%S2]!"
7837 [(set_attr "type" "store1")
7838 (set_attr "predicable" "yes")]
7841 (define_insn "*loadqi_shiftpreinc"
7842 [(set (match_operand:QI 5 "s_register_operand" "=r")
7843 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
7844 [(match_operand:SI 3 "s_register_operand" "r")
7845 (match_operand:SI 4 "const_shift_operand" "n")])
7846 (match_operand:SI 1 "s_register_operand" "0"))))
7847 (set (match_operand:SI 0 "s_register_operand" "=r")
7848 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7851 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7852 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7853 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7854 "ldr%?b\\t%5, [%0, %3%S2]!"
7855 [(set_attr "type" "load")
7856 (set_attr "predicable" "yes")]
7859 (define_insn "*loadqi_shiftpredec"
7860 [(set (match_operand:QI 5 "s_register_operand" "=r")
7861 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7862 (match_operator:SI 2 "shift_operator"
7863 [(match_operand:SI 3 "s_register_operand" "r")
7864 (match_operand:SI 4 "const_shift_operand" "n")]))))
7865 (set (match_operand:SI 0 "s_register_operand" "=r")
7866 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7869 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7870 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7871 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7872 "ldr%?b\\t%5, [%0, -%3%S2]!"
7873 [(set_attr "type" "load")
7874 (set_attr "predicable" "yes")]
7877 (define_insn "*strsi_shiftpreinc"
7878 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
7879 [(match_operand:SI 3 "s_register_operand" "r")
7880 (match_operand:SI 4 "const_shift_operand" "n")])
7881 (match_operand:SI 1 "s_register_operand" "0")))
7882 (match_operand:SI 5 "s_register_operand" "r"))
7883 (set (match_operand:SI 0 "s_register_operand" "=r")
7884 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7887 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7888 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7889 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7890 "str%?\\t%5, [%0, %3%S2]!"
7891 [(set_attr "type" "store1")
7892 (set_attr "predicable" "yes")]
7895 (define_insn "*strsi_shiftpredec"
7896 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7897 (match_operator:SI 2 "shift_operator"
7898 [(match_operand:SI 3 "s_register_operand" "r")
7899 (match_operand:SI 4 "const_shift_operand" "n")])))
7900 (match_operand:SI 5 "s_register_operand" "r"))
7901 (set (match_operand:SI 0 "s_register_operand" "=r")
7902 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7905 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7906 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7907 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7908 "str%?\\t%5, [%0, -%3%S2]!"
7909 [(set_attr "type" "store1")
7910 (set_attr "predicable" "yes")]
7913 (define_insn "*loadsi_shiftpreinc"
7914 [(set (match_operand:SI 5 "s_register_operand" "=r")
7915 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
7916 [(match_operand:SI 3 "s_register_operand" "r")
7917 (match_operand:SI 4 "const_shift_operand" "n")])
7918 (match_operand:SI 1 "s_register_operand" "0"))))
7919 (set (match_operand:SI 0 "s_register_operand" "=r")
7920 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7923 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7924 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7925 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7926 "ldr%?\\t%5, [%0, %3%S2]!"
7927 [(set_attr "type" "load")
7928 (set_attr "predicable" "yes")]
7931 (define_insn "*loadsi_shiftpredec"
7932 [(set (match_operand:SI 5 "s_register_operand" "=r")
7933 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7934 (match_operator:SI 2 "shift_operator"
7935 [(match_operand:SI 3 "s_register_operand" "r")
7936 (match_operand:SI 4 "const_shift_operand" "n")]))))
7937 (set (match_operand:SI 0 "s_register_operand" "=r")
7938 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7941 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7942 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7943 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7944 "ldr%?\\t%5, [%0, -%3%S2]!"
7945 [(set_attr "type" "load")
7946 (set_attr "predicable" "yes")])
7948 (define_insn "*loadhi_shiftpreinc"
7949 [(set (match_operand:HI 5 "s_register_operand" "=r")
7950 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
7951 [(match_operand:SI 3 "s_register_operand" "r")
7952 (match_operand:SI 4 "const_shift_operand" "n")])
7953 (match_operand:SI 1 "s_register_operand" "0"))))
7954 (set (match_operand:SI 0 "s_register_operand" "=r")
7955 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7958 && !BYTES_BIG_ENDIAN
7959 && !TARGET_MMU_TRAPS
7961 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7962 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7963 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7964 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
7965 [(set_attr "type" "load")
7966 (set_attr "predicable" "yes")]
7969 (define_insn "*loadhi_shiftpredec"
7970 [(set (match_operand:HI 5 "s_register_operand" "=r")
7971 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7972 (match_operator:SI 2 "shift_operator"
7973 [(match_operand:SI 3 "s_register_operand" "r")
7974 (match_operand:SI 4 "const_shift_operand" "n")]))))
7975 (set (match_operand:SI 0 "s_register_operand" "=r")
7976 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7979 && !BYTES_BIG_ENDIAN
7980 && !TARGET_MMU_TRAPS
7982 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7983 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7984 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7985 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
7986 [(set_attr "type" "load")
7987 (set_attr "predicable" "yes")]
7990 ; It can also support extended post-inc expressions, but combine doesn't
7992 ; It doesn't seem worth adding peepholes for anything but the most common
7993 ; cases since, unlike combine, the increment must immediately follow the load
7994 ; for this pattern to match.
7995 ; We must watch to see that the source/destination register isn't also the
7996 ; same as the base address register, and that if the index is a register,
7997 ; that it is not the same as the base address register. In such cases the
7998 ; instruction that we would generate would have UNPREDICTABLE behavior so
8002 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8003 (match_operand:QI 2 "s_register_operand" "r"))
8005 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8007 && (REGNO (operands[2]) != REGNO (operands[0]))
8008 && (GET_CODE (operands[1]) != REG
8009 || (REGNO (operands[1]) != REGNO (operands[0])))"
8010 "str%?b\\t%2, [%0], %1"
8014 [(set (match_operand:QI 0 "s_register_operand" "=r")
8015 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8017 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8019 && REGNO (operands[0]) != REGNO(operands[1])
8020 && (GET_CODE (operands[2]) != REG
8021 || REGNO(operands[0]) != REGNO (operands[2]))"
8022 "ldr%?b\\t%0, [%1], %2"
8026 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8027 (match_operand:SI 2 "s_register_operand" "r"))
8029 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8031 && (REGNO (operands[2]) != REGNO (operands[0]))
8032 && (GET_CODE (operands[1]) != REG
8033 || (REGNO (operands[1]) != REGNO (operands[0])))"
8034 "str%?\\t%2, [%0], %1"
8038 [(set (match_operand:HI 0 "s_register_operand" "=r")
8039 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8041 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8043 && !BYTES_BIG_ENDIAN
8044 && !TARGET_MMU_TRAPS
8046 && REGNO (operands[0]) != REGNO(operands[1])
8047 && (GET_CODE (operands[2]) != REG
8048 || REGNO(operands[0]) != REGNO (operands[2]))"
8049 "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8053 [(set (match_operand:SI 0 "s_register_operand" "=r")
8054 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8056 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8058 && REGNO (operands[0]) != REGNO(operands[1])
8059 && (GET_CODE (operands[2]) != REG
8060 || REGNO(operands[0]) != REGNO (operands[2]))"
8061 "ldr%?\\t%0, [%1], %2"
8065 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8066 (match_operand:SI 1 "index_operand" "rJ")))
8067 (match_operand:QI 2 "s_register_operand" "r"))
8068 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8070 && (REGNO (operands[2]) != REGNO (operands[0]))
8071 && (GET_CODE (operands[1]) != REG
8072 || (REGNO (operands[1]) != REGNO (operands[0])))"
8073 "str%?b\\t%2, [%0, %1]!"
8077 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8078 [(match_operand:SI 0 "s_register_operand" "r")
8079 (match_operand:SI 1 "const_int_operand" "n")])
8080 (match_operand:SI 2 "s_register_operand" "+r")))
8081 (match_operand:QI 3 "s_register_operand" "r"))
8082 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8085 && (REGNO (operands[3]) != REGNO (operands[2]))
8086 && (REGNO (operands[0]) != REGNO (operands[2]))"
8087 "str%?b\\t%3, [%2, %0%S4]!"
8090 ; This pattern is never tried by combine, so do it as a peephole
8093 [(set (match_operand:SI 0 "s_register_operand" "")
8094 (match_operand:SI 1 "s_register_operand" ""))
8095 (set (reg:CC CC_REGNUM)
8096 (compare:CC (match_dup 1) (const_int 0)))]
8099 || (!cirrus_fp_register (operands[0], SImode)
8100 && !cirrus_fp_register (operands[1], SImode)))
8102 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8103 (set (match_dup 0) (match_dup 1))])]
8107 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8108 ; reversed, check that the memory references aren't volatile.
8111 [(set (match_operand:SI 0 "s_register_operand" "=r")
8112 (match_operand:SI 4 "memory_operand" "m"))
8113 (set (match_operand:SI 1 "s_register_operand" "=r")
8114 (match_operand:SI 5 "memory_operand" "m"))
8115 (set (match_operand:SI 2 "s_register_operand" "=r")
8116 (match_operand:SI 6 "memory_operand" "m"))
8117 (set (match_operand:SI 3 "s_register_operand" "=r")
8118 (match_operand:SI 7 "memory_operand" "m"))]
8119 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8121 return emit_ldm_seq (operands, 4);
8126 [(set (match_operand:SI 0 "s_register_operand" "=r")
8127 (match_operand:SI 3 "memory_operand" "m"))
8128 (set (match_operand:SI 1 "s_register_operand" "=r")
8129 (match_operand:SI 4 "memory_operand" "m"))
8130 (set (match_operand:SI 2 "s_register_operand" "=r")
8131 (match_operand:SI 5 "memory_operand" "m"))]
8132 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8134 return emit_ldm_seq (operands, 3);
8139 [(set (match_operand:SI 0 "s_register_operand" "=r")
8140 (match_operand:SI 2 "memory_operand" "m"))
8141 (set (match_operand:SI 1 "s_register_operand" "=r")
8142 (match_operand:SI 3 "memory_operand" "m"))]
8143 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8145 return emit_ldm_seq (operands, 2);
8150 [(set (match_operand:SI 4 "memory_operand" "=m")
8151 (match_operand:SI 0 "s_register_operand" "r"))
8152 (set (match_operand:SI 5 "memory_operand" "=m")
8153 (match_operand:SI 1 "s_register_operand" "r"))
8154 (set (match_operand:SI 6 "memory_operand" "=m")
8155 (match_operand:SI 2 "s_register_operand" "r"))
8156 (set (match_operand:SI 7 "memory_operand" "=m")
8157 (match_operand:SI 3 "s_register_operand" "r"))]
8158 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8160 return emit_stm_seq (operands, 4);
8165 [(set (match_operand:SI 3 "memory_operand" "=m")
8166 (match_operand:SI 0 "s_register_operand" "r"))
8167 (set (match_operand:SI 4 "memory_operand" "=m")
8168 (match_operand:SI 1 "s_register_operand" "r"))
8169 (set (match_operand:SI 5 "memory_operand" "=m")
8170 (match_operand:SI 2 "s_register_operand" "r"))]
8171 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8173 return emit_stm_seq (operands, 3);
8178 [(set (match_operand:SI 2 "memory_operand" "=m")
8179 (match_operand:SI 0 "s_register_operand" "r"))
8180 (set (match_operand:SI 3 "memory_operand" "=m")
8181 (match_operand:SI 1 "s_register_operand" "r"))]
8182 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8184 return emit_stm_seq (operands, 2);
8189 [(set (match_operand:SI 0 "s_register_operand" "")
8190 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8192 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8193 [(match_operand:SI 3 "s_register_operand" "")
8194 (match_operand:SI 4 "arm_rhs_operand" "")]))))
8195 (clobber (match_operand:SI 5 "s_register_operand" ""))]
8197 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8198 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8203 ;; This split can be used because CC_Z mode implies that the following
8204 ;; branch will be an equality, or an unsigned inequality, so the sign
8205 ;; extension is not needed.
8208 [(set (reg:CC_Z CC_REGNUM)
8210 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8212 (match_operand 1 "const_int_operand" "")))
8213 (clobber (match_scratch:SI 2 ""))]
8215 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8216 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8217 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8218 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8220 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8224 (define_expand "prologue"
8225 [(clobber (const_int 0))]
8228 arm_expand_prologue ();
8230 thumb_expand_prologue ();
8235 (define_expand "epilogue"
8236 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8240 thumb_expand_epilogue ();
8241 else if (USE_RETURN_INSN (FALSE))
8243 emit_jump_insn (gen_return ());
8246 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8248 gen_rtx_RETURN (VOIDmode)),
8254 ;; Note - although unspec_volatile's USE all hard registers,
8255 ;; USEs are ignored after relaod has completed. Thus we need
8256 ;; to add an unspec of the link register to ensure that flow
8257 ;; does not think that it is unused by the sibcall branch that
8258 ;; will replace the standard function epilogue.
8259 (define_insn "sibcall_epilogue"
8260 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
8261 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
8264 if (USE_RETURN_INSN (FALSE))
8265 return output_return_instruction (const_true_rtx, FALSE, FALSE);
8266 return arm_output_epilogue (FALSE);
8268 ;; Length is absolute worst case
8269 [(set_attr "length" "44")
8270 (set_attr "type" "block")
8271 ;; We don't clobber the conditions, but the potential length of this
8272 ;; operation is sufficient to make conditionalizing the sequence
8273 ;; unlikely to be profitable.
8274 (set_attr "conds" "clob")]
8277 (define_insn "*epilogue_insns"
8278 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8282 return arm_output_epilogue (TRUE);
8283 else /* TARGET_THUMB */
8284 return thumb_unexpanded_epilogue ();
8286 ; Length is absolute worst case
8287 [(set_attr "length" "44")
8288 (set_attr "type" "block")
8289 ;; We don't clobber the conditions, but the potential length of this
8290 ;; operation is sufficient to make conditionalizing the sequence
8291 ;; unlikely to be profitable.
8292 (set_attr "conds" "clob")]
8295 (define_expand "eh_epilogue"
8296 [(use (match_operand:SI 0 "register_operand" ""))
8297 (use (match_operand:SI 1 "register_operand" ""))
8298 (use (match_operand:SI 2 "register_operand" ""))]
8302 cfun->machine->eh_epilogue_sp_ofs = operands[1];
8303 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8305 rtx ra = gen_rtx_REG (Pmode, 2);
8307 emit_move_insn (ra, operands[2]);
8310 /* This is a hack -- we may have crystalized the function type too
8312 cfun->machine->func_type = 0;
8316 ;; This split is only used during output to reduce the number of patterns
8317 ;; that need assembler instructions adding to them. We allowed the setting
8318 ;; of the conditions to be implicit during rtl generation so that
8319 ;; the conditional compare patterns would work. However this conflicts to
8320 ;; some extent with the conditional data operations, so we have to split them
8324 [(set (match_operand:SI 0 "s_register_operand" "")
8325 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8326 [(match_operand 2 "" "") (match_operand 3 "" "")])
8328 (match_operand 4 "" "")))
8329 (clobber (reg:CC CC_REGNUM))]
8330 "TARGET_ARM && reload_completed"
8331 [(set (match_dup 5) (match_dup 6))
8332 (cond_exec (match_dup 7)
8333 (set (match_dup 0) (match_dup 4)))]
8336 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8337 operands[2], operands[3]);
8338 enum rtx_code rc = GET_CODE (operands[1]);
8340 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8341 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8342 if (mode == CCFPmode || mode == CCFPEmode)
8343 rc = reverse_condition_maybe_unordered (rc);
8345 rc = reverse_condition (rc);
8347 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8352 [(set (match_operand:SI 0 "s_register_operand" "")
8353 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8354 [(match_operand 2 "" "") (match_operand 3 "" "")])
8355 (match_operand 4 "" "")
8357 (clobber (reg:CC CC_REGNUM))]
8358 "TARGET_ARM && reload_completed"
8359 [(set (match_dup 5) (match_dup 6))
8360 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8361 (set (match_dup 0) (match_dup 4)))]
8364 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8365 operands[2], operands[3]);
8367 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8368 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8373 [(set (match_operand:SI 0 "s_register_operand" "")
8374 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8375 [(match_operand 2 "" "") (match_operand 3 "" "")])
8376 (match_operand 4 "" "")
8377 (match_operand 5 "" "")))
8378 (clobber (reg:CC CC_REGNUM))]
8379 "TARGET_ARM && reload_completed"
8380 [(set (match_dup 6) (match_dup 7))
8381 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8382 (set (match_dup 0) (match_dup 4)))
8383 (cond_exec (match_dup 8)
8384 (set (match_dup 0) (match_dup 5)))]
8387 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8388 operands[2], operands[3]);
8389 enum rtx_code rc = GET_CODE (operands[1]);
8391 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8392 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8393 if (mode == CCFPmode || mode == CCFPEmode)
8394 rc = reverse_condition_maybe_unordered (rc);
8396 rc = reverse_condition (rc);
8398 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8403 [(set (match_operand:SI 0 "s_register_operand" "")
8404 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8405 [(match_operand:SI 2 "s_register_operand" "")
8406 (match_operand:SI 3 "arm_add_operand" "")])
8407 (match_operand:SI 4 "arm_rhs_operand" "")
8409 (match_operand:SI 5 "s_register_operand" ""))))
8410 (clobber (reg:CC CC_REGNUM))]
8411 "TARGET_ARM && reload_completed"
8412 [(set (match_dup 6) (match_dup 7))
8413 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8414 (set (match_dup 0) (match_dup 4)))
8415 (cond_exec (match_dup 8)
8416 (set (match_dup 0) (not:SI (match_dup 5))))]
8419 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8420 operands[2], operands[3]);
8421 enum rtx_code rc = GET_CODE (operands[1]);
8423 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8424 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8425 if (mode == CCFPmode || mode == CCFPEmode)
8426 rc = reverse_condition_maybe_unordered (rc);
8428 rc = reverse_condition (rc);
8430 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8434 (define_insn "*cond_move_not"
8435 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8436 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8437 [(match_operand 3 "cc_register" "") (const_int 0)])
8438 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8440 (match_operand:SI 2 "s_register_operand" "r,r"))))]
8444 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8445 [(set_attr "conds" "use")
8446 (set_attr "length" "4,8")]
8449 ;; The next two patterns occur when an AND operation is followed by a
8450 ;; scc insn sequence
8452 (define_insn "*sign_extract_onebit"
8453 [(set (match_operand:SI 0 "s_register_operand" "=r")
8454 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8456 (match_operand:SI 2 "const_int_operand" "n")))
8457 (clobber (reg:CC CC_REGNUM))]
8460 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8461 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8462 return \"mvnne\\t%0, #0\";
8464 [(set_attr "conds" "clob")
8465 (set_attr "length" "8")]
8468 (define_insn "*not_signextract_onebit"
8469 [(set (match_operand:SI 0 "s_register_operand" "=r")
8471 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8473 (match_operand:SI 2 "const_int_operand" "n"))))
8474 (clobber (reg:CC CC_REGNUM))]
8477 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8478 output_asm_insn (\"tst\\t%1, %2\", operands);
8479 output_asm_insn (\"mvneq\\t%0, #0\", operands);
8480 return \"movne\\t%0, #0\";
8482 [(set_attr "conds" "clob")
8483 (set_attr "length" "12")]
8486 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
8487 ;; expressions. For simplicity, the first register is also in the unspec
8489 (define_insn "*push_multi"
8490 [(match_parallel 2 "multi_register_push"
8491 [(set (match_operand:BLK 0 "memory_operand" "=m")
8492 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8493 UNSPEC_PUSH_MULT))])]
8497 int num_saves = XVECLEN (operands[2], 0);
8499 /* For the StrongARM at least it is faster to
8500 use STR to store only a single register. */
8502 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8508 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
8510 for (i = 1; i < num_saves; i++)
8512 strcat (pattern, \", %|\");
8514 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
8517 strcat (pattern, \"}\");
8518 output_asm_insn (pattern, operands);
8523 [(set_attr "type" "store4")]
8526 (define_insn "stack_tie"
8527 [(set (mem:BLK (scratch))
8528 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
8529 (match_operand:SI 1 "s_register_operand" "r")]
8533 [(set_attr "length" "0")]
8536 ;; Similarly for the floating point registers
8537 (define_insn "*push_fp_multi"
8538 [(match_parallel 2 "multi_register_push"
8539 [(set (match_operand:BLK 0 "memory_operand" "=m")
8540 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
8541 UNSPEC_PUSH_MULT))])]
8547 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
8548 output_asm_insn (pattern, operands);
8551 [(set_attr "type" "f_store")]
8554 ;; Special patterns for dealing with the constant pool
8556 (define_insn "align_4"
8557 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
8560 assemble_align (32);
8565 (define_insn "consttable_end"
8566 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
8569 making_const_table = FALSE;
8574 (define_insn "consttable_1"
8575 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
8578 making_const_table = TRUE;
8579 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
8583 [(set_attr "length" "4")]
8586 (define_insn "consttable_2"
8587 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
8590 making_const_table = TRUE;
8591 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
8595 [(set_attr "length" "4")]
8598 (define_insn "consttable_4"
8599 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
8603 making_const_table = TRUE;
8604 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8609 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8610 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8614 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
8619 [(set_attr "length" "4")]
8622 (define_insn "consttable_8"
8623 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
8627 making_const_table = TRUE;
8628 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8633 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8634 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8638 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
8643 [(set_attr "length" "8")]
8646 ;; Miscellaneous Thumb patterns
8648 (define_expand "tablejump"
8649 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
8650 (use (label_ref (match_operand 1 "" "")))])]
8655 /* Hopefully, CSE will eliminate this copy. */
8656 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
8657 rtx reg2 = gen_reg_rtx (SImode);
8659 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
8665 (define_insn "*thumb_tablejump"
8666 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
8667 (use (label_ref (match_operand 1 "" "")))]
8670 [(set_attr "length" "2")]
8675 (define_insn "clzsi2"
8676 [(set (match_operand:SI 0 "s_register_operand" "=r")
8677 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
8678 "TARGET_ARM && arm_arch5"
8680 [(set_attr "predicable" "yes")])
8682 (define_expand "ffssi2"
8683 [(set (match_operand:SI 0 "s_register_operand" "")
8684 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
8685 "TARGET_ARM && arm_arch5"
8690 t1 = gen_reg_rtx (SImode);
8691 t2 = gen_reg_rtx (SImode);
8692 t3 = gen_reg_rtx (SImode);
8694 emit_insn (gen_negsi2 (t1, operands[1]));
8695 emit_insn (gen_andsi3 (t2, operands[1], t1));
8696 emit_insn (gen_clzsi2 (t3, t2));
8697 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
8702 (define_expand "ctzsi2"
8703 [(set (match_operand:SI 0 "s_register_operand" "")
8704 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
8705 "TARGET_ARM && arm_arch5"
8710 t1 = gen_reg_rtx (SImode);
8711 t2 = gen_reg_rtx (SImode);
8712 t3 = gen_reg_rtx (SImode);
8714 emit_insn (gen_negsi2 (t1, operands[1]));
8715 emit_insn (gen_andsi3 (t2, operands[1], t1));
8716 emit_insn (gen_clzsi2 (t3, t2));
8717 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
8722 ;; V5E instructions.
8724 (define_insn "prefetch"
8725 [(prefetch (match_operand:SI 0 "address_operand" "p")
8726 (match_operand:SI 1 "" "")
8727 (match_operand:SI 2 "" ""))]
8728 "TARGET_ARM && arm_arch5e"
8731 ;; General predication pattern
8734 [(match_operator 0 "arm_comparison_operator"
8735 [(match_operand 1 "cc_register" "")
8741 (define_insn "prologue_use"
8742 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
8744 "%@ %0 needed for prologue"
8747 ;; Load the FPA co-processor patterns
8749 ;; Load the Maverick co-processor patterns
8750 (include "cirrus.md")