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
43 ;; Note: sin and cos are no-longer used.
46 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
47 ; operand 0 is the result,
48 ; operand 1 the parameter.
49 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
50 ; operand 0 is the result,
51 ; operand 1 the parameter.
52 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
53 ; operand 0 is the first register,
54 ; subsequent registers are in parallel (use ...)
56 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
57 ; usage, that is, we will add the pic_register
58 ; value to it before trying to dereference it.
59 (UNSPEC_PRLG_STK 4) ; A special barrier that prevents frame accesses
60 ; being scheduled before the stack adjustment insn.
61 (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
62 ; this unspec is used to prevent the deletion of
63 ; instructions setting registers for EH handling
64 ; and stack frame generation. Operand 0 is the
66 (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
70 ;; UNSPEC_VOLATILE Usage:
73 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
75 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
76 ; instruction epilogue sequence that isn't expanded
77 ; into normal RTL. Used for both normal and sibcall
79 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
80 ; for inlined constants.
81 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
83 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
85 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
87 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
89 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
94 ;;---------------------------------------------------------------------------
97 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
98 ; generating ARM code. This is used to control the length of some insn
99 ; patterns that share the same RTL in both ARM and Thumb code.
100 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
102 ; PROG_MODE attribute is used to determine whether condition codes are
103 ; clobbered by a call insn: they are if in prog32 mode. This is controlled
104 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
105 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
107 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
108 ; scheduling decisions for the load unit and the multiplier.
109 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
111 ;; Operand number of an input operand that is shifted. Zero if the
112 ;; given instruction does not shift one of its input operands.
113 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_is_xscale")))
114 (define_attr "shift" "" (const_int 0))
116 ; Floating Point Unit. If we only have floating point emulation, then there
117 ; is no point in scheduling the floating point insns. (Well, for best
118 ; performance we should try and group them together).
119 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
121 ; LENGTH of an instruction (in bytes)
122 (define_attr "length" "" (const_int 4))
124 ; POOL_RANGE is how far away from a constant pool entry that this insn
125 ; can be placed. If the distance is zero, then this insn will never
126 ; reference the pool.
127 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
128 ; before its address.
129 (define_attr "pool_range" "" (const_int 0))
130 (define_attr "neg_pool_range" "" (const_int 0))
132 ; An assembler sequence may clobber the condition codes without us knowing.
133 ; If such an insn references the pool, then we have no way of knowing how,
134 ; so use the most conservative value for pool_range.
135 (define_asm_attributes
136 [(set_attr "conds" "clob")
137 (set_attr "length" "4")
138 (set_attr "pool_range" "250")])
140 ; TYPE attribute is used to detect floating point instructions which, if
141 ; running on a co-processor can run in parallel with other, basic instructions
142 ; If write-buffer scheduling is enabled then it can also be used in the
143 ; scheduling of writes.
145 ; Classification of each insn
146 ; normal any data instruction that doesn't hit memory or fp regs
147 ; mult a multiply instruction
148 ; block blockage insn, this blocks all functional units
149 ; float a floating point arithmetic operation (subject to expansion)
150 ; fdivd DFmode floating point division
151 ; fdivs SFmode floating point division
152 ; fmul Floating point multiply
153 ; ffmul Fast floating point multiply
154 ; farith Floating point arithmetic (4 cycle)
155 ; ffarith Fast floating point arithmetic (2 cycle)
156 ; float_em a floating point arithmetic operation that is normally emulated
157 ; even on a machine with an fpa.
158 ; f_load a floating point load from memory
159 ; f_store a floating point store to memory
160 ; f_mem_r a transfer of a floating point register to a real reg via mem
161 ; r_mem_f the reverse of f_mem_r
162 ; f_2_r fast transfer float to arm (no memory needed)
163 ; r_2_f fast transfer arm to float
164 ; call a subroutine call
165 ; load any load from memory
166 ; store1 store 1 word to memory from arm registers
167 ; store2 store 2 words
168 ; store3 store 3 words
169 ; store4 store 4 words
170 ; Additions for Cirrus Maverick co-processor:
171 ; mav_farith Floating point arithmetic (4 cycle)
172 ; mav_dmult Double multiplies (7 cycle)
175 "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"
176 (const_string "normal"))
178 ; Load scheduling, set from the arm_ld_sched variable
179 ; initialized by arm_override_options()
180 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
182 ; condition codes: this one is used by final_prescan_insn to speed up
183 ; conditionalizing instructions. It saves having to scan the rtl to see if
184 ; it uses or alters the condition codes.
186 ; USE means that the condition codes are used by the insn in the process of
187 ; outputting code, this means (at present) that we can't use the insn in
190 ; SET means that the purpose of the insn is to set the condition codes in a
191 ; well defined manner.
193 ; CLOB means that the condition codes are altered in an undefined manner, if
194 ; they are altered at all
196 ; JUMP_CLOB is used when the condition cannot be represented by a single
197 ; instruction (UNEQ and LTGT). These cannot be predicated.
199 ; NOCOND means that the condition codes are neither altered nor affect the
200 ; output of this insn
202 (define_attr "conds" "use,set,clob,jump_clob,nocond"
203 (if_then_else (eq_attr "type" "call")
204 (if_then_else (eq_attr "prog_mode" "prog32")
205 (const_string "clob") (const_string "nocond"))
206 (const_string "nocond")))
208 ; Predicable means that the insn can be conditionally executed based on
209 ; an automatically added predicate (additional patterns are generated by
210 ; gen...). We default to 'no' because no Thumb patterns match this rule
211 ; and not all ARM patterns do.
212 (define_attr "predicable" "no,yes" (const_string "no"))
214 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
215 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
216 ; suffer blockages enough to warrent modelling this (and it can adversely
217 ; affect the schedule).
218 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
220 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
221 ; to stall the processor. Used with model_wbuf above.
222 (define_attr "write_conflict" "no,yes"
223 (if_then_else (eq_attr "type"
224 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
226 (const_string "no")))
228 ; Classify the insns into those that take one cycle and those that take more
229 ; than one on the main cpu execution unit.
230 (define_attr "core_cycles" "single,multi"
231 (if_then_else (eq_attr "type"
232 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
233 (const_string "single")
234 (const_string "multi")))
236 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
237 ;; distant label. Only applicable to Thumb code.
238 (define_attr "far_jump" "yes,no" (const_string "no"))
240 ;; (define_function_unit {name} {num-units} {n-users} {test}
241 ;; {ready-delay} {issue-delay} [{conflict-list}])
243 ;;--------------------------------------------------------------------
245 ;;--------------------------------------------------------------------
246 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
248 ; The write buffer on some of the arm6 processors is hard to model exactly.
249 ; There is room in the buffer for up to two addresses and up to eight words
250 ; of memory, but the two needn't be split evenly. When writing the two
251 ; addresses are fully pipelined. However, a read from memory that is not
252 ; currently in the cache will block until the writes have completed.
253 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
254 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
255 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
256 ; cycle to add as well.
258 (define_function_unit "write_buf" 1 2
259 (and (eq_attr "model_wbuf" "yes")
260 (eq_attr "type" "store1,r_mem_f")) 5 3)
261 (define_function_unit "write_buf" 1 2
262 (and (eq_attr "model_wbuf" "yes")
263 (eq_attr "type" "store2")) 7 4)
264 (define_function_unit "write_buf" 1 2
265 (and (eq_attr "model_wbuf" "yes")
266 (eq_attr "type" "store3")) 9 5)
267 (define_function_unit "write_buf" 1 2
268 (and (eq_attr "model_wbuf" "yes")
269 (eq_attr "type" "store4")) 11 6)
271 ;;--------------------------------------------------------------------
272 ;; Write blockage unit
273 ;;--------------------------------------------------------------------
274 ; The write_blockage unit models (partially), the fact that reads will stall
275 ; until the write buffer empties.
276 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
277 ; so we don't model them here
278 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
279 (eq_attr "type" "store1")) 5 5
280 [(eq_attr "write_conflict" "yes")])
281 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
282 (eq_attr "type" "store2")) 7 7
283 [(eq_attr "write_conflict" "yes")])
284 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
285 (eq_attr "type" "store3")) 9 9
286 [(eq_attr "write_conflict" "yes")])
287 (define_function_unit "write_blockage" 1 0
288 (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
289 [(eq_attr "write_conflict" "yes")])
290 (define_function_unit "write_blockage" 1 0
291 (and (eq_attr "model_wbuf" "yes")
292 (eq_attr "write_conflict" "yes")) 1 1)
294 ;;--------------------------------------------------------------------
296 ;;--------------------------------------------------------------------
297 ; Everything must spend at least one cycle in the core unit
298 (define_function_unit "core" 1 0 (eq_attr "core_cycles" "single") 1 1)
300 (define_function_unit "core" 1 0
301 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
303 (define_function_unit "core" 1 0
304 (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
306 ;; We do not need to conditionalize the define_function_unit immediately
307 ;; above. This one will be ignored for anything other than xscale
308 ;; compiles and for xscale compiles it provides a larger delay
309 ;; and the scheduler will DTRT.
310 ;; FIXME: this test needs to be revamped to not depend on this feature
313 (define_function_unit "core" 1 0
314 (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
315 (eq_attr "is_xscale" "yes"))
318 (define_function_unit "core" 1 0
319 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
321 (define_function_unit "core" 1 0
322 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
324 (define_function_unit "core" 1 0
325 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
327 (define_function_unit "core" 1 0
328 (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
330 (define_function_unit "core" 1 0
331 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
333 (define_function_unit "core" 1 0
334 (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
336 (define_function_unit "core" 1 0
337 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
338 (eq_attr "type" "mult")) 4 4)
340 (define_function_unit "core" 1 0
341 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
342 (eq_attr "type" "mult")) 3 2)
344 (define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
346 (define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
348 (define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
350 (define_function_unit "core" 1 0
351 (and (eq_attr "core_cycles" "multi")
352 (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
354 ;;---------------------------------------------------------------------------
359 ;; Note: For DImode insns, there is normally no reason why operands should
360 ;; not be in the same register, what we don't want is for something being
361 ;; written to partially overlap something that is an input.
362 ;; Cirrus 64bit additions should not be split because we have a native
363 ;; 64bit addition instructions.
365 (define_expand "adddi3"
367 [(set (match_operand:DI 0 "s_register_operand" "")
368 (plus:DI (match_operand:DI 1 "s_register_operand" "")
369 (match_operand:DI 2 "s_register_operand" "")))
370 (clobber (reg:CC CC_REGNUM))])]
375 if (!cirrus_fp_register (operands[0], DImode))
376 operands[0] = force_reg (DImode, operands[0]);
377 if (!cirrus_fp_register (operands[1], DImode))
378 operands[1] = force_reg (DImode, operands[1]);
379 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
385 if (GET_CODE (operands[1]) != REG)
386 operands[1] = force_reg (SImode, operands[1]);
387 if (GET_CODE (operands[2]) != REG)
388 operands[2] = force_reg (SImode, operands[2]);
393 (define_insn "*thumb_adddi3"
394 [(set (match_operand:DI 0 "register_operand" "=l")
395 (plus:DI (match_operand:DI 1 "register_operand" "%0")
396 (match_operand:DI 2 "register_operand" "l")))
397 (clobber (reg:CC CC_REGNUM))
400 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
401 [(set_attr "length" "4")]
404 (define_insn_and_split "*arm_adddi3"
405 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
406 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
407 (match_operand:DI 2 "s_register_operand" "r, 0")))
408 (clobber (reg:CC CC_REGNUM))]
409 "TARGET_ARM && !TARGET_CIRRUS"
411 "TARGET_ARM && reload_completed"
412 [(parallel [(set (reg:CC_C CC_REGNUM)
413 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
415 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
416 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
417 (plus:SI (match_dup 4) (match_dup 5))))]
420 operands[3] = gen_highpart (SImode, operands[0]);
421 operands[0] = gen_lowpart (SImode, operands[0]);
422 operands[4] = gen_highpart (SImode, operands[1]);
423 operands[1] = gen_lowpart (SImode, operands[1]);
424 operands[5] = gen_highpart (SImode, operands[2]);
425 operands[2] = gen_lowpart (SImode, operands[2]);
427 [(set_attr "conds" "clob")
428 (set_attr "length" "8")]
431 (define_insn_and_split "*adddi_sesidi_di"
432 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
433 (plus:DI (sign_extend:DI
434 (match_operand:SI 2 "s_register_operand" "r,r"))
435 (match_operand:DI 1 "s_register_operand" "r,0")))
436 (clobber (reg:CC CC_REGNUM))]
437 "TARGET_ARM && !TARGET_CIRRUS"
439 "TARGET_ARM && reload_completed"
440 [(parallel [(set (reg:CC_C CC_REGNUM)
441 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
443 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
444 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
445 (plus:SI (ashiftrt:SI (match_dup 2)
450 operands[3] = gen_highpart (SImode, operands[0]);
451 operands[0] = gen_lowpart (SImode, operands[0]);
452 operands[4] = gen_highpart (SImode, operands[1]);
453 operands[1] = gen_lowpart (SImode, operands[1]);
454 operands[2] = gen_lowpart (SImode, operands[2]);
456 [(set_attr "conds" "clob")
457 (set_attr "length" "8")]
460 (define_insn_and_split "*adddi_zesidi_di"
461 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
462 (plus:DI (zero_extend:DI
463 (match_operand:SI 2 "s_register_operand" "r,r"))
464 (match_operand:DI 1 "s_register_operand" "r,0")))
465 (clobber (reg:CC CC_REGNUM))]
466 "TARGET_ARM && !TARGET_CIRRUS"
468 "TARGET_ARM && reload_completed"
469 [(parallel [(set (reg:CC_C CC_REGNUM)
470 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
472 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
473 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
474 (plus:SI (match_dup 4) (const_int 0))))]
477 operands[3] = gen_highpart (SImode, operands[0]);
478 operands[0] = gen_lowpart (SImode, operands[0]);
479 operands[4] = gen_highpart (SImode, operands[1]);
480 operands[1] = gen_lowpart (SImode, operands[1]);
481 operands[2] = gen_lowpart (SImode, operands[2]);
483 [(set_attr "conds" "clob")
484 (set_attr "length" "8")]
487 (define_expand "addsi3"
488 [(set (match_operand:SI 0 "s_register_operand" "")
489 (plus:SI (match_operand:SI 1 "s_register_operand" "")
490 (match_operand:SI 2 "reg_or_int_operand" "")))]
493 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
495 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
497 (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
503 ; If there is a scratch available, this will be faster than synthesising the
506 [(match_scratch:SI 3 "r")
507 (set (match_operand:SI 0 "s_register_operand" "")
508 (plus:SI (match_operand:SI 1 "s_register_operand" "")
509 (match_operand:SI 2 "const_int_operand" "")))]
511 !(const_ok_for_arm (INTVAL (operands[2]))
512 || const_ok_for_arm (-INTVAL (operands[2])))
513 && const_ok_for_arm (~INTVAL (operands[2]))"
514 [(set (match_dup 3) (match_dup 2))
515 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
519 (define_insn_and_split "*arm_addsi3"
520 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
521 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
522 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
529 GET_CODE (operands[2]) == CONST_INT
530 && !(const_ok_for_arm (INTVAL (operands[2]))
531 || const_ok_for_arm (-INTVAL (operands[2])))"
532 [(clobber (const_int 0))]
534 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
538 [(set_attr "length" "4,4,16")
539 (set_attr "predicable" "yes")]
542 ;; Register group 'k' is a single register group containing only the stack
543 ;; register. Trying to reload it will always fail catastrophically,
544 ;; so never allow those alternatives to match if reloading is needed.
546 (define_insn "*thumb_addsi3"
547 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
548 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
549 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
552 static const char * const asms[] =
554 \"add\\t%0, %0, %2\",
555 \"sub\\t%0, %0, #%n2\",
556 \"add\\t%0, %1, %2\",
557 \"add\\t%0, %0, %2\",
558 \"add\\t%0, %0, %2\",
559 \"add\\t%0, %1, %2\",
562 if ((which_alternative == 2 || which_alternative == 6)
563 && GET_CODE (operands[2]) == CONST_INT
564 && INTVAL (operands[2]) < 0)
565 return \"sub\\t%0, %1, #%n2\";
566 return asms[which_alternative];
568 [(set_attr "length" "2")]
571 ;; Reloading and elimination of the frame pointer can
572 ;; sometimes cause this optimization to be missed.
574 [(set (match_operand:SI 0 "register_operand" "")
575 (match_operand:SI 1 "const_int_operand" ""))
577 (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
579 && REGNO (operands[2]) == STACK_POINTER_REGNUM
580 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
581 && (INTVAL (operands[1]) & 3) == 0"
582 [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
586 (define_insn "*addsi3_compare0"
587 [(set (reg:CC_NOOV CC_REGNUM)
589 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
590 (match_operand:SI 2 "arm_add_operand" "rI,L"))
592 (set (match_operand:SI 0 "s_register_operand" "=r,r")
593 (plus:SI (match_dup 1) (match_dup 2)))]
597 sub%?s\\t%0, %1, #%n2"
598 [(set_attr "conds" "set")]
601 (define_insn "*addsi3_compare0_scratch"
602 [(set (reg:CC_NOOV CC_REGNUM)
604 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
605 (match_operand:SI 1 "arm_add_operand" "rI,L"))
611 [(set_attr "conds" "set")]
614 ;; These patterns are the same ones as the two regular addsi3_compare0
615 ;; patterns, except we write them slightly different - the combiner
616 ;; tends to generate them this way.
617 (define_insn "*addsi3_compare0_for_combiner"
618 [(set (reg:CC CC_REGNUM)
620 (match_operand:SI 1 "s_register_operand" "r,r")
621 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
622 (set (match_operand:SI 0 "s_register_operand" "=r,r")
623 (plus:SI (match_dup 1) (match_dup 2)))]
627 sub%?s\\t%0, %1, #%n2"
628 [(set_attr "conds" "set")]
631 (define_insn "*addsi3_compare0_scratch_for_combiner"
632 [(set (reg:CC CC_REGNUM)
634 (match_operand:SI 0 "s_register_operand" "r,r")
635 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
640 [(set_attr "conds" "set")]
643 ;; The next four insns work because they compare the result with one of
644 ;; the operands, and we know that the use of the condition code is
645 ;; either GEU or LTU, so we can use the carry flag from the addition
646 ;; instead of doing the compare a second time.
647 (define_insn "*addsi3_compare_op1"
648 [(set (reg:CC_C CC_REGNUM)
650 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
651 (match_operand:SI 2 "arm_add_operand" "rI,L"))
653 (set (match_operand:SI 0 "s_register_operand" "=r,r")
654 (plus:SI (match_dup 1) (match_dup 2)))]
658 sub%?s\\t%0, %1, #%n2"
659 [(set_attr "conds" "set")]
662 (define_insn "*addsi3_compare_op2"
663 [(set (reg:CC_C CC_REGNUM)
665 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
666 (match_operand:SI 2 "arm_add_operand" "rI,L"))
668 (set (match_operand:SI 0 "s_register_operand" "=r,r")
669 (plus:SI (match_dup 1) (match_dup 2)))]
673 sub%?s\\t%0, %1, #%n2"
674 [(set_attr "conds" "set")]
677 (define_insn "*compare_addsi2_op0"
678 [(set (reg:CC_C CC_REGNUM)
680 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
681 (match_operand:SI 1 "arm_add_operand" "rI,L"))
687 [(set_attr "conds" "set")]
690 (define_insn "*compare_addsi2_op1"
691 [(set (reg:CC_C CC_REGNUM)
693 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
694 (match_operand:SI 1 "arm_add_operand" "rI,L"))
700 [(set_attr "conds" "set")]
703 (define_insn "*addsi3_carryin"
704 [(set (match_operand:SI 0 "s_register_operand" "=r")
705 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
706 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
707 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
710 [(set_attr "conds" "use")]
713 (define_insn "*addsi3_carryin_shift"
714 [(set (match_operand:SI 0 "s_register_operand" "")
715 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
717 (match_operator:SI 2 "shift_operator"
718 [(match_operand:SI 3 "s_register_operand" "")
719 (match_operand:SI 4 "reg_or_int_operand" "")])
720 (match_operand:SI 1 "s_register_operand" ""))))]
722 "adc%?\\t%0, %1, %3%S2"
723 [(set_attr "conds" "use")]
726 (define_insn "*addsi3_carryin_alt1"
727 [(set (match_operand:SI 0 "s_register_operand" "=r")
728 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
729 (match_operand:SI 2 "arm_rhs_operand" "rI"))
730 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
733 [(set_attr "conds" "use")]
736 (define_insn "*addsi3_carryin_alt2"
737 [(set (match_operand:SI 0 "s_register_operand" "=r")
738 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
739 (match_operand:SI 1 "s_register_operand" "r"))
740 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
743 [(set_attr "conds" "use")]
746 (define_insn "*addsi3_carryin_alt3"
747 [(set (match_operand:SI 0 "s_register_operand" "=r")
748 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
749 (match_operand:SI 2 "arm_rhs_operand" "rI"))
750 (match_operand:SI 1 "s_register_operand" "r")))]
753 [(set_attr "conds" "use")]
756 (define_insn "incscc"
757 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
758 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
759 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
760 (match_operand:SI 1 "s_register_operand" "0,?r")))]
764 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
765 [(set_attr "conds" "use")
766 (set_attr "length" "4,8")]
769 (define_expand "addsf3"
770 [(set (match_operand:SF 0 "s_register_operand" "")
771 (plus:SF (match_operand:SF 1 "s_register_operand" "")
772 (match_operand:SF 2 "fpa_add_operand" "")))]
773 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
776 && !cirrus_fp_register (operands[2], SFmode))
777 operands[2] = force_reg (SFmode, operands[2]);
780 (define_expand "adddf3"
781 [(set (match_operand:DF 0 "s_register_operand" "")
782 (plus:DF (match_operand:DF 1 "s_register_operand" "")
783 (match_operand:DF 2 "fpa_add_operand" "")))]
784 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
787 && !cirrus_fp_register (operands[2], DFmode))
788 operands[2] = force_reg (DFmode, operands[2]);
791 (define_expand "subdi3"
793 [(set (match_operand:DI 0 "s_register_operand" "")
794 (minus:DI (match_operand:DI 1 "s_register_operand" "")
795 (match_operand:DI 2 "s_register_operand" "")))
796 (clobber (reg:CC CC_REGNUM))])]
801 && cirrus_fp_register (operands[0], DImode)
802 && cirrus_fp_register (operands[1], DImode))
804 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
810 if (GET_CODE (operands[1]) != REG)
811 operands[1] = force_reg (SImode, operands[1]);
812 if (GET_CODE (operands[2]) != REG)
813 operands[2] = force_reg (SImode, operands[2]);
818 (define_insn "*arm_subdi3"
819 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
820 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
821 (match_operand:DI 2 "s_register_operand" "r,0,0")))
822 (clobber (reg:CC CC_REGNUM))]
824 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
825 [(set_attr "conds" "clob")
826 (set_attr "length" "8")]
829 (define_insn "*thumb_subdi3"
830 [(set (match_operand:DI 0 "register_operand" "=l")
831 (minus:DI (match_operand:DI 1 "register_operand" "0")
832 (match_operand:DI 2 "register_operand" "l")))
833 (clobber (reg:CC CC_REGNUM))]
835 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
836 [(set_attr "length" "4")]
839 (define_insn "*subdi_di_zesidi"
840 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
841 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
843 (match_operand:SI 2 "s_register_operand" "r,r"))))
844 (clobber (reg:CC CC_REGNUM))]
846 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
847 [(set_attr "conds" "clob")
848 (set_attr "length" "8")]
851 (define_insn "*subdi_di_sesidi"
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, %2, asr #31"
859 [(set_attr "conds" "clob")
860 (set_attr "length" "8")]
863 (define_insn "*subdi_zesidi_di"
864 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
865 (minus:DI (zero_extend:DI
866 (match_operand:SI 2 "s_register_operand" "r,r"))
867 (match_operand:DI 1 "s_register_operand" "?r,0")))
868 (clobber (reg:CC CC_REGNUM))]
870 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
871 [(set_attr "conds" "clob")
872 (set_attr "length" "8")]
875 (define_insn "*subdi_sesidi_di"
876 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
877 (minus:DI (sign_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, %2, asr #31"
883 [(set_attr "conds" "clob")
884 (set_attr "length" "8")]
887 (define_insn "*subdi_zesidi_zesidi"
888 [(set (match_operand:DI 0 "s_register_operand" "=r")
889 (minus:DI (zero_extend:DI
890 (match_operand:SI 1 "s_register_operand" "r"))
892 (match_operand:SI 2 "s_register_operand" "r"))))
893 (clobber (reg:CC CC_REGNUM))]
895 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
896 [(set_attr "conds" "clob")
897 (set_attr "length" "8")]
900 (define_expand "subsi3"
901 [(set (match_operand:SI 0 "s_register_operand" "")
902 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
903 (match_operand:SI 2 "s_register_operand" "")))]
906 if (GET_CODE (operands[1]) == CONST_INT)
910 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
913 : preserve_subexpressions_p ()));
916 else /* TARGET_THUMB */
917 operands[1] = force_reg (SImode, operands[1]);
922 (define_insn "*thumb_subsi3_insn"
923 [(set (match_operand:SI 0 "register_operand" "=l")
924 (minus:SI (match_operand:SI 1 "register_operand" "l")
925 (match_operand:SI 2 "register_operand" "l")))]
928 [(set_attr "length" "2")]
931 (define_insn_and_split "*arm_subsi3_insn"
932 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
933 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
934 (match_operand:SI 2 "s_register_operand" "r,r")))]
940 && GET_CODE (operands[1]) == CONST_INT
941 && !const_ok_for_arm (INTVAL (operands[1]))"
942 [(clobber (const_int 0))]
944 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
948 [(set_attr "length" "4,16")
949 (set_attr "predicable" "yes")]
953 [(match_scratch:SI 3 "r")
954 (set (match_operand:SI 0 "s_register_operand" "")
955 (minus:SI (match_operand:SI 1 "const_int_operand" "")
956 (match_operand:SI 2 "s_register_operand" "")))]
958 && !const_ok_for_arm (INTVAL (operands[1]))
959 && const_ok_for_arm (~INTVAL (operands[1]))"
960 [(set (match_dup 3) (match_dup 1))
961 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
965 (define_insn "*subsi3_compare0"
966 [(set (reg:CC_NOOV CC_REGNUM)
968 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
969 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
971 (set (match_operand:SI 0 "s_register_operand" "=r,r")
972 (minus:SI (match_dup 1) (match_dup 2)))]
977 [(set_attr "conds" "set")]
980 (define_insn "decscc"
981 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
982 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
983 (match_operator:SI 2 "arm_comparison_operator"
984 [(match_operand 3 "cc_register" "") (const_int 0)])))]
988 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
989 [(set_attr "conds" "use")
990 (set_attr "length" "*,8")]
993 (define_expand "subsf3"
994 [(set (match_operand:SF 0 "s_register_operand" "")
995 (minus:SF (match_operand:SF 1 "fpa_rhs_operand" "")
996 (match_operand:SF 2 "fpa_rhs_operand" "")))]
997 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1001 if (!cirrus_fp_register (operands[1], SFmode))
1002 operands[1] = force_reg (SFmode, operands[1]);
1003 if (!cirrus_fp_register (operands[2], SFmode))
1004 operands[2] = force_reg (SFmode, operands[2]);
1008 (define_expand "subdf3"
1009 [(set (match_operand:DF 0 "s_register_operand" "")
1010 (minus:DF (match_operand:DF 1 "fpa_rhs_operand" "")
1011 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1012 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1016 if (!cirrus_fp_register (operands[1], DFmode))
1017 operands[1] = force_reg (DFmode, operands[1]);
1018 if (!cirrus_fp_register (operands[2], DFmode))
1019 operands[2] = force_reg (DFmode, operands[2]);
1024 ;; Multiplication insns
1026 (define_expand "mulsi3"
1027 [(set (match_operand:SI 0 "s_register_operand" "")
1028 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1029 (match_operand:SI 1 "s_register_operand" "")))]
1034 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1035 (define_insn "*arm_mulsi3"
1036 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1037 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1038 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1040 "mul%?\\t%0, %2, %1"
1041 [(set_attr "type" "mult")
1042 (set_attr "predicable" "yes")]
1045 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1046 ; 1 and 2; are the same, because reload will make operand 0 match
1047 ; operand 1 without realizing that this conflicts with operand 2. We fix
1048 ; this by adding another alternative to match this case, and then `reload'
1049 ; it ourselves. This alternative must come first.
1050 (define_insn "*thumb_mulsi3"
1051 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1052 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1053 (match_operand:SI 2 "register_operand" "l,l,l")))]
1056 if (which_alternative < 2)
1057 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1059 return \"mul\\t%0, %0, %2\";
1061 [(set_attr "length" "4,4,2")
1062 (set_attr "type" "mult")]
1065 (define_insn "*mulsi3_compare0"
1066 [(set (reg:CC_NOOV CC_REGNUM)
1067 (compare:CC_NOOV (mult:SI
1068 (match_operand:SI 2 "s_register_operand" "r,r")
1069 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1071 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1072 (mult:SI (match_dup 2) (match_dup 1)))]
1073 "TARGET_ARM && !arm_is_xscale"
1074 "mul%?s\\t%0, %2, %1"
1075 [(set_attr "conds" "set")
1076 (set_attr "type" "mult")]
1079 (define_insn "*mulsi_compare0_scratch"
1080 [(set (reg:CC_NOOV CC_REGNUM)
1081 (compare:CC_NOOV (mult:SI
1082 (match_operand:SI 2 "s_register_operand" "r,r")
1083 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1085 (clobber (match_scratch:SI 0 "=&r,&r"))]
1086 "TARGET_ARM && !arm_is_xscale"
1087 "mul%?s\\t%0, %2, %1"
1088 [(set_attr "conds" "set")
1089 (set_attr "type" "mult")]
1092 ;; Unnamed templates to match MLA instruction.
1094 (define_insn "*mulsi3addsi"
1095 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1097 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1098 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1099 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1101 "mla%?\\t%0, %2, %1, %3"
1102 [(set_attr "type" "mult")
1103 (set_attr "predicable" "yes")]
1106 (define_insn "*mulsi3addsi_compare0"
1107 [(set (reg:CC_NOOV CC_REGNUM)
1110 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1111 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1112 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1114 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1115 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1117 "TARGET_ARM && !arm_is_xscale"
1118 "mla%?s\\t%0, %2, %1, %3"
1119 [(set_attr "conds" "set")
1120 (set_attr "type" "mult")]
1123 (define_insn "*mulsi3addsi_compare0_scratch"
1124 [(set (reg:CC_NOOV CC_REGNUM)
1127 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1128 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1129 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1131 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1132 "TARGET_ARM && !arm_is_xscale"
1133 "mla%?s\\t%0, %2, %1, %3"
1134 [(set_attr "conds" "set")
1135 (set_attr "type" "mult")]
1138 ;; Unnamed template to match long long multiply-accumlate (smlal)
1140 (define_insn "*mulsidi3adddi"
1141 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1144 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1145 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1146 (match_operand:DI 1 "s_register_operand" "0")))]
1147 "TARGET_ARM && arm_fast_multiply"
1148 "smlal%?\\t%Q0, %R0, %3, %2"
1149 [(set_attr "type" "mult")
1150 (set_attr "predicable" "yes")]
1153 (define_insn "mulsidi3"
1154 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1156 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1157 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1158 "TARGET_ARM && arm_fast_multiply"
1159 "smull%?\\t%Q0, %R0, %1, %2"
1160 [(set_attr "type" "mult")
1161 (set_attr "predicable" "yes")]
1164 (define_insn "umulsidi3"
1165 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1167 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1168 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1169 "TARGET_ARM && arm_fast_multiply"
1170 "umull%?\\t%Q0, %R0, %1, %2"
1171 [(set_attr "type" "mult")
1172 (set_attr "predicable" "yes")]
1175 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1177 (define_insn "*umulsidi3adddi"
1178 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1181 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1182 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1183 (match_operand:DI 1 "s_register_operand" "0")))]
1184 "TARGET_ARM && arm_fast_multiply"
1185 "umlal%?\\t%Q0, %R0, %3, %2"
1186 [(set_attr "type" "mult")
1187 (set_attr "predicable" "yes")]
1190 (define_insn "smulsi3_highpart"
1191 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1195 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1196 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1198 (clobber (match_scratch:SI 3 "=&r,&r"))]
1199 "TARGET_ARM && arm_fast_multiply"
1200 "smull%?\\t%3, %0, %2, %1"
1201 [(set_attr "type" "mult")
1202 (set_attr "predicable" "yes")]
1205 (define_insn "umulsi3_highpart"
1206 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1210 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1211 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1213 (clobber (match_scratch:SI 3 "=&r,&r"))]
1214 "TARGET_ARM && arm_fast_multiply"
1215 "umull%?\\t%3, %0, %2, %1"
1216 [(set_attr "type" "mult")
1217 (set_attr "predicable" "yes")]
1220 (define_insn "mulhisi3"
1221 [(set (match_operand:SI 0 "s_register_operand" "=r")
1222 (mult:SI (sign_extend:SI
1223 (match_operand:HI 1 "s_register_operand" "%r"))
1225 (match_operand:HI 2 "s_register_operand" "r"))))]
1226 "TARGET_ARM && arm_arch5e"
1227 "smulbb%?\\t%0, %1, %2"
1228 [(set_attr "type" "mult")
1229 (set_attr "predicable" "yes")]
1232 (define_insn "*mulhisi3tb"
1233 [(set (match_operand:SI 0 "s_register_operand" "=r")
1234 (mult:SI (ashiftrt:SI
1235 (match_operand:SI 1 "s_register_operand" "r")
1238 (match_operand:HI 2 "s_register_operand" "r"))))]
1239 "TARGET_ARM && arm_arch5e"
1240 "smultb%?\\t%0, %1, %2"
1241 [(set_attr "type" "mult")
1242 (set_attr "predicable" "yes")]
1245 (define_insn "*mulhisi3bt"
1246 [(set (match_operand:SI 0 "s_register_operand" "=r")
1247 (mult:SI (sign_extend:SI
1248 (match_operand:HI 1 "s_register_operand" "r"))
1250 (match_operand:SI 2 "s_register_operand" "r")
1252 "TARGET_ARM && arm_arch5e"
1253 "smulbt%?\\t%0, %1, %2"
1254 [(set_attr "type" "mult")
1255 (set_attr "predicable" "yes")]
1258 (define_insn "*mulhisi3tt"
1259 [(set (match_operand:SI 0 "s_register_operand" "=r")
1260 (mult:SI (ashiftrt:SI
1261 (match_operand:SI 1 "s_register_operand" "r")
1264 (match_operand:SI 2 "s_register_operand" "r")
1266 "TARGET_ARM && arm_arch5e"
1267 "smultt%?\\t%0, %1, %2"
1268 [(set_attr "type" "mult")
1269 (set_attr "predicable" "yes")]
1272 (define_insn "*mulhisi3addsi"
1273 [(set (match_operand:SI 0 "s_register_operand" "=r")
1274 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1275 (mult:SI (sign_extend:SI
1276 (match_operand:HI 2 "s_register_operand" "%r"))
1278 (match_operand:HI 3 "s_register_operand" "r")))))]
1279 "TARGET_ARM && arm_arch5e"
1280 "smlabb%?\\t%0, %2, %3, %1"
1281 [(set_attr "type" "mult")
1282 (set_attr "predicable" "yes")]
1285 (define_insn "*mulhidi3adddi"
1286 [(set (match_operand:DI 0 "s_register_operand" "=r")
1288 (match_operand:DI 1 "s_register_operand" "0")
1289 (mult:DI (sign_extend:DI
1290 (match_operand:HI 2 "s_register_operand" "%r"))
1292 (match_operand:HI 3 "s_register_operand" "r")))))]
1293 "TARGET_ARM && arm_arch5e"
1294 "smlalbb%?\\t%Q0, %R0, %2, %3"
1295 [(set_attr "type" "mult")
1296 (set_attr "predicable" "yes")])
1298 (define_expand "mulsf3"
1299 [(set (match_operand:SF 0 "s_register_operand" "")
1300 (mult:SF (match_operand:SF 1 "s_register_operand" "")
1301 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1302 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1305 && !cirrus_fp_register (operands[2], SFmode))
1306 operands[2] = force_reg (SFmode, operands[2]);
1309 (define_expand "muldf3"
1310 [(set (match_operand:DF 0 "s_register_operand" "")
1311 (mult:DF (match_operand:DF 1 "s_register_operand" "")
1312 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1313 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1316 && !cirrus_fp_register (operands[2], DFmode))
1317 operands[2] = force_reg (DFmode, operands[2]);
1322 (define_expand "divsf3"
1323 [(set (match_operand:SF 0 "s_register_operand" "")
1324 (div:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1325 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1326 "TARGET_ARM && TARGET_HARD_FLOAT"
1329 (define_expand "divdf3"
1330 [(set (match_operand:DF 0 "s_register_operand" "")
1331 (div:DF (match_operand:DF 1 "fpa_rhs_operand" "")
1332 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1333 "TARGET_ARM && TARGET_HARD_FLOAT"
1338 (define_expand "modsf3"
1339 [(set (match_operand:SF 0 "s_register_operand" "")
1340 (mod:SF (match_operand:SF 1 "s_register_operand" "")
1341 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1342 "TARGET_ARM && TARGET_HARD_FLOAT"
1345 (define_expand "moddf3"
1346 [(set (match_operand:DF 0 "s_register_operand" "")
1347 (mod:DF (match_operand:DF 1 "s_register_operand" "")
1348 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1349 "TARGET_ARM && TARGET_HARD_FLOAT"
1352 ;; Boolean and,ior,xor insns
1354 ;; Split up double word logical operations
1356 ;; Split up simple DImode logical operations. Simply perform the logical
1357 ;; operation on the upper and lower halves of the registers.
1359 [(set (match_operand:DI 0 "s_register_operand" "")
1360 (match_operator:DI 6 "logical_binary_operator"
1361 [(match_operand:DI 1 "s_register_operand" "")
1362 (match_operand:DI 2 "s_register_operand" "")]))]
1363 "TARGET_ARM && reload_completed"
1364 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1365 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1368 operands[3] = gen_highpart (SImode, operands[0]);
1369 operands[0] = gen_lowpart (SImode, operands[0]);
1370 operands[4] = gen_highpart (SImode, operands[1]);
1371 operands[1] = gen_lowpart (SImode, operands[1]);
1372 operands[5] = gen_highpart (SImode, operands[2]);
1373 operands[2] = gen_lowpart (SImode, operands[2]);
1378 [(set (match_operand:DI 0 "s_register_operand" "")
1379 (match_operator:DI 6 "logical_binary_operator"
1380 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1381 (match_operand:DI 1 "s_register_operand" "")]))]
1382 "TARGET_ARM && reload_completed"
1383 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1384 (set (match_dup 3) (match_op_dup:SI 6
1385 [(ashiftrt:SI (match_dup 2) (const_int 31))
1389 operands[3] = gen_highpart (SImode, operands[0]);
1390 operands[0] = gen_lowpart (SImode, operands[0]);
1391 operands[4] = gen_highpart (SImode, operands[1]);
1392 operands[1] = gen_lowpart (SImode, operands[1]);
1393 operands[5] = gen_highpart (SImode, operands[2]);
1394 operands[2] = gen_lowpart (SImode, operands[2]);
1398 ;; The zero extend of operand 2 means we can just copy the high part of
1399 ;; operand1 into operand0.
1401 [(set (match_operand:DI 0 "s_register_operand" "")
1403 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1404 (match_operand:DI 1 "s_register_operand" "")))]
1405 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1406 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1407 (set (match_dup 3) (match_dup 4))]
1410 operands[4] = gen_highpart (SImode, operands[1]);
1411 operands[3] = gen_highpart (SImode, operands[0]);
1412 operands[0] = gen_lowpart (SImode, operands[0]);
1413 operands[1] = gen_lowpart (SImode, operands[1]);
1417 ;; The zero extend of operand 2 means we can just copy the high part of
1418 ;; operand1 into operand0.
1420 [(set (match_operand:DI 0 "s_register_operand" "")
1422 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1423 (match_operand:DI 1 "s_register_operand" "")))]
1424 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1425 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1426 (set (match_dup 3) (match_dup 4))]
1429 operands[4] = gen_highpart (SImode, operands[1]);
1430 operands[3] = gen_highpart (SImode, operands[0]);
1431 operands[0] = gen_lowpart (SImode, operands[0]);
1432 operands[1] = gen_lowpart (SImode, operands[1]);
1436 (define_insn "anddi3"
1437 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1438 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1439 (match_operand:DI 2 "s_register_operand" "r,r")))]
1442 [(set_attr "length" "8")]
1445 (define_insn_and_split "*anddi_zesidi_di"
1446 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1447 (and:DI (zero_extend:DI
1448 (match_operand:SI 2 "s_register_operand" "r,r"))
1449 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1452 "TARGET_ARM && reload_completed"
1453 ; The zero extend of operand 2 clears the high word of the output
1455 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1456 (set (match_dup 3) (const_int 0))]
1459 operands[3] = gen_highpart (SImode, operands[0]);
1460 operands[0] = gen_lowpart (SImode, operands[0]);
1461 operands[1] = gen_lowpart (SImode, operands[1]);
1463 [(set_attr "length" "8")]
1466 (define_insn "*anddi_sesdi_di"
1467 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1468 (and:DI (sign_extend:DI
1469 (match_operand:SI 2 "s_register_operand" "r,r"))
1470 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1473 [(set_attr "length" "8")]
1476 (define_expand "andsi3"
1477 [(set (match_operand:SI 0 "s_register_operand" "")
1478 (and:SI (match_operand:SI 1 "s_register_operand" "")
1479 (match_operand:SI 2 "reg_or_int_operand" "")))]
1484 if (GET_CODE (operands[2]) == CONST_INT)
1486 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1489 ? 0 : preserve_subexpressions_p ()));
1493 else /* TARGET_THUMB */
1495 if (GET_CODE (operands[2]) != CONST_INT)
1496 operands[2] = force_reg (SImode, operands[2]);
1501 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1503 operands[2] = force_reg (SImode,
1504 GEN_INT (~INTVAL (operands[2])));
1506 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1511 for (i = 9; i <= 31; i++)
1513 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1515 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1519 else if ((((HOST_WIDE_INT) 1) << i) - 1
1520 == ~INTVAL (operands[2]))
1522 rtx shift = GEN_INT (i);
1523 rtx reg = gen_reg_rtx (SImode);
1525 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1526 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1532 operands[2] = force_reg (SImode, operands[2]);
1538 (define_insn_and_split "*arm_andsi3_insn"
1539 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1540 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1541 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1545 bic%?\\t%0, %1, #%B2
1548 && GET_CODE (operands[2]) == CONST_INT
1549 && !(const_ok_for_arm (INTVAL (operands[2]))
1550 || const_ok_for_arm (~INTVAL (operands[2])))"
1551 [(clobber (const_int 0))]
1553 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1557 [(set_attr "length" "4,4,16")
1558 (set_attr "predicable" "yes")]
1561 (define_insn "*thumb_andsi3_insn"
1562 [(set (match_operand:SI 0 "register_operand" "=l")
1563 (and:SI (match_operand:SI 1 "register_operand" "%0")
1564 (match_operand:SI 2 "register_operand" "l")))]
1567 [(set_attr "length" "2")]
1570 (define_insn "*andsi3_compare0"
1571 [(set (reg:CC_NOOV CC_REGNUM)
1573 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1574 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1576 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1577 (and:SI (match_dup 1) (match_dup 2)))]
1581 bic%?s\\t%0, %1, #%B2"
1582 [(set_attr "conds" "set")]
1585 (define_insn "*andsi3_compare0_scratch"
1586 [(set (reg:CC_NOOV CC_REGNUM)
1588 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1589 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1591 (clobber (match_scratch:SI 2 "=X,r"))]
1595 bic%?s\\t%2, %0, #%B1"
1596 [(set_attr "conds" "set")]
1599 (define_insn "*zeroextractsi_compare0_scratch"
1600 [(set (reg:CC_NOOV CC_REGNUM)
1601 (compare:CC_NOOV (zero_extract:SI
1602 (match_operand:SI 0 "s_register_operand" "r")
1603 (match_operand 1 "const_int_operand" "n")
1604 (match_operand 2 "const_int_operand" "n"))
1607 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1608 && INTVAL (operands[1]) > 0
1609 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1610 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1612 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1613 << INTVAL (operands[2]));
1614 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1617 [(set_attr "conds" "set")]
1620 (define_insn "*ne_zeroextractsi"
1621 [(set (match_operand:SI 0 "s_register_operand" "=r")
1622 (ne:SI (zero_extract:SI
1623 (match_operand:SI 1 "s_register_operand" "r")
1624 (match_operand:SI 2 "const_int_operand" "n")
1625 (match_operand:SI 3 "const_int_operand" "n"))
1627 (clobber (reg:CC CC_REGNUM))]
1629 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1630 && INTVAL (operands[2]) > 0
1631 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1632 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1634 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1635 << INTVAL (operands[3]));
1636 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1637 return \"movne\\t%0, #1\";
1639 [(set_attr "conds" "clob")
1640 (set_attr "length" "8")]
1643 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1644 ;;; represented by the bitfield, then this will produce incorrect results.
1645 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1646 ;;; which have a real bit-field insert instruction, the truncation happens
1647 ;;; in the bit-field insert instruction itself. Since arm does not have a
1648 ;;; bit-field insert instruction, we would have to emit code here to truncate
1649 ;;; the value before we insert. This loses some of the advantage of having
1650 ;;; this insv pattern, so this pattern needs to be reevalutated.
1652 (define_expand "insv"
1653 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1654 (match_operand:SI 1 "general_operand" "")
1655 (match_operand:SI 2 "general_operand" ""))
1656 (match_operand:SI 3 "reg_or_int_operand" ""))]
1660 int start_bit = INTVAL (operands[2]);
1661 int width = INTVAL (operands[1]);
1662 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1663 rtx target, subtarget;
1665 target = operands[0];
1666 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1667 subreg as the final target. */
1668 if (GET_CODE (target) == SUBREG)
1670 subtarget = gen_reg_rtx (SImode);
1671 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1672 < GET_MODE_SIZE (SImode))
1673 target = SUBREG_REG (target);
1678 if (GET_CODE (operands[3]) == CONST_INT)
1680 /* Since we are inserting a known constant, we may be able to
1681 reduce the number of bits that we have to clear so that
1682 the mask becomes simple. */
1683 /* ??? This code does not check to see if the new mask is actually
1684 simpler. It may not be. */
1685 rtx op1 = gen_reg_rtx (SImode);
1686 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1687 start of this pattern. */
1688 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1689 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1691 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1692 emit_insn (gen_iorsi3 (subtarget, op1,
1693 GEN_INT (op3_value << start_bit)));
1695 else if (start_bit == 0
1696 && !(const_ok_for_arm (mask)
1697 || const_ok_for_arm (~mask)))
1699 /* A Trick, since we are setting the bottom bits in the word,
1700 we can shift operand[3] up, operand[0] down, OR them together
1701 and rotate the result back again. This takes 3 insns, and
1702 the third might be mergable into another op. */
1703 /* The shift up copes with the possibility that operand[3] is
1704 wider than the bitfield. */
1705 rtx op0 = gen_reg_rtx (SImode);
1706 rtx op1 = gen_reg_rtx (SImode);
1708 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1709 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1710 emit_insn (gen_iorsi3 (op1, op1, op0));
1711 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1713 else if ((width + start_bit == 32)
1714 && !(const_ok_for_arm (mask)
1715 || const_ok_for_arm (~mask)))
1717 /* Similar trick, but slightly less efficient. */
1719 rtx op0 = gen_reg_rtx (SImode);
1720 rtx op1 = gen_reg_rtx (SImode);
1722 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1723 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1724 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1725 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1729 rtx op0 = GEN_INT (mask);
1730 rtx op1 = gen_reg_rtx (SImode);
1731 rtx op2 = gen_reg_rtx (SImode);
1733 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1735 rtx tmp = gen_reg_rtx (SImode);
1737 emit_insn (gen_movsi (tmp, op0));
1741 /* Mask out any bits in operand[3] that are not needed. */
1742 emit_insn (gen_andsi3 (op1, operands[3], op0));
1744 if (GET_CODE (op0) == CONST_INT
1745 && (const_ok_for_arm (mask << start_bit)
1746 || const_ok_for_arm (~(mask << start_bit))))
1748 op0 = GEN_INT (~(mask << start_bit));
1749 emit_insn (gen_andsi3 (op2, operands[0], op0));
1753 if (GET_CODE (op0) == CONST_INT)
1755 rtx tmp = gen_reg_rtx (SImode);
1757 emit_insn (gen_movsi (tmp, op0));
1762 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1764 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1768 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1770 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1773 if (subtarget != target)
1775 /* If TARGET is still a SUBREG, then it must be wider than a word,
1776 so we must be careful only to set the subword we were asked to. */
1777 if (GET_CODE (target) == SUBREG)
1778 emit_move_insn (target, subtarget);
1780 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1787 ; constants for op 2 will never be given to these patterns.
1788 (define_insn_and_split "*anddi_notdi_di"
1789 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1790 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1791 (match_operand:DI 2 "s_register_operand" "0,r")))]
1794 "TARGET_ARM && reload_completed"
1795 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1796 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1799 operands[3] = gen_highpart (SImode, operands[0]);
1800 operands[0] = gen_lowpart (SImode, operands[0]);
1801 operands[4] = gen_highpart (SImode, operands[1]);
1802 operands[1] = gen_lowpart (SImode, operands[1]);
1803 operands[5] = gen_highpart (SImode, operands[2]);
1804 operands[2] = gen_lowpart (SImode, operands[2]);
1806 [(set_attr "length" "8")
1807 (set_attr "predicable" "yes")]
1810 (define_insn_and_split "*anddi_notzesidi_di"
1811 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1812 (and:DI (not:DI (zero_extend:DI
1813 (match_operand:SI 2 "s_register_operand" "r,r")))
1814 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1817 bic%?\\t%Q0, %Q1, %2
1819 ; (not (zero_extend ...)) allows us to just copy the high word from
1820 ; operand1 to operand0.
1823 && operands[0] != operands[1]"
1824 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1825 (set (match_dup 3) (match_dup 4))]
1828 operands[3] = gen_highpart (SImode, operands[0]);
1829 operands[0] = gen_lowpart (SImode, operands[0]);
1830 operands[4] = gen_highpart (SImode, operands[1]);
1831 operands[1] = gen_lowpart (SImode, operands[1]);
1833 [(set_attr "length" "4,8")
1834 (set_attr "predicable" "yes")]
1837 (define_insn_and_split "*anddi_notsesidi_di"
1838 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1839 (and:DI (not:DI (sign_extend:DI
1840 (match_operand:SI 2 "s_register_operand" "r,r")))
1841 (match_operand:DI 1 "s_register_operand" "0,r")))]
1844 "TARGET_ARM && reload_completed"
1845 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1846 (set (match_dup 3) (and:SI (not:SI
1847 (ashiftrt:SI (match_dup 2) (const_int 31)))
1851 operands[3] = gen_highpart (SImode, operands[0]);
1852 operands[0] = gen_lowpart (SImode, operands[0]);
1853 operands[4] = gen_highpart (SImode, operands[1]);
1854 operands[1] = gen_lowpart (SImode, operands[1]);
1856 [(set_attr "length" "8")
1857 (set_attr "predicable" "yes")]
1860 (define_insn "andsi_notsi_si"
1861 [(set (match_operand:SI 0 "s_register_operand" "=r")
1862 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1863 (match_operand:SI 1 "s_register_operand" "r")))]
1865 "bic%?\\t%0, %1, %2"
1866 [(set_attr "predicable" "yes")]
1869 (define_insn "bicsi3"
1870 [(set (match_operand:SI 0 "register_operand" "=l")
1871 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
1872 (match_operand:SI 2 "register_operand" "0")))]
1875 [(set_attr "length" "2")]
1878 (define_insn "andsi_not_shiftsi_si"
1879 [(set (match_operand:SI 0 "s_register_operand" "=r")
1880 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
1881 [(match_operand:SI 2 "s_register_operand" "r")
1882 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
1883 (match_operand:SI 1 "s_register_operand" "r")))]
1885 "bic%?\\t%0, %1, %2%S4"
1886 [(set_attr "predicable" "yes")
1887 (set_attr "shift" "2")
1891 (define_insn "*andsi_notsi_si_compare0"
1892 [(set (reg:CC_NOOV CC_REGNUM)
1894 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1895 (match_operand:SI 1 "s_register_operand" "r"))
1897 (set (match_operand:SI 0 "s_register_operand" "=r")
1898 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
1900 "bic%?s\\t%0, %1, %2"
1901 [(set_attr "conds" "set")]
1904 (define_insn "*andsi_notsi_si_compare0_scratch"
1905 [(set (reg:CC_NOOV CC_REGNUM)
1907 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1908 (match_operand:SI 1 "s_register_operand" "r"))
1910 (clobber (match_scratch:SI 0 "=r"))]
1912 "bic%?s\\t%0, %1, %2"
1913 [(set_attr "conds" "set")]
1916 (define_insn "iordi3"
1917 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1918 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1919 (match_operand:DI 2 "s_register_operand" "r,r")))]
1922 [(set_attr "length" "8")
1923 (set_attr "predicable" "yes")]
1926 (define_insn "*iordi_zesidi_di"
1927 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1928 (ior:DI (zero_extend:DI
1929 (match_operand:SI 2 "s_register_operand" "r,r"))
1930 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1933 orr%?\\t%Q0, %Q1, %2
1935 [(set_attr "length" "4,8")
1936 (set_attr "predicable" "yes")]
1939 (define_insn "*iordi_sesidi_di"
1940 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1941 (ior:DI (sign_extend:DI
1942 (match_operand:SI 2 "s_register_operand" "r,r"))
1943 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1946 [(set_attr "length" "8")
1947 (set_attr "predicable" "yes")]
1950 (define_expand "iorsi3"
1951 [(set (match_operand:SI 0 "s_register_operand" "")
1952 (ior:SI (match_operand:SI 1 "s_register_operand" "")
1953 (match_operand:SI 2 "reg_or_int_operand" "")))]
1956 if (GET_CODE (operands[2]) == CONST_INT)
1960 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1963 ? 0 : preserve_subexpressions_p ()));
1966 else /* TARGET_THUMB */
1967 operands [2] = force_reg (SImode, operands [2]);
1972 (define_insn_and_split "*arm_iorsi3"
1973 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1974 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
1975 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
1981 && GET_CODE (operands[2]) == CONST_INT
1982 && !const_ok_for_arm (INTVAL (operands[2]))"
1983 [(clobber (const_int 0))]
1985 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1989 [(set_attr "length" "4,16")
1990 (set_attr "predicable" "yes")]
1993 (define_insn "*thumb_iorsi3"
1994 [(set (match_operand:SI 0 "register_operand" "=l")
1995 (ior:SI (match_operand:SI 1 "register_operand" "%0")
1996 (match_operand:SI 2 "register_operand" "l")))]
1999 [(set_attr "length" "2")]
2003 [(match_scratch:SI 3 "r")
2004 (set (match_operand:SI 0 "s_register_operand" "")
2005 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2006 (match_operand:SI 2 "const_int_operand" "")))]
2008 && !const_ok_for_arm (INTVAL (operands[2]))
2009 && const_ok_for_arm (~INTVAL (operands[2]))"
2010 [(set (match_dup 3) (match_dup 2))
2011 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2015 (define_insn "*iorsi3_compare0"
2016 [(set (reg:CC_NOOV CC_REGNUM)
2017 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2018 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2020 (set (match_operand:SI 0 "s_register_operand" "=r")
2021 (ior:SI (match_dup 1) (match_dup 2)))]
2023 "orr%?s\\t%0, %1, %2"
2024 [(set_attr "conds" "set")]
2027 (define_insn "*iorsi3_compare0_scratch"
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 (clobber (match_scratch:SI 0 "=r"))]
2034 "orr%?s\\t%0, %1, %2"
2035 [(set_attr "conds" "set")]
2038 (define_insn "xordi3"
2039 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2040 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2041 (match_operand:DI 2 "s_register_operand" "r,r")))]
2044 [(set_attr "length" "8")
2045 (set_attr "predicable" "yes")]
2048 (define_insn "*xordi_zesidi_di"
2049 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2050 (xor:DI (zero_extend:DI
2051 (match_operand:SI 2 "s_register_operand" "r,r"))
2052 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2055 eor%?\\t%Q0, %Q1, %2
2057 [(set_attr "length" "4,8")
2058 (set_attr "predicable" "yes")]
2061 (define_insn "*xordi_sesidi_di"
2062 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2063 (xor:DI (sign_extend:DI
2064 (match_operand:SI 2 "s_register_operand" "r,r"))
2065 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2068 [(set_attr "length" "8")
2069 (set_attr "predicable" "yes")]
2072 (define_expand "xorsi3"
2073 [(set (match_operand:SI 0 "s_register_operand" "")
2074 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2075 (match_operand:SI 2 "arm_rhs_operand" "")))]
2078 if (GET_CODE (operands[2]) == CONST_INT)
2079 operands[2] = force_reg (SImode, operands[2]);
2083 (define_insn "*arm_xorsi3"
2084 [(set (match_operand:SI 0 "s_register_operand" "=r")
2085 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2086 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2088 "eor%?\\t%0, %1, %2"
2089 [(set_attr "predicable" "yes")]
2092 (define_insn "*thumb_xorsi3"
2093 [(set (match_operand:SI 0 "register_operand" "=l")
2094 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2095 (match_operand:SI 2 "register_operand" "l")))]
2098 [(set_attr "length" "2")]
2101 (define_insn "*xorsi3_compare0"
2102 [(set (reg:CC_NOOV CC_REGNUM)
2103 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2104 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2106 (set (match_operand:SI 0 "s_register_operand" "=r")
2107 (xor:SI (match_dup 1) (match_dup 2)))]
2109 "eor%?s\\t%0, %1, %2"
2110 [(set_attr "conds" "set")]
2113 (define_insn "*xorsi3_compare0_scratch"
2114 [(set (reg:CC_NOOV CC_REGNUM)
2115 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2116 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2120 [(set_attr "conds" "set")]
2123 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2124 ; (NOT D) we can sometimes merge the final NOT into one of the following
2128 [(set (match_operand:SI 0 "s_register_operand" "")
2129 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2130 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2131 (match_operand:SI 3 "arm_rhs_operand" "")))
2132 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2134 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2135 (not:SI (match_dup 3))))
2136 (set (match_dup 0) (not:SI (match_dup 4)))]
2140 (define_insn "*andsi_iorsi3_notsi"
2141 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2142 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2143 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2144 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2146 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2147 [(set_attr "length" "8")
2148 (set_attr "predicable" "yes")]
2153 ;; Minimum and maximum insns
2155 (define_insn "smaxsi3"
2156 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2157 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2158 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2159 (clobber (reg:CC CC_REGNUM))]
2162 cmp\\t%1, %2\;movlt\\t%0, %2
2163 cmp\\t%1, %2\;movge\\t%0, %1
2164 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2165 [(set_attr "conds" "clob")
2166 (set_attr "length" "8,8,12")]
2169 (define_insn "sminsi3"
2170 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2171 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2172 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2173 (clobber (reg:CC CC_REGNUM))]
2176 cmp\\t%1, %2\;movge\\t%0, %2
2177 cmp\\t%1, %2\;movlt\\t%0, %1
2178 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2179 [(set_attr "conds" "clob")
2180 (set_attr "length" "8,8,12")]
2183 (define_insn "umaxsi3"
2184 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2185 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2186 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2187 (clobber (reg:CC CC_REGNUM))]
2190 cmp\\t%1, %2\;movcc\\t%0, %2
2191 cmp\\t%1, %2\;movcs\\t%0, %1
2192 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2193 [(set_attr "conds" "clob")
2194 (set_attr "length" "8,8,12")]
2197 (define_insn "uminsi3"
2198 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2199 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2200 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2201 (clobber (reg:CC CC_REGNUM))]
2204 cmp\\t%1, %2\;movcs\\t%0, %2
2205 cmp\\t%1, %2\;movcc\\t%0, %1
2206 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2207 [(set_attr "conds" "clob")
2208 (set_attr "length" "8,8,12")]
2211 (define_insn "*store_minmaxsi"
2212 [(set (match_operand:SI 0 "memory_operand" "=m")
2213 (match_operator:SI 3 "minmax_operator"
2214 [(match_operand:SI 1 "s_register_operand" "r")
2215 (match_operand:SI 2 "s_register_operand" "r")]))
2216 (clobber (reg:CC CC_REGNUM))]
2219 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2221 output_asm_insn (\"cmp\\t%1, %2\", operands);
2222 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2223 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2226 [(set_attr "conds" "clob")
2227 (set_attr "length" "12")
2228 (set_attr "type" "store1")]
2231 ; Reject the frame pointer in operand[1], since reloading this after
2232 ; it has been eliminated can cause carnage.
2233 (define_insn "*minmax_arithsi"
2234 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2235 (match_operator:SI 4 "shiftable_operator"
2236 [(match_operator:SI 5 "minmax_operator"
2237 [(match_operand:SI 2 "s_register_operand" "r,r")
2238 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2239 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2240 (clobber (reg:CC CC_REGNUM))]
2242 && (GET_CODE (operands[1]) != REG
2243 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2244 && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2247 enum rtx_code code = GET_CODE (operands[4]);
2249 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2251 output_asm_insn (\"cmp\\t%2, %3\", operands);
2252 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2253 if (which_alternative != 0 || operands[3] != const0_rtx
2254 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2255 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2258 [(set_attr "conds" "clob")
2259 (set_attr "length" "12")]
2263 ;; Shift and rotation insns
2265 (define_expand "ashlsi3"
2266 [(set (match_operand:SI 0 "s_register_operand" "")
2267 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2268 (match_operand:SI 2 "arm_rhs_operand" "")))]
2271 if (GET_CODE (operands[2]) == CONST_INT
2272 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2274 emit_insn (gen_movsi (operands[0], const0_rtx));
2280 (define_insn "*thumb_ashlsi3"
2281 [(set (match_operand:SI 0 "register_operand" "=l,l")
2282 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2283 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2286 [(set_attr "length" "2")]
2289 (define_expand "ashrsi3"
2290 [(set (match_operand:SI 0 "s_register_operand" "")
2291 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2292 (match_operand:SI 2 "arm_rhs_operand" "")))]
2295 if (GET_CODE (operands[2]) == CONST_INT
2296 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2297 operands[2] = GEN_INT (31);
2301 (define_insn "*thumb_ashrsi3"
2302 [(set (match_operand:SI 0 "register_operand" "=l,l")
2303 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2304 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2307 [(set_attr "length" "2")]
2310 (define_expand "lshrsi3"
2311 [(set (match_operand:SI 0 "s_register_operand" "")
2312 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2313 (match_operand:SI 2 "arm_rhs_operand" "")))]
2316 if (GET_CODE (operands[2]) == CONST_INT
2317 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2319 emit_insn (gen_movsi (operands[0], const0_rtx));
2325 (define_insn "*thumb_lshrsi3"
2326 [(set (match_operand:SI 0 "register_operand" "=l,l")
2327 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2328 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2331 [(set_attr "length" "2")]
2334 (define_expand "rotlsi3"
2335 [(set (match_operand:SI 0 "s_register_operand" "")
2336 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2337 (match_operand:SI 2 "reg_or_int_operand" "")))]
2340 if (GET_CODE (operands[2]) == CONST_INT)
2341 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2344 rtx reg = gen_reg_rtx (SImode);
2345 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2351 (define_expand "rotrsi3"
2352 [(set (match_operand:SI 0 "s_register_operand" "")
2353 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2354 (match_operand:SI 2 "arm_rhs_operand" "")))]
2359 if (GET_CODE (operands[2]) == CONST_INT
2360 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2361 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2363 else /* TARGET_THUMB */
2365 if (GET_CODE (operands [2]) == CONST_INT)
2366 operands [2] = force_reg (SImode, operands[2]);
2371 (define_insn "*thumb_rotrsi3"
2372 [(set (match_operand:SI 0 "register_operand" "=l")
2373 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2374 (match_operand:SI 2 "register_operand" "l")))]
2377 [(set_attr "length" "2")]
2380 (define_expand "ashldi3"
2381 [(set (match_operand:DI 0 "s_register_operand" "")
2382 (ashift:DI (match_operand:DI 1 "general_operand" "")
2383 (match_operand:SI 2 "general_operand" "")))]
2384 "TARGET_ARM && (TARGET_CIRRUS)"
2386 if (! s_register_operand (operands[1], DImode))
2387 operands[1] = copy_to_mode_reg (DImode, operands[1]);
2388 if (! s_register_operand (operands[2], SImode))
2389 operands[2] = copy_to_mode_reg (SImode, operands[2]);
2393 (define_insn "*arm_shiftsi3"
2394 [(set (match_operand:SI 0 "s_register_operand" "=r")
2395 (match_operator:SI 3 "shift_operator"
2396 [(match_operand:SI 1 "s_register_operand" "r")
2397 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2400 [(set_attr "predicable" "yes")
2401 (set_attr "shift" "1")
2405 (define_insn "*shiftsi3_compare0"
2406 [(set (reg:CC_NOOV CC_REGNUM)
2407 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2408 [(match_operand:SI 1 "s_register_operand" "r")
2409 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2411 (set (match_operand:SI 0 "s_register_operand" "=r")
2412 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2414 "mov%?s\\t%0, %1%S3"
2415 [(set_attr "conds" "set")
2416 (set_attr "shift" "1")
2420 (define_insn "*shiftsi3_compare0_scratch"
2421 [(set (reg:CC_NOOV CC_REGNUM)
2422 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2423 [(match_operand:SI 1 "s_register_operand" "r")
2424 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2426 (clobber (match_scratch:SI 0 "=r"))]
2428 "mov%?s\\t%0, %1%S3"
2429 [(set_attr "conds" "set")
2430 (set_attr "shift" "1")
2434 (define_insn "*notsi_shiftsi"
2435 [(set (match_operand:SI 0 "s_register_operand" "=r")
2436 (not:SI (match_operator:SI 3 "shift_operator"
2437 [(match_operand:SI 1 "s_register_operand" "r")
2438 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2441 [(set_attr "predicable" "yes")
2442 (set_attr "shift" "1")
2446 (define_insn "*notsi_shiftsi_compare0"
2447 [(set (reg:CC_NOOV CC_REGNUM)
2448 (compare:CC_NOOV (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")]))
2452 (set (match_operand:SI 0 "s_register_operand" "=r")
2453 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2455 "mvn%?s\\t%0, %1%S3"
2456 [(set_attr "conds" "set")
2457 (set_attr "shift" "1")
2461 (define_insn "*not_shiftsi_compare0_scratch"
2462 [(set (reg:CC_NOOV CC_REGNUM)
2463 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2464 [(match_operand:SI 1 "s_register_operand" "r")
2465 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2467 (clobber (match_scratch:SI 0 "=r"))]
2469 "mvn%?s\\t%0, %1%S3"
2470 [(set_attr "conds" "set")
2471 (set_attr "shift" "1")
2475 ;; We don't really have extzv, but defining this using shifts helps
2476 ;; to reduce register pressure later on.
2478 (define_expand "extzv"
2480 (ashift:SI (match_operand:SI 1 "register_operand" "")
2481 (match_operand:SI 2 "const_int_operand" "")))
2482 (set (match_operand:SI 0 "register_operand" "")
2483 (lshiftrt:SI (match_dup 4)
2484 (match_operand:SI 3 "const_int_operand" "")))]
2488 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2489 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2491 operands[3] = GEN_INT (rshift);
2495 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2499 operands[2] = GEN_INT (lshift);
2500 operands[4] = gen_reg_rtx (SImode);
2505 ;; Unary arithmetic insns
2507 (define_expand "negdi2"
2509 [(set (match_operand:DI 0 "s_register_operand" "")
2510 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2511 (clobber (reg:CC CC_REGNUM))])]
2516 if (GET_CODE (operands[1]) != REG)
2517 operands[1] = force_reg (SImode, operands[1]);
2522 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2523 ;; The second alternative is to allow the common case of a *full* overlap.
2524 (define_insn "*arm_negdi2"
2525 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2526 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2527 (clobber (reg:CC CC_REGNUM))]
2529 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2530 [(set_attr "conds" "clob")
2531 (set_attr "length" "8")]
2534 (define_insn "*thumb_negdi2"
2535 [(set (match_operand:DI 0 "register_operand" "=&l")
2536 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2537 (clobber (reg:CC CC_REGNUM))]
2539 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2540 [(set_attr "length" "6")]
2543 (define_expand "negsi2"
2544 [(set (match_operand:SI 0 "s_register_operand" "")
2545 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2550 (define_insn "*arm_negsi2"
2551 [(set (match_operand:SI 0 "s_register_operand" "=r")
2552 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2554 "rsb%?\\t%0, %1, #0"
2555 [(set_attr "predicable" "yes")]
2558 (define_insn "*thumb_negsi2"
2559 [(set (match_operand:SI 0 "register_operand" "=l")
2560 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2563 [(set_attr "length" "2")]
2566 (define_expand "negsf2"
2567 [(set (match_operand:SF 0 "s_register_operand" "")
2568 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2569 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2573 (define_expand "negdf2"
2574 [(set (match_operand:DF 0 "s_register_operand" "")
2575 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2576 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2579 ;; abssi2 doesn't really clobber the condition codes if a different register
2580 ;; is being set. To keep things simple, assume during rtl manipulations that
2581 ;; it does, but tell the final scan operator the truth. Similarly for
2584 (define_expand "abssi2"
2586 [(set (match_operand:SI 0 "s_register_operand" "")
2587 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2588 (clobber (reg:CC CC_REGNUM))])]
2592 (define_insn "*arm_abssi2"
2593 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2594 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2595 (clobber (reg:CC CC_REGNUM))]
2598 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2599 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2600 [(set_attr "conds" "clob,*")
2601 (set_attr "shift" "1")
2602 ;; predicable can't be set based on the variant, so left as no
2603 (set_attr "length" "8")]
2606 (define_insn "*neg_abssi2"
2607 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2608 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2609 (clobber (reg:CC CC_REGNUM))]
2612 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2613 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2614 [(set_attr "conds" "clob,*")
2615 (set_attr "shift" "1")
2616 ;; predicable can't be set based on the variant, so left as no
2617 (set_attr "length" "8")]
2620 (define_expand "abssf2"
2621 [(set (match_operand:SF 0 "s_register_operand" "")
2622 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
2623 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2626 (define_expand "absdf2"
2627 [(set (match_operand:DF 0 "s_register_operand" "")
2628 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
2629 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2632 (define_expand "sqrtsf2"
2633 [(set (match_operand:SF 0 "s_register_operand" "")
2634 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
2635 "TARGET_ARM && TARGET_HARD_FLOAT"
2638 (define_expand "sqrtdf2"
2639 [(set (match_operand:DF 0 "s_register_operand" "")
2640 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
2641 "TARGET_ARM && TARGET_HARD_FLOAT"
2644 (define_insn_and_split "one_cmpldi2"
2645 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2646 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2649 "TARGET_ARM && reload_completed"
2650 [(set (match_dup 0) (not:SI (match_dup 1)))
2651 (set (match_dup 2) (not:SI (match_dup 3)))]
2654 operands[2] = gen_highpart (SImode, operands[0]);
2655 operands[0] = gen_lowpart (SImode, operands[0]);
2656 operands[3] = gen_highpart (SImode, operands[1]);
2657 operands[1] = gen_lowpart (SImode, operands[1]);
2659 [(set_attr "length" "8")
2660 (set_attr "predicable" "yes")]
2663 (define_expand "one_cmplsi2"
2664 [(set (match_operand:SI 0 "s_register_operand" "")
2665 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2670 (define_insn "*arm_one_cmplsi2"
2671 [(set (match_operand:SI 0 "s_register_operand" "=r")
2672 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
2675 [(set_attr "predicable" "yes")]
2678 (define_insn "*thumb_one_cmplsi2"
2679 [(set (match_operand:SI 0 "register_operand" "=l")
2680 (not:SI (match_operand:SI 1 "register_operand" "l")))]
2683 [(set_attr "length" "2")]
2686 (define_insn "*notsi_compare0"
2687 [(set (reg:CC_NOOV CC_REGNUM)
2688 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2690 (set (match_operand:SI 0 "s_register_operand" "=r")
2691 (not:SI (match_dup 1)))]
2694 [(set_attr "conds" "set")]
2697 (define_insn "*notsi_compare0_scratch"
2698 [(set (reg:CC_NOOV CC_REGNUM)
2699 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2701 (clobber (match_scratch:SI 0 "=r"))]
2704 [(set_attr "conds" "set")]
2707 ;; Fixed <--> Floating conversion insns
2709 (define_expand "floatsisf2"
2710 [(set (match_operand:SF 0 "s_register_operand" "")
2711 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
2712 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2716 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
2721 (define_expand "floatsidf2"
2722 [(set (match_operand:DF 0 "s_register_operand" "")
2723 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
2724 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2728 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
2733 (define_expand "fix_truncsfsi2"
2734 [(set (match_operand:SI 0 "s_register_operand" "")
2735 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
2736 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2740 if (!cirrus_fp_register (operands[0], SImode))
2741 operands[0] = force_reg (SImode, operands[0]);
2742 if (!cirrus_fp_register (operands[1], SFmode))
2743 operands[1] = force_reg (SFmode, operands[0]);
2744 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
2749 (define_expand "fix_truncdfsi2"
2750 [(set (match_operand:SI 0 "s_register_operand" "")
2751 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
2752 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2756 if (!cirrus_fp_register (operands[1], DFmode))
2757 operands[1] = force_reg (DFmode, operands[0]);
2758 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
2765 (define_expand "truncdfsf2"
2766 [(set (match_operand:SF 0 "s_register_operand" "")
2768 (match_operand:DF 1 "s_register_operand" "")))]
2769 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2773 ;; Zero and sign extension instructions.
2775 (define_insn "zero_extendsidi2"
2776 [(set (match_operand:DI 0 "s_register_operand" "=r")
2777 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2780 if (REGNO (operands[1])
2781 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2782 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2783 return \"mov%?\\t%R0, #0\";
2785 [(set_attr "length" "8")
2786 (set_attr "predicable" "yes")]
2789 (define_insn "zero_extendqidi2"
2790 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
2791 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2794 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
2795 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
2796 [(set_attr "length" "8")
2797 (set_attr "predicable" "yes")
2798 (set_attr "type" "*,load")
2799 (set_attr "pool_range" "*,4092")
2800 (set_attr "neg_pool_range" "*,4084")]
2803 (define_insn "extendsidi2"
2804 [(set (match_operand:DI 0 "s_register_operand" "=r")
2805 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2808 if (REGNO (operands[1])
2809 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2810 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2811 return \"mov%?\\t%R0, %Q0, asr #31\";
2813 [(set_attr "length" "8")
2814 (set_attr "shift" "1")
2815 (set_attr "predicable" "yes")]
2818 (define_expand "zero_extendhisi2"
2820 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2822 (set (match_operand:SI 0 "s_register_operand" "")
2823 (lshiftrt:SI (match_dup 2) (const_int 16)))]
2829 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2831 /* Note: We do not have to worry about TARGET_MMU_TRAPS
2832 here because the insn below will generate an LDRH instruction
2833 rather than an LDR instruction, so we cannot get an unaligned
2835 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2836 gen_rtx_ZERO_EXTEND (SImode,
2840 if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
2842 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
2845 if (!s_register_operand (operands[1], HImode))
2846 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2847 operands[1] = gen_lowpart (SImode, operands[1]);
2848 operands[2] = gen_reg_rtx (SImode);
2850 else /* TARGET_THUMB */
2852 if (GET_CODE (operands[1]) == MEM)
2856 tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
2857 tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
2864 if (!s_register_operand (operands[1], HImode))
2865 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2866 operands[1] = gen_lowpart (SImode, operands[1]);
2867 operands[2] = gen_reg_rtx (SImode);
2869 ops[0] = operands[2];
2870 ops[1] = operands[1];
2871 ops[2] = GEN_INT (16);
2873 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
2874 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
2876 ops[0] = operands[0];
2877 ops[1] = operands[2];
2878 ops[2] = GEN_INT (16);
2880 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
2881 gen_rtx_LSHIFTRT (SImode, ops[1],
2889 (define_insn "*thumb_zero_extendhisi2"
2890 [(set (match_operand:SI 0 "register_operand" "=l")
2891 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2894 rtx mem = XEXP (operands[1], 0);
2896 if (GET_CODE (mem) == CONST)
2897 mem = XEXP (mem, 0);
2899 if (GET_CODE (mem) == LABEL_REF)
2900 return \"ldr\\t%0, %1\";
2902 if (GET_CODE (mem) == PLUS)
2904 rtx a = XEXP (mem, 0);
2905 rtx b = XEXP (mem, 1);
2907 /* This can happen due to bugs in reload. */
2908 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
2911 ops[0] = operands[0];
2914 output_asm_insn (\"mov %0, %1\", ops);
2916 XEXP (mem, 0) = operands[0];
2919 else if ( GET_CODE (a) == LABEL_REF
2920 && GET_CODE (b) == CONST_INT)
2921 return \"ldr\\t%0, %1\";
2924 return \"ldrh\\t%0, %1\";
2926 [(set_attr "length" "4")
2927 (set_attr "type" "load")
2928 (set_attr "pool_range" "60")]
2931 (define_insn "*arm_zero_extendhisi2"
2932 [(set (match_operand:SI 0 "s_register_operand" "=r")
2933 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2934 "TARGET_ARM && arm_arch4"
2936 [(set_attr "type" "load")
2937 (set_attr "predicable" "yes")
2938 (set_attr "pool_range" "256")
2939 (set_attr "neg_pool_range" "244")]
2943 [(set (match_operand:SI 0 "s_register_operand" "")
2944 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2945 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2946 "TARGET_ARM && (!arm_arch4)"
2947 [(set (match_dup 2) (match_dup 1))
2948 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
2950 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
2956 [(set (match_operand:SI 0 "s_register_operand" "")
2957 (match_operator:SI 3 "shiftable_operator"
2958 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2959 (match_operand:SI 4 "s_register_operand" "")]))
2960 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2961 "TARGET_ARM && (!arm_arch4)"
2962 [(set (match_dup 2) (match_dup 1))
2965 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2967 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
2972 (define_expand "zero_extendqisi2"
2973 [(set (match_operand:SI 0 "s_register_operand" "")
2974 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
2977 if (GET_CODE (operands[1]) != MEM)
2981 emit_insn (gen_andsi3 (operands[0],
2982 gen_lowpart (SImode, operands[1]),
2985 else /* TARGET_THUMB */
2987 rtx temp = gen_reg_rtx (SImode);
2990 operands[1] = copy_to_mode_reg (QImode, operands[1]);
2991 operands[1] = gen_lowpart (SImode, operands[1]);
2994 ops[1] = operands[1];
2995 ops[2] = GEN_INT (24);
2997 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
2998 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3000 ops[0] = operands[0];
3002 ops[2] = GEN_INT (24);
3004 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3005 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3012 (define_insn "*thumb_zero_extendqisi2"
3013 [(set (match_operand:SI 0 "register_operand" "=l")
3014 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3017 [(set_attr "length" "2")
3018 (set_attr "type" "load")
3019 (set_attr "pool_range" "32")]
3022 (define_insn "*arm_zero_extendqisi2"
3023 [(set (match_operand:SI 0 "s_register_operand" "=r")
3024 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3026 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3027 [(set_attr "type" "load")
3028 (set_attr "predicable" "yes")
3029 (set_attr "pool_range" "4096")
3030 (set_attr "neg_pool_range" "4084")]
3034 [(set (match_operand:SI 0 "s_register_operand" "")
3035 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3036 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3037 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3038 [(set (match_dup 2) (match_dup 1))
3039 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3043 (define_insn "*compareqi_eq0"
3044 [(set (reg:CC_Z CC_REGNUM)
3045 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3049 [(set_attr "conds" "set")]
3052 (define_expand "extendhisi2"
3054 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3056 (set (match_operand:SI 0 "s_register_operand" "")
3057 (ashiftrt:SI (match_dup 2)
3062 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3064 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3065 here because the insn below will generate an LDRH instruction
3066 rather than an LDR instruction, so we cannot get an unaligned
3068 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3069 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3073 if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3075 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3078 if (!s_register_operand (operands[1], HImode))
3079 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3080 operands[1] = gen_lowpart (SImode, operands[1]);
3081 operands[2] = gen_reg_rtx (SImode);
3087 ops[0] = operands[2];
3088 ops[1] = operands[1];
3089 ops[2] = GEN_INT (16);
3091 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3092 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3094 ops[0] = operands[0];
3095 ops[1] = operands[2];
3096 ops[2] = GEN_INT (16);
3098 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3099 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3106 (define_insn "*thumb_extendhisi2_insn"
3107 [(set (match_operand:SI 0 "register_operand" "=l")
3108 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3109 (clobber (match_scratch:SI 2 "=&l"))]
3114 rtx mem = XEXP (operands[1], 0);
3116 /* This code used to try to use 'V', and fix the address only if it was
3117 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3118 range of QImode offsets, and offsettable_address_p does a QImode
3121 if (GET_CODE (mem) == CONST)
3122 mem = XEXP (mem, 0);
3124 if (GET_CODE (mem) == LABEL_REF)
3125 return \"ldr\\t%0, %1\";
3127 if (GET_CODE (mem) == PLUS)
3129 rtx a = XEXP (mem, 0);
3130 rtx b = XEXP (mem, 1);
3132 if (GET_CODE (a) == LABEL_REF
3133 && GET_CODE (b) == CONST_INT)
3134 return \"ldr\\t%0, %1\";
3136 if (GET_CODE (b) == REG)
3137 return \"ldrsh\\t%0, %1\";
3145 ops[2] = const0_rtx;
3148 if (GET_CODE (ops[1]) != REG)
3154 ops[0] = operands[0];
3155 ops[3] = operands[2];
3156 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3159 [(set_attr "length" "4")
3160 (set_attr "type" "load")
3161 (set_attr "pool_range" "1020")]
3164 (define_expand "extendhisi2_mem"
3165 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3167 (zero_extend:SI (match_dup 7)))
3168 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3169 (set (match_operand:SI 0 "" "")
3170 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3175 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3177 mem1 = gen_rtx_MEM (QImode, addr);
3178 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3179 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3180 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3181 operands[0] = gen_lowpart (SImode, operands[0]);
3183 operands[2] = gen_reg_rtx (SImode);
3184 operands[3] = gen_reg_rtx (SImode);
3185 operands[6] = gen_reg_rtx (SImode);
3188 if (BYTES_BIG_ENDIAN)
3190 operands[4] = operands[2];
3191 operands[5] = operands[3];
3195 operands[4] = operands[3];
3196 operands[5] = operands[2];
3201 (define_insn "*arm_extendhisi_insn"
3202 [(set (match_operand:SI 0 "s_register_operand" "=r")
3203 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3204 "TARGET_ARM && arm_arch4"
3206 [(set_attr "type" "load")
3207 (set_attr "predicable" "yes")
3208 (set_attr "pool_range" "256")
3209 (set_attr "neg_pool_range" "244")]
3213 [(set (match_operand:SI 0 "s_register_operand" "")
3214 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3215 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3216 "TARGET_ARM && (!arm_arch4)"
3217 [(set (match_dup 2) (match_dup 1))
3218 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3220 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3226 [(set (match_operand:SI 0 "s_register_operand" "")
3227 (match_operator:SI 3 "shiftable_operator"
3228 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3229 (match_operand:SI 4 "s_register_operand" "")]))
3230 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3231 "TARGET_ARM && (!arm_arch4)"
3232 [(set (match_dup 2) (match_dup 1))
3235 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3236 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3241 (define_expand "extendqihi2"
3243 (ashift:SI (match_operand:QI 1 "general_operand" "")
3245 (set (match_operand:HI 0 "s_register_operand" "")
3246 (ashiftrt:SI (match_dup 2)
3251 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3253 emit_insn (gen_rtx_SET (VOIDmode,
3255 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3258 if (!s_register_operand (operands[1], QImode))
3259 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3260 operands[0] = gen_lowpart (SImode, operands[0]);
3261 operands[1] = gen_lowpart (SImode, operands[1]);
3262 operands[2] = gen_reg_rtx (SImode);
3266 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3267 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3268 (define_insn "*extendqihi_insn"
3269 [(set (match_operand:HI 0 "s_register_operand" "=r")
3270 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3271 "TARGET_ARM && arm_arch4"
3273 /* If the address is invalid, this will split the instruction into two. */
3274 if (bad_signed_byte_operand (operands[1], VOIDmode))
3276 return \"ldr%?sb\\t%0, %1\";
3278 [(set_attr "type" "load")
3279 (set_attr "predicable" "yes")
3280 (set_attr "length" "8")
3281 (set_attr "pool_range" "256")
3282 (set_attr "neg_pool_range" "244")]
3286 [(set (match_operand:HI 0 "s_register_operand" "")
3287 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3288 "TARGET_ARM && arm_arch4 && reload_completed"
3289 [(set (match_dup 3) (match_dup 1))
3290 (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3293 HOST_WIDE_INT offset;
3295 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3296 operands[2] = gen_rtx_MEM (QImode, operands[3]);
3297 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3298 operands[1] = XEXP (operands[1], 0);
3299 if (GET_CODE (operands[1]) == PLUS
3300 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3301 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3302 || const_ok_for_arm (-offset)))
3304 HOST_WIDE_INT low = (offset > 0
3305 ? (offset & 0xff) : -((-offset) & 0xff));
3306 XEXP (operands[2], 0) = plus_constant (operands[3], low);
3307 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3309 /* Ensure the sum is in correct canonical form */
3310 else if (GET_CODE (operands[1]) == PLUS
3311 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3312 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3313 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3314 XEXP (operands[1], 1),
3315 XEXP (operands[1], 0));
3319 (define_expand "extendqisi2"
3321 (ashift:SI (match_operand:QI 1 "general_operand" "")
3323 (set (match_operand:SI 0 "s_register_operand" "")
3324 (ashiftrt:SI (match_dup 2)
3329 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3331 emit_insn (gen_rtx_SET (VOIDmode,
3333 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3336 if (!s_register_operand (operands[1], QImode))
3337 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3338 operands[1] = gen_lowpart (SImode, operands[1]);
3339 operands[2] = gen_reg_rtx (SImode);
3345 ops[0] = operands[2];
3346 ops[1] = operands[1];
3347 ops[2] = GEN_INT (24);
3349 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3350 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3352 ops[0] = operands[0];
3353 ops[1] = operands[2];
3354 ops[2] = GEN_INT (24);
3356 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3357 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3364 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3365 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3366 (define_insn "*arm_extendqisi_insn"
3367 [(set (match_operand:SI 0 "s_register_operand" "=r")
3368 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3369 "TARGET_ARM && arm_arch4"
3371 /* If the address is invalid, this will split the instruction into two. */
3372 if (bad_signed_byte_operand (operands[1], VOIDmode))
3374 return \"ldr%?sb\\t%0, %1\";
3376 [(set_attr "type" "load")
3377 (set_attr "predicable" "yes")
3378 (set_attr "length" "8")
3379 (set_attr "pool_range" "256")
3380 (set_attr "neg_pool_range" "244")]
3384 [(set (match_operand:SI 0 "s_register_operand" "")
3385 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3386 "TARGET_ARM && arm_arch4 && reload_completed"
3387 [(set (match_dup 0) (match_dup 1))
3388 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3391 HOST_WIDE_INT offset;
3393 operands[2] = gen_rtx_MEM (QImode, operands[0]);
3394 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3395 operands[1] = XEXP (operands[1], 0);
3396 if (GET_CODE (operands[1]) == PLUS
3397 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3398 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3399 || const_ok_for_arm (-offset)))
3401 HOST_WIDE_INT low = (offset > 0
3402 ? (offset & 0xff) : -((-offset) & 0xff));
3403 XEXP (operands[2], 0) = plus_constant (operands[0], low);
3404 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3406 /* Ensure the sum is in correct canonical form */
3407 else if (GET_CODE (operands[1]) == PLUS
3408 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3409 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3410 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3411 XEXP (operands[1], 1),
3412 XEXP (operands[1], 0));
3416 (define_insn "*thumb_extendqisi2_insn"
3417 [(set (match_operand:SI 0 "register_operand" "=l,l")
3418 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3423 rtx mem = XEXP (operands[1], 0);
3425 if (GET_CODE (mem) == CONST)
3426 mem = XEXP (mem, 0);
3428 if (GET_CODE (mem) == LABEL_REF)
3429 return \"ldr\\t%0, %1\";
3431 if (GET_CODE (mem) == PLUS
3432 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3433 return \"ldr\\t%0, %1\";
3435 if (which_alternative == 0)
3436 return \"ldrsb\\t%0, %1\";
3438 ops[0] = operands[0];
3440 if (GET_CODE (mem) == PLUS)
3442 rtx a = XEXP (mem, 0);
3443 rtx b = XEXP (mem, 1);
3448 if (GET_CODE (a) == REG)
3450 if (GET_CODE (b) == REG)
3451 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3452 else if (REGNO (a) == REGNO (ops[0]))
3454 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3455 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3456 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3459 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3461 else if (GET_CODE (b) != REG)
3465 if (REGNO (b) == REGNO (ops[0]))
3467 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3468 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3469 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3472 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3475 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3477 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3478 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3479 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3484 ops[2] = const0_rtx;
3486 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3490 [(set_attr "length" "2,6")
3491 (set_attr "type" "load,load")
3492 (set_attr "pool_range" "32,32")]
3495 (define_expand "extendsfdf2"
3496 [(set (match_operand:DF 0 "s_register_operand" "")
3497 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
3498 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3502 ;; Move insns (including loads and stores)
3504 ;; XXX Just some ideas about movti.
3505 ;; I don't think these are a good idea on the arm, there just aren't enough
3507 ;;(define_expand "loadti"
3508 ;; [(set (match_operand:TI 0 "s_register_operand" "")
3509 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
3512 ;;(define_expand "storeti"
3513 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3514 ;; (match_operand:TI 1 "s_register_operand" ""))]
3517 ;;(define_expand "movti"
3518 ;; [(set (match_operand:TI 0 "general_operand" "")
3519 ;; (match_operand:TI 1 "general_operand" ""))]
3525 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3526 ;; operands[1] = copy_to_reg (operands[1]);
3527 ;; if (GET_CODE (operands[0]) == MEM)
3528 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3529 ;; else if (GET_CODE (operands[1]) == MEM)
3530 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3534 ;; emit_insn (insn);
3538 ;; Recognize garbage generated above.
3541 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3542 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3546 ;; register mem = (which_alternative < 3);
3547 ;; register const char *template;
3549 ;; operands[mem] = XEXP (operands[mem], 0);
3550 ;; switch (which_alternative)
3552 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3553 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
3554 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
3555 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
3556 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
3557 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
3559 ;; output_asm_insn (template, operands);
3563 (define_expand "movdi"
3564 [(set (match_operand:DI 0 "general_operand" "")
3565 (match_operand:DI 1 "general_operand" ""))]
3570 if (!no_new_pseudos)
3572 if (GET_CODE (operands[0]) != REG)
3573 operands[1] = force_reg (DImode, operands[1]);
3579 (define_insn "*arm_movdi"
3580 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3581 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
3582 "TARGET_ARM && !TARGET_CIRRUS"
3584 return (output_move_double (operands));
3586 [(set_attr "length" "8")
3587 (set_attr "type" "*,load,store2")
3588 (set_attr "pool_range" "*,1020,*")
3589 (set_attr "neg_pool_range" "*,1008,*")]
3592 ;;; ??? This should have alternatives for constants.
3593 ;;; ??? This was originally identical to the movdf_insn pattern.
3594 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3595 ;;; thumb_reorg with a memory reference.
3596 (define_insn "*thumb_movdi_insn"
3597 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3598 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
3601 && ( register_operand (operands[0], DImode)
3602 || register_operand (operands[1], DImode))"
3605 switch (which_alternative)
3609 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3610 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
3611 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
3613 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3615 operands[1] = GEN_INT (- INTVAL (operands[1]));
3616 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3618 return \"ldmia\\t%1, {%0, %H0}\";
3620 return \"stmia\\t%0, {%1, %H1}\";
3622 return thumb_load_double_from_address (operands);
3624 operands[2] = gen_rtx (MEM, SImode,
3625 plus_constant (XEXP (operands[0], 0), 4));
3626 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3629 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3630 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
3631 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
3634 [(set_attr "length" "4,4,6,2,2,6,4,4")
3635 (set_attr "type" "*,*,*,load,store2,load,store2,*")
3636 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
3639 (define_expand "movsi"
3640 [(set (match_operand:SI 0 "general_operand" "")
3641 (match_operand:SI 1 "general_operand" ""))]
3646 /* Everything except mem = const or mem = mem can be done easily */
3647 if (GET_CODE (operands[0]) == MEM)
3648 operands[1] = force_reg (SImode, operands[1]);
3649 if (GET_CODE (operands[1]) == CONST_INT
3650 && !(const_ok_for_arm (INTVAL (operands[1]))
3651 || const_ok_for_arm (~INTVAL (operands[1]))))
3653 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3656 : preserve_subexpressions_p ()));
3660 else /* TARGET_THUMB.... */
3662 if (!no_new_pseudos)
3664 if (GET_CODE (operands[0]) != REG)
3665 operands[1] = force_reg (SImode, operands[1]);
3670 && (CONSTANT_P (operands[1])
3671 || symbol_mentioned_p (operands[1])
3672 || label_mentioned_p (operands[1])))
3673 operands[1] = legitimize_pic_address (operands[1], SImode,
3674 (no_new_pseudos ? operands[0] : 0));
3678 (define_insn "*arm_movsi_insn"
3679 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
3680 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
3682 && ( register_operand (operands[0], SImode)
3683 || register_operand (operands[1], SImode))"
3689 [(set_attr "type" "*,*,load,store1")
3690 (set_attr "predicable" "yes")
3691 (set_attr "pool_range" "*,*,4096,*")
3692 (set_attr "neg_pool_range" "*,*,4084,*")]
3696 [(set (match_operand:SI 0 "s_register_operand" "")
3697 (match_operand:SI 1 "const_int_operand" ""))]
3699 && (!(const_ok_for_arm (INTVAL (operands[1]))
3700 || const_ok_for_arm (~INTVAL (operands[1]))))"
3701 [(clobber (const_int 0))]
3703 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3709 (define_insn "*thumb_movsi_insn"
3710 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
3711 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
3713 && ( register_operand (operands[0], SImode)
3714 || register_operand (operands[1], SImode))"
3725 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
3726 (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
3727 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
3731 [(set (match_operand:SI 0 "register_operand" "")
3732 (match_operand:SI 1 "const_int_operand" ""))]
3733 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
3734 [(set (match_dup 0) (match_dup 1))
3735 (set (match_dup 0) (neg:SI (match_dup 0)))]
3736 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
3740 [(set (match_operand:SI 0 "register_operand" "")
3741 (match_operand:SI 1 "const_int_operand" ""))]
3742 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
3743 [(set (match_dup 0) (match_dup 1))
3744 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
3747 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
3748 unsigned HOST_WIDE_INT mask = 0xff;
3751 for (i = 0; i < 25; i++)
3752 if ((val & (mask << i)) == val)
3755 /* Shouldn't happen, but we don't want to split if the shift is zero. */
3759 operands[1] = GEN_INT (val >> i);
3760 operands[2] = GEN_INT (i);
3764 ;; When generating pic, we need to load the symbol offset into a register.
3765 ;; So that the optimizer does not confuse this with a normal symbol load
3766 ;; we use an unspec. The offset will be loaded from a constant pool entry,
3767 ;; since that is the only type of relocation we can use.
3769 ;; The rather odd constraints on the following are to force reload to leave
3770 ;; the insn alone, and to force the minipool generation pass to then move
3771 ;; the GOT symbol to memory.
3773 (define_insn "pic_load_addr_arm"
3774 [(set (match_operand:SI 0 "s_register_operand" "=r")
3775 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3776 "TARGET_ARM && flag_pic"
3778 [(set_attr "type" "load")
3779 (set (attr "pool_range") (const_int 4096))
3780 (set (attr "neg_pool_range") (const_int 4084))]
3783 (define_insn "pic_load_addr_thumb"
3784 [(set (match_operand:SI 0 "s_register_operand" "=l")
3785 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3786 "TARGET_THUMB && flag_pic"
3788 [(set_attr "type" "load")
3789 (set (attr "pool_range") (const_int 1024))]
3792 ;; This variant is used for AOF assembly, since it needs to mention the
3793 ;; pic register in the rtl.
3794 (define_expand "pic_load_addr_based"
3795 [(set (match_operand:SI 0 "s_register_operand" "")
3796 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
3797 "TARGET_ARM && flag_pic"
3798 "operands[2] = pic_offset_table_rtx;"
3801 (define_insn "*pic_load_addr_based_insn"
3802 [(set (match_operand:SI 0 "s_register_operand" "=r")
3803 (unspec:SI [(match_operand 1 "" "")
3804 (match_operand 2 "s_register_operand" "r")]
3806 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
3808 #ifdef AOF_ASSEMBLER
3809 operands[1] = aof_pic_entry (operands[1]);
3811 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
3814 [(set_attr "type" "load")
3815 (set (attr "pool_range")
3816 (if_then_else (eq_attr "is_thumb" "yes")
3819 (set (attr "neg_pool_range")
3820 (if_then_else (eq_attr "is_thumb" "yes")
3825 (define_insn "pic_add_dot_plus_four"
3826 [(set (match_operand:SI 0 "register_operand" "+r")
3827 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
3828 (use (label_ref (match_operand 1 "" "")))]
3829 "TARGET_THUMB && flag_pic"
3831 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3832 CODE_LABEL_NUMBER (operands[1]));
3833 return \"add\\t%0, %|pc\";
3835 [(set_attr "length" "2")]
3838 (define_insn "pic_add_dot_plus_eight"
3839 [(set (match_operand:SI 0 "register_operand" "+r")
3840 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
3841 (use (label_ref (match_operand 1 "" "")))]
3842 "TARGET_ARM && flag_pic"
3844 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3845 CODE_LABEL_NUMBER (operands[1]));
3846 return \"add%?\\t%0, %|pc, %0\";
3848 [(set_attr "predicable" "yes")]
3851 (define_expand "builtin_setjmp_receiver"
3852 [(label_ref (match_operand 0 "" ""))]
3856 arm_finalize_pic (0);
3860 ;; If copying one reg to another we can set the condition codes according to
3861 ;; its value. Such a move is common after a return from subroutine and the
3862 ;; result is being tested against zero.
3864 (define_insn "*movsi_compare0"
3865 [(set (reg:CC CC_REGNUM)
3866 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
3868 (set (match_operand:SI 0 "s_register_operand" "=r,r")
3873 sub%?s\\t%0, %1, #0"
3874 [(set_attr "conds" "set")]
3877 ;; Subroutine to store a half word from a register into memory.
3878 ;; Operand 0 is the source register (HImode)
3879 ;; Operand 1 is the destination address in a register (SImode)
3881 ;; In both this routine and the next, we must be careful not to spill
3882 ;; a memory address of reg+large_const into a separate PLUS insn, since this
3883 ;; can generate unrecognizable rtl.
3885 (define_expand "storehi"
3886 [;; store the low byte
3887 (set (match_operand 1 "" "") (match_dup 3))
3888 ;; extract the high byte
3890 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
3891 ;; store the high byte
3892 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
3896 rtx op1 = operands[1];
3897 rtx addr = XEXP (op1, 0);
3898 enum rtx_code code = GET_CODE (addr);
3900 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
3902 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
3904 operands[4] = adjust_address (op1, QImode, 1);
3905 operands[1] = adjust_address (operands[1], QImode, 0);
3906 operands[3] = gen_lowpart (QImode, operands[0]);
3907 operands[0] = gen_lowpart (SImode, operands[0]);
3908 operands[2] = gen_reg_rtx (SImode);
3912 (define_expand "storehi_bigend"
3913 [(set (match_dup 4) (match_dup 3))
3915 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
3916 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 3))]
3920 rtx op1 = operands[1];
3921 rtx addr = XEXP (op1, 0);
3922 enum rtx_code code = GET_CODE (addr);
3924 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
3926 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
3928 operands[4] = adjust_address (op1, QImode, 1);
3929 operands[1] = adjust_address (operands[1], QImode, 0);
3930 operands[3] = gen_lowpart (QImode, operands[0]);
3931 operands[0] = gen_lowpart (SImode, operands[0]);
3932 operands[2] = gen_reg_rtx (SImode);
3936 ;; Subroutine to store a half word integer constant into memory.
3937 (define_expand "storeinthi"
3938 [(set (match_operand 0 "" "")
3939 (subreg:QI (match_operand 1 "" "") 0))
3940 (set (match_dup 3) (match_dup 2))]
3944 HOST_WIDE_INT value = INTVAL (operands[1]);
3945 rtx addr = XEXP (operands[0], 0);
3946 rtx op0 = operands[0];
3947 enum rtx_code code = GET_CODE (addr);
3949 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
3951 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
3953 operands[1] = gen_reg_rtx (SImode);
3954 if (BYTES_BIG_ENDIAN)
3956 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
3957 if ((value & 255) == ((value >> 8) & 255))
3958 operands[2] = operands[1];
3961 operands[2] = gen_reg_rtx (SImode);
3962 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
3967 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
3968 if ((value & 255) == ((value >> 8) & 255))
3969 operands[2] = operands[1];
3972 operands[2] = gen_reg_rtx (SImode);
3973 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
3977 operands[3] = adjust_address (op0, QImode, 1);
3978 operands[0] = adjust_address (operands[0], QImode, 0);
3979 operands[2] = gen_lowpart (QImode, operands[2]);
3983 (define_expand "storehi_single_op"
3984 [(set (match_operand:HI 0 "memory_operand" "")
3985 (match_operand:HI 1 "general_operand" ""))]
3986 "TARGET_ARM && arm_arch4"
3988 if (!s_register_operand (operands[1], HImode))
3989 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3993 (define_expand "movhi"
3994 [(set (match_operand:HI 0 "general_operand" "")
3995 (match_operand:HI 1 "general_operand" ""))]
4000 if (!no_new_pseudos)
4002 if (GET_CODE (operands[0]) == MEM)
4006 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4009 if (GET_CODE (operands[1]) == CONST_INT)
4010 emit_insn (gen_storeinthi (operands[0], operands[1]));
4013 if (GET_CODE (operands[1]) == MEM)
4014 operands[1] = force_reg (HImode, operands[1]);
4015 if (BYTES_BIG_ENDIAN)
4016 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4018 emit_insn (gen_storehi (operands[1], operands[0]));
4022 /* Sign extend a constant, and keep it in an SImode reg. */
4023 else if (GET_CODE (operands[1]) == CONST_INT)
4025 rtx reg = gen_reg_rtx (SImode);
4026 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4028 /* If the constant is already valid, leave it alone. */
4029 if (!const_ok_for_arm (val))
4031 /* If setting all the top bits will make the constant
4032 loadable in a single instruction, then set them.
4033 Otherwise, sign extend the number. */
4035 if (const_ok_for_arm (~(val | ~0xffff)))
4037 else if (val & 0x8000)
4041 emit_insn (gen_movsi (reg, GEN_INT (val)));
4042 operands[1] = gen_lowpart (HImode, reg);
4044 else if (arm_arch4 && !no_new_pseudos && optimize > 0
4045 && GET_CODE (operands[1]) == MEM)
4047 rtx reg = gen_reg_rtx (SImode);
4049 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4050 operands[1] = gen_lowpart (HImode, reg);
4052 else if (!arm_arch4)
4054 /* Note: We do not have to worry about TARGET_MMU_TRAPS
4055 for v4 and up architectures because LDRH instructions will
4056 be used to access the HI values, and these cannot generate
4057 unaligned word access faults in the MMU. */
4058 if (GET_CODE (operands[1]) == MEM)
4060 if (TARGET_MMU_TRAPS)
4063 rtx offset = const0_rtx;
4064 rtx reg = gen_reg_rtx (SImode);
4066 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4067 || (GET_CODE (base) == PLUS
4068 && (GET_CODE (offset = XEXP (base, 1))
4070 && ((INTVAL(offset) & 1) != 1)
4071 && GET_CODE (base = XEXP (base, 0)) == REG))
4072 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4074 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4077 new = gen_rtx_MEM (SImode,
4078 plus_constant (base, new_offset));
4079 MEM_COPY_ATTRIBUTES (new, operands[1]);
4080 emit_insn (gen_movsi (reg, new));
4081 if (((INTVAL (offset) & 2) != 0)
4082 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4084 rtx reg2 = gen_reg_rtx (SImode);
4086 emit_insn (gen_lshrsi3 (reg2, reg,
4092 emit_insn (gen_movhi_bytes (reg, operands[1]));
4094 operands[1] = gen_lowpart (HImode, reg);
4096 else if (BYTES_BIG_ENDIAN)
4099 rtx offset = const0_rtx;
4101 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4102 || (GET_CODE (base) == PLUS
4103 && (GET_CODE (offset = XEXP (base, 1))
4105 && GET_CODE (base = XEXP (base, 0)) == REG))
4106 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4108 rtx reg = gen_reg_rtx (SImode);
4111 if ((INTVAL (offset) & 2) == 2)
4113 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4114 new = gen_rtx_MEM (SImode,
4115 plus_constant (base,
4117 MEM_COPY_ATTRIBUTES (new, operands[1]);
4118 emit_insn (gen_movsi (reg, new));
4122 new = gen_rtx_MEM (SImode,
4123 XEXP (operands[1], 0));
4124 MEM_COPY_ATTRIBUTES (new, operands[1]);
4125 emit_insn (gen_rotated_loadsi (reg, new));
4128 operands[1] = gen_lowpart (HImode, reg);
4132 emit_insn (gen_movhi_bigend (operands[0],
4140 /* Handle loading a large integer during reload */
4141 else if (GET_CODE (operands[1]) == CONST_INT
4142 && !const_ok_for_arm (INTVAL (operands[1]))
4143 && !const_ok_for_arm (~INTVAL (operands[1])))
4145 /* Writing a constant to memory needs a scratch, which should
4146 be handled with SECONDARY_RELOADs. */
4147 if (GET_CODE (operands[0]) != REG)
4150 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4151 emit_insn (gen_movsi (operands[0], operands[1]));
4155 else /* TARGET_THUMB */
4157 if (!no_new_pseudos)
4159 if (GET_CODE (operands[0]) != REG)
4160 operands[1] = force_reg (HImode, operands[1]);
4162 /* ??? We shouldn't really get invalid addresses here, but this can
4163 happen if we are passed a SP (never OK for HImode/QImode) or
4164 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4165 HImode/QImode) relative address. */
4166 /* ??? This should perhaps be fixed elsewhere, for instance, in
4167 fixup_stack_1, by checking for other kinds of invalid addresses,
4168 e.g. a bare reference to a virtual register. This may confuse the
4169 alpha though, which must handle this case differently. */
4170 if (GET_CODE (operands[0]) == MEM
4171 && !memory_address_p (GET_MODE (operands[0]),
4172 XEXP (operands[0], 0)))
4174 = replace_equiv_address (operands[0],
4175 copy_to_reg (XEXP (operands[0], 0)));
4177 if (GET_CODE (operands[1]) == MEM
4178 && !memory_address_p (GET_MODE (operands[1]),
4179 XEXP (operands[1], 0)))
4181 = replace_equiv_address (operands[1],
4182 copy_to_reg (XEXP (operands[1], 0)));
4184 /* Handle loading a large integer during reload */
4185 else if (GET_CODE (operands[1]) == CONST_INT
4186 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4188 /* Writing a constant to memory needs a scratch, which should
4189 be handled with SECONDARY_RELOADs. */
4190 if (GET_CODE (operands[0]) != REG)
4193 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4194 emit_insn (gen_movsi (operands[0], operands[1]));
4201 (define_insn "*thumb_movhi_insn"
4202 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4203 (match_operand:HI 1 "general_operand" "l,mn,l,*h,*r,I"))]
4205 && ( register_operand (operands[0], HImode)
4206 || register_operand (operands[1], HImode))"
4208 switch (which_alternative)
4210 case 0: return \"add %0, %1, #0\";
4211 case 2: return \"strh %1, %0\";
4212 case 3: return \"mov %0, %1\";
4213 case 4: return \"mov %0, %1\";
4214 case 5: return \"mov %0, %1\";
4217 /* The stack pointer can end up being taken as an index register.
4218 Catch this case here and deal with it. */
4219 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4220 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4221 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4224 ops[0] = operands[0];
4225 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4227 output_asm_insn (\"mov %0, %1\", ops);
4229 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4232 return \"ldrh %0, %1\";
4234 [(set_attr "length" "2,4,2,2,2,2")
4235 (set_attr "type" "*,load,store1,*,*,*")
4236 (set_attr "pool_range" "*,64,*,*,*,*")]
4240 (define_insn "rotated_loadsi"
4241 [(set (match_operand:SI 0 "s_register_operand" "=r")
4242 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4244 "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4249 ops[0] = operands[0];
4250 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4251 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4254 [(set_attr "type" "load")
4255 (set_attr "predicable" "yes")]
4258 (define_expand "movhi_bytes"
4259 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4261 (zero_extend:SI (match_dup 6)))
4262 (set (match_operand:SI 0 "" "")
4263 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4268 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4270 mem1 = gen_rtx_MEM (QImode, addr);
4271 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4272 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4273 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4274 operands[0] = gen_lowpart (SImode, operands[0]);
4276 operands[2] = gen_reg_rtx (SImode);
4277 operands[3] = gen_reg_rtx (SImode);
4280 if (BYTES_BIG_ENDIAN)
4282 operands[4] = operands[2];
4283 operands[5] = operands[3];
4287 operands[4] = operands[3];
4288 operands[5] = operands[2];
4293 (define_expand "movhi_bigend"
4295 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4298 (ashiftrt:SI (match_dup 2) (const_int 16)))
4299 (set (match_operand:HI 0 "s_register_operand" "")
4300 (subreg:HI (match_dup 3) 0))]
4303 operands[2] = gen_reg_rtx (SImode);
4304 operands[3] = gen_reg_rtx (SImode);
4308 ;; Pattern to recognize insn generated default case above
4309 (define_insn "*movhi_insn_arch4"
4310 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4311 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4314 && (GET_CODE (operands[1]) != CONST_INT
4315 || const_ok_for_arm (INTVAL (operands[1]))
4316 || const_ok_for_arm (~INTVAL (operands[1])))"
4318 mov%?\\t%0, %1\\t%@ movhi
4319 mvn%?\\t%0, #%B1\\t%@ movhi
4320 str%?h\\t%1, %0\\t%@ movhi
4321 ldr%?h\\t%0, %1\\t%@ movhi"
4322 [(set_attr "type" "*,*,store1,load")
4323 (set_attr "predicable" "yes")
4324 (set_attr "pool_range" "*,*,*,256")
4325 (set_attr "neg_pool_range" "*,*,*,244")]
4328 (define_insn "*movhi_insn_littleend"
4329 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4330 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4333 && !BYTES_BIG_ENDIAN
4334 && !TARGET_MMU_TRAPS
4335 && (GET_CODE (operands[1]) != CONST_INT
4336 || const_ok_for_arm (INTVAL (operands[1]))
4337 || const_ok_for_arm (~INTVAL (operands[1])))"
4339 mov%?\\t%0, %1\\t%@ movhi
4340 mvn%?\\t%0, #%B1\\t%@ movhi
4341 ldr%?\\t%0, %1\\t%@ movhi"
4342 [(set_attr "type" "*,*,load")
4343 (set_attr "predicable" "yes")
4344 (set_attr "pool_range" "4096")
4345 (set_attr "neg_pool_range" "4084")]
4348 (define_insn "*movhi_insn_bigend"
4349 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4350 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4354 && !TARGET_MMU_TRAPS
4355 && (GET_CODE (operands[1]) != CONST_INT
4356 || const_ok_for_arm (INTVAL (operands[1]))
4357 || const_ok_for_arm (~INTVAL (operands[1])))"
4359 mov%?\\t%0, %1\\t%@ movhi
4360 mvn%?\\t%0, #%B1\\t%@ movhi
4361 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4362 [(set_attr "type" "*,*,load")
4363 (set_attr "predicable" "yes")
4364 (set_attr "length" "4,4,8")
4365 (set_attr "pool_range" "*,*,4092")
4366 (set_attr "neg_pool_range" "*,*,4084")]
4369 (define_insn "*loadhi_si_bigend"
4370 [(set (match_operand:SI 0 "s_register_operand" "=r")
4371 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
4375 && !TARGET_MMU_TRAPS"
4376 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4377 [(set_attr "type" "load")
4378 (set_attr "predicable" "yes")
4379 (set_attr "pool_range" "4096")
4380 (set_attr "neg_pool_range" "4084")]
4383 (define_insn "*movhi_bytes"
4384 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4385 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4386 "TARGET_ARM && TARGET_MMU_TRAPS"
4388 mov%?\\t%0, %1\\t%@ movhi
4389 mvn%?\\t%0, #%B1\\t%@ movhi"
4390 [(set_attr "predicable" "yes")]
4393 (define_insn "thumb_movhi_clobber"
4394 [(set (match_operand:HI 0 "memory_operand" "=m")
4395 (match_operand:HI 1 "register_operand" "l"))
4396 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4402 ;; We use a DImode scratch because we may occasionally need an additional
4403 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4404 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4405 (define_expand "reload_outhi"
4406 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4407 (match_operand:HI 1 "s_register_operand" "r")
4408 (match_operand:DI 2 "s_register_operand" "=&l")])]
4411 arm_reload_out_hi (operands);
4413 thumb_reload_out_hi (operands);
4418 (define_expand "reload_inhi"
4419 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4420 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4421 (match_operand:DI 2 "s_register_operand" "=&r")])]
4422 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4425 arm_reload_in_hi (operands);
4427 thumb_reload_out_hi (operands);
4431 (define_expand "movqi"
4432 [(set (match_operand:QI 0 "general_operand" "")
4433 (match_operand:QI 1 "general_operand" ""))]
4438 /* Everything except mem = const or mem = mem can be done easily */
4440 if (!no_new_pseudos)
4442 if (GET_CODE (operands[1]) == CONST_INT)
4444 rtx reg = gen_reg_rtx (SImode);
4446 emit_insn (gen_movsi (reg, operands[1]));
4447 operands[1] = gen_lowpart (QImode, reg);
4449 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4451 rtx reg = gen_reg_rtx (SImode);
4453 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4454 operands[1] = gen_lowpart (QImode, reg);
4456 if (GET_CODE (operands[0]) == MEM)
4457 operands[1] = force_reg (QImode, operands[1]);
4460 else /* TARGET_THUMB */
4462 if (!no_new_pseudos)
4464 if (GET_CODE (operands[0]) != REG)
4465 operands[1] = force_reg (QImode, operands[1]);
4467 /* ??? We shouldn't really get invalid addresses here, but this can
4468 happen if we are passed a SP (never OK for HImode/QImode) or
4469 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4470 HImode/QImode) relative address. */
4471 /* ??? This should perhaps be fixed elsewhere, for instance, in
4472 fixup_stack_1, by checking for other kinds of invalid addresses,
4473 e.g. a bare reference to a virtual register. This may confuse the
4474 alpha though, which must handle this case differently. */
4475 if (GET_CODE (operands[0]) == MEM
4476 && !memory_address_p (GET_MODE (operands[0]),
4477 XEXP (operands[0], 0)))
4479 = replace_equiv_address (operands[0],
4480 copy_to_reg (XEXP (operands[0], 0)));
4481 if (GET_CODE (operands[1]) == MEM
4482 && !memory_address_p (GET_MODE (operands[1]),
4483 XEXP (operands[1], 0)))
4485 = replace_equiv_address (operands[1],
4486 copy_to_reg (XEXP (operands[1], 0)));
4488 /* Handle loading a large integer during reload */
4489 else if (GET_CODE (operands[1]) == CONST_INT
4490 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4492 /* Writing a constant to memory needs a scratch, which should
4493 be handled with SECONDARY_RELOADs. */
4494 if (GET_CODE (operands[0]) != REG)
4497 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4498 emit_insn (gen_movsi (operands[0], operands[1]));
4506 (define_insn "*arm_movqi_insn"
4507 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4508 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4510 && ( register_operand (operands[0], QImode)
4511 || register_operand (operands[1], QImode))"
4517 [(set_attr "type" "*,*,load,store1")
4518 (set_attr "predicable" "yes")]
4521 (define_insn "*thumb_movqi_insn"
4522 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4523 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
4525 && ( register_operand (operands[0], QImode)
4526 || register_operand (operands[1], QImode))"
4534 [(set_attr "length" "2")
4535 (set_attr "type" "*,load,store1,*,*,*")
4536 (set_attr "pool_range" "*,32,*,*,*,*")]
4539 (define_expand "movsf"
4540 [(set (match_operand:SF 0 "general_operand" "")
4541 (match_operand:SF 1 "general_operand" ""))]
4546 if (GET_CODE (operands[0]) == MEM)
4547 operands[1] = force_reg (SFmode, operands[1]);
4549 else /* TARGET_THUMB */
4551 if (!no_new_pseudos)
4553 if (GET_CODE (operands[0]) != REG)
4554 operands[1] = force_reg (SFmode, operands[1]);
4561 [(set (match_operand:SF 0 "nonimmediate_operand" "")
4562 (match_operand:SF 1 "immediate_operand" ""))]
4564 && !TARGET_HARD_FLOAT
4566 && GET_CODE (operands[1]) == CONST_DOUBLE"
4567 [(set (match_dup 2) (match_dup 3))]
4569 operands[2] = gen_lowpart (SImode, operands[0]);
4570 operands[3] = gen_lowpart (SImode, operands[1]);
4571 if (operands[2] == 0 || operands[3] == 0)
4576 (define_insn "*arm_movsf_soft_insn"
4577 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4578 (match_operand:SF 1 "general_operand" "r,mE,r"))]
4581 && TARGET_SOFT_FLOAT
4582 && (GET_CODE (operands[0]) != MEM
4583 || register_operand (operands[1], SFmode))"
4586 ldr%?\\t%0, %1\\t%@ float
4587 str%?\\t%1, %0\\t%@ float"
4588 [(set_attr "length" "4,4,4")
4589 (set_attr "predicable" "yes")
4590 (set_attr "type" "*,load,store1")
4591 (set_attr "pool_range" "*,4096,*")
4592 (set_attr "neg_pool_range" "*,4084,*")]
4595 ;;; ??? This should have alternatives for constants.
4596 (define_insn "*thumb_movsf_insn"
4597 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4598 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
4600 && ( register_operand (operands[0], SFmode)
4601 || register_operand (operands[1], SFmode))"
4610 [(set_attr "length" "2")
4611 (set_attr "type" "*,load,store1,load,store1,*,*")
4612 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
4615 (define_expand "movdf"
4616 [(set (match_operand:DF 0 "general_operand" "")
4617 (match_operand:DF 1 "general_operand" ""))]
4622 if (GET_CODE (operands[0]) == MEM)
4623 operands[1] = force_reg (DFmode, operands[1]);
4625 else /* TARGET_THUMB */
4627 if (!no_new_pseudos)
4629 if (GET_CODE (operands[0]) != REG)
4630 operands[1] = force_reg (DFmode, operands[1]);
4636 ;; Reloading a df mode value stored in integer regs to memory can require a
4638 (define_expand "reload_outdf"
4639 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
4640 (match_operand:DF 1 "s_register_operand" "r")
4641 (match_operand:SI 2 "s_register_operand" "=&r")]
4645 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
4648 operands[2] = XEXP (operands[0], 0);
4649 else if (code == POST_INC || code == PRE_DEC)
4651 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
4652 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
4653 emit_insn (gen_movdi (operands[0], operands[1]));
4656 else if (code == PRE_INC)
4658 rtx reg = XEXP (XEXP (operands[0], 0), 0);
4660 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
4663 else if (code == POST_DEC)
4664 operands[2] = XEXP (XEXP (operands[0], 0), 0);
4666 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
4667 XEXP (XEXP (operands[0], 0), 1)));
4669 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
4672 if (code == POST_DEC)
4673 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
4679 (define_insn "*movdf_soft_insn"
4680 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
4681 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
4682 "TARGET_ARM && TARGET_SOFT_FLOAT
4685 "* return output_move_double (operands);"
4686 [(set_attr "length" "8,8,8")
4687 (set_attr "type" "*,load,store2")
4688 (set_attr "pool_range" "1020")
4689 (set_attr "neg_pool_range" "1008")]
4692 ;;; ??? This should have alternatives for constants.
4693 ;;; ??? This was originally identical to the movdi_insn pattern.
4694 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
4695 ;;; thumb_reorg with a memory reference.
4696 (define_insn "*thumb_movdf_insn"
4697 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
4698 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
4700 && ( register_operand (operands[0], DFmode)
4701 || register_operand (operands[1], DFmode))"
4703 switch (which_alternative)
4707 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4708 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4709 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4711 return \"ldmia\\t%1, {%0, %H0}\";
4713 return \"stmia\\t%0, {%1, %H1}\";
4715 return thumb_load_double_from_address (operands);
4717 operands[2] = gen_rtx (MEM, SImode,
4718 plus_constant (XEXP (operands[0], 0), 4));
4719 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4722 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4723 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4724 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4727 [(set_attr "length" "4,2,2,6,4,4")
4728 (set_attr "type" "*,load,store2,load,store2,*")
4729 (set_attr "pool_range" "*,*,*,1020,*,*")]
4733 ;; load- and store-multiple insns
4734 ;; The arm can load/store any set of registers, provided that they are in
4735 ;; ascending order; but that is beyond GCC so stick with what it knows.
4737 (define_expand "load_multiple"
4738 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
4739 (match_operand:SI 1 "" ""))
4740 (use (match_operand:SI 2 "" ""))])]
4743 /* Support only fixed point registers. */
4744 if (GET_CODE (operands[2]) != CONST_INT
4745 || INTVAL (operands[2]) > 14
4746 || INTVAL (operands[2]) < 2
4747 || GET_CODE (operands[1]) != MEM
4748 || GET_CODE (operands[0]) != REG
4749 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
4750 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
4754 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
4755 force_reg (SImode, XEXP (operands[1], 0)),
4756 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
4757 MEM_IN_STRUCT_P(operands[1]),
4758 MEM_SCALAR_P (operands[1]));
4762 ;; Load multiple with write-back
4764 (define_insn "*ldmsi_postinc4"
4765 [(match_parallel 0 "load_multiple_operation"
4766 [(set (match_operand:SI 1 "s_register_operand" "=r")
4767 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4769 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4770 (mem:SI (match_dup 2)))
4771 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4772 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
4773 (set (match_operand:SI 5 "arm_hard_register_operand" "")
4774 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
4775 (set (match_operand:SI 6 "arm_hard_register_operand" "")
4776 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
4777 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
4778 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
4779 [(set_attr "type" "load")
4780 (set_attr "predicable" "yes")]
4783 (define_insn "*ldmsi_postinc3"
4784 [(match_parallel 0 "load_multiple_operation"
4785 [(set (match_operand:SI 1 "s_register_operand" "=r")
4786 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4788 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4789 (mem:SI (match_dup 2)))
4790 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4791 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
4792 (set (match_operand:SI 5 "arm_hard_register_operand" "")
4793 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
4794 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4795 "ldm%?ia\\t%1!, {%3, %4, %5}"
4796 [(set_attr "type" "load")
4797 (set_attr "predicable" "yes")]
4800 (define_insn "*ldmsi_postinc2"
4801 [(match_parallel 0 "load_multiple_operation"
4802 [(set (match_operand:SI 1 "s_register_operand" "=r")
4803 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4805 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4806 (mem:SI (match_dup 2)))
4807 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4808 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
4809 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4810 "ldm%?ia\\t%1!, {%3, %4}"
4811 [(set_attr "type" "load")
4812 (set_attr "predicable" "yes")]
4815 ;; Ordinary load multiple
4817 (define_insn "*ldmsi4"
4818 [(match_parallel 0 "load_multiple_operation"
4819 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4820 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4821 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4822 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
4823 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4824 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
4825 (set (match_operand:SI 5 "arm_hard_register_operand" "")
4826 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
4827 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4828 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
4829 [(set_attr "type" "load")
4830 (set_attr "predicable" "yes")]
4833 (define_insn "*ldmsi3"
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 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4842 "ldm%?ia\\t%1, {%2, %3, %4}"
4843 [(set_attr "type" "load")
4844 (set_attr "predicable" "yes")]
4847 (define_insn "*ldmsi2"
4848 [(match_parallel 0 "load_multiple_operation"
4849 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4850 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4851 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4852 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
4853 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
4854 "ldm%?ia\\t%1, {%2, %3}"
4855 [(set_attr "type" "load")
4856 (set_attr "predicable" "yes")]
4859 (define_expand "store_multiple"
4860 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
4861 (match_operand:SI 1 "" ""))
4862 (use (match_operand:SI 2 "" ""))])]
4865 /* Support only fixed point registers */
4866 if (GET_CODE (operands[2]) != CONST_INT
4867 || INTVAL (operands[2]) > 14
4868 || INTVAL (operands[2]) < 2
4869 || GET_CODE (operands[1]) != REG
4870 || GET_CODE (operands[0]) != MEM
4871 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
4872 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
4876 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
4877 force_reg (SImode, XEXP (operands[0], 0)),
4878 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
4879 MEM_IN_STRUCT_P(operands[0]),
4880 MEM_SCALAR_P (operands[0]));
4884 ;; Store multiple with write-back
4886 (define_insn "*stmsi_postinc4"
4887 [(match_parallel 0 "store_multiple_operation"
4888 [(set (match_operand:SI 1 "s_register_operand" "=r")
4889 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4891 (set (mem:SI (match_dup 2))
4892 (match_operand:SI 3 "arm_hard_register_operand" ""))
4893 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
4894 (match_operand:SI 4 "arm_hard_register_operand" ""))
4895 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
4896 (match_operand:SI 5 "arm_hard_register_operand" ""))
4897 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
4898 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
4899 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
4900 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
4901 [(set_attr "predicable" "yes")
4902 (set_attr "type" "store4")]
4905 (define_insn "*stmsi_postinc3"
4906 [(match_parallel 0 "store_multiple_operation"
4907 [(set (match_operand:SI 1 "s_register_operand" "=r")
4908 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4910 (set (mem:SI (match_dup 2))
4911 (match_operand:SI 3 "arm_hard_register_operand" ""))
4912 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
4913 (match_operand:SI 4 "arm_hard_register_operand" ""))
4914 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
4915 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
4916 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4917 "stm%?ia\\t%1!, {%3, %4, %5}"
4918 [(set_attr "predicable" "yes")
4919 (set_attr "type" "store3")]
4922 (define_insn "*stmsi_postinc2"
4923 [(match_parallel 0 "store_multiple_operation"
4924 [(set (match_operand:SI 1 "s_register_operand" "=r")
4925 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4927 (set (mem:SI (match_dup 2))
4928 (match_operand:SI 3 "arm_hard_register_operand" ""))
4929 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
4930 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
4931 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4932 "stm%?ia\\t%1!, {%3, %4}"
4933 [(set_attr "predicable" "yes")
4934 (set_attr "type" "store2")]
4937 ;; Ordinary store multiple
4939 (define_insn "*stmsi4"
4940 [(match_parallel 0 "store_multiple_operation"
4941 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
4942 (match_operand:SI 2 "arm_hard_register_operand" ""))
4943 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
4944 (match_operand:SI 3 "arm_hard_register_operand" ""))
4945 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
4946 (match_operand:SI 4 "arm_hard_register_operand" ""))
4947 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
4948 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
4949 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4950 "stm%?ia\\t%1, {%2, %3, %4, %5}"
4951 [(set_attr "predicable" "yes")
4952 (set_attr "type" "store4")]
4955 (define_insn "*stmsi3"
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 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4964 "stm%?ia\\t%1, {%2, %3, %4}"
4965 [(set_attr "predicable" "yes")
4966 (set_attr "type" "store3")]
4969 (define_insn "*stmsi2"
4970 [(match_parallel 0 "store_multiple_operation"
4971 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
4972 (match_operand:SI 2 "arm_hard_register_operand" ""))
4973 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
4974 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
4975 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
4976 "stm%?ia\\t%1, {%2, %3}"
4977 [(set_attr "predicable" "yes")
4978 (set_attr "type" "store2")]
4981 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
4982 ;; We could let this apply for blocks of less than this, but it clobbers so
4983 ;; many registers that there is then probably a better way.
4985 (define_expand "movstrqi"
4986 [(match_operand:BLK 0 "general_operand" "")
4987 (match_operand:BLK 1 "general_operand" "")
4988 (match_operand:SI 2 "const_int_operand" "")
4989 (match_operand:SI 3 "const_int_operand" "")]
4994 if (arm_gen_movstrqi (operands))
4998 else /* TARGET_THUMB */
5000 if ( INTVAL (operands[3]) != 4
5001 || INTVAL (operands[2]) > 48)
5004 thumb_expand_movstrqi (operands);
5010 ;; Thumb block-move insns
5012 (define_insn "movmem12b"
5013 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5014 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5015 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5016 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5017 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5018 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5019 (set (match_operand:SI 0 "register_operand" "=l")
5020 (plus:SI (match_dup 2) (const_int 12)))
5021 (set (match_operand:SI 1 "register_operand" "=l")
5022 (plus:SI (match_dup 3) (const_int 12)))
5023 (clobber (match_scratch:SI 4 "=&l"))
5024 (clobber (match_scratch:SI 5 "=&l"))
5025 (clobber (match_scratch:SI 6 "=&l"))]
5027 "* return thumb_output_move_mem_multiple (3, operands);"
5028 [(set_attr "length" "4")
5029 ; This isn't entirely accurate... It loads as well, but in terms of
5030 ; scheduling the following insn it is better to consider it as a store
5031 (set_attr "type" "store3")]
5034 (define_insn "movmem8b"
5035 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5036 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5037 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5038 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5039 (set (match_operand:SI 0 "register_operand" "=l")
5040 (plus:SI (match_dup 2) (const_int 8)))
5041 (set (match_operand:SI 1 "register_operand" "=l")
5042 (plus:SI (match_dup 3) (const_int 8)))
5043 (clobber (match_scratch:SI 4 "=&l"))
5044 (clobber (match_scratch:SI 5 "=&l"))]
5046 "* return thumb_output_move_mem_multiple (2, operands);"
5047 [(set_attr "length" "4")
5048 ; This isn't entirely accurate... It loads as well, but in terms of
5049 ; scheduling the following insn it is better to consider it as a store
5050 (set_attr "type" "store2")]
5055 ;; Compare & branch insns
5056 ;; The range calcualations are based as follows:
5057 ;; For forward branches, the address calculation returns the address of
5058 ;; the next instruction. This is 2 beyond the branch instruction.
5059 ;; For backward branches, the address calculation returns the address of
5060 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5061 ;; instruction for the shortest sequence, and 4 before the branch instruction
5062 ;; if we have to jump around an unconditional branch.
5063 ;; To the basic branch range the PC offset must be added (this is +4).
5064 ;; So for forward branches we have
5065 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5066 ;; And for backward branches we have
5067 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5069 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5070 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5072 (define_insn "cbranchsi4"
5075 (match_operator 0 "arm_comparison_operator"
5076 [(match_operand:SI 1 "register_operand" "l,r")
5077 (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5078 (label_ref (match_operand 3 "" ""))
5082 output_asm_insn (\"cmp\\t%1, %2\", operands);
5083 switch (get_attr_length (insn))
5085 case 4: return \"b%d0\\t%l3\";
5086 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5087 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5090 [(set (attr "far_jump")
5092 (eq_attr "length" "8")
5093 (const_string "yes")
5094 (const_string "no")))
5095 (set (attr "length")
5097 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5098 (le (minus (match_dup 3) (pc)) (const_int 256)))
5101 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5102 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5107 (define_insn "*negated_cbranchsi4"
5110 (match_operator 0 "arm_comparison_operator"
5111 [(match_operand:SI 1 "register_operand" "l")
5112 (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5113 (label_ref (match_operand 3 "" ""))
5117 output_asm_insn (\"cmn\\t%1, %2\", operands);
5118 switch (get_attr_length (insn))
5120 case 4: return \"b%d0\\t%l3\";
5121 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5122 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5125 [(set (attr "far_jump")
5127 (eq_attr "length" "8")
5128 (const_string "yes")
5129 (const_string "no")))
5130 (set (attr "length")
5132 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5133 (le (minus (match_dup 3) (pc)) (const_int 256)))
5136 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5137 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5143 ;; Comparison and test insns
5145 (define_expand "cmpsi"
5146 [(match_operand:SI 0 "s_register_operand" "")
5147 (match_operand:SI 1 "arm_add_operand" "")]
5150 arm_compare_op0 = operands[0];
5151 arm_compare_op1 = operands[1];
5156 (define_expand "cmpsf"
5157 [(match_operand:SF 0 "s_register_operand" "")
5158 (match_operand:SF 1 "fpa_rhs_operand" "")]
5159 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5161 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
5162 operands[1] = force_reg (SFmode, operands[1]);
5164 arm_compare_op0 = operands[0];
5165 arm_compare_op1 = operands[1];
5170 (define_expand "cmpdf"
5171 [(match_operand:DF 0 "s_register_operand" "")
5172 (match_operand:DF 1 "fpa_rhs_operand" "")]
5173 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5175 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
5176 operands[1] = force_reg (DFmode, operands[1]);
5178 arm_compare_op0 = operands[0];
5179 arm_compare_op1 = operands[1];
5184 (define_insn "*arm_cmpsi_insn"
5185 [(set (reg:CC CC_REGNUM)
5186 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5187 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
5192 [(set_attr "conds" "set")]
5195 (define_insn "*cmpsi_shiftsi"
5196 [(set (reg:CC CC_REGNUM)
5197 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5198 (match_operator:SI 3 "shift_operator"
5199 [(match_operand:SI 1 "s_register_operand" "r")
5200 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
5203 [(set_attr "conds" "set")
5204 (set_attr "shift" "1")
5208 (define_insn "*cmpsi_shiftsi_swp"
5209 [(set (reg:CC_SWP CC_REGNUM)
5210 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5211 [(match_operand:SI 1 "s_register_operand" "r")
5212 (match_operand:SI 2 "reg_or_int_operand" "rM")])
5213 (match_operand:SI 0 "s_register_operand" "r")))]
5216 [(set_attr "conds" "set")
5217 (set_attr "shift" "1")
5221 (define_insn "*cmpsi_neg_shiftsi"
5222 [(set (reg:CC CC_REGNUM)
5223 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5224 (neg:SI (match_operator:SI 3 "shift_operator"
5225 [(match_operand:SI 1 "s_register_operand" "r")
5226 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5229 [(set_attr "conds" "set")
5230 (set_attr "shift" "1")
5234 ;; Cirrus SF compare instruction
5235 (define_insn "*cirrus_cmpsf"
5236 [(set (reg:CCFP CC_REGNUM)
5237 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
5238 (match_operand:SF 1 "cirrus_fp_register" "v")))]
5239 "TARGET_ARM && TARGET_CIRRUS"
5240 "cfcmps%?\\tr15, %V0, %V1"
5241 [(set_attr "type" "mav_farith")
5242 (set_attr "cirrus" "compare")]
5245 ;; Cirrus DF compare instruction
5246 (define_insn "*cirrus_cmpdf"
5247 [(set (reg:CCFP CC_REGNUM)
5248 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
5249 (match_operand:DF 1 "cirrus_fp_register" "v")))]
5250 "TARGET_ARM && TARGET_CIRRUS"
5251 "cfcmpd%?\\tr15, %V0, %V1"
5252 [(set_attr "type" "mav_farith")
5253 (set_attr "cirrus" "compare")]
5256 ;; Cirrus DI compare instruction
5257 (define_expand "cmpdi"
5258 [(match_operand:DI 0 "cirrus_fp_register" "")
5259 (match_operand:DI 1 "cirrus_fp_register" "")]
5260 "TARGET_ARM && TARGET_CIRRUS"
5262 arm_compare_op0 = operands[0];
5263 arm_compare_op1 = operands[1];
5267 (define_insn "*cirrus_cmpdi"
5268 [(set (reg:CC CC_REGNUM)
5269 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
5270 (match_operand:DI 1 "cirrus_fp_register" "v")))]
5271 "TARGET_ARM && TARGET_CIRRUS"
5272 "cfcmp64%?\\tr15, %V0, %V1"
5273 [(set_attr "type" "mav_farith")
5274 (set_attr "cirrus" "compare")]
5277 ; This insn allows redundant compares to be removed by cse, nothing should
5278 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5279 ; is deleted later on. The match_dup will match the mode here, so that
5280 ; mode changes of the condition codes aren't lost by this even though we don't
5281 ; specify what they are.
5283 (define_insn "*deleted_compare"
5284 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5286 "\\t%@ deleted compare"
5287 [(set_attr "conds" "set")
5288 (set_attr "length" "0")]
5292 ;; Conditional branch insns
5294 (define_expand "beq"
5296 (if_then_else (eq (match_dup 1) (const_int 0))
5297 (label_ref (match_operand 0 "" ""))
5300 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5303 (define_expand "bne"
5305 (if_then_else (ne (match_dup 1) (const_int 0))
5306 (label_ref (match_operand 0 "" ""))
5309 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5312 (define_expand "bgt"
5314 (if_then_else (gt (match_dup 1) (const_int 0))
5315 (label_ref (match_operand 0 "" ""))
5318 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5321 (define_expand "ble"
5323 (if_then_else (le (match_dup 1) (const_int 0))
5324 (label_ref (match_operand 0 "" ""))
5327 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5330 (define_expand "bge"
5332 (if_then_else (ge (match_dup 1) (const_int 0))
5333 (label_ref (match_operand 0 "" ""))
5336 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5339 (define_expand "blt"
5341 (if_then_else (lt (match_dup 1) (const_int 0))
5342 (label_ref (match_operand 0 "" ""))
5345 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5348 (define_expand "bgtu"
5350 (if_then_else (gtu (match_dup 1) (const_int 0))
5351 (label_ref (match_operand 0 "" ""))
5354 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5357 (define_expand "bleu"
5359 (if_then_else (leu (match_dup 1) (const_int 0))
5360 (label_ref (match_operand 0 "" ""))
5363 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5366 (define_expand "bgeu"
5368 (if_then_else (geu (match_dup 1) (const_int 0))
5369 (label_ref (match_operand 0 "" ""))
5372 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5375 (define_expand "bltu"
5377 (if_then_else (ltu (match_dup 1) (const_int 0))
5378 (label_ref (match_operand 0 "" ""))
5381 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5384 (define_expand "bunordered"
5386 (if_then_else (unordered (match_dup 1) (const_int 0))
5387 (label_ref (match_operand 0 "" ""))
5389 "TARGET_ARM && TARGET_HARD_FLOAT"
5390 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5394 (define_expand "bordered"
5396 (if_then_else (ordered (match_dup 1) (const_int 0))
5397 (label_ref (match_operand 0 "" ""))
5399 "TARGET_ARM && TARGET_HARD_FLOAT"
5400 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5404 (define_expand "bungt"
5406 (if_then_else (ungt (match_dup 1) (const_int 0))
5407 (label_ref (match_operand 0 "" ""))
5409 "TARGET_ARM && TARGET_HARD_FLOAT"
5410 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5413 (define_expand "bunlt"
5415 (if_then_else (unlt (match_dup 1) (const_int 0))
5416 (label_ref (match_operand 0 "" ""))
5418 "TARGET_ARM && TARGET_HARD_FLOAT"
5419 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5422 (define_expand "bunge"
5424 (if_then_else (unge (match_dup 1) (const_int 0))
5425 (label_ref (match_operand 0 "" ""))
5427 "TARGET_ARM && TARGET_HARD_FLOAT"
5428 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5431 (define_expand "bunle"
5433 (if_then_else (unle (match_dup 1) (const_int 0))
5434 (label_ref (match_operand 0 "" ""))
5436 "TARGET_ARM && TARGET_HARD_FLOAT"
5437 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5440 ;; The following two patterns need two branch instructions, since there is
5441 ;; no single instruction that will handle all cases.
5442 (define_expand "buneq"
5444 (if_then_else (uneq (match_dup 1) (const_int 0))
5445 (label_ref (match_operand 0 "" ""))
5447 "TARGET_ARM && TARGET_HARD_FLOAT"
5448 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
5451 (define_expand "bltgt"
5453 (if_then_else (ltgt (match_dup 1) (const_int 0))
5454 (label_ref (match_operand 0 "" ""))
5456 "TARGET_ARM && TARGET_HARD_FLOAT"
5457 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
5461 ;; Patterns to match conditional branch insns.
5464 ; Special pattern to match UNEQ.
5465 (define_insn "*arm_buneq"
5467 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5468 (label_ref (match_operand 0 "" ""))
5470 "TARGET_ARM && TARGET_HARD_FLOAT"
5472 if (arm_ccfsm_state != 0)
5475 return \"bvs\\t%l0\;beq\\t%l0\";
5477 [(set_attr "conds" "jump_clob")
5478 (set_attr "length" "8")]
5481 ; Special pattern to match LTGT.
5482 (define_insn "*arm_bltgt"
5484 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5485 (label_ref (match_operand 0 "" ""))
5487 "TARGET_ARM && TARGET_HARD_FLOAT"
5489 if (arm_ccfsm_state != 0)
5492 return \"bmi\\t%l0\;bgt\\t%l0\";
5494 [(set_attr "conds" "jump_clob")
5495 (set_attr "length" "8")]
5498 (define_insn "*arm_cond_branch"
5500 (if_then_else (match_operator 1 "arm_comparison_operator"
5501 [(match_operand 2 "cc_register" "") (const_int 0)])
5502 (label_ref (match_operand 0 "" ""))
5506 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5508 arm_ccfsm_state += 2;
5511 return \"b%d1\\t%l0\";
5513 [(set_attr "conds" "use")]
5516 ; Special pattern to match reversed UNEQ.
5517 (define_insn "*arm_buneq_reversed"
5519 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5521 (label_ref (match_operand 0 "" ""))))]
5522 "TARGET_ARM && TARGET_HARD_FLOAT"
5524 if (arm_ccfsm_state != 0)
5527 return \"bmi\\t%l0\;bgt\\t%l0\";
5529 [(set_attr "conds" "jump_clob")
5530 (set_attr "length" "8")]
5533 ; Special pattern to match reversed LTGT.
5534 (define_insn "*arm_bltgt_reversed"
5536 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5538 (label_ref (match_operand 0 "" ""))))]
5539 "TARGET_ARM && TARGET_HARD_FLOAT"
5541 if (arm_ccfsm_state != 0)
5544 return \"bvs\\t%l0\;beq\\t%l0\";
5546 [(set_attr "conds" "jump_clob")
5547 (set_attr "length" "8")]
5550 (define_insn "*arm_cond_branch_reversed"
5552 (if_then_else (match_operator 1 "arm_comparison_operator"
5553 [(match_operand 2 "cc_register" "") (const_int 0)])
5555 (label_ref (match_operand 0 "" ""))))]
5558 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5560 arm_ccfsm_state += 2;
5563 return \"b%D1\\t%l0\";
5565 [(set_attr "conds" "use")]
5572 (define_expand "seq"
5573 [(set (match_operand:SI 0 "s_register_operand" "")
5574 (eq:SI (match_dup 1) (const_int 0)))]
5576 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5579 (define_expand "sne"
5580 [(set (match_operand:SI 0 "s_register_operand" "")
5581 (ne:SI (match_dup 1) (const_int 0)))]
5583 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5586 (define_expand "sgt"
5587 [(set (match_operand:SI 0 "s_register_operand" "")
5588 (gt:SI (match_dup 1) (const_int 0)))]
5590 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5593 (define_expand "sle"
5594 [(set (match_operand:SI 0 "s_register_operand" "")
5595 (le:SI (match_dup 1) (const_int 0)))]
5597 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5600 (define_expand "sge"
5601 [(set (match_operand:SI 0 "s_register_operand" "")
5602 (ge:SI (match_dup 1) (const_int 0)))]
5604 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5607 (define_expand "slt"
5608 [(set (match_operand:SI 0 "s_register_operand" "")
5609 (lt:SI (match_dup 1) (const_int 0)))]
5611 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5614 (define_expand "sgtu"
5615 [(set (match_operand:SI 0 "s_register_operand" "")
5616 (gtu:SI (match_dup 1) (const_int 0)))]
5618 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5621 (define_expand "sleu"
5622 [(set (match_operand:SI 0 "s_register_operand" "")
5623 (leu:SI (match_dup 1) (const_int 0)))]
5625 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5628 (define_expand "sgeu"
5629 [(set (match_operand:SI 0 "s_register_operand" "")
5630 (geu:SI (match_dup 1) (const_int 0)))]
5632 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5635 (define_expand "sltu"
5636 [(set (match_operand:SI 0 "s_register_operand" "")
5637 (ltu:SI (match_dup 1) (const_int 0)))]
5639 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5642 (define_expand "sunordered"
5643 [(set (match_operand:SI 0 "s_register_operand" "")
5644 (unordered:SI (match_dup 1) (const_int 0)))]
5645 "TARGET_ARM && TARGET_HARD_FLOAT"
5646 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5650 (define_expand "sordered"
5651 [(set (match_operand:SI 0 "s_register_operand" "")
5652 (ordered:SI (match_dup 1) (const_int 0)))]
5653 "TARGET_ARM && TARGET_HARD_FLOAT"
5654 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5658 (define_expand "sungt"
5659 [(set (match_operand:SI 0 "s_register_operand" "")
5660 (ungt:SI (match_dup 1) (const_int 0)))]
5661 "TARGET_ARM && TARGET_HARD_FLOAT"
5662 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
5666 (define_expand "sunge"
5667 [(set (match_operand:SI 0 "s_register_operand" "")
5668 (unge:SI (match_dup 1) (const_int 0)))]
5669 "TARGET_ARM && TARGET_HARD_FLOAT"
5670 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
5674 (define_expand "sunlt"
5675 [(set (match_operand:SI 0 "s_register_operand" "")
5676 (unlt:SI (match_dup 1) (const_int 0)))]
5677 "TARGET_ARM && TARGET_HARD_FLOAT"
5678 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
5682 (define_expand "sunle"
5683 [(set (match_operand:SI 0 "s_register_operand" "")
5684 (unle:SI (match_dup 1) (const_int 0)))]
5685 "TARGET_ARM && TARGET_HARD_FLOAT"
5686 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
5690 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
5691 ;;; simple ARM instructions.
5693 ; (define_expand "suneq"
5694 ; [(set (match_operand:SI 0 "s_register_operand" "")
5695 ; (uneq:SI (match_dup 1) (const_int 0)))]
5696 ; "TARGET_ARM && TARGET_HARD_FLOAT"
5700 ; (define_expand "sltgt"
5701 ; [(set (match_operand:SI 0 "s_register_operand" "")
5702 ; (ltgt:SI (match_dup 1) (const_int 0)))]
5703 ; "TARGET_ARM && TARGET_HARD_FLOAT"
5707 (define_insn "*mov_scc"
5708 [(set (match_operand:SI 0 "s_register_operand" "=r")
5709 (match_operator:SI 1 "arm_comparison_operator"
5710 [(match_operand 2 "cc_register" "") (const_int 0)]))]
5712 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
5713 [(set_attr "conds" "use")
5714 (set_attr "length" "8")]
5717 (define_insn "*mov_negscc"
5718 [(set (match_operand:SI 0 "s_register_operand" "=r")
5719 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
5720 [(match_operand 2 "cc_register" "") (const_int 0)])))]
5722 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
5723 [(set_attr "conds" "use")
5724 (set_attr "length" "8")]
5727 (define_insn "*mov_notscc"
5728 [(set (match_operand:SI 0 "s_register_operand" "=r")
5729 (not:SI (match_operator:SI 1 "arm_comparison_operator"
5730 [(match_operand 2 "cc_register" "") (const_int 0)])))]
5732 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
5733 [(set_attr "conds" "use")
5734 (set_attr "length" "8")]
5738 ;; Conditional move insns
5740 (define_expand "movsicc"
5741 [(set (match_operand:SI 0 "s_register_operand" "")
5742 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
5743 (match_operand:SI 2 "arm_not_operand" "")
5744 (match_operand:SI 3 "arm_not_operand" "")))]
5748 enum rtx_code code = GET_CODE (operands[1]);
5751 if (code == UNEQ || code == LTGT)
5754 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
5755 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
5759 (define_expand "movsfcc"
5760 [(set (match_operand:SF 0 "s_register_operand" "")
5761 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
5762 (match_operand:SF 2 "s_register_operand" "")
5763 (match_operand:SF 3 "nonmemory_operand" "")))]
5767 enum rtx_code code = GET_CODE (operands[1]);
5770 if (code == UNEQ || code == LTGT)
5773 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
5774 Otherwise, ensure it is a valid FP add operand */
5775 if ((!TARGET_HARD_FLOAT)
5776 || (!fpa_add_operand (operands[3], SFmode)))
5777 operands[3] = force_reg (SFmode, operands[3]);
5779 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
5780 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
5784 (define_expand "movdfcc"
5785 [(set (match_operand:DF 0 "s_register_operand" "")
5786 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
5787 (match_operand:DF 2 "s_register_operand" "")
5788 (match_operand:DF 3 "fpa_add_operand" "")))]
5789 "TARGET_ARM && TARGET_HARD_FLOAT"
5792 enum rtx_code code = GET_CODE (operands[1]);
5795 if (code == UNEQ || code == LTGT)
5798 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
5799 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
5803 (define_insn "*movsicc_insn"
5804 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
5806 (match_operator 3 "arm_comparison_operator"
5807 [(match_operand 4 "cc_register" "") (const_int 0)])
5808 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
5809 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
5816 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
5817 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
5818 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
5819 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
5820 [(set_attr "length" "4,4,4,4,8,8,8,8")
5821 (set_attr "conds" "use")]
5824 (define_insn "*movsfcc_soft_insn"
5825 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
5826 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
5827 [(match_operand 4 "cc_register" "") (const_int 0)])
5828 (match_operand:SF 1 "s_register_operand" "0,r")
5829 (match_operand:SF 2 "s_register_operand" "r,0")))]
5830 "TARGET_ARM && TARGET_SOFT_FLOAT"
5834 [(set_attr "conds" "use")]
5838 ;; Jump and linkage insns
5840 (define_expand "jump"
5842 (label_ref (match_operand 0 "" "")))]
5847 (define_insn "*arm_jump"
5849 (label_ref (match_operand 0 "" "")))]
5853 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5855 arm_ccfsm_state += 2;
5858 return \"b%?\\t%l0\";
5861 [(set_attr "predicable" "yes")]
5864 (define_insn "*thumb_jump"
5866 (label_ref (match_operand 0 "" "")))]
5869 if (get_attr_length (insn) == 2)
5871 return \"bl\\t%l0\\t%@ far jump\";
5873 [(set (attr "far_jump")
5875 (eq_attr "length" "4")
5876 (const_string "yes")
5877 (const_string "no")))
5878 (set (attr "length")
5880 (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
5881 (le (minus (match_dup 0) (pc)) (const_int 2044)))
5886 (define_expand "call"
5887 [(parallel [(call (match_operand 0 "memory_operand" "")
5888 (match_operand 1 "general_operand" ""))
5889 (use (match_operand 2 "" ""))
5890 (clobber (reg:SI LR_REGNUM))])]
5896 /* In an untyped call, we can get NULL for operand 2. */
5897 if (operands[2] == NULL_RTX)
5898 operands[2] = const0_rtx;
5900 /* This is to decide if we should generate indirect calls by loading the
5901 32 bit address of the callee into a register before performing the
5902 branch and link. operand[2] encodes the long_call/short_call
5903 attribute of the function being called. This attribute is set whenever
5904 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
5905 is used, and the short_call attribute can also be set if function is
5906 declared as static or if it has already been defined in the current
5907 compilation unit. See arm.c and arm.h for info about this. The third
5908 parameter to arm_is_longcall_p is used to tell it which pattern
5910 callee = XEXP (operands[0], 0);
5912 if (GET_CODE (callee) != REG
5913 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
5914 XEXP (operands[0], 0) = force_reg (Pmode, callee);
5918 (define_insn "*call_reg"
5919 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
5920 (match_operand 1 "" ""))
5921 (use (match_operand 2 "" ""))
5922 (clobber (reg:SI LR_REGNUM))]
5925 return output_call (operands);
5927 ;; length is worst case, normally it is only two
5928 [(set_attr "length" "12")
5929 (set_attr "type" "call")]
5932 (define_insn "*call_mem"
5933 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
5934 (match_operand 1 "" ""))
5935 (use (match_operand 2 "" ""))
5936 (clobber (reg:SI LR_REGNUM))]
5939 return output_call_mem (operands);
5941 [(set_attr "length" "12")
5942 (set_attr "type" "call")]
5945 (define_insn "*call_indirect"
5946 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
5947 (match_operand 1 "" ""))
5948 (use (match_operand 2 "" ""))
5949 (clobber (reg:SI LR_REGNUM))]
5953 if (TARGET_CALLER_INTERWORKING)
5954 return \"bl\\t%__interwork_call_via_%0\";
5956 return \"bl\\t%__call_via_%0\";
5958 [(set_attr "type" "call")]
5961 (define_insn "*call_value_indirect"
5962 [(set (match_operand 0 "" "=l")
5963 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
5964 (match_operand 2 "" "")))
5965 (use (match_operand 3 "" ""))
5966 (clobber (reg:SI LR_REGNUM))]
5970 if (TARGET_CALLER_INTERWORKING)
5971 return \"bl\\t%__interwork_call_via_%1\";
5973 return \"bl\\t%__call_via_%1\";
5975 [(set_attr "type" "call")]
5978 (define_expand "call_value"
5979 [(parallel [(set (match_operand 0 "" "")
5980 (call (match_operand 1 "memory_operand" "")
5981 (match_operand 2 "general_operand" "")))
5982 (use (match_operand 3 "" ""))
5983 (clobber (reg:SI LR_REGNUM))])]
5987 rtx callee = XEXP (operands[1], 0);
5989 /* In an untyped call, we can get NULL for operand 2. */
5990 if (operands[3] == 0)
5991 operands[3] = const0_rtx;
5993 /* See the comment in define_expand \"call\". */
5994 if (GET_CODE (callee) != REG
5995 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
5996 XEXP (operands[1], 0) = force_reg (Pmode, callee);
6000 (define_insn "*call_value_reg"
6001 [(set (match_operand 0 "" "=r,f,v")
6002 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r,r"))
6003 (match_operand 2 "" "")))
6004 (use (match_operand 3 "" ""))
6005 (clobber (reg:SI LR_REGNUM))]
6008 return output_call (&operands[1]);
6010 [(set_attr "length" "12")
6011 (set_attr "type" "call")]
6014 (define_insn "*call_value_mem"
6015 [(set (match_operand 0 "" "=r,f,v")
6016 (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m,m"))
6017 (match_operand 2 "" "")))
6018 (use (match_operand 3 "" ""))
6019 (clobber (reg:SI LR_REGNUM))]
6020 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6022 return output_call_mem (&operands[1]);
6024 [(set_attr "length" "12")
6025 (set_attr "type" "call")]
6028 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6029 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6031 (define_insn "*call_symbol"
6032 [(call (mem:SI (match_operand:SI 0 "" "X"))
6033 (match_operand 1 "" ""))
6034 (use (match_operand 2 "" ""))
6035 (clobber (reg:SI LR_REGNUM))]
6037 && (GET_CODE (operands[0]) == SYMBOL_REF)
6038 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6041 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6043 [(set_attr "type" "call")]
6046 (define_insn "*call_value_symbol"
6047 [(set (match_operand 0 "s_register_operand" "=r,f,v")
6048 (call (mem:SI (match_operand:SI 1 "" "X,X,X"))
6049 (match_operand:SI 2 "" "")))
6050 (use (match_operand 3 "" ""))
6051 (clobber (reg:SI LR_REGNUM))]
6053 && (GET_CODE (operands[1]) == SYMBOL_REF)
6054 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6057 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6059 [(set_attr "type" "call")]
6062 (define_insn "*call_insn"
6063 [(call (mem:SI (match_operand:SI 0 "" "X"))
6064 (match_operand:SI 1 "" ""))
6065 (use (match_operand 2 "" ""))
6066 (clobber (reg:SI LR_REGNUM))]
6068 && GET_CODE (operands[0]) == SYMBOL_REF
6069 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6071 [(set_attr "length" "4")
6072 (set_attr "type" "call")]
6075 (define_insn "*call_value_insn"
6076 [(set (match_operand 0 "register_operand" "=l")
6077 (call (mem:SI (match_operand 1 "" "X"))
6078 (match_operand 2 "" "")))
6079 (use (match_operand 3 "" ""))
6080 (clobber (reg:SI LR_REGNUM))]
6082 && GET_CODE (operands[1]) == SYMBOL_REF
6083 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6085 [(set_attr "length" "4")
6086 (set_attr "type" "call")]
6089 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6090 (define_expand "sibcall"
6091 [(parallel [(call (match_operand 0 "memory_operand" "")
6092 (match_operand 1 "general_operand" ""))
6094 (use (match_operand 2 "" ""))])]
6098 if (operands[2] == NULL_RTX)
6099 operands[2] = const0_rtx;
6103 (define_expand "sibcall_value"
6104 [(parallel [(set (match_operand 0 "register_operand" "")
6105 (call (match_operand 1 "memory_operand" "")
6106 (match_operand 2 "general_operand" "")))
6108 (use (match_operand 3 "" ""))])]
6112 if (operands[3] == NULL_RTX)
6113 operands[3] = const0_rtx;
6117 (define_insn "*sibcall_insn"
6118 [(call (mem:SI (match_operand:SI 0 "" "X"))
6119 (match_operand 1 "" ""))
6121 (use (match_operand 2 "" ""))]
6122 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6124 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6126 [(set_attr "type" "call")]
6129 (define_insn "*sibcall_value_insn"
6130 [(set (match_operand 0 "s_register_operand" "=r,f,v")
6131 (call (mem:SI (match_operand:SI 1 "" "X,X,X"))
6132 (match_operand 2 "" "")))
6134 (use (match_operand 3 "" ""))]
6135 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6137 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6139 [(set_attr "type" "call")]
6142 ;; Often the return insn will be the same as loading from memory, so set attr
6143 (define_insn "return"
6145 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6148 if (arm_ccfsm_state == 2)
6150 arm_ccfsm_state += 2;
6153 return output_return_instruction (const_true_rtx, TRUE, FALSE);
6155 [(set_attr "type" "load")
6156 (set_attr "predicable" "yes")]
6159 (define_insn "*cond_return"
6161 (if_then_else (match_operator 0 "arm_comparison_operator"
6162 [(match_operand 1 "cc_register" "") (const_int 0)])
6165 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6168 if (arm_ccfsm_state == 2)
6170 arm_ccfsm_state += 2;
6173 return output_return_instruction (operands[0], TRUE, FALSE);
6175 [(set_attr "conds" "use")
6176 (set_attr "type" "load")]
6179 (define_insn "*cond_return_inverted"
6181 (if_then_else (match_operator 0 "arm_comparison_operator"
6182 [(match_operand 1 "cc_register" "") (const_int 0)])
6185 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6188 if (arm_ccfsm_state == 2)
6190 arm_ccfsm_state += 2;
6193 return output_return_instruction (operands[0], TRUE, TRUE);
6195 [(set_attr "conds" "use")
6196 (set_attr "type" "load")]
6199 ;; Generate a sequence of instructions to determine if the processor is
6200 ;; in 26-bit or 32-bit mode, and return the appropriate return address
6203 (define_expand "return_addr_mask"
6205 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6207 (set (match_operand:SI 0 "s_register_operand" "")
6208 (if_then_else:SI (eq (match_dup 1) (const_int 0))
6210 (const_int 67108860)))] ; 0x03fffffc
6213 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
6216 (define_insn "*check_arch2"
6217 [(set (match_operand:CC_NOOV 0 "cc_register" "")
6218 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6221 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
6222 [(set_attr "length" "8")
6223 (set_attr "conds" "set")]
6226 ;; Call subroutine returning any type.
6228 (define_expand "untyped_call"
6229 [(parallel [(call (match_operand 0 "" "")
6231 (match_operand 1 "" "")
6232 (match_operand 2 "" "")])]
6238 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6240 for (i = 0; i < XVECLEN (operands[2], 0); i++)
6242 rtx set = XVECEXP (operands[2], 0, i);
6244 emit_move_insn (SET_DEST (set), SET_SRC (set));
6247 /* The optimizer does not know that the call sets the function value
6248 registers we stored in the result block. We avoid problems by
6249 claiming that all hard registers are used and clobbered at this
6251 emit_insn (gen_blockage ());
6257 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6258 ;; all of memory. This blocks insns from being moved across this point.
6260 (define_insn "blockage"
6261 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6264 [(set_attr "length" "0")
6265 (set_attr "type" "block")]
6268 (define_expand "casesi"
6269 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6270 (match_operand:SI 1 "const_int_operand" "") ; lower bound
6271 (match_operand:SI 2 "const_int_operand" "") ; total range
6272 (match_operand:SI 3 "" "") ; table label
6273 (match_operand:SI 4 "" "")] ; Out of range label
6278 if (operands[1] != const0_rtx)
6280 reg = gen_reg_rtx (SImode);
6282 emit_insn (gen_addsi3 (reg, operands[0],
6283 GEN_INT (-INTVAL (operands[1]))));
6287 if (!const_ok_for_arm (INTVAL (operands[2])))
6288 operands[2] = force_reg (SImode, operands[2]);
6290 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6296 ;; The USE in this pattern is needed to tell flow analysis that this is
6297 ;; a CASESI insn. It has no other purpose.
6298 (define_insn "casesi_internal"
6299 [(parallel [(set (pc)
6301 (leu (match_operand:SI 0 "s_register_operand" "r")
6302 (match_operand:SI 1 "arm_rhs_operand" "rI"))
6303 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6304 (label_ref (match_operand 2 "" ""))))
6305 (label_ref (match_operand 3 "" ""))))
6306 (clobber (reg:CC CC_REGNUM))
6307 (use (label_ref (match_dup 2)))])]
6311 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6312 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6314 [(set_attr "conds" "clob")
6315 (set_attr "length" "12")]
6318 (define_expand "indirect_jump"
6320 (match_operand:SI 0 "s_register_operand" ""))]
6325 (define_insn "*arm_indirect_jump"
6327 (match_operand:SI 0 "s_register_operand" "r"))]
6329 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6330 [(set_attr "predicable" "yes")]
6333 ;; Although not supported by the define_expand above,
6334 ;; cse/combine may generate this form.
6335 (define_insn "*load_indirect_jump"
6337 (match_operand:SI 0 "memory_operand" "m"))]
6339 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6340 [(set_attr "type" "load")
6341 (set_attr "pool_range" "4096")
6342 (set_attr "neg_pool_range" "4084")
6343 (set_attr "predicable" "yes")]
6346 (define_insn "*thumb_indirect_jump"
6348 (match_operand:SI 0 "register_operand" "l*r"))]
6351 [(set_attr "conds" "clob")
6352 (set_attr "length" "2")]
6363 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6364 return \"mov\\tr8, r8\";
6366 [(set (attr "length")
6367 (if_then_else (eq_attr "is_thumb" "yes")
6373 ;; Patterns to allow combination of arithmetic, cond code and shifts
6375 (define_insn "*arith_shiftsi"
6376 [(set (match_operand:SI 0 "s_register_operand" "=r")
6377 (match_operator:SI 1 "shiftable_operator"
6378 [(match_operator:SI 3 "shift_operator"
6379 [(match_operand:SI 4 "s_register_operand" "r")
6380 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6381 (match_operand:SI 2 "s_register_operand" "r")]))]
6383 "%i1%?\\t%0, %2, %4%S3"
6384 [(set_attr "predicable" "yes")
6385 (set_attr "shift" "4")
6389 (define_insn "*arith_shiftsi_compare0"
6390 [(set (reg:CC_NOOV CC_REGNUM)
6391 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6392 [(match_operator:SI 3 "shift_operator"
6393 [(match_operand:SI 4 "s_register_operand" "r")
6394 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6395 (match_operand:SI 2 "s_register_operand" "r")])
6397 (set (match_operand:SI 0 "s_register_operand" "=r")
6398 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6401 "%i1%?s\\t%0, %2, %4%S3"
6402 [(set_attr "conds" "set")
6403 (set_attr "shift" "4")
6407 (define_insn "*arith_shiftsi_compare0_scratch"
6408 [(set (reg:CC_NOOV CC_REGNUM)
6409 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6410 [(match_operator:SI 3 "shift_operator"
6411 [(match_operand:SI 4 "s_register_operand" "r")
6412 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6413 (match_operand:SI 2 "s_register_operand" "r")])
6415 (clobber (match_scratch:SI 0 "=r"))]
6417 "%i1%?s\\t%0, %2, %4%S3"
6418 [(set_attr "conds" "set")
6419 (set_attr "shift" "4")
6423 (define_insn "*sub_shiftsi"
6424 [(set (match_operand:SI 0 "s_register_operand" "=r")
6425 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6426 (match_operator:SI 2 "shift_operator"
6427 [(match_operand:SI 3 "s_register_operand" "r")
6428 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
6430 "sub%?\\t%0, %1, %3%S2"
6431 [(set_attr "predicable" "yes")
6432 (set_attr "shift" "3")
6436 (define_insn "*sub_shiftsi_compare0"
6437 [(set (reg:CC_NOOV CC_REGNUM)
6439 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6440 (match_operator:SI 2 "shift_operator"
6441 [(match_operand:SI 3 "s_register_operand" "r")
6442 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6444 (set (match_operand:SI 0 "s_register_operand" "=r")
6445 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6448 "sub%?s\\t%0, %1, %3%S2"
6449 [(set_attr "conds" "set")
6450 (set_attr "shift" "3")
6454 (define_insn "*sub_shiftsi_compare0_scratch"
6455 [(set (reg:CC_NOOV CC_REGNUM)
6457 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6458 (match_operator:SI 2 "shift_operator"
6459 [(match_operand:SI 3 "s_register_operand" "r")
6460 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6462 (clobber (match_scratch:SI 0 "=r"))]
6464 "sub%?s\\t%0, %1, %3%S2"
6465 [(set_attr "conds" "set")
6466 (set_attr "shift" "3")
6472 (define_insn "*and_scc"
6473 [(set (match_operand:SI 0 "s_register_operand" "=r")
6474 (and:SI (match_operator:SI 1 "arm_comparison_operator"
6475 [(match_operand 3 "cc_register" "") (const_int 0)])
6476 (match_operand:SI 2 "s_register_operand" "r")))]
6478 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
6479 [(set_attr "conds" "use")
6480 (set_attr "length" "8")]
6483 (define_insn "*ior_scc"
6484 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6485 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
6486 [(match_operand 3 "cc_register" "") (const_int 0)])
6487 (match_operand:SI 1 "s_register_operand" "0,?r")))]
6491 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
6492 [(set_attr "conds" "use")
6493 (set_attr "length" "4,8")]
6496 (define_insn "*compare_scc"
6497 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6498 (match_operator:SI 1 "arm_comparison_operator"
6499 [(match_operand:SI 2 "s_register_operand" "r,r")
6500 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
6501 (clobber (reg:CC CC_REGNUM))]
6504 if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
6505 return \"mov\\t%0, %2, lsr #31\";
6507 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
6508 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
6510 if (GET_CODE (operands[1]) == NE)
6512 if (which_alternative == 1)
6513 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
6514 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
6516 if (which_alternative == 1)
6517 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
6519 output_asm_insn (\"cmp\\t%2, %3\", operands);
6520 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
6522 [(set_attr "conds" "clob")
6523 (set_attr "length" "12")]
6526 (define_insn "*cond_move"
6527 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
6528 (if_then_else:SI (match_operator 3 "equality_operator"
6529 [(match_operator 4 "arm_comparison_operator"
6530 [(match_operand 5 "cc_register" "") (const_int 0)])
6532 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
6533 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
6536 if (GET_CODE (operands[3]) == NE)
6538 if (which_alternative != 1)
6539 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
6540 if (which_alternative != 0)
6541 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
6544 if (which_alternative != 0)
6545 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6546 if (which_alternative != 1)
6547 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
6550 [(set_attr "conds" "use")
6551 (set_attr "length" "4,4,8")]
6554 (define_insn "*cond_arith"
6555 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6556 (match_operator:SI 5 "shiftable_operator"
6557 [(match_operator:SI 4 "arm_comparison_operator"
6558 [(match_operand:SI 2 "s_register_operand" "r,r")
6559 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
6560 (match_operand:SI 1 "s_register_operand" "0,?r")]))
6561 (clobber (reg:CC CC_REGNUM))]
6564 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
6565 return \"%i5\\t%0, %1, %2, lsr #31\";
6567 output_asm_insn (\"cmp\\t%2, %3\", operands);
6568 if (GET_CODE (operands[5]) == AND)
6569 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
6570 else if (GET_CODE (operands[5]) == MINUS)
6571 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
6572 else if (which_alternative != 0)
6573 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6574 return \"%i5%d4\\t%0, %1, #1\";
6576 [(set_attr "conds" "clob")
6577 (set_attr "length" "12")]
6580 (define_insn "*cond_sub"
6581 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6582 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
6583 (match_operator:SI 4 "arm_comparison_operator"
6584 [(match_operand:SI 2 "s_register_operand" "r,r")
6585 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
6586 (clobber (reg:CC CC_REGNUM))]
6589 output_asm_insn (\"cmp\\t%2, %3\", operands);
6590 if (which_alternative != 0)
6591 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6592 return \"sub%d4\\t%0, %1, #1\";
6594 [(set_attr "conds" "clob")
6595 (set_attr "length" "8,12")]
6598 (define_insn "*cmp_ite0"
6599 [(set (match_operand 6 "dominant_cc_register" "")
6602 (match_operator 4 "arm_comparison_operator"
6603 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6604 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6605 (match_operator:SI 5 "arm_comparison_operator"
6606 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6607 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
6613 static const char * const opcodes[4][2] =
6615 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
6616 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
6617 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
6618 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
6619 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
6620 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
6621 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
6622 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
6625 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
6627 return opcodes[which_alternative][swap];
6629 [(set_attr "conds" "set")
6630 (set_attr "length" "8")]
6633 (define_insn "*cmp_ite1"
6634 [(set (match_operand 6 "dominant_cc_register" "")
6637 (match_operator 4 "arm_comparison_operator"
6638 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6639 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6640 (match_operator:SI 5 "arm_comparison_operator"
6641 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6642 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
6648 static const char * const opcodes[4][2] =
6650 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
6651 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
6652 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
6653 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
6654 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
6655 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
6656 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
6657 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
6660 comparison_dominates_p (GET_CODE (operands[5]),
6661 reverse_condition (GET_CODE (operands[4])));
6663 return opcodes[which_alternative][swap];
6665 [(set_attr "conds" "set")
6666 (set_attr "length" "8")]
6669 (define_insn "*cmp_and"
6670 [(set (match_operand 6 "dominant_cc_register" "")
6673 (match_operator 4 "arm_comparison_operator"
6674 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6675 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6676 (match_operator:SI 5 "arm_comparison_operator"
6677 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6678 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
6683 static const char *const opcodes[4][2] =
6685 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
6686 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
6687 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
6688 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
6689 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
6690 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
6691 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
6692 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
6695 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
6697 return opcodes[which_alternative][swap];
6699 [(set_attr "conds" "set")
6700 (set_attr "predicable" "no")
6701 (set_attr "length" "8")]
6704 (define_insn "*cmp_ior"
6705 [(set (match_operand 6 "dominant_cc_register" "")
6708 (match_operator 4 "arm_comparison_operator"
6709 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6710 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6711 (match_operator:SI 5 "arm_comparison_operator"
6712 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6713 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
6718 static const char *const opcodes[4][2] =
6720 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
6721 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
6722 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
6723 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
6724 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
6725 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
6726 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
6727 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
6730 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
6732 return opcodes[which_alternative][swap];
6735 [(set_attr "conds" "set")
6736 (set_attr "length" "8")]
6739 (define_insn "*negscc"
6740 [(set (match_operand:SI 0 "s_register_operand" "=r")
6741 (neg:SI (match_operator 3 "arm_comparison_operator"
6742 [(match_operand:SI 1 "s_register_operand" "r")
6743 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
6744 (clobber (reg:CC CC_REGNUM))]
6747 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
6748 return \"mov\\t%0, %1, asr #31\";
6750 if (GET_CODE (operands[3]) == NE)
6751 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
6753 if (GET_CODE (operands[3]) == GT)
6754 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
6756 output_asm_insn (\"cmp\\t%1, %2\", operands);
6757 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
6758 return \"mvn%d3\\t%0, #0\";
6760 [(set_attr "conds" "clob")
6761 (set_attr "length" "12")]
6764 (define_insn "movcond"
6765 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
6767 (match_operator 5 "arm_comparison_operator"
6768 [(match_operand:SI 3 "s_register_operand" "r,r,r")
6769 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
6770 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
6771 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
6772 (clobber (reg:CC CC_REGNUM))]
6775 if (GET_CODE (operands[5]) == LT
6776 && (operands[4] == const0_rtx))
6778 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
6780 if (operands[2] == const0_rtx)
6781 return \"and\\t%0, %1, %3, asr #31\";
6782 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
6784 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
6786 if (operands[1] == const0_rtx)
6787 return \"bic\\t%0, %2, %3, asr #31\";
6788 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
6790 /* The only case that falls through to here is when both ops 1 & 2
6794 if (GET_CODE (operands[5]) == GE
6795 && (operands[4] == const0_rtx))
6797 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
6799 if (operands[2] == const0_rtx)
6800 return \"bic\\t%0, %1, %3, asr #31\";
6801 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
6803 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
6805 if (operands[1] == const0_rtx)
6806 return \"and\\t%0, %2, %3, asr #31\";
6807 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
6809 /* The only case that falls through to here is when both ops 1 & 2
6812 if (GET_CODE (operands[4]) == CONST_INT
6813 && !const_ok_for_arm (INTVAL (operands[4])))
6814 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
6816 output_asm_insn (\"cmp\\t%3, %4\", operands);
6817 if (which_alternative != 0)
6818 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
6819 if (which_alternative != 1)
6820 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
6823 [(set_attr "conds" "clob")
6824 (set_attr "length" "8,8,12")]
6827 (define_insn "*ifcompare_plus_move"
6828 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6829 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
6830 [(match_operand:SI 4 "s_register_operand" "r,r")
6831 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
6833 (match_operand:SI 2 "s_register_operand" "r,r")
6834 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
6835 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
6836 (clobber (reg:CC CC_REGNUM))]
6839 [(set_attr "conds" "clob")
6840 (set_attr "length" "8,12")]
6843 (define_insn "*if_plus_move"
6844 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
6846 (match_operator 4 "arm_comparison_operator"
6847 [(match_operand 5 "cc_register" "") (const_int 0)])
6849 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
6850 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
6851 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
6855 sub%d4\\t%0, %2, #%n3
6856 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
6857 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
6858 [(set_attr "conds" "use")
6859 (set_attr "length" "4,4,8,8")
6860 (set_attr "type" "*,*,*,*")]
6863 (define_insn "*ifcompare_move_plus"
6864 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6865 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
6866 [(match_operand:SI 4 "s_register_operand" "r,r")
6867 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
6868 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
6870 (match_operand:SI 2 "s_register_operand" "r,r")
6871 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
6872 (clobber (reg:CC CC_REGNUM))]
6875 [(set_attr "conds" "clob")
6876 (set_attr "length" "8,12")]
6879 (define_insn "*if_move_plus"
6880 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
6882 (match_operator 4 "arm_comparison_operator"
6883 [(match_operand 5 "cc_register" "") (const_int 0)])
6884 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
6886 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
6887 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
6891 sub%D4\\t%0, %2, #%n3
6892 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
6893 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
6894 [(set_attr "conds" "use")
6895 (set_attr "length" "4,4,8,8")
6896 (set_attr "type" "*,*,*,*")]
6899 (define_insn "*ifcompare_arith_arith"
6900 [(set (match_operand:SI 0 "s_register_operand" "=r")
6901 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
6902 [(match_operand:SI 5 "s_register_operand" "r")
6903 (match_operand:SI 6 "arm_add_operand" "rIL")])
6904 (match_operator:SI 8 "shiftable_operator"
6905 [(match_operand:SI 1 "s_register_operand" "r")
6906 (match_operand:SI 2 "arm_rhs_operand" "rI")])
6907 (match_operator:SI 7 "shiftable_operator"
6908 [(match_operand:SI 3 "s_register_operand" "r")
6909 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
6910 (clobber (reg:CC CC_REGNUM))]
6913 [(set_attr "conds" "clob")
6914 (set_attr "length" "12")]
6917 (define_insn "*if_arith_arith"
6918 [(set (match_operand:SI 0 "s_register_operand" "=r")
6919 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
6920 [(match_operand 8 "cc_register" "") (const_int 0)])
6921 (match_operator:SI 6 "shiftable_operator"
6922 [(match_operand:SI 1 "s_register_operand" "r")
6923 (match_operand:SI 2 "arm_rhs_operand" "rI")])
6924 (match_operator:SI 7 "shiftable_operator"
6925 [(match_operand:SI 3 "s_register_operand" "r")
6926 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
6928 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
6929 [(set_attr "conds" "use")
6930 (set_attr "length" "8")]
6933 (define_insn "*ifcompare_arith_move"
6934 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6935 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
6936 [(match_operand:SI 2 "s_register_operand" "r,r")
6937 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
6938 (match_operator:SI 7 "shiftable_operator"
6939 [(match_operand:SI 4 "s_register_operand" "r,r")
6940 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
6941 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
6942 (clobber (reg:CC CC_REGNUM))]
6945 /* If we have an operation where (op x 0) is the identity operation and
6946 the conditional operator is LT or GE and we are comparing against zero and
6947 everything is in registers then we can do this in two instructions */
6948 if (operands[3] == const0_rtx
6949 && GET_CODE (operands[7]) != AND
6950 && GET_CODE (operands[5]) == REG
6951 && GET_CODE (operands[1]) == REG
6952 && REGNO (operands[1]) == REGNO (operands[4])
6953 && REGNO (operands[4]) != REGNO (operands[0]))
6955 if (GET_CODE (operands[6]) == LT)
6956 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
6957 else if (GET_CODE (operands[6]) == GE)
6958 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
6960 if (GET_CODE (operands[3]) == CONST_INT
6961 && !const_ok_for_arm (INTVAL (operands[3])))
6962 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
6964 output_asm_insn (\"cmp\\t%2, %3\", operands);
6965 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
6966 if (which_alternative != 0)
6967 return \"mov%D6\\t%0, %1\";
6970 [(set_attr "conds" "clob")
6971 (set_attr "length" "8,12")]
6974 (define_insn "*if_arith_move"
6975 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6976 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
6977 [(match_operand 6 "cc_register" "") (const_int 0)])
6978 (match_operator:SI 5 "shiftable_operator"
6979 [(match_operand:SI 2 "s_register_operand" "r,r")
6980 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
6981 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
6985 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
6986 [(set_attr "conds" "use")
6987 (set_attr "length" "4,8")
6988 (set_attr "type" "*,*")]
6991 (define_insn "*ifcompare_move_arith"
6992 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6993 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
6994 [(match_operand:SI 4 "s_register_operand" "r,r")
6995 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
6996 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
6997 (match_operator:SI 7 "shiftable_operator"
6998 [(match_operand:SI 2 "s_register_operand" "r,r")
6999 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7000 (clobber (reg:CC CC_REGNUM))]
7003 /* If we have an operation where (op x 0) is the identity operation and
7004 the conditional operator is LT or GE and we are comparing against zero and
7005 everything is in registers then we can do this in two instructions */
7006 if (operands[5] == const0_rtx
7007 && GET_CODE (operands[7]) != AND
7008 && GET_CODE (operands[3]) == REG
7009 && GET_CODE (operands[1]) == REG
7010 && REGNO (operands[1]) == REGNO (operands[2])
7011 && REGNO (operands[2]) != REGNO (operands[0]))
7013 if (GET_CODE (operands[6]) == GE)
7014 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7015 else if (GET_CODE (operands[6]) == LT)
7016 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7019 if (GET_CODE (operands[5]) == CONST_INT
7020 && !const_ok_for_arm (INTVAL (operands[5])))
7021 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7023 output_asm_insn (\"cmp\\t%4, %5\", operands);
7025 if (which_alternative != 0)
7026 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7027 return \"%I7%D6\\t%0, %2, %3\";
7029 [(set_attr "conds" "clob")
7030 (set_attr "length" "8,12")]
7033 (define_insn "*if_move_arith"
7034 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7036 (match_operator 4 "arm_comparison_operator"
7037 [(match_operand 6 "cc_register" "") (const_int 0)])
7038 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7039 (match_operator:SI 5 "shiftable_operator"
7040 [(match_operand:SI 2 "s_register_operand" "r,r")
7041 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7045 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7046 [(set_attr "conds" "use")
7047 (set_attr "length" "4,8")
7048 (set_attr "type" "*,*")]
7051 (define_insn "*ifcompare_move_not"
7052 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7054 (match_operator 5 "arm_comparison_operator"
7055 [(match_operand:SI 3 "s_register_operand" "r,r")
7056 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7057 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7059 (match_operand:SI 2 "s_register_operand" "r,r"))))
7060 (clobber (reg:CC CC_REGNUM))]
7063 [(set_attr "conds" "clob")
7064 (set_attr "length" "8,12")]
7067 (define_insn "*if_move_not"
7068 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7070 (match_operator 4 "arm_comparison_operator"
7071 [(match_operand 3 "cc_register" "") (const_int 0)])
7072 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7073 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7077 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7078 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7079 [(set_attr "conds" "use")
7080 (set_attr "length" "4,8,8")]
7083 (define_insn "*ifcompare_not_move"
7084 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7086 (match_operator 5 "arm_comparison_operator"
7087 [(match_operand:SI 3 "s_register_operand" "r,r")
7088 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7090 (match_operand:SI 2 "s_register_operand" "r,r"))
7091 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7092 (clobber (reg:CC CC_REGNUM))]
7095 [(set_attr "conds" "clob")
7096 (set_attr "length" "8,12")]
7099 (define_insn "*if_not_move"
7100 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7102 (match_operator 4 "arm_comparison_operator"
7103 [(match_operand 3 "cc_register" "") (const_int 0)])
7104 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7105 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7109 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7110 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7111 [(set_attr "conds" "use")
7112 (set_attr "length" "4,8,8")]
7115 (define_insn "*ifcompare_shift_move"
7116 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7118 (match_operator 6 "arm_comparison_operator"
7119 [(match_operand:SI 4 "s_register_operand" "r,r")
7120 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7121 (match_operator:SI 7 "shift_operator"
7122 [(match_operand:SI 2 "s_register_operand" "r,r")
7123 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7124 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7125 (clobber (reg:CC CC_REGNUM))]
7128 [(set_attr "conds" "clob")
7129 (set_attr "length" "8,12")]
7132 (define_insn "*if_shift_move"
7133 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7135 (match_operator 5 "arm_comparison_operator"
7136 [(match_operand 6 "cc_register" "") (const_int 0)])
7137 (match_operator:SI 4 "shift_operator"
7138 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7139 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7140 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7144 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7145 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7146 [(set_attr "conds" "use")
7147 (set_attr "shift" "2")
7148 (set_attr "length" "4,8,8")]
7151 (define_insn "*ifcompare_move_shift"
7152 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7154 (match_operator 6 "arm_comparison_operator"
7155 [(match_operand:SI 4 "s_register_operand" "r,r")
7156 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7157 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7158 (match_operator:SI 7 "shift_operator"
7159 [(match_operand:SI 2 "s_register_operand" "r,r")
7160 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7161 (clobber (reg:CC CC_REGNUM))]
7164 [(set_attr "conds" "clob")
7165 (set_attr "length" "8,12")]
7168 (define_insn "*if_move_shift"
7169 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7171 (match_operator 5 "arm_comparison_operator"
7172 [(match_operand 6 "cc_register" "") (const_int 0)])
7173 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7174 (match_operator:SI 4 "shift_operator"
7175 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7176 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7180 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7181 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7182 [(set_attr "conds" "use")
7183 (set_attr "shift" "2")
7184 (set_attr "length" "4,8,8")]
7187 (define_insn "*ifcompare_shift_shift"
7188 [(set (match_operand:SI 0 "s_register_operand" "=r")
7190 (match_operator 7 "arm_comparison_operator"
7191 [(match_operand:SI 5 "s_register_operand" "r")
7192 (match_operand:SI 6 "arm_add_operand" "rIL")])
7193 (match_operator:SI 8 "shift_operator"
7194 [(match_operand:SI 1 "s_register_operand" "r")
7195 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7196 (match_operator:SI 9 "shift_operator"
7197 [(match_operand:SI 3 "s_register_operand" "r")
7198 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7199 (clobber (reg:CC CC_REGNUM))]
7202 [(set_attr "conds" "clob")
7203 (set_attr "length" "12")]
7206 (define_insn "*if_shift_shift"
7207 [(set (match_operand:SI 0 "s_register_operand" "=r")
7209 (match_operator 5 "arm_comparison_operator"
7210 [(match_operand 8 "cc_register" "") (const_int 0)])
7211 (match_operator:SI 6 "shift_operator"
7212 [(match_operand:SI 1 "s_register_operand" "r")
7213 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7214 (match_operator:SI 7 "shift_operator"
7215 [(match_operand:SI 3 "s_register_operand" "r")
7216 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7218 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7219 [(set_attr "conds" "use")
7220 (set_attr "shift" "1")
7221 (set_attr "length" "8")]
7224 (define_insn "*ifcompare_not_arith"
7225 [(set (match_operand:SI 0 "s_register_operand" "=r")
7227 (match_operator 6 "arm_comparison_operator"
7228 [(match_operand:SI 4 "s_register_operand" "r")
7229 (match_operand:SI 5 "arm_add_operand" "rIL")])
7230 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7231 (match_operator:SI 7 "shiftable_operator"
7232 [(match_operand:SI 2 "s_register_operand" "r")
7233 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7234 (clobber (reg:CC CC_REGNUM))]
7237 [(set_attr "conds" "clob")
7238 (set_attr "length" "12")]
7241 (define_insn "*if_not_arith"
7242 [(set (match_operand:SI 0 "s_register_operand" "=r")
7244 (match_operator 5 "arm_comparison_operator"
7245 [(match_operand 4 "cc_register" "") (const_int 0)])
7246 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7247 (match_operator:SI 6 "shiftable_operator"
7248 [(match_operand:SI 2 "s_register_operand" "r")
7249 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7251 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7252 [(set_attr "conds" "use")
7253 (set_attr "length" "8")]
7256 (define_insn "*ifcompare_arith_not"
7257 [(set (match_operand:SI 0 "s_register_operand" "=r")
7259 (match_operator 6 "arm_comparison_operator"
7260 [(match_operand:SI 4 "s_register_operand" "r")
7261 (match_operand:SI 5 "arm_add_operand" "rIL")])
7262 (match_operator:SI 7 "shiftable_operator"
7263 [(match_operand:SI 2 "s_register_operand" "r")
7264 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7265 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7266 (clobber (reg:CC CC_REGNUM))]
7269 [(set_attr "conds" "clob")
7270 (set_attr "length" "12")]
7273 (define_insn "*if_arith_not"
7274 [(set (match_operand:SI 0 "s_register_operand" "=r")
7276 (match_operator 5 "arm_comparison_operator"
7277 [(match_operand 4 "cc_register" "") (const_int 0)])
7278 (match_operator:SI 6 "shiftable_operator"
7279 [(match_operand:SI 2 "s_register_operand" "r")
7280 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7281 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7283 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7284 [(set_attr "conds" "use")
7285 (set_attr "length" "8")]
7288 (define_insn "*ifcompare_neg_move"
7289 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7291 (match_operator 5 "arm_comparison_operator"
7292 [(match_operand:SI 3 "s_register_operand" "r,r")
7293 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7294 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7295 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7296 (clobber (reg:CC CC_REGNUM))]
7299 [(set_attr "conds" "clob")
7300 (set_attr "length" "8,12")]
7303 (define_insn "*if_neg_move"
7304 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7306 (match_operator 4 "arm_comparison_operator"
7307 [(match_operand 3 "cc_register" "") (const_int 0)])
7308 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7309 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7313 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7314 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
7315 [(set_attr "conds" "use")
7316 (set_attr "length" "4,8,8")]
7319 (define_insn "*ifcompare_move_neg"
7320 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7322 (match_operator 5 "arm_comparison_operator"
7323 [(match_operand:SI 3 "s_register_operand" "r,r")
7324 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7325 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7326 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
7327 (clobber (reg:CC CC_REGNUM))]
7330 [(set_attr "conds" "clob")
7331 (set_attr "length" "8,12")]
7334 (define_insn "*if_move_neg"
7335 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7337 (match_operator 4 "arm_comparison_operator"
7338 [(match_operand 3 "cc_register" "") (const_int 0)])
7339 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7340 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7344 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
7345 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
7346 [(set_attr "conds" "use")
7347 (set_attr "length" "4,8,8")]
7350 (define_insn "*arith_adjacentmem"
7351 [(set (match_operand:SI 0 "s_register_operand" "=r")
7352 (match_operator:SI 1 "shiftable_operator"
7353 [(match_operand:SI 2 "memory_operand" "m")
7354 (match_operand:SI 3 "memory_operand" "m")]))
7355 (clobber (match_scratch:SI 4 "=r"))]
7356 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
7361 int val1 = 0, val2 = 0;
7363 if (REGNO (operands[0]) > REGNO (operands[4]))
7365 ldm[1] = operands[4];
7366 ldm[2] = operands[0];
7370 ldm[1] = operands[0];
7371 ldm[2] = operands[4];
7373 if (GET_CODE (XEXP (operands[2], 0)) != REG)
7374 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
7375 if (GET_CODE (XEXP (operands[3], 0)) != REG)
7376 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
7377 arith[0] = operands[0];
7378 arith[3] = operands[1];
7392 ldm[0] = ops[0] = operands[4];
7393 ops[1] = XEXP (XEXP (operands[2], 0), 0);
7394 ops[2] = XEXP (XEXP (operands[2], 0), 1);
7395 output_add_immediate (ops);
7397 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7399 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7403 ldm[0] = XEXP (operands[3], 0);
7405 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7407 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7411 ldm[0] = XEXP (operands[2], 0);
7413 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7415 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7417 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
7420 [(set_attr "length" "12")
7421 (set_attr "predicable" "yes")
7422 (set_attr "type" "load")]
7425 ;; the arm can support extended pre-inc instructions
7427 ;; In all these cases, we use operands 0 and 1 for the register being
7428 ;; incremented because those are the operands that local-alloc will
7429 ;; tie and these are the pair most likely to be tieable (and the ones
7430 ;; that will benefit the most).
7432 ;; We reject the frame pointer if it occurs anywhere in these patterns since
7433 ;; elimination will cause too many headaches.
7435 (define_insn "*strqi_preinc"
7436 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7437 (match_operand:SI 2 "index_operand" "rJ")))
7438 (match_operand:QI 3 "s_register_operand" "r"))
7439 (set (match_operand:SI 0 "s_register_operand" "=r")
7440 (plus:SI (match_dup 1) (match_dup 2)))]
7442 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7443 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7444 && (GET_CODE (operands[2]) != REG
7445 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7446 "str%?b\\t%3, [%0, %2]!"
7447 [(set_attr "type" "store1")
7448 (set_attr "predicable" "yes")]
7451 (define_insn "*strqi_predec"
7452 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7453 (match_operand:SI 2 "s_register_operand" "r")))
7454 (match_operand:QI 3 "s_register_operand" "r"))
7455 (set (match_operand:SI 0 "s_register_operand" "=r")
7456 (minus:SI (match_dup 1) (match_dup 2)))]
7458 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7459 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7460 && (GET_CODE (operands[2]) != REG
7461 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7462 "str%?b\\t%3, [%0, -%2]!"
7463 [(set_attr "type" "store1")
7464 (set_attr "predicable" "yes")]
7467 (define_insn "*loadqi_preinc"
7468 [(set (match_operand:QI 3 "s_register_operand" "=r")
7469 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7470 (match_operand:SI 2 "index_operand" "rJ"))))
7471 (set (match_operand:SI 0 "s_register_operand" "=r")
7472 (plus:SI (match_dup 1) (match_dup 2)))]
7474 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7475 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7476 && (GET_CODE (operands[2]) != REG
7477 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7478 "ldr%?b\\t%3, [%0, %2]!"
7479 [(set_attr "type" "load")
7480 (set_attr "predicable" "yes")]
7483 (define_insn "*loadqi_predec"
7484 [(set (match_operand:QI 3 "s_register_operand" "=r")
7485 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7486 (match_operand:SI 2 "s_register_operand" "r"))))
7487 (set (match_operand:SI 0 "s_register_operand" "=r")
7488 (minus:SI (match_dup 1) (match_dup 2)))]
7490 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7491 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7492 && (GET_CODE (operands[2]) != REG
7493 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7494 "ldr%?b\\t%3, [%0, -%2]!"
7495 [(set_attr "type" "load")
7496 (set_attr "predicable" "yes")]
7499 (define_insn "*loadqisi_preinc"
7500 [(set (match_operand:SI 3 "s_register_operand" "=r")
7502 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7503 (match_operand:SI 2 "index_operand" "rJ")))))
7504 (set (match_operand:SI 0 "s_register_operand" "=r")
7505 (plus:SI (match_dup 1) (match_dup 2)))]
7507 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7508 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7509 && (GET_CODE (operands[2]) != REG
7510 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7511 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
7512 [(set_attr "type" "load")
7513 (set_attr "predicable" "yes")]
7516 (define_insn "*loadqisi_predec"
7517 [(set (match_operand:SI 3 "s_register_operand" "=r")
7519 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7520 (match_operand:SI 2 "s_register_operand" "r")))))
7521 (set (match_operand:SI 0 "s_register_operand" "=r")
7522 (minus:SI (match_dup 1) (match_dup 2)))]
7524 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7525 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7526 && (GET_CODE (operands[2]) != REG
7527 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7528 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
7529 [(set_attr "type" "load")
7530 (set_attr "predicable" "yes")]
7533 (define_insn "*strsi_preinc"
7534 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7535 (match_operand:SI 2 "index_operand" "rJ")))
7536 (match_operand:SI 3 "s_register_operand" "r"))
7537 (set (match_operand:SI 0 "s_register_operand" "=r")
7538 (plus:SI (match_dup 1) (match_dup 2)))]
7540 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7541 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7542 && (GET_CODE (operands[2]) != REG
7543 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7544 "str%?\\t%3, [%0, %2]!"
7545 [(set_attr "type" "store1")
7546 (set_attr "predicable" "yes")]
7549 (define_insn "*strsi_predec"
7550 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7551 (match_operand:SI 2 "s_register_operand" "r")))
7552 (match_operand:SI 3 "s_register_operand" "r"))
7553 (set (match_operand:SI 0 "s_register_operand" "=r")
7554 (minus:SI (match_dup 1) (match_dup 2)))]
7556 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7557 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7558 && (GET_CODE (operands[2]) != REG
7559 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7560 "str%?\\t%3, [%0, -%2]!"
7561 [(set_attr "type" "store1")
7562 (set_attr "predicable" "yes")]
7565 (define_insn "*loadsi_preinc"
7566 [(set (match_operand:SI 3 "s_register_operand" "=r")
7567 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7568 (match_operand:SI 2 "index_operand" "rJ"))))
7569 (set (match_operand:SI 0 "s_register_operand" "=r")
7570 (plus:SI (match_dup 1) (match_dup 2)))]
7572 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7573 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7574 && (GET_CODE (operands[2]) != REG
7575 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7576 "ldr%?\\t%3, [%0, %2]!"
7577 [(set_attr "type" "load")
7578 (set_attr "predicable" "yes")]
7581 (define_insn "*loadsi_predec"
7582 [(set (match_operand:SI 3 "s_register_operand" "=r")
7583 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7584 (match_operand:SI 2 "s_register_operand" "r"))))
7585 (set (match_operand:SI 0 "s_register_operand" "=r")
7586 (minus:SI (match_dup 1) (match_dup 2)))]
7588 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7589 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7590 && (GET_CODE (operands[2]) != REG
7591 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7592 "ldr%?\\t%3, [%0, -%2]!"
7593 [(set_attr "type" "load")
7594 (set_attr "predicable" "yes")]
7597 (define_insn "*loadhi_preinc"
7598 [(set (match_operand:HI 3 "s_register_operand" "=r")
7599 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7600 (match_operand:SI 2 "index_operand" "rJ"))))
7601 (set (match_operand:SI 0 "s_register_operand" "=r")
7602 (plus:SI (match_dup 1) (match_dup 2)))]
7604 && !BYTES_BIG_ENDIAN
7605 && !TARGET_MMU_TRAPS
7607 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7608 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7609 && (GET_CODE (operands[2]) != REG
7610 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7611 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
7612 [(set_attr "type" "load")
7613 (set_attr "predicable" "yes")]
7616 (define_insn "*loadhi_predec"
7617 [(set (match_operand:HI 3 "s_register_operand" "=r")
7618 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7619 (match_operand:SI 2 "s_register_operand" "r"))))
7620 (set (match_operand:SI 0 "s_register_operand" "=r")
7621 (minus:SI (match_dup 1) (match_dup 2)))]
7623 && !BYTES_BIG_ENDIAN
7624 && !TARGET_MMU_TRAPS
7626 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7627 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7628 && (GET_CODE (operands[2]) != REG
7629 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7630 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
7631 [(set_attr "type" "load")
7632 (set_attr "predicable" "yes")]
7635 (define_insn "*strqi_shiftpreinc"
7636 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
7637 [(match_operand:SI 3 "s_register_operand" "r")
7638 (match_operand:SI 4 "const_shift_operand" "n")])
7639 (match_operand:SI 1 "s_register_operand" "0")))
7640 (match_operand:QI 5 "s_register_operand" "r"))
7641 (set (match_operand:SI 0 "s_register_operand" "=r")
7642 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7645 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7646 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7647 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7648 "str%?b\\t%5, [%0, %3%S2]!"
7649 [(set_attr "type" "store1")
7650 (set_attr "predicable" "yes")]
7653 (define_insn "*strqi_shiftpredec"
7654 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7655 (match_operator:SI 2 "shift_operator"
7656 [(match_operand:SI 3 "s_register_operand" "r")
7657 (match_operand:SI 4 "const_shift_operand" "n")])))
7658 (match_operand:QI 5 "s_register_operand" "r"))
7659 (set (match_operand:SI 0 "s_register_operand" "=r")
7660 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7663 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7664 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7665 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7666 "str%?b\\t%5, [%0, -%3%S2]!"
7667 [(set_attr "type" "store1")
7668 (set_attr "predicable" "yes")]
7671 (define_insn "*loadqi_shiftpreinc"
7672 [(set (match_operand:QI 5 "s_register_operand" "=r")
7673 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
7674 [(match_operand:SI 3 "s_register_operand" "r")
7675 (match_operand:SI 4 "const_shift_operand" "n")])
7676 (match_operand:SI 1 "s_register_operand" "0"))))
7677 (set (match_operand:SI 0 "s_register_operand" "=r")
7678 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7681 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7682 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7683 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7684 "ldr%?b\\t%5, [%0, %3%S2]!"
7685 [(set_attr "type" "load")
7686 (set_attr "predicable" "yes")]
7689 (define_insn "*loadqi_shiftpredec"
7690 [(set (match_operand:QI 5 "s_register_operand" "=r")
7691 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7692 (match_operator:SI 2 "shift_operator"
7693 [(match_operand:SI 3 "s_register_operand" "r")
7694 (match_operand:SI 4 "const_shift_operand" "n")]))))
7695 (set (match_operand:SI 0 "s_register_operand" "=r")
7696 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7699 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7700 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7701 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7702 "ldr%?b\\t%5, [%0, -%3%S2]!"
7703 [(set_attr "type" "load")
7704 (set_attr "predicable" "yes")]
7707 (define_insn "*strsi_shiftpreinc"
7708 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
7709 [(match_operand:SI 3 "s_register_operand" "r")
7710 (match_operand:SI 4 "const_shift_operand" "n")])
7711 (match_operand:SI 1 "s_register_operand" "0")))
7712 (match_operand:SI 5 "s_register_operand" "r"))
7713 (set (match_operand:SI 0 "s_register_operand" "=r")
7714 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7717 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7718 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7719 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7720 "str%?\\t%5, [%0, %3%S2]!"
7721 [(set_attr "type" "store1")
7722 (set_attr "predicable" "yes")]
7725 (define_insn "*strsi_shiftpredec"
7726 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7727 (match_operator:SI 2 "shift_operator"
7728 [(match_operand:SI 3 "s_register_operand" "r")
7729 (match_operand:SI 4 "const_shift_operand" "n")])))
7730 (match_operand:SI 5 "s_register_operand" "r"))
7731 (set (match_operand:SI 0 "s_register_operand" "=r")
7732 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7735 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7736 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7737 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7738 "str%?\\t%5, [%0, -%3%S2]!"
7739 [(set_attr "type" "store1")
7740 (set_attr "predicable" "yes")]
7743 (define_insn "*loadsi_shiftpreinc"
7744 [(set (match_operand:SI 5 "s_register_operand" "=r")
7745 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
7746 [(match_operand:SI 3 "s_register_operand" "r")
7747 (match_operand:SI 4 "const_shift_operand" "n")])
7748 (match_operand:SI 1 "s_register_operand" "0"))))
7749 (set (match_operand:SI 0 "s_register_operand" "=r")
7750 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7753 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7754 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7755 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7756 "ldr%?\\t%5, [%0, %3%S2]!"
7757 [(set_attr "type" "load")
7758 (set_attr "predicable" "yes")]
7761 (define_insn "*loadsi_shiftpredec"
7762 [(set (match_operand:SI 5 "s_register_operand" "=r")
7763 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7764 (match_operator:SI 2 "shift_operator"
7765 [(match_operand:SI 3 "s_register_operand" "r")
7766 (match_operand:SI 4 "const_shift_operand" "n")]))))
7767 (set (match_operand:SI 0 "s_register_operand" "=r")
7768 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7771 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7772 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7773 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7774 "ldr%?\\t%5, [%0, -%3%S2]!"
7775 [(set_attr "type" "load")
7776 (set_attr "predicable" "yes")])
7778 (define_insn "*loadhi_shiftpreinc"
7779 [(set (match_operand:HI 5 "s_register_operand" "=r")
7780 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
7781 [(match_operand:SI 3 "s_register_operand" "r")
7782 (match_operand:SI 4 "const_shift_operand" "n")])
7783 (match_operand:SI 1 "s_register_operand" "0"))))
7784 (set (match_operand:SI 0 "s_register_operand" "=r")
7785 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7788 && !BYTES_BIG_ENDIAN
7789 && !TARGET_MMU_TRAPS
7791 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7792 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7793 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7794 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
7795 [(set_attr "type" "load")
7796 (set_attr "predicable" "yes")]
7799 (define_insn "*loadhi_shiftpredec"
7800 [(set (match_operand:HI 5 "s_register_operand" "=r")
7801 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7802 (match_operator:SI 2 "shift_operator"
7803 [(match_operand:SI 3 "s_register_operand" "r")
7804 (match_operand:SI 4 "const_shift_operand" "n")]))))
7805 (set (match_operand:SI 0 "s_register_operand" "=r")
7806 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7809 && !BYTES_BIG_ENDIAN
7810 && !TARGET_MMU_TRAPS
7812 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7813 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7814 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7815 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
7816 [(set_attr "type" "load")
7817 (set_attr "predicable" "yes")]
7820 ; It can also support extended post-inc expressions, but combine doesn't
7822 ; It doesn't seem worth adding peepholes for anything but the most common
7823 ; cases since, unlike combine, the increment must immediately follow the load
7824 ; for this pattern to match.
7825 ; We must watch to see that the source/destination register isn't also the
7826 ; same as the base address register, and that if the index is a register,
7827 ; that it is not the same as the base address register. In such cases the
7828 ; instruction that we would generate would have UNPREDICTABLE behavior so
7832 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
7833 (match_operand:QI 2 "s_register_operand" "r"))
7835 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
7837 && (REGNO (operands[2]) != REGNO (operands[0]))
7838 && (GET_CODE (operands[1]) != REG
7839 || (REGNO (operands[1]) != REGNO (operands[0])))"
7840 "str%?b\\t%2, [%0], %1"
7844 [(set (match_operand:QI 0 "s_register_operand" "=r")
7845 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
7847 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
7849 && REGNO (operands[0]) != REGNO(operands[1])
7850 && (GET_CODE (operands[2]) != REG
7851 || REGNO(operands[0]) != REGNO (operands[2]))"
7852 "ldr%?b\\t%0, [%1], %2"
7856 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
7857 (match_operand:SI 2 "s_register_operand" "r"))
7859 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
7861 && (REGNO (operands[2]) != REGNO (operands[0]))
7862 && (GET_CODE (operands[1]) != REG
7863 || (REGNO (operands[1]) != REGNO (operands[0])))"
7864 "str%?\\t%2, [%0], %1"
7868 [(set (match_operand:HI 0 "s_register_operand" "=r")
7869 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
7871 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
7873 && !BYTES_BIG_ENDIAN
7874 && !TARGET_MMU_TRAPS
7876 && REGNO (operands[0]) != REGNO(operands[1])
7877 && (GET_CODE (operands[2]) != REG
7878 || REGNO(operands[0]) != REGNO (operands[2]))"
7879 "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
7883 [(set (match_operand:SI 0 "s_register_operand" "=r")
7884 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
7886 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
7888 && REGNO (operands[0]) != REGNO(operands[1])
7889 && (GET_CODE (operands[2]) != REG
7890 || REGNO(operands[0]) != REGNO (operands[2]))"
7891 "ldr%?\\t%0, [%1], %2"
7895 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
7896 (match_operand:SI 1 "index_operand" "rJ")))
7897 (match_operand:QI 2 "s_register_operand" "r"))
7898 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
7900 && (REGNO (operands[2]) != REGNO (operands[0]))
7901 && (GET_CODE (operands[1]) != REG
7902 || (REGNO (operands[1]) != REGNO (operands[0])))"
7903 "str%?b\\t%2, [%0, %1]!"
7907 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
7908 [(match_operand:SI 0 "s_register_operand" "r")
7909 (match_operand:SI 1 "const_int_operand" "n")])
7910 (match_operand:SI 2 "s_register_operand" "+r")))
7911 (match_operand:QI 3 "s_register_operand" "r"))
7912 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
7915 && (REGNO (operands[3]) != REGNO (operands[2]))
7916 && (REGNO (operands[0]) != REGNO (operands[2]))"
7917 "str%?b\\t%3, [%2, %0%S4]!"
7920 ; This pattern is never tried by combine, so do it as a peephole
7923 [(set (match_operand:SI 0 "s_register_operand" "")
7924 (match_operand:SI 1 "s_register_operand" ""))
7925 (set (reg:CC CC_REGNUM)
7926 (compare:CC (match_dup 1) (const_int 0)))]
7929 || (!cirrus_fp_register (operands[0], SImode)
7930 && !cirrus_fp_register (operands[1], SImode)))
7932 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
7933 (set (match_dup 0) (match_dup 1))])]
7937 ; Peepholes to spot possible load- and store-multiples, if the ordering is
7938 ; reversed, check that the memory references aren't volatile.
7941 [(set (match_operand:SI 0 "s_register_operand" "=r")
7942 (match_operand:SI 4 "memory_operand" "m"))
7943 (set (match_operand:SI 1 "s_register_operand" "=r")
7944 (match_operand:SI 5 "memory_operand" "m"))
7945 (set (match_operand:SI 2 "s_register_operand" "=r")
7946 (match_operand:SI 6 "memory_operand" "m"))
7947 (set (match_operand:SI 3 "s_register_operand" "=r")
7948 (match_operand:SI 7 "memory_operand" "m"))]
7949 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
7951 return emit_ldm_seq (operands, 4);
7956 [(set (match_operand:SI 0 "s_register_operand" "=r")
7957 (match_operand:SI 3 "memory_operand" "m"))
7958 (set (match_operand:SI 1 "s_register_operand" "=r")
7959 (match_operand:SI 4 "memory_operand" "m"))
7960 (set (match_operand:SI 2 "s_register_operand" "=r")
7961 (match_operand:SI 5 "memory_operand" "m"))]
7962 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
7964 return emit_ldm_seq (operands, 3);
7969 [(set (match_operand:SI 0 "s_register_operand" "=r")
7970 (match_operand:SI 2 "memory_operand" "m"))
7971 (set (match_operand:SI 1 "s_register_operand" "=r")
7972 (match_operand:SI 3 "memory_operand" "m"))]
7973 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
7975 return emit_ldm_seq (operands, 2);
7980 [(set (match_operand:SI 4 "memory_operand" "=m")
7981 (match_operand:SI 0 "s_register_operand" "r"))
7982 (set (match_operand:SI 5 "memory_operand" "=m")
7983 (match_operand:SI 1 "s_register_operand" "r"))
7984 (set (match_operand:SI 6 "memory_operand" "=m")
7985 (match_operand:SI 2 "s_register_operand" "r"))
7986 (set (match_operand:SI 7 "memory_operand" "=m")
7987 (match_operand:SI 3 "s_register_operand" "r"))]
7988 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
7990 return emit_stm_seq (operands, 4);
7995 [(set (match_operand:SI 3 "memory_operand" "=m")
7996 (match_operand:SI 0 "s_register_operand" "r"))
7997 (set (match_operand:SI 4 "memory_operand" "=m")
7998 (match_operand:SI 1 "s_register_operand" "r"))
7999 (set (match_operand:SI 5 "memory_operand" "=m")
8000 (match_operand:SI 2 "s_register_operand" "r"))]
8001 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8003 return emit_stm_seq (operands, 3);
8008 [(set (match_operand:SI 2 "memory_operand" "=m")
8009 (match_operand:SI 0 "s_register_operand" "r"))
8010 (set (match_operand:SI 3 "memory_operand" "=m")
8011 (match_operand:SI 1 "s_register_operand" "r"))]
8012 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8014 return emit_stm_seq (operands, 2);
8019 [(set (match_operand:SI 0 "s_register_operand" "")
8020 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8022 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8023 [(match_operand:SI 3 "s_register_operand" "")
8024 (match_operand:SI 4 "arm_rhs_operand" "")]))))
8025 (clobber (match_operand:SI 5 "s_register_operand" ""))]
8027 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8028 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8033 ;; This split can be used because CC_Z mode implies that the following
8034 ;; branch will be an equality, or an unsigned inequality, so the sign
8035 ;; extension is not needed.
8038 [(set (reg:CC_Z CC_REGNUM)
8040 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8042 (match_operand 1 "const_int_operand" "")))
8043 (clobber (match_scratch:SI 2 ""))]
8045 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8046 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8047 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8048 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8050 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8054 (define_expand "prologue"
8055 [(clobber (const_int 0))]
8058 arm_expand_prologue ();
8060 thumb_expand_prologue ();
8065 (define_expand "epilogue"
8066 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8070 thumb_expand_epilogue ();
8071 else if (USE_RETURN_INSN (FALSE))
8073 emit_jump_insn (gen_return ());
8076 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8078 gen_rtx_RETURN (VOIDmode)),
8084 ;; Note - although unspec_volatile's USE all hard registers,
8085 ;; USEs are ignored after relaod has completed. Thus we need
8086 ;; to add an unspec of the link register to ensure that flow
8087 ;; does not think that it is unused by the sibcall branch that
8088 ;; will replace the standard function epilogue.
8089 (define_insn "sibcall_epilogue"
8090 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
8091 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
8094 if (USE_RETURN_INSN (FALSE))
8095 return output_return_instruction (const_true_rtx, FALSE, FALSE);
8096 return arm_output_epilogue (FALSE);
8098 ;; Length is absolute worst case
8099 [(set_attr "length" "44")
8100 (set_attr "type" "block")
8101 ;; We don't clobber the conditions, but the potential length of this
8102 ;; operation is sufficient to make conditionalizing the sequence
8103 ;; unlikely to be profitable.
8104 (set_attr "conds" "clob")]
8107 (define_insn "*epilogue_insns"
8108 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8112 return arm_output_epilogue (TRUE);
8113 else /* TARGET_THUMB */
8114 return thumb_unexpanded_epilogue ();
8116 ; Length is absolute worst case
8117 [(set_attr "length" "44")
8118 (set_attr "type" "block")
8119 ;; We don't clobber the conditions, but the potential length of this
8120 ;; operation is sufficient to make conditionalizing the sequence
8121 ;; unlikely to be profitable.
8122 (set_attr "conds" "clob")]
8125 (define_expand "eh_epilogue"
8126 [(use (match_operand:SI 0 "register_operand" ""))
8127 (use (match_operand:SI 1 "register_operand" ""))
8128 (use (match_operand:SI 2 "register_operand" ""))]
8132 cfun->machine->eh_epilogue_sp_ofs = operands[1];
8133 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8135 rtx ra = gen_rtx_REG (Pmode, 2);
8137 emit_move_insn (ra, operands[2]);
8140 /* This is a hack -- we may have crystalized the function type too
8142 cfun->machine->func_type = 0;
8146 ;; This split is only used during output to reduce the number of patterns
8147 ;; that need assembler instructions adding to them. We allowed the setting
8148 ;; of the conditions to be implicit during rtl generation so that
8149 ;; the conditional compare patterns would work. However this conflicts to
8150 ;; some extent with the conditional data operations, so we have to split them
8154 [(set (match_operand:SI 0 "s_register_operand" "")
8155 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8156 [(match_operand 2 "" "") (match_operand 3 "" "")])
8158 (match_operand 4 "" "")))
8159 (clobber (reg:CC CC_REGNUM))]
8160 "TARGET_ARM && reload_completed"
8161 [(set (match_dup 5) (match_dup 6))
8162 (cond_exec (match_dup 7)
8163 (set (match_dup 0) (match_dup 4)))]
8166 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8167 operands[2], operands[3]);
8168 enum rtx_code rc = GET_CODE (operands[1]);
8170 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8171 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8172 if (mode == CCFPmode || mode == CCFPEmode)
8173 rc = reverse_condition_maybe_unordered (rc);
8175 rc = reverse_condition (rc);
8177 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8182 [(set (match_operand:SI 0 "s_register_operand" "")
8183 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8184 [(match_operand 2 "" "") (match_operand 3 "" "")])
8185 (match_operand 4 "" "")
8187 (clobber (reg:CC CC_REGNUM))]
8188 "TARGET_ARM && reload_completed"
8189 [(set (match_dup 5) (match_dup 6))
8190 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8191 (set (match_dup 0) (match_dup 4)))]
8194 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8195 operands[2], operands[3]);
8197 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8198 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8203 [(set (match_operand:SI 0 "s_register_operand" "")
8204 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8205 [(match_operand 2 "" "") (match_operand 3 "" "")])
8206 (match_operand 4 "" "")
8207 (match_operand 5 "" "")))
8208 (clobber (reg:CC CC_REGNUM))]
8209 "TARGET_ARM && reload_completed"
8210 [(set (match_dup 6) (match_dup 7))
8211 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8212 (set (match_dup 0) (match_dup 4)))
8213 (cond_exec (match_dup 8)
8214 (set (match_dup 0) (match_dup 5)))]
8217 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8218 operands[2], operands[3]);
8219 enum rtx_code rc = GET_CODE (operands[1]);
8221 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8222 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8223 if (mode == CCFPmode || mode == CCFPEmode)
8224 rc = reverse_condition_maybe_unordered (rc);
8226 rc = reverse_condition (rc);
8228 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8233 [(set (match_operand:SI 0 "s_register_operand" "")
8234 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8235 [(match_operand:SI 2 "s_register_operand" "")
8236 (match_operand:SI 3 "arm_add_operand" "")])
8237 (match_operand:SI 4 "arm_rhs_operand" "")
8239 (match_operand:SI 5 "s_register_operand" ""))))
8240 (clobber (reg:CC CC_REGNUM))]
8241 "TARGET_ARM && reload_completed"
8242 [(set (match_dup 6) (match_dup 7))
8243 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8244 (set (match_dup 0) (match_dup 4)))
8245 (cond_exec (match_dup 8)
8246 (set (match_dup 0) (not:SI (match_dup 5))))]
8249 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8250 operands[2], operands[3]);
8251 enum rtx_code rc = GET_CODE (operands[1]);
8253 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8254 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8255 if (mode == CCFPmode || mode == CCFPEmode)
8256 rc = reverse_condition_maybe_unordered (rc);
8258 rc = reverse_condition (rc);
8260 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8264 (define_insn "*cond_move_not"
8265 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8266 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8267 [(match_operand 3 "cc_register" "") (const_int 0)])
8268 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8270 (match_operand:SI 2 "s_register_operand" "r,r"))))]
8274 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8275 [(set_attr "conds" "use")
8276 (set_attr "length" "4,8")]
8279 ;; The next two patterns occur when an AND operation is followed by a
8280 ;; scc insn sequence
8282 (define_insn "*sign_extract_onebit"
8283 [(set (match_operand:SI 0 "s_register_operand" "=r")
8284 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8286 (match_operand:SI 2 "const_int_operand" "n")))
8287 (clobber (reg:CC CC_REGNUM))]
8290 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8291 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8292 return \"mvnne\\t%0, #0\";
8294 [(set_attr "conds" "clob")
8295 (set_attr "length" "8")]
8298 (define_insn "*not_signextract_onebit"
8299 [(set (match_operand:SI 0 "s_register_operand" "=r")
8301 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8303 (match_operand:SI 2 "const_int_operand" "n"))))
8304 (clobber (reg:CC CC_REGNUM))]
8307 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8308 output_asm_insn (\"tst\\t%1, %2\", operands);
8309 output_asm_insn (\"mvneq\\t%0, #0\", operands);
8310 return \"movne\\t%0, #0\";
8312 [(set_attr "conds" "clob")
8313 (set_attr "length" "12")]
8316 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
8317 ;; expressions. For simplicity, the first register is also in the unspec
8319 (define_insn "*push_multi"
8320 [(match_parallel 2 "multi_register_push"
8321 [(set (match_operand:BLK 0 "memory_operand" "=m")
8322 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8323 UNSPEC_PUSH_MULT))])]
8327 int num_saves = XVECLEN (operands[2], 0);
8329 /* For the StrongARM at least it is faster to
8330 use STR to store only a single register. */
8332 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8338 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
8340 for (i = 1; i < num_saves; i++)
8342 strcat (pattern, \", %|\");
8344 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
8347 strcat (pattern, \"}\");
8348 output_asm_insn (pattern, operands);
8353 [(set_attr "type" "store4")]
8356 (define_insn "stack_tie"
8357 [(set (mem:BLK (scratch))
8358 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
8359 (match_operand:SI 1 "s_register_operand" "r")]
8363 [(set_attr "length" "0")]
8366 ;; Similarly for the floating point registers
8367 (define_insn "*push_fp_multi"
8368 [(match_parallel 2 "multi_register_push"
8369 [(set (match_operand:BLK 0 "memory_operand" "=m")
8370 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
8371 UNSPEC_PUSH_MULT))])]
8377 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
8378 output_asm_insn (pattern, operands);
8381 [(set_attr "type" "f_store")]
8384 ;; Special patterns for dealing with the constant pool
8386 (define_insn "align_4"
8387 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
8390 assemble_align (32);
8395 (define_insn "consttable_end"
8396 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
8399 making_const_table = FALSE;
8404 (define_insn "consttable_1"
8405 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
8408 making_const_table = TRUE;
8409 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
8413 [(set_attr "length" "4")]
8416 (define_insn "consttable_2"
8417 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
8420 making_const_table = TRUE;
8421 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
8425 [(set_attr "length" "4")]
8428 (define_insn "consttable_4"
8429 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
8433 making_const_table = TRUE;
8434 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8439 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8440 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8444 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
8449 [(set_attr "length" "4")]
8452 (define_insn "consttable_8"
8453 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
8457 making_const_table = TRUE;
8458 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8463 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8464 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8468 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
8473 [(set_attr "length" "8")]
8476 ;; Miscellaneous Thumb patterns
8478 (define_expand "tablejump"
8479 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
8480 (use (label_ref (match_operand 1 "" "")))])]
8485 /* Hopefully, CSE will eliminate this copy. */
8486 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
8487 rtx reg2 = gen_reg_rtx (SImode);
8489 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
8495 (define_insn "*thumb_tablejump"
8496 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
8497 (use (label_ref (match_operand 1 "" "")))]
8500 [(set_attr "length" "2")]
8505 (define_insn "clzsi2"
8506 [(set (match_operand:SI 0 "s_register_operand" "=r")
8507 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
8508 "TARGET_ARM && arm_arch5"
8511 (define_expand "ffssi2"
8512 [(set (match_operand:SI 0 "s_register_operand" "")
8513 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
8514 "TARGET_ARM && arm_arch5"
8519 t1 = gen_reg_rtx (SImode);
8520 t2 = gen_reg_rtx (SImode);
8521 t3 = gen_reg_rtx (SImode);
8523 emit_insn (gen_negsi2 (t1, operands[1]));
8524 emit_insn (gen_andsi3 (t2, operands[1], t1));
8525 emit_insn (gen_clzsi2 (t3, t2));
8526 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
8531 (define_expand "ctzsi2"
8532 [(set (match_operand:SI 0 "s_register_operand" "")
8533 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
8534 "TARGET_ARM && arm_arch5"
8539 t1 = gen_reg_rtx (SImode);
8540 t2 = gen_reg_rtx (SImode);
8541 t3 = gen_reg_rtx (SImode);
8543 emit_insn (gen_negsi2 (t1, operands[1]));
8544 emit_insn (gen_andsi3 (t2, operands[1], t1));
8545 emit_insn (gen_clzsi2 (t3, t2));
8546 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
8551 ;; V5E instructions.
8553 (define_insn "prefetch"
8554 [(prefetch (match_operand:SI 0 "address_operand" "p")
8555 (match_operand:SI 1 "" "")
8556 (match_operand:SI 2 "" ""))]
8557 "TARGET_ARM && arm_arch5e"
8560 ;; General predication pattern
8563 [(match_operator 0 "arm_comparison_operator"
8564 [(match_operand 1 "cc_register" "")
8570 (define_insn "prologue_use"
8571 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
8573 "%@ %0 needed for prologue"
8576 ;; Load the FPA co-processor patterns
8578 ;; Load the Maverick co-processor patterns
8579 (include "cirrus.md")