1 ;;- Machine description for ARM for GNU compiler
2 ;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;; 2001, 2002, 2003 Free Software Foundation, Inc.
4 ;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;; and Martin Simmons (@harleqn.co.uk).
6 ;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
8 ;; This file is part of GCC.
10 ;; GCC is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 2, or (at your
13 ;; option) any later version.
15 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
18 ;; License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; see the file COPYING. If not, write to
22 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
28 ;;---------------------------------------------------------------------------
33 [(IP_REGNUM 12) ; Scratch register
34 (SP_REGNUM 13) ; Stack pointer
35 (LR_REGNUM 14) ; Return address register
36 (PC_REGNUM 15) ; Program counter
37 (CC_REGNUM 24) ; Condition code pseudo register
41 ;; 3rd operand to select_dominance_cc_mode
50 ;; Note: sin and cos are no-longer used.
53 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
54 ; operand 0 is the result,
55 ; operand 1 the parameter.
56 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
57 ; operand 0 is the result,
58 ; operand 1 the parameter.
59 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
60 ; operand 0 is the first register,
61 ; subsequent registers are in parallel (use ...)
63 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
64 ; usage, that is, we will add the pic_register
65 ; value to it before trying to dereference it.
66 (UNSPEC_PIC_BASE 4) ; Adding the PC value to the offset to the
67 ; GLOBAL_OFFSET_TABLE. The operation is fully
68 ; described by the RTL but must be wrapped to
69 ; prevent combine from trying to rip it apart.
70 (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses
71 ; being scheduled before the stack adjustment insn.
72 (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
73 ; this unspec is used to prevent the deletion of
74 ; instructions setting registers for EH handling
75 ; and stack frame generation. Operand 0 is the
77 (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
81 ;; UNSPEC_VOLATILE Usage:
84 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
86 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
87 ; instruction epilogue sequence that isn't expanded
88 ; into normal RTL. Used for both normal and sibcall
90 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
91 ; for inlined constants.
92 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
94 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
96 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
98 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
100 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
105 ;;---------------------------------------------------------------------------
108 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
109 ; generating ARM code. This is used to control the length of some insn
110 ; patterns that share the same RTL in both ARM and Thumb code.
111 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
113 ; PROG_MODE attribute is used to determine whether condition codes are
114 ; clobbered by a call insn: they are if in prog32 mode. This is controlled
115 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
116 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
118 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
119 ; scheduling decisions for the load unit and the multiplier.
120 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
122 ;; Operand number of an input operand that is shifted. Zero if the
123 ;; given instruction does not shift one of its input operands.
124 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
125 (define_attr "shift" "" (const_int 0))
127 ; Floating Point Unit. If we only have floating point emulation, then there
128 ; is no point in scheduling the floating point insns. (Well, for best
129 ; performance we should try and group them together).
130 (define_attr "fpu" "softfpa,fpa,fpe2,fpe3,maverick"
131 (const (symbol_ref "arm_fpu_attr")))
133 ; LENGTH of an instruction (in bytes)
134 (define_attr "length" "" (const_int 4))
136 ; POOL_RANGE is how far away from a constant pool entry that this insn
137 ; can be placed. If the distance is zero, then this insn will never
138 ; reference the pool.
139 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
140 ; before its address.
141 (define_attr "pool_range" "" (const_int 0))
142 (define_attr "neg_pool_range" "" (const_int 0))
144 ; An assembler sequence may clobber the condition codes without us knowing.
145 ; If such an insn references the pool, then we have no way of knowing how,
146 ; so use the most conservative value for pool_range.
147 (define_asm_attributes
148 [(set_attr "conds" "clob")
149 (set_attr "length" "4")
150 (set_attr "pool_range" "250")])
152 ; TYPE attribute is used to detect floating point instructions which, if
153 ; running on a co-processor can run in parallel with other, basic instructions
154 ; If write-buffer scheduling is enabled then it can also be used in the
155 ; scheduling of writes.
157 ; Classification of each insn
158 ; normal any data instruction that doesn't hit memory or fp regs
159 ; mult a multiply instruction
160 ; block blockage insn, this blocks all functional units
161 ; float a floating point arithmetic operation (subject to expansion)
162 ; fdivd DFmode floating point division
163 ; fdivs SFmode floating point division
164 ; fmul Floating point multiply
165 ; ffmul Fast floating point multiply
166 ; farith Floating point arithmetic (4 cycle)
167 ; ffarith Fast floating point arithmetic (2 cycle)
168 ; float_em a floating point arithmetic operation that is normally emulated
169 ; even on a machine with an fpa.
170 ; f_load a floating point load from memory
171 ; f_store a floating point store to memory
172 ; f_mem_r a transfer of a floating point register to a real reg via mem
173 ; r_mem_f the reverse of f_mem_r
174 ; f_2_r fast transfer float to arm (no memory needed)
175 ; r_2_f fast transfer arm to float
176 ; call a subroutine call
177 ; load any load from memory
178 ; store1 store 1 word to memory from arm registers
179 ; store2 store 2 words
180 ; store3 store 3 words
181 ; store4 store 4 words
182 ; Additions for Cirrus Maverick co-processor:
183 ; mav_farith Floating point arithmetic (4 cycle)
184 ; mav_dmult Double multiplies (7 cycle)
187 "normal,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,call,load,store1,store2,store3,store4,mav_farith,mav_dmult"
188 (const_string "normal"))
190 ; Load scheduling, set from the arm_ld_sched variable
191 ; initialized by arm_override_options()
192 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
194 ; condition codes: this one is used by final_prescan_insn to speed up
195 ; conditionalizing instructions. It saves having to scan the rtl to see if
196 ; it uses or alters the condition codes.
198 ; USE means that the condition codes are used by the insn in the process of
199 ; outputting code, this means (at present) that we can't use the insn in
202 ; SET means that the purpose of the insn is to set the condition codes in a
203 ; well defined manner.
205 ; CLOB means that the condition codes are altered in an undefined manner, if
206 ; they are altered at all
208 ; JUMP_CLOB is used when the condition cannot be represented by a single
209 ; instruction (UNEQ and LTGT). These cannot be predicated.
211 ; NOCOND means that the condition codes are neither altered nor affect the
212 ; output of this insn
214 (define_attr "conds" "use,set,clob,jump_clob,nocond"
215 (if_then_else (eq_attr "type" "call")
216 (if_then_else (eq_attr "prog_mode" "prog32")
217 (const_string "clob") (const_string "nocond"))
218 (const_string "nocond")))
220 ; Predicable means that the insn can be conditionally executed based on
221 ; an automatically added predicate (additional patterns are generated by
222 ; gen...). We default to 'no' because no Thumb patterns match this rule
223 ; and not all ARM patterns do.
224 (define_attr "predicable" "no,yes" (const_string "no"))
226 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
227 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
228 ; suffer blockages enough to warrent modelling this (and it can adversely
229 ; affect the schedule).
230 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
232 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
233 ; to stall the processor. Used with model_wbuf above.
234 (define_attr "write_conflict" "no,yes"
235 (if_then_else (eq_attr "type"
236 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
238 (const_string "no")))
240 ; Classify the insns into those that take one cycle and those that take more
241 ; than one on the main cpu execution unit.
242 (define_attr "core_cycles" "single,multi"
243 (if_then_else (eq_attr "type"
244 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
245 (const_string "single")
246 (const_string "multi")))
248 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
249 ;; distant label. Only applicable to Thumb code.
250 (define_attr "far_jump" "yes,no" (const_string "no"))
252 (define_automaton "arm")
256 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
258 ; The write buffer on some of the arm6 processors is hard to model exactly.
259 ; There is room in the buffer for up to two addresses and up to eight words
260 ; of memory, but the two needn't be split evenly. When writing the two
261 ; addresses are fully pipelined. However, a read from memory that is not
262 ; currently in the cache will block until the writes have completed.
263 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
264 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
265 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
266 ; cycle to add as well.
267 (define_cpu_unit "write_buf" "arm")
269 ;; Write blockage unit
271 ; The write_blockage unit models (partially), the fact that reads will stall
272 ; until the write buffer empties.
273 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
274 ; so we don't model them here
275 (define_cpu_unit "write_blockage" "arm")
279 (define_cpu_unit "core" "arm")
281 (define_insn_reservation "r_mem_f_wbuf" 5
282 (and (eq_attr "model_wbuf" "yes")
283 (eq_attr "type" "r_mem_f"))
286 (define_insn_reservation "store1_wbuf" 5
287 (and (eq_attr "model_wbuf" "yes")
288 (eq_attr "type" "store1"))
289 "core+write_buf*3+write_blockage*5")
291 (define_insn_reservation "store2_wbuf" 7
292 (and (eq_attr "model_wbuf" "yes")
293 (eq_attr "type" "store2"))
294 "core+write_buf*4+write_blockage*7")
296 (define_insn_reservation "store3_wbuf" 9
297 (and (eq_attr "model_wbuf" "yes")
298 (eq_attr "type" "store3"))
299 "core+write_buf*5+write_blockage*9")
301 (define_insn_reservation "store4_wbuf" 11
302 (and (eq_attr "model_wbuf" "yes")
303 (eq_attr "type" "store4"))
304 "core+write_buf*6+write_blockage*11")
306 (define_insn_reservation "store2" 3
307 (and (eq_attr "model_wbuf" "no")
308 (eq_attr "type" "store2"))
311 (define_insn_reservation "store3" 4
312 (and (eq_attr "model_wbuf" "no")
313 (eq_attr "type" "store3"))
316 (define_insn_reservation "store4" 5
317 (and (eq_attr "model_wbuf" "no")
318 (eq_attr "type" "store4"))
321 (define_insn_reservation "store1_ldsched" 1
322 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1"))
325 (define_insn_reservation "load_ldsched_xscale" 3
326 (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
327 (eq_attr "is_xscale" "yes"))
330 (define_insn_reservation "load_ldsched" 2
331 (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
332 (eq_attr "is_xscale" "no"))
335 (define_insn_reservation "load_or_store" 2
336 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1"))
339 (define_insn_reservation "mult" 16
340 (and (eq_attr "ldsched" "no") (eq_attr "type" "mult"))
343 (define_insn_reservation "mult_ldsched_strongarm" 3
344 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
345 (eq_attr "type" "mult"))
348 (define_insn_reservation "mult_ldsched" 4
349 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
350 (eq_attr "type" "mult"))
353 (define_insn_reservation "multi_cycle" 32
354 (and (eq_attr "core_cycles" "multi")
355 (eq_attr "type" "!mult,load,store1,store2,store3,store4"))
358 (define_insn_reservation "single_cycle" 1
359 (eq_attr "core_cycles" "single")
363 ;;---------------------------------------------------------------------------
368 ;; Note: For DImode insns, there is normally no reason why operands should
369 ;; not be in the same register, what we don't want is for something being
370 ;; written to partially overlap something that is an input.
371 ;; Cirrus 64bit additions should not be split because we have a native
372 ;; 64bit addition instructions.
374 (define_expand "adddi3"
376 [(set (match_operand:DI 0 "s_register_operand" "")
377 (plus:DI (match_operand:DI 1 "s_register_operand" "")
378 (match_operand:DI 2 "s_register_operand" "")))
379 (clobber (reg:CC CC_REGNUM))])]
384 if (!cirrus_fp_register (operands[0], DImode))
385 operands[0] = force_reg (DImode, operands[0]);
386 if (!cirrus_fp_register (operands[1], DImode))
387 operands[1] = force_reg (DImode, operands[1]);
388 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
394 if (GET_CODE (operands[1]) != REG)
395 operands[1] = force_reg (SImode, operands[1]);
396 if (GET_CODE (operands[2]) != REG)
397 operands[2] = force_reg (SImode, operands[2]);
402 (define_insn "*thumb_adddi3"
403 [(set (match_operand:DI 0 "register_operand" "=l")
404 (plus:DI (match_operand:DI 1 "register_operand" "%0")
405 (match_operand:DI 2 "register_operand" "l")))
406 (clobber (reg:CC CC_REGNUM))
409 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
410 [(set_attr "length" "4")]
413 (define_insn_and_split "*arm_adddi3"
414 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
415 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
416 (match_operand:DI 2 "s_register_operand" "r, 0")))
417 (clobber (reg:CC CC_REGNUM))]
418 "TARGET_ARM && !TARGET_CIRRUS"
420 "TARGET_ARM && reload_completed"
421 [(parallel [(set (reg:CC_C CC_REGNUM)
422 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
424 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
425 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
426 (plus:SI (match_dup 4) (match_dup 5))))]
429 operands[3] = gen_highpart (SImode, operands[0]);
430 operands[0] = gen_lowpart (SImode, operands[0]);
431 operands[4] = gen_highpart (SImode, operands[1]);
432 operands[1] = gen_lowpart (SImode, operands[1]);
433 operands[5] = gen_highpart (SImode, operands[2]);
434 operands[2] = gen_lowpart (SImode, operands[2]);
436 [(set_attr "conds" "clob")
437 (set_attr "length" "8")]
440 (define_insn_and_split "*adddi_sesidi_di"
441 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
442 (plus:DI (sign_extend:DI
443 (match_operand:SI 2 "s_register_operand" "r,r"))
444 (match_operand:DI 1 "s_register_operand" "r,0")))
445 (clobber (reg:CC CC_REGNUM))]
446 "TARGET_ARM && !TARGET_CIRRUS"
448 "TARGET_ARM && reload_completed"
449 [(parallel [(set (reg:CC_C CC_REGNUM)
450 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
452 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
453 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
454 (plus:SI (ashiftrt:SI (match_dup 2)
459 operands[3] = gen_highpart (SImode, operands[0]);
460 operands[0] = gen_lowpart (SImode, operands[0]);
461 operands[4] = gen_highpart (SImode, operands[1]);
462 operands[1] = gen_lowpart (SImode, operands[1]);
463 operands[2] = gen_lowpart (SImode, operands[2]);
465 [(set_attr "conds" "clob")
466 (set_attr "length" "8")]
469 (define_insn_and_split "*adddi_zesidi_di"
470 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
471 (plus:DI (zero_extend:DI
472 (match_operand:SI 2 "s_register_operand" "r,r"))
473 (match_operand:DI 1 "s_register_operand" "r,0")))
474 (clobber (reg:CC CC_REGNUM))]
475 "TARGET_ARM && !TARGET_CIRRUS"
477 "TARGET_ARM && reload_completed"
478 [(parallel [(set (reg:CC_C CC_REGNUM)
479 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
481 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
482 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
483 (plus:SI (match_dup 4) (const_int 0))))]
486 operands[3] = gen_highpart (SImode, operands[0]);
487 operands[0] = gen_lowpart (SImode, operands[0]);
488 operands[4] = gen_highpart (SImode, operands[1]);
489 operands[1] = gen_lowpart (SImode, operands[1]);
490 operands[2] = gen_lowpart (SImode, operands[2]);
492 [(set_attr "conds" "clob")
493 (set_attr "length" "8")]
496 (define_expand "addsi3"
497 [(set (match_operand:SI 0 "s_register_operand" "")
498 (plus:SI (match_operand:SI 1 "s_register_operand" "")
499 (match_operand:SI 2 "reg_or_int_operand" "")))]
502 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
504 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
506 (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
512 ; If there is a scratch available, this will be faster than synthesising the
515 [(match_scratch:SI 3 "r")
516 (set (match_operand:SI 0 "s_register_operand" "")
517 (plus:SI (match_operand:SI 1 "s_register_operand" "")
518 (match_operand:SI 2 "const_int_operand" "")))]
520 !(const_ok_for_arm (INTVAL (operands[2]))
521 || const_ok_for_arm (-INTVAL (operands[2])))
522 && const_ok_for_arm (~INTVAL (operands[2]))"
523 [(set (match_dup 3) (match_dup 2))
524 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
528 (define_insn_and_split "*arm_addsi3"
529 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
530 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
531 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
538 GET_CODE (operands[2]) == CONST_INT
539 && !(const_ok_for_arm (INTVAL (operands[2]))
540 || const_ok_for_arm (-INTVAL (operands[2])))"
541 [(clobber (const_int 0))]
543 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
547 [(set_attr "length" "4,4,16")
548 (set_attr "predicable" "yes")]
551 ;; Register group 'k' is a single register group containing only the stack
552 ;; register. Trying to reload it will always fail catastrophically,
553 ;; so never allow those alternatives to match if reloading is needed.
555 (define_insn "*thumb_addsi3"
556 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
557 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
558 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
561 static const char * const asms[] =
563 \"add\\t%0, %0, %2\",
564 \"sub\\t%0, %0, #%n2\",
565 \"add\\t%0, %1, %2\",
566 \"add\\t%0, %0, %2\",
567 \"add\\t%0, %0, %2\",
568 \"add\\t%0, %1, %2\",
571 if ((which_alternative == 2 || which_alternative == 6)
572 && GET_CODE (operands[2]) == CONST_INT
573 && INTVAL (operands[2]) < 0)
574 return \"sub\\t%0, %1, #%n2\";
575 return asms[which_alternative];
577 [(set_attr "length" "2")]
580 ;; Reloading and elimination of the frame pointer can
581 ;; sometimes cause this optimization to be missed.
583 [(set (match_operand:SI 0 "register_operand" "")
584 (match_operand:SI 1 "const_int_operand" ""))
586 (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
588 && REGNO (operands[2]) == STACK_POINTER_REGNUM
589 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
590 && (INTVAL (operands[1]) & 3) == 0"
591 [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
595 (define_insn "*addsi3_compare0"
596 [(set (reg:CC_NOOV CC_REGNUM)
598 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
599 (match_operand:SI 2 "arm_add_operand" "rI,L"))
601 (set (match_operand:SI 0 "s_register_operand" "=r,r")
602 (plus:SI (match_dup 1) (match_dup 2)))]
606 sub%?s\\t%0, %1, #%n2"
607 [(set_attr "conds" "set")]
610 (define_insn "*addsi3_compare0_scratch"
611 [(set (reg:CC_NOOV CC_REGNUM)
613 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
614 (match_operand:SI 1 "arm_add_operand" "rI,L"))
620 [(set_attr "conds" "set")]
623 ;; These patterns are the same ones as the two regular addsi3_compare0
624 ;; patterns, except we write them slightly different - the combiner
625 ;; tends to generate them this way.
626 (define_insn "*addsi3_compare0_for_combiner"
627 [(set (reg:CC CC_REGNUM)
629 (match_operand:SI 1 "s_register_operand" "r,r")
630 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
631 (set (match_operand:SI 0 "s_register_operand" "=r,r")
632 (plus:SI (match_dup 1) (match_dup 2)))]
636 sub%?s\\t%0, %1, #%n2"
637 [(set_attr "conds" "set")]
640 (define_insn "*addsi3_compare0_scratch_for_combiner"
641 [(set (reg:CC CC_REGNUM)
643 (match_operand:SI 0 "s_register_operand" "r,r")
644 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
649 [(set_attr "conds" "set")]
652 ;; The next four insns work because they compare the result with one of
653 ;; the operands, and we know that the use of the condition code is
654 ;; either GEU or LTU, so we can use the carry flag from the addition
655 ;; instead of doing the compare a second time.
656 (define_insn "*addsi3_compare_op1"
657 [(set (reg:CC_C CC_REGNUM)
659 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
660 (match_operand:SI 2 "arm_add_operand" "rI,L"))
662 (set (match_operand:SI 0 "s_register_operand" "=r,r")
663 (plus:SI (match_dup 1) (match_dup 2)))]
667 sub%?s\\t%0, %1, #%n2"
668 [(set_attr "conds" "set")]
671 (define_insn "*addsi3_compare_op2"
672 [(set (reg:CC_C CC_REGNUM)
674 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
675 (match_operand:SI 2 "arm_add_operand" "rI,L"))
677 (set (match_operand:SI 0 "s_register_operand" "=r,r")
678 (plus:SI (match_dup 1) (match_dup 2)))]
682 sub%?s\\t%0, %1, #%n2"
683 [(set_attr "conds" "set")]
686 (define_insn "*compare_addsi2_op0"
687 [(set (reg:CC_C CC_REGNUM)
689 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
690 (match_operand:SI 1 "arm_add_operand" "rI,L"))
696 [(set_attr "conds" "set")]
699 (define_insn "*compare_addsi2_op1"
700 [(set (reg:CC_C CC_REGNUM)
702 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
703 (match_operand:SI 1 "arm_add_operand" "rI,L"))
709 [(set_attr "conds" "set")]
712 (define_insn "*addsi3_carryin"
713 [(set (match_operand:SI 0 "s_register_operand" "=r")
714 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
715 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
716 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
719 [(set_attr "conds" "use")]
722 (define_insn "*addsi3_carryin_shift"
723 [(set (match_operand:SI 0 "s_register_operand" "")
724 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
726 (match_operator:SI 2 "shift_operator"
727 [(match_operand:SI 3 "s_register_operand" "")
728 (match_operand:SI 4 "reg_or_int_operand" "")])
729 (match_operand:SI 1 "s_register_operand" ""))))]
731 "adc%?\\t%0, %1, %3%S2"
732 [(set_attr "conds" "use")]
735 (define_insn "*addsi3_carryin_alt1"
736 [(set (match_operand:SI 0 "s_register_operand" "=r")
737 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
738 (match_operand:SI 2 "arm_rhs_operand" "rI"))
739 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
742 [(set_attr "conds" "use")]
745 (define_insn "*addsi3_carryin_alt2"
746 [(set (match_operand:SI 0 "s_register_operand" "=r")
747 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
748 (match_operand:SI 1 "s_register_operand" "r"))
749 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
752 [(set_attr "conds" "use")]
755 (define_insn "*addsi3_carryin_alt3"
756 [(set (match_operand:SI 0 "s_register_operand" "=r")
757 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
758 (match_operand:SI 2 "arm_rhs_operand" "rI"))
759 (match_operand:SI 1 "s_register_operand" "r")))]
762 [(set_attr "conds" "use")]
765 (define_insn "incscc"
766 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
767 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
768 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
769 (match_operand:SI 1 "s_register_operand" "0,?r")))]
773 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
774 [(set_attr "conds" "use")
775 (set_attr "length" "4,8")]
778 (define_expand "addsf3"
779 [(set (match_operand:SF 0 "s_register_operand" "")
780 (plus:SF (match_operand:SF 1 "s_register_operand" "")
781 (match_operand:SF 2 "fpa_add_operand" "")))]
782 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
785 && !cirrus_fp_register (operands[2], SFmode))
786 operands[2] = force_reg (SFmode, operands[2]);
789 (define_expand "adddf3"
790 [(set (match_operand:DF 0 "s_register_operand" "")
791 (plus:DF (match_operand:DF 1 "s_register_operand" "")
792 (match_operand:DF 2 "fpa_add_operand" "")))]
793 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
796 && !cirrus_fp_register (operands[2], DFmode))
797 operands[2] = force_reg (DFmode, operands[2]);
800 (define_expand "subdi3"
802 [(set (match_operand:DI 0 "s_register_operand" "")
803 (minus:DI (match_operand:DI 1 "s_register_operand" "")
804 (match_operand:DI 2 "s_register_operand" "")))
805 (clobber (reg:CC CC_REGNUM))])]
810 && cirrus_fp_register (operands[0], DImode)
811 && cirrus_fp_register (operands[1], DImode))
813 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
819 if (GET_CODE (operands[1]) != REG)
820 operands[1] = force_reg (SImode, operands[1]);
821 if (GET_CODE (operands[2]) != REG)
822 operands[2] = force_reg (SImode, operands[2]);
827 (define_insn "*arm_subdi3"
828 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
829 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
830 (match_operand:DI 2 "s_register_operand" "r,0,0")))
831 (clobber (reg:CC CC_REGNUM))]
833 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
834 [(set_attr "conds" "clob")
835 (set_attr "length" "8")]
838 (define_insn "*thumb_subdi3"
839 [(set (match_operand:DI 0 "register_operand" "=l")
840 (minus:DI (match_operand:DI 1 "register_operand" "0")
841 (match_operand:DI 2 "register_operand" "l")))
842 (clobber (reg:CC CC_REGNUM))]
844 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
845 [(set_attr "length" "4")]
848 (define_insn "*subdi_di_zesidi"
849 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
850 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
852 (match_operand:SI 2 "s_register_operand" "r,r"))))
853 (clobber (reg:CC CC_REGNUM))]
855 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
856 [(set_attr "conds" "clob")
857 (set_attr "length" "8")]
860 (define_insn "*subdi_di_sesidi"
861 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
862 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
864 (match_operand:SI 2 "s_register_operand" "r,r"))))
865 (clobber (reg:CC CC_REGNUM))]
867 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
868 [(set_attr "conds" "clob")
869 (set_attr "length" "8")]
872 (define_insn "*subdi_zesidi_di"
873 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
874 (minus:DI (zero_extend:DI
875 (match_operand:SI 2 "s_register_operand" "r,r"))
876 (match_operand:DI 1 "s_register_operand" "?r,0")))
877 (clobber (reg:CC CC_REGNUM))]
879 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
880 [(set_attr "conds" "clob")
881 (set_attr "length" "8")]
884 (define_insn "*subdi_sesidi_di"
885 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
886 (minus:DI (sign_extend:DI
887 (match_operand:SI 2 "s_register_operand" "r,r"))
888 (match_operand:DI 1 "s_register_operand" "?r,0")))
889 (clobber (reg:CC CC_REGNUM))]
891 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
892 [(set_attr "conds" "clob")
893 (set_attr "length" "8")]
896 (define_insn "*subdi_zesidi_zesidi"
897 [(set (match_operand:DI 0 "s_register_operand" "=r")
898 (minus:DI (zero_extend:DI
899 (match_operand:SI 1 "s_register_operand" "r"))
901 (match_operand:SI 2 "s_register_operand" "r"))))
902 (clobber (reg:CC CC_REGNUM))]
904 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
905 [(set_attr "conds" "clob")
906 (set_attr "length" "8")]
909 (define_expand "subsi3"
910 [(set (match_operand:SI 0 "s_register_operand" "")
911 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
912 (match_operand:SI 2 "s_register_operand" "")))]
915 if (GET_CODE (operands[1]) == CONST_INT)
919 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
922 : preserve_subexpressions_p ()));
925 else /* TARGET_THUMB */
926 operands[1] = force_reg (SImode, operands[1]);
931 (define_insn "*thumb_subsi3_insn"
932 [(set (match_operand:SI 0 "register_operand" "=l")
933 (minus:SI (match_operand:SI 1 "register_operand" "l")
934 (match_operand:SI 2 "register_operand" "l")))]
937 [(set_attr "length" "2")]
940 (define_insn_and_split "*arm_subsi3_insn"
941 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
942 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
943 (match_operand:SI 2 "s_register_operand" "r,r")))]
949 && GET_CODE (operands[1]) == CONST_INT
950 && !const_ok_for_arm (INTVAL (operands[1]))"
951 [(clobber (const_int 0))]
953 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
957 [(set_attr "length" "4,16")
958 (set_attr "predicable" "yes")]
962 [(match_scratch:SI 3 "r")
963 (set (match_operand:SI 0 "s_register_operand" "")
964 (minus:SI (match_operand:SI 1 "const_int_operand" "")
965 (match_operand:SI 2 "s_register_operand" "")))]
967 && !const_ok_for_arm (INTVAL (operands[1]))
968 && const_ok_for_arm (~INTVAL (operands[1]))"
969 [(set (match_dup 3) (match_dup 1))
970 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
974 (define_insn "*subsi3_compare0"
975 [(set (reg:CC_NOOV CC_REGNUM)
977 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
978 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
980 (set (match_operand:SI 0 "s_register_operand" "=r,r")
981 (minus:SI (match_dup 1) (match_dup 2)))]
986 [(set_attr "conds" "set")]
989 (define_insn "decscc"
990 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
991 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
992 (match_operator:SI 2 "arm_comparison_operator"
993 [(match_operand 3 "cc_register" "") (const_int 0)])))]
997 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
998 [(set_attr "conds" "use")
999 (set_attr "length" "*,8")]
1002 (define_expand "subsf3"
1003 [(set (match_operand:SF 0 "s_register_operand" "")
1004 (minus:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1005 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1006 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1010 if (!cirrus_fp_register (operands[1], SFmode))
1011 operands[1] = force_reg (SFmode, operands[1]);
1012 if (!cirrus_fp_register (operands[2], SFmode))
1013 operands[2] = force_reg (SFmode, operands[2]);
1017 (define_expand "subdf3"
1018 [(set (match_operand:DF 0 "s_register_operand" "")
1019 (minus:DF (match_operand:DF 1 "fpa_rhs_operand" "")
1020 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1021 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1025 if (!cirrus_fp_register (operands[1], DFmode))
1026 operands[1] = force_reg (DFmode, operands[1]);
1027 if (!cirrus_fp_register (operands[2], DFmode))
1028 operands[2] = force_reg (DFmode, operands[2]);
1033 ;; Multiplication insns
1035 (define_expand "mulsi3"
1036 [(set (match_operand:SI 0 "s_register_operand" "")
1037 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1038 (match_operand:SI 1 "s_register_operand" "")))]
1043 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1044 (define_insn "*arm_mulsi3"
1045 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1046 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1047 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1049 "mul%?\\t%0, %2, %1"
1050 [(set_attr "type" "mult")
1051 (set_attr "predicable" "yes")]
1054 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1055 ; 1 and 2; are the same, because reload will make operand 0 match
1056 ; operand 1 without realizing that this conflicts with operand 2. We fix
1057 ; this by adding another alternative to match this case, and then `reload'
1058 ; it ourselves. This alternative must come first.
1059 (define_insn "*thumb_mulsi3"
1060 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1061 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1062 (match_operand:SI 2 "register_operand" "l,l,l")))]
1065 if (which_alternative < 2)
1066 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1068 return \"mul\\t%0, %0, %2\";
1070 [(set_attr "length" "4,4,2")
1071 (set_attr "type" "mult")]
1074 (define_insn "*mulsi3_compare0"
1075 [(set (reg:CC_NOOV CC_REGNUM)
1076 (compare:CC_NOOV (mult:SI
1077 (match_operand:SI 2 "s_register_operand" "r,r")
1078 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1080 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1081 (mult:SI (match_dup 2) (match_dup 1)))]
1082 "TARGET_ARM && !arm_arch_xscale"
1083 "mul%?s\\t%0, %2, %1"
1084 [(set_attr "conds" "set")
1085 (set_attr "type" "mult")]
1088 (define_insn "*mulsi_compare0_scratch"
1089 [(set (reg:CC_NOOV CC_REGNUM)
1090 (compare:CC_NOOV (mult:SI
1091 (match_operand:SI 2 "s_register_operand" "r,r")
1092 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1094 (clobber (match_scratch:SI 0 "=&r,&r"))]
1095 "TARGET_ARM && !arm_arch_xscale"
1096 "mul%?s\\t%0, %2, %1"
1097 [(set_attr "conds" "set")
1098 (set_attr "type" "mult")]
1101 ;; Unnamed templates to match MLA instruction.
1103 (define_insn "*mulsi3addsi"
1104 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1106 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1107 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1108 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1110 "mla%?\\t%0, %2, %1, %3"
1111 [(set_attr "type" "mult")
1112 (set_attr "predicable" "yes")]
1115 (define_insn "*mulsi3addsi_compare0"
1116 [(set (reg:CC_NOOV CC_REGNUM)
1119 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1120 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1121 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1123 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1124 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1126 "TARGET_ARM && !arm_arch_xscale"
1127 "mla%?s\\t%0, %2, %1, %3"
1128 [(set_attr "conds" "set")
1129 (set_attr "type" "mult")]
1132 (define_insn "*mulsi3addsi_compare0_scratch"
1133 [(set (reg:CC_NOOV CC_REGNUM)
1136 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1137 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1138 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1140 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1141 "TARGET_ARM && !arm_arch_xscale"
1142 "mla%?s\\t%0, %2, %1, %3"
1143 [(set_attr "conds" "set")
1144 (set_attr "type" "mult")]
1147 ;; Unnamed template to match long long multiply-accumlate (smlal)
1149 (define_insn "*mulsidi3adddi"
1150 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1153 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1154 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1155 (match_operand:DI 1 "s_register_operand" "0")))]
1156 "TARGET_ARM && arm_fast_multiply"
1157 "smlal%?\\t%Q0, %R0, %3, %2"
1158 [(set_attr "type" "mult")
1159 (set_attr "predicable" "yes")]
1162 (define_insn "mulsidi3"
1163 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1165 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1166 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1167 "TARGET_ARM && arm_fast_multiply"
1168 "smull%?\\t%Q0, %R0, %1, %2"
1169 [(set_attr "type" "mult")
1170 (set_attr "predicable" "yes")]
1173 (define_insn "umulsidi3"
1174 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1176 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1177 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1178 "TARGET_ARM && arm_fast_multiply"
1179 "umull%?\\t%Q0, %R0, %1, %2"
1180 [(set_attr "type" "mult")
1181 (set_attr "predicable" "yes")]
1184 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1186 (define_insn "*umulsidi3adddi"
1187 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1190 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1191 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1192 (match_operand:DI 1 "s_register_operand" "0")))]
1193 "TARGET_ARM && arm_fast_multiply"
1194 "umlal%?\\t%Q0, %R0, %3, %2"
1195 [(set_attr "type" "mult")
1196 (set_attr "predicable" "yes")]
1199 (define_insn "smulsi3_highpart"
1200 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1204 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1205 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1207 (clobber (match_scratch:SI 3 "=&r,&r"))]
1208 "TARGET_ARM && arm_fast_multiply"
1209 "smull%?\\t%3, %0, %2, %1"
1210 [(set_attr "type" "mult")
1211 (set_attr "predicable" "yes")]
1214 (define_insn "umulsi3_highpart"
1215 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1219 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1220 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1222 (clobber (match_scratch:SI 3 "=&r,&r"))]
1223 "TARGET_ARM && arm_fast_multiply"
1224 "umull%?\\t%3, %0, %2, %1"
1225 [(set_attr "type" "mult")
1226 (set_attr "predicable" "yes")]
1229 (define_insn "mulhisi3"
1230 [(set (match_operand:SI 0 "s_register_operand" "=r")
1231 (mult:SI (sign_extend:SI
1232 (match_operand:HI 1 "s_register_operand" "%r"))
1234 (match_operand:HI 2 "s_register_operand" "r"))))]
1235 "TARGET_ARM && arm_arch5e"
1236 "smulbb%?\\t%0, %1, %2"
1237 [(set_attr "type" "mult")
1238 (set_attr "predicable" "yes")]
1241 (define_insn "*mulhisi3tb"
1242 [(set (match_operand:SI 0 "s_register_operand" "=r")
1243 (mult:SI (ashiftrt:SI
1244 (match_operand:SI 1 "s_register_operand" "r")
1247 (match_operand:HI 2 "s_register_operand" "r"))))]
1248 "TARGET_ARM && arm_arch5e"
1249 "smultb%?\\t%0, %1, %2"
1250 [(set_attr "type" "mult")
1251 (set_attr "predicable" "yes")]
1254 (define_insn "*mulhisi3bt"
1255 [(set (match_operand:SI 0 "s_register_operand" "=r")
1256 (mult:SI (sign_extend:SI
1257 (match_operand:HI 1 "s_register_operand" "r"))
1259 (match_operand:SI 2 "s_register_operand" "r")
1261 "TARGET_ARM && arm_arch5e"
1262 "smulbt%?\\t%0, %1, %2"
1263 [(set_attr "type" "mult")
1264 (set_attr "predicable" "yes")]
1267 (define_insn "*mulhisi3tt"
1268 [(set (match_operand:SI 0 "s_register_operand" "=r")
1269 (mult:SI (ashiftrt:SI
1270 (match_operand:SI 1 "s_register_operand" "r")
1273 (match_operand:SI 2 "s_register_operand" "r")
1275 "TARGET_ARM && arm_arch5e"
1276 "smultt%?\\t%0, %1, %2"
1277 [(set_attr "type" "mult")
1278 (set_attr "predicable" "yes")]
1281 (define_insn "*mulhisi3addsi"
1282 [(set (match_operand:SI 0 "s_register_operand" "=r")
1283 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1284 (mult:SI (sign_extend:SI
1285 (match_operand:HI 2 "s_register_operand" "%r"))
1287 (match_operand:HI 3 "s_register_operand" "r")))))]
1288 "TARGET_ARM && arm_arch5e"
1289 "smlabb%?\\t%0, %2, %3, %1"
1290 [(set_attr "type" "mult")
1291 (set_attr "predicable" "yes")]
1294 (define_insn "*mulhidi3adddi"
1295 [(set (match_operand:DI 0 "s_register_operand" "=r")
1297 (match_operand:DI 1 "s_register_operand" "0")
1298 (mult:DI (sign_extend:DI
1299 (match_operand:HI 2 "s_register_operand" "%r"))
1301 (match_operand:HI 3 "s_register_operand" "r")))))]
1302 "TARGET_ARM && arm_arch5e"
1303 "smlalbb%?\\t%Q0, %R0, %2, %3"
1304 [(set_attr "type" "mult")
1305 (set_attr "predicable" "yes")])
1307 (define_expand "mulsf3"
1308 [(set (match_operand:SF 0 "s_register_operand" "")
1309 (mult:SF (match_operand:SF 1 "s_register_operand" "")
1310 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1311 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1314 && !cirrus_fp_register (operands[2], SFmode))
1315 operands[2] = force_reg (SFmode, operands[2]);
1318 (define_expand "muldf3"
1319 [(set (match_operand:DF 0 "s_register_operand" "")
1320 (mult:DF (match_operand:DF 1 "s_register_operand" "")
1321 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1322 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1325 && !cirrus_fp_register (operands[2], DFmode))
1326 operands[2] = force_reg (DFmode, operands[2]);
1331 (define_expand "divsf3"
1332 [(set (match_operand:SF 0 "s_register_operand" "")
1333 (div:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1334 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1335 "TARGET_ARM && TARGET_HARD_FLOAT"
1338 (define_expand "divdf3"
1339 [(set (match_operand:DF 0 "s_register_operand" "")
1340 (div:DF (match_operand:DF 1 "fpa_rhs_operand" "")
1341 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1342 "TARGET_ARM && TARGET_HARD_FLOAT"
1347 (define_expand "modsf3"
1348 [(set (match_operand:SF 0 "s_register_operand" "")
1349 (mod:SF (match_operand:SF 1 "s_register_operand" "")
1350 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1351 "TARGET_ARM && TARGET_HARD_FLOAT"
1354 (define_expand "moddf3"
1355 [(set (match_operand:DF 0 "s_register_operand" "")
1356 (mod:DF (match_operand:DF 1 "s_register_operand" "")
1357 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1358 "TARGET_ARM && TARGET_HARD_FLOAT"
1361 ;; Boolean and,ior,xor insns
1363 ;; Split up double word logical operations
1365 ;; Split up simple DImode logical operations. Simply perform the logical
1366 ;; operation on the upper and lower halves of the registers.
1368 [(set (match_operand:DI 0 "s_register_operand" "")
1369 (match_operator:DI 6 "logical_binary_operator"
1370 [(match_operand:DI 1 "s_register_operand" "")
1371 (match_operand:DI 2 "s_register_operand" "")]))]
1372 "TARGET_ARM && reload_completed"
1373 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1374 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1377 operands[3] = gen_highpart (SImode, operands[0]);
1378 operands[0] = gen_lowpart (SImode, operands[0]);
1379 operands[4] = gen_highpart (SImode, operands[1]);
1380 operands[1] = gen_lowpart (SImode, operands[1]);
1381 operands[5] = gen_highpart (SImode, operands[2]);
1382 operands[2] = gen_lowpart (SImode, operands[2]);
1387 [(set (match_operand:DI 0 "s_register_operand" "")
1388 (match_operator:DI 6 "logical_binary_operator"
1389 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1390 (match_operand:DI 1 "s_register_operand" "")]))]
1391 "TARGET_ARM && reload_completed"
1392 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1393 (set (match_dup 3) (match_op_dup:SI 6
1394 [(ashiftrt:SI (match_dup 2) (const_int 31))
1398 operands[3] = gen_highpart (SImode, operands[0]);
1399 operands[0] = gen_lowpart (SImode, operands[0]);
1400 operands[4] = gen_highpart (SImode, operands[1]);
1401 operands[1] = gen_lowpart (SImode, operands[1]);
1402 operands[5] = gen_highpart (SImode, operands[2]);
1403 operands[2] = gen_lowpart (SImode, operands[2]);
1407 ;; The zero extend of operand 2 means we can just copy the high part of
1408 ;; operand1 into operand0.
1410 [(set (match_operand:DI 0 "s_register_operand" "")
1412 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1413 (match_operand:DI 1 "s_register_operand" "")))]
1414 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1415 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1416 (set (match_dup 3) (match_dup 4))]
1419 operands[4] = gen_highpart (SImode, operands[1]);
1420 operands[3] = gen_highpart (SImode, operands[0]);
1421 operands[0] = gen_lowpart (SImode, operands[0]);
1422 operands[1] = gen_lowpart (SImode, operands[1]);
1426 ;; The zero extend of operand 2 means we can just copy the high part of
1427 ;; operand1 into operand0.
1429 [(set (match_operand:DI 0 "s_register_operand" "")
1431 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1432 (match_operand:DI 1 "s_register_operand" "")))]
1433 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1434 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1435 (set (match_dup 3) (match_dup 4))]
1438 operands[4] = gen_highpart (SImode, operands[1]);
1439 operands[3] = gen_highpart (SImode, operands[0]);
1440 operands[0] = gen_lowpart (SImode, operands[0]);
1441 operands[1] = gen_lowpart (SImode, operands[1]);
1445 (define_insn "anddi3"
1446 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1447 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1448 (match_operand:DI 2 "s_register_operand" "r,r")))]
1451 [(set_attr "length" "8")]
1454 (define_insn_and_split "*anddi_zesidi_di"
1455 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1456 (and:DI (zero_extend:DI
1457 (match_operand:SI 2 "s_register_operand" "r,r"))
1458 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1461 "TARGET_ARM && reload_completed"
1462 ; The zero extend of operand 2 clears the high word of the output
1464 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1465 (set (match_dup 3) (const_int 0))]
1468 operands[3] = gen_highpart (SImode, operands[0]);
1469 operands[0] = gen_lowpart (SImode, operands[0]);
1470 operands[1] = gen_lowpart (SImode, operands[1]);
1472 [(set_attr "length" "8")]
1475 (define_insn "*anddi_sesdi_di"
1476 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1477 (and:DI (sign_extend:DI
1478 (match_operand:SI 2 "s_register_operand" "r,r"))
1479 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1482 [(set_attr "length" "8")]
1485 (define_expand "andsi3"
1486 [(set (match_operand:SI 0 "s_register_operand" "")
1487 (and:SI (match_operand:SI 1 "s_register_operand" "")
1488 (match_operand:SI 2 "reg_or_int_operand" "")))]
1493 if (GET_CODE (operands[2]) == CONST_INT)
1495 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1498 ? 0 : preserve_subexpressions_p ()));
1502 else /* TARGET_THUMB */
1504 if (GET_CODE (operands[2]) != CONST_INT)
1505 operands[2] = force_reg (SImode, operands[2]);
1510 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1512 operands[2] = force_reg (SImode,
1513 GEN_INT (~INTVAL (operands[2])));
1515 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1520 for (i = 9; i <= 31; i++)
1522 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1524 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1528 else if ((((HOST_WIDE_INT) 1) << i) - 1
1529 == ~INTVAL (operands[2]))
1531 rtx shift = GEN_INT (i);
1532 rtx reg = gen_reg_rtx (SImode);
1534 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1535 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1541 operands[2] = force_reg (SImode, operands[2]);
1547 (define_insn_and_split "*arm_andsi3_insn"
1548 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1549 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1550 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1554 bic%?\\t%0, %1, #%B2
1557 && GET_CODE (operands[2]) == CONST_INT
1558 && !(const_ok_for_arm (INTVAL (operands[2]))
1559 || const_ok_for_arm (~INTVAL (operands[2])))"
1560 [(clobber (const_int 0))]
1562 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1566 [(set_attr "length" "4,4,16")
1567 (set_attr "predicable" "yes")]
1570 (define_insn "*thumb_andsi3_insn"
1571 [(set (match_operand:SI 0 "register_operand" "=l")
1572 (and:SI (match_operand:SI 1 "register_operand" "%0")
1573 (match_operand:SI 2 "register_operand" "l")))]
1576 [(set_attr "length" "2")]
1579 (define_insn "*andsi3_compare0"
1580 [(set (reg:CC_NOOV CC_REGNUM)
1582 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1583 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1585 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1586 (and:SI (match_dup 1) (match_dup 2)))]
1590 bic%?s\\t%0, %1, #%B2"
1591 [(set_attr "conds" "set")]
1594 (define_insn "*andsi3_compare0_scratch"
1595 [(set (reg:CC_NOOV CC_REGNUM)
1597 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1598 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1600 (clobber (match_scratch:SI 2 "=X,r"))]
1604 bic%?s\\t%2, %0, #%B1"
1605 [(set_attr "conds" "set")]
1608 (define_insn "*zeroextractsi_compare0_scratch"
1609 [(set (reg:CC_NOOV CC_REGNUM)
1610 (compare:CC_NOOV (zero_extract:SI
1611 (match_operand:SI 0 "s_register_operand" "r")
1612 (match_operand 1 "const_int_operand" "n")
1613 (match_operand 2 "const_int_operand" "n"))
1616 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1617 && INTVAL (operands[1]) > 0
1618 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1619 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1621 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1622 << INTVAL (operands[2]));
1623 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1626 [(set_attr "conds" "set")]
1629 (define_insn "*ne_zeroextractsi"
1630 [(set (match_operand:SI 0 "s_register_operand" "=r")
1631 (ne:SI (zero_extract:SI
1632 (match_operand:SI 1 "s_register_operand" "r")
1633 (match_operand:SI 2 "const_int_operand" "n")
1634 (match_operand:SI 3 "const_int_operand" "n"))
1636 (clobber (reg:CC CC_REGNUM))]
1638 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1639 && INTVAL (operands[2]) > 0
1640 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1641 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1643 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1644 << INTVAL (operands[3]));
1645 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1646 return \"movne\\t%0, #1\";
1648 [(set_attr "conds" "clob")
1649 (set_attr "length" "8")]
1652 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1653 ;;; represented by the bitfield, then this will produce incorrect results.
1654 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1655 ;;; which have a real bit-field insert instruction, the truncation happens
1656 ;;; in the bit-field insert instruction itself. Since arm does not have a
1657 ;;; bit-field insert instruction, we would have to emit code here to truncate
1658 ;;; the value before we insert. This loses some of the advantage of having
1659 ;;; this insv pattern, so this pattern needs to be reevalutated.
1661 (define_expand "insv"
1662 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1663 (match_operand:SI 1 "general_operand" "")
1664 (match_operand:SI 2 "general_operand" ""))
1665 (match_operand:SI 3 "reg_or_int_operand" ""))]
1669 int start_bit = INTVAL (operands[2]);
1670 int width = INTVAL (operands[1]);
1671 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1672 rtx target, subtarget;
1674 target = operands[0];
1675 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1676 subreg as the final target. */
1677 if (GET_CODE (target) == SUBREG)
1679 subtarget = gen_reg_rtx (SImode);
1680 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1681 < GET_MODE_SIZE (SImode))
1682 target = SUBREG_REG (target);
1687 if (GET_CODE (operands[3]) == CONST_INT)
1689 /* Since we are inserting a known constant, we may be able to
1690 reduce the number of bits that we have to clear so that
1691 the mask becomes simple. */
1692 /* ??? This code does not check to see if the new mask is actually
1693 simpler. It may not be. */
1694 rtx op1 = gen_reg_rtx (SImode);
1695 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1696 start of this pattern. */
1697 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1698 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1700 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1701 emit_insn (gen_iorsi3 (subtarget, op1,
1702 GEN_INT (op3_value << start_bit)));
1704 else if (start_bit == 0
1705 && !(const_ok_for_arm (mask)
1706 || const_ok_for_arm (~mask)))
1708 /* A Trick, since we are setting the bottom bits in the word,
1709 we can shift operand[3] up, operand[0] down, OR them together
1710 and rotate the result back again. This takes 3 insns, and
1711 the third might be mergable into another op. */
1712 /* The shift up copes with the possibility that operand[3] is
1713 wider than the bitfield. */
1714 rtx op0 = gen_reg_rtx (SImode);
1715 rtx op1 = gen_reg_rtx (SImode);
1717 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1718 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1719 emit_insn (gen_iorsi3 (op1, op1, op0));
1720 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1722 else if ((width + start_bit == 32)
1723 && !(const_ok_for_arm (mask)
1724 || const_ok_for_arm (~mask)))
1726 /* Similar trick, but slightly less efficient. */
1728 rtx op0 = gen_reg_rtx (SImode);
1729 rtx op1 = gen_reg_rtx (SImode);
1731 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1732 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1733 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1734 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1738 rtx op0 = GEN_INT (mask);
1739 rtx op1 = gen_reg_rtx (SImode);
1740 rtx op2 = gen_reg_rtx (SImode);
1742 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1744 rtx tmp = gen_reg_rtx (SImode);
1746 emit_insn (gen_movsi (tmp, op0));
1750 /* Mask out any bits in operand[3] that are not needed. */
1751 emit_insn (gen_andsi3 (op1, operands[3], op0));
1753 if (GET_CODE (op0) == CONST_INT
1754 && (const_ok_for_arm (mask << start_bit)
1755 || const_ok_for_arm (~(mask << start_bit))))
1757 op0 = GEN_INT (~(mask << start_bit));
1758 emit_insn (gen_andsi3 (op2, operands[0], op0));
1762 if (GET_CODE (op0) == CONST_INT)
1764 rtx tmp = gen_reg_rtx (SImode);
1766 emit_insn (gen_movsi (tmp, op0));
1771 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1773 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1777 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1779 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1782 if (subtarget != target)
1784 /* If TARGET is still a SUBREG, then it must be wider than a word,
1785 so we must be careful only to set the subword we were asked to. */
1786 if (GET_CODE (target) == SUBREG)
1787 emit_move_insn (target, subtarget);
1789 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1796 ; constants for op 2 will never be given to these patterns.
1797 (define_insn_and_split "*anddi_notdi_di"
1798 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1799 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1800 (match_operand:DI 2 "s_register_operand" "0,r")))]
1803 "TARGET_ARM && reload_completed"
1804 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1805 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1808 operands[3] = gen_highpart (SImode, operands[0]);
1809 operands[0] = gen_lowpart (SImode, operands[0]);
1810 operands[4] = gen_highpart (SImode, operands[1]);
1811 operands[1] = gen_lowpart (SImode, operands[1]);
1812 operands[5] = gen_highpart (SImode, operands[2]);
1813 operands[2] = gen_lowpart (SImode, operands[2]);
1815 [(set_attr "length" "8")
1816 (set_attr "predicable" "yes")]
1819 (define_insn_and_split "*anddi_notzesidi_di"
1820 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1821 (and:DI (not:DI (zero_extend:DI
1822 (match_operand:SI 2 "s_register_operand" "r,r")))
1823 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1826 bic%?\\t%Q0, %Q1, %2
1828 ; (not (zero_extend ...)) allows us to just copy the high word from
1829 ; operand1 to operand0.
1832 && operands[0] != operands[1]"
1833 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1834 (set (match_dup 3) (match_dup 4))]
1837 operands[3] = gen_highpart (SImode, operands[0]);
1838 operands[0] = gen_lowpart (SImode, operands[0]);
1839 operands[4] = gen_highpart (SImode, operands[1]);
1840 operands[1] = gen_lowpart (SImode, operands[1]);
1842 [(set_attr "length" "4,8")
1843 (set_attr "predicable" "yes")]
1846 (define_insn_and_split "*anddi_notsesidi_di"
1847 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1848 (and:DI (not:DI (sign_extend:DI
1849 (match_operand:SI 2 "s_register_operand" "r,r")))
1850 (match_operand:DI 1 "s_register_operand" "0,r")))]
1853 "TARGET_ARM && reload_completed"
1854 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1855 (set (match_dup 3) (and:SI (not:SI
1856 (ashiftrt:SI (match_dup 2) (const_int 31)))
1860 operands[3] = gen_highpart (SImode, operands[0]);
1861 operands[0] = gen_lowpart (SImode, operands[0]);
1862 operands[4] = gen_highpart (SImode, operands[1]);
1863 operands[1] = gen_lowpart (SImode, operands[1]);
1865 [(set_attr "length" "8")
1866 (set_attr "predicable" "yes")]
1869 (define_insn "andsi_notsi_si"
1870 [(set (match_operand:SI 0 "s_register_operand" "=r")
1871 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1872 (match_operand:SI 1 "s_register_operand" "r")))]
1874 "bic%?\\t%0, %1, %2"
1875 [(set_attr "predicable" "yes")]
1878 (define_insn "bicsi3"
1879 [(set (match_operand:SI 0 "register_operand" "=l")
1880 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
1881 (match_operand:SI 2 "register_operand" "0")))]
1884 [(set_attr "length" "2")]
1887 (define_insn "andsi_not_shiftsi_si"
1888 [(set (match_operand:SI 0 "s_register_operand" "=r")
1889 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
1890 [(match_operand:SI 2 "s_register_operand" "r")
1891 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
1892 (match_operand:SI 1 "s_register_operand" "r")))]
1894 "bic%?\\t%0, %1, %2%S4"
1895 [(set_attr "predicable" "yes")
1896 (set_attr "shift" "2")
1900 (define_insn "*andsi_notsi_si_compare0"
1901 [(set (reg:CC_NOOV CC_REGNUM)
1903 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1904 (match_operand:SI 1 "s_register_operand" "r"))
1906 (set (match_operand:SI 0 "s_register_operand" "=r")
1907 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
1909 "bic%?s\\t%0, %1, %2"
1910 [(set_attr "conds" "set")]
1913 (define_insn "*andsi_notsi_si_compare0_scratch"
1914 [(set (reg:CC_NOOV CC_REGNUM)
1916 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1917 (match_operand:SI 1 "s_register_operand" "r"))
1919 (clobber (match_scratch:SI 0 "=r"))]
1921 "bic%?s\\t%0, %1, %2"
1922 [(set_attr "conds" "set")]
1925 (define_insn "iordi3"
1926 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1927 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1928 (match_operand:DI 2 "s_register_operand" "r,r")))]
1931 [(set_attr "length" "8")
1932 (set_attr "predicable" "yes")]
1935 (define_insn "*iordi_zesidi_di"
1936 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1937 (ior:DI (zero_extend:DI
1938 (match_operand:SI 2 "s_register_operand" "r,r"))
1939 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1942 orr%?\\t%Q0, %Q1, %2
1944 [(set_attr "length" "4,8")
1945 (set_attr "predicable" "yes")]
1948 (define_insn "*iordi_sesidi_di"
1949 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1950 (ior:DI (sign_extend:DI
1951 (match_operand:SI 2 "s_register_operand" "r,r"))
1952 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1955 [(set_attr "length" "8")
1956 (set_attr "predicable" "yes")]
1959 (define_expand "iorsi3"
1960 [(set (match_operand:SI 0 "s_register_operand" "")
1961 (ior:SI (match_operand:SI 1 "s_register_operand" "")
1962 (match_operand:SI 2 "reg_or_int_operand" "")))]
1965 if (GET_CODE (operands[2]) == CONST_INT)
1969 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1972 ? 0 : preserve_subexpressions_p ()));
1975 else /* TARGET_THUMB */
1976 operands [2] = force_reg (SImode, operands [2]);
1981 (define_insn_and_split "*arm_iorsi3"
1982 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1983 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
1984 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
1990 && GET_CODE (operands[2]) == CONST_INT
1991 && !const_ok_for_arm (INTVAL (operands[2]))"
1992 [(clobber (const_int 0))]
1994 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1998 [(set_attr "length" "4,16")
1999 (set_attr "predicable" "yes")]
2002 (define_insn "*thumb_iorsi3"
2003 [(set (match_operand:SI 0 "register_operand" "=l")
2004 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2005 (match_operand:SI 2 "register_operand" "l")))]
2008 [(set_attr "length" "2")]
2012 [(match_scratch:SI 3 "r")
2013 (set (match_operand:SI 0 "s_register_operand" "")
2014 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2015 (match_operand:SI 2 "const_int_operand" "")))]
2017 && !const_ok_for_arm (INTVAL (operands[2]))
2018 && const_ok_for_arm (~INTVAL (operands[2]))"
2019 [(set (match_dup 3) (match_dup 2))
2020 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2024 (define_insn "*iorsi3_compare0"
2025 [(set (reg:CC_NOOV CC_REGNUM)
2026 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2027 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2029 (set (match_operand:SI 0 "s_register_operand" "=r")
2030 (ior:SI (match_dup 1) (match_dup 2)))]
2032 "orr%?s\\t%0, %1, %2"
2033 [(set_attr "conds" "set")]
2036 (define_insn "*iorsi3_compare0_scratch"
2037 [(set (reg:CC_NOOV CC_REGNUM)
2038 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2039 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2041 (clobber (match_scratch:SI 0 "=r"))]
2043 "orr%?s\\t%0, %1, %2"
2044 [(set_attr "conds" "set")]
2047 (define_insn "xordi3"
2048 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2049 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2050 (match_operand:DI 2 "s_register_operand" "r,r")))]
2053 [(set_attr "length" "8")
2054 (set_attr "predicable" "yes")]
2057 (define_insn "*xordi_zesidi_di"
2058 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2059 (xor:DI (zero_extend:DI
2060 (match_operand:SI 2 "s_register_operand" "r,r"))
2061 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2064 eor%?\\t%Q0, %Q1, %2
2066 [(set_attr "length" "4,8")
2067 (set_attr "predicable" "yes")]
2070 (define_insn "*xordi_sesidi_di"
2071 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2072 (xor:DI (sign_extend:DI
2073 (match_operand:SI 2 "s_register_operand" "r,r"))
2074 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2077 [(set_attr "length" "8")
2078 (set_attr "predicable" "yes")]
2081 (define_expand "xorsi3"
2082 [(set (match_operand:SI 0 "s_register_operand" "")
2083 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2084 (match_operand:SI 2 "arm_rhs_operand" "")))]
2087 if (GET_CODE (operands[2]) == CONST_INT)
2088 operands[2] = force_reg (SImode, operands[2]);
2092 (define_insn "*arm_xorsi3"
2093 [(set (match_operand:SI 0 "s_register_operand" "=r")
2094 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2095 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2097 "eor%?\\t%0, %1, %2"
2098 [(set_attr "predicable" "yes")]
2101 (define_insn "*thumb_xorsi3"
2102 [(set (match_operand:SI 0 "register_operand" "=l")
2103 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2104 (match_operand:SI 2 "register_operand" "l")))]
2107 [(set_attr "length" "2")]
2110 (define_insn "*xorsi3_compare0"
2111 [(set (reg:CC_NOOV CC_REGNUM)
2112 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2113 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2115 (set (match_operand:SI 0 "s_register_operand" "=r")
2116 (xor:SI (match_dup 1) (match_dup 2)))]
2118 "eor%?s\\t%0, %1, %2"
2119 [(set_attr "conds" "set")]
2122 (define_insn "*xorsi3_compare0_scratch"
2123 [(set (reg:CC_NOOV CC_REGNUM)
2124 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2125 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2129 [(set_attr "conds" "set")]
2132 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2133 ; (NOT D) we can sometimes merge the final NOT into one of the following
2137 [(set (match_operand:SI 0 "s_register_operand" "")
2138 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2139 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2140 (match_operand:SI 3 "arm_rhs_operand" "")))
2141 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2143 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2144 (not:SI (match_dup 3))))
2145 (set (match_dup 0) (not:SI (match_dup 4)))]
2149 (define_insn "*andsi_iorsi3_notsi"
2150 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2151 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2152 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2153 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2155 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2156 [(set_attr "length" "8")
2157 (set_attr "predicable" "yes")]
2162 ;; Minimum and maximum insns
2164 (define_insn "smaxsi3"
2165 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2166 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2167 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2168 (clobber (reg:CC CC_REGNUM))]
2171 cmp\\t%1, %2\;movlt\\t%0, %2
2172 cmp\\t%1, %2\;movge\\t%0, %1
2173 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2174 [(set_attr "conds" "clob")
2175 (set_attr "length" "8,8,12")]
2178 (define_insn "sminsi3"
2179 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2180 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2181 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2182 (clobber (reg:CC CC_REGNUM))]
2185 cmp\\t%1, %2\;movge\\t%0, %2
2186 cmp\\t%1, %2\;movlt\\t%0, %1
2187 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2188 [(set_attr "conds" "clob")
2189 (set_attr "length" "8,8,12")]
2192 (define_insn "umaxsi3"
2193 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2194 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2195 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2196 (clobber (reg:CC CC_REGNUM))]
2199 cmp\\t%1, %2\;movcc\\t%0, %2
2200 cmp\\t%1, %2\;movcs\\t%0, %1
2201 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2202 [(set_attr "conds" "clob")
2203 (set_attr "length" "8,8,12")]
2206 (define_insn "uminsi3"
2207 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2208 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2209 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2210 (clobber (reg:CC CC_REGNUM))]
2213 cmp\\t%1, %2\;movcs\\t%0, %2
2214 cmp\\t%1, %2\;movcc\\t%0, %1
2215 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2216 [(set_attr "conds" "clob")
2217 (set_attr "length" "8,8,12")]
2220 (define_insn "*store_minmaxsi"
2221 [(set (match_operand:SI 0 "memory_operand" "=m")
2222 (match_operator:SI 3 "minmax_operator"
2223 [(match_operand:SI 1 "s_register_operand" "r")
2224 (match_operand:SI 2 "s_register_operand" "r")]))
2225 (clobber (reg:CC CC_REGNUM))]
2228 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2230 output_asm_insn (\"cmp\\t%1, %2\", operands);
2231 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2232 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2235 [(set_attr "conds" "clob")
2236 (set_attr "length" "12")
2237 (set_attr "type" "store1")]
2240 ; Reject the frame pointer in operand[1], since reloading this after
2241 ; it has been eliminated can cause carnage.
2242 (define_insn "*minmax_arithsi"
2243 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2244 (match_operator:SI 4 "shiftable_operator"
2245 [(match_operator:SI 5 "minmax_operator"
2246 [(match_operand:SI 2 "s_register_operand" "r,r")
2247 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2248 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2249 (clobber (reg:CC CC_REGNUM))]
2251 && (GET_CODE (operands[1]) != REG
2252 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2253 && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2256 enum rtx_code code = GET_CODE (operands[4]);
2258 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2260 output_asm_insn (\"cmp\\t%2, %3\", operands);
2261 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2262 if (which_alternative != 0 || operands[3] != const0_rtx
2263 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2264 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2267 [(set_attr "conds" "clob")
2268 (set_attr "length" "12")]
2272 ;; Shift and rotation insns
2274 (define_expand "ashlsi3"
2275 [(set (match_operand:SI 0 "s_register_operand" "")
2276 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2277 (match_operand:SI 2 "arm_rhs_operand" "")))]
2280 if (GET_CODE (operands[2]) == CONST_INT
2281 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2283 emit_insn (gen_movsi (operands[0], const0_rtx));
2289 (define_insn "*thumb_ashlsi3"
2290 [(set (match_operand:SI 0 "register_operand" "=l,l")
2291 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2292 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2295 [(set_attr "length" "2")]
2298 (define_expand "ashrsi3"
2299 [(set (match_operand:SI 0 "s_register_operand" "")
2300 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2301 (match_operand:SI 2 "arm_rhs_operand" "")))]
2304 if (GET_CODE (operands[2]) == CONST_INT
2305 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2306 operands[2] = GEN_INT (31);
2310 (define_insn "*thumb_ashrsi3"
2311 [(set (match_operand:SI 0 "register_operand" "=l,l")
2312 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2313 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2316 [(set_attr "length" "2")]
2319 (define_expand "lshrsi3"
2320 [(set (match_operand:SI 0 "s_register_operand" "")
2321 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2322 (match_operand:SI 2 "arm_rhs_operand" "")))]
2325 if (GET_CODE (operands[2]) == CONST_INT
2326 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2328 emit_insn (gen_movsi (operands[0], const0_rtx));
2334 (define_insn "*thumb_lshrsi3"
2335 [(set (match_operand:SI 0 "register_operand" "=l,l")
2336 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2337 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2340 [(set_attr "length" "2")]
2343 (define_expand "rotlsi3"
2344 [(set (match_operand:SI 0 "s_register_operand" "")
2345 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2346 (match_operand:SI 2 "reg_or_int_operand" "")))]
2349 if (GET_CODE (operands[2]) == CONST_INT)
2350 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2353 rtx reg = gen_reg_rtx (SImode);
2354 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2360 (define_expand "rotrsi3"
2361 [(set (match_operand:SI 0 "s_register_operand" "")
2362 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2363 (match_operand:SI 2 "arm_rhs_operand" "")))]
2368 if (GET_CODE (operands[2]) == CONST_INT
2369 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2370 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2372 else /* TARGET_THUMB */
2374 if (GET_CODE (operands [2]) == CONST_INT)
2375 operands [2] = force_reg (SImode, operands[2]);
2380 (define_insn "*thumb_rotrsi3"
2381 [(set (match_operand:SI 0 "register_operand" "=l")
2382 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2383 (match_operand:SI 2 "register_operand" "l")))]
2386 [(set_attr "length" "2")]
2389 (define_expand "ashldi3"
2390 [(set (match_operand:DI 0 "s_register_operand" "")
2391 (ashift:DI (match_operand:DI 1 "general_operand" "")
2392 (match_operand:SI 2 "general_operand" "")))]
2393 "TARGET_ARM && (TARGET_CIRRUS)"
2395 if (! s_register_operand (operands[1], DImode))
2396 operands[1] = copy_to_mode_reg (DImode, operands[1]);
2397 if (! s_register_operand (operands[2], SImode))
2398 operands[2] = copy_to_mode_reg (SImode, operands[2]);
2402 (define_insn "*arm_shiftsi3"
2403 [(set (match_operand:SI 0 "s_register_operand" "=r")
2404 (match_operator:SI 3 "shift_operator"
2405 [(match_operand:SI 1 "s_register_operand" "r")
2406 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2409 [(set_attr "predicable" "yes")
2410 (set_attr "shift" "1")
2414 (define_insn "*shiftsi3_compare0"
2415 [(set (reg:CC_NOOV CC_REGNUM)
2416 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2417 [(match_operand:SI 1 "s_register_operand" "r")
2418 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2420 (set (match_operand:SI 0 "s_register_operand" "=r")
2421 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2423 "mov%?s\\t%0, %1%S3"
2424 [(set_attr "conds" "set")
2425 (set_attr "shift" "1")
2429 (define_insn "*shiftsi3_compare0_scratch"
2430 [(set (reg:CC_NOOV CC_REGNUM)
2431 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2432 [(match_operand:SI 1 "s_register_operand" "r")
2433 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2435 (clobber (match_scratch:SI 0 "=r"))]
2437 "mov%?s\\t%0, %1%S3"
2438 [(set_attr "conds" "set")
2439 (set_attr "shift" "1")
2443 (define_insn "*notsi_shiftsi"
2444 [(set (match_operand:SI 0 "s_register_operand" "=r")
2445 (not:SI (match_operator:SI 3 "shift_operator"
2446 [(match_operand:SI 1 "s_register_operand" "r")
2447 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2450 [(set_attr "predicable" "yes")
2451 (set_attr "shift" "1")
2455 (define_insn "*notsi_shiftsi_compare0"
2456 [(set (reg:CC_NOOV CC_REGNUM)
2457 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2458 [(match_operand:SI 1 "s_register_operand" "r")
2459 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2461 (set (match_operand:SI 0 "s_register_operand" "=r")
2462 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2464 "mvn%?s\\t%0, %1%S3"
2465 [(set_attr "conds" "set")
2466 (set_attr "shift" "1")
2470 (define_insn "*not_shiftsi_compare0_scratch"
2471 [(set (reg:CC_NOOV CC_REGNUM)
2472 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2473 [(match_operand:SI 1 "s_register_operand" "r")
2474 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2476 (clobber (match_scratch:SI 0 "=r"))]
2478 "mvn%?s\\t%0, %1%S3"
2479 [(set_attr "conds" "set")
2480 (set_attr "shift" "1")
2484 ;; We don't really have extzv, but defining this using shifts helps
2485 ;; to reduce register pressure later on.
2487 (define_expand "extzv"
2489 (ashift:SI (match_operand:SI 1 "register_operand" "")
2490 (match_operand:SI 2 "const_int_operand" "")))
2491 (set (match_operand:SI 0 "register_operand" "")
2492 (lshiftrt:SI (match_dup 4)
2493 (match_operand:SI 3 "const_int_operand" "")))]
2497 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2498 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2500 operands[3] = GEN_INT (rshift);
2504 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2508 operands[2] = GEN_INT (lshift);
2509 operands[4] = gen_reg_rtx (SImode);
2514 ;; Unary arithmetic insns
2516 (define_expand "negdi2"
2518 [(set (match_operand:DI 0 "s_register_operand" "")
2519 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2520 (clobber (reg:CC CC_REGNUM))])]
2525 if (GET_CODE (operands[1]) != REG)
2526 operands[1] = force_reg (SImode, operands[1]);
2531 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2532 ;; The second alternative is to allow the common case of a *full* overlap.
2533 (define_insn "*arm_negdi2"
2534 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2535 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2536 (clobber (reg:CC CC_REGNUM))]
2538 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2539 [(set_attr "conds" "clob")
2540 (set_attr "length" "8")]
2543 (define_insn "*thumb_negdi2"
2544 [(set (match_operand:DI 0 "register_operand" "=&l")
2545 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2546 (clobber (reg:CC CC_REGNUM))]
2548 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2549 [(set_attr "length" "6")]
2552 (define_expand "negsi2"
2553 [(set (match_operand:SI 0 "s_register_operand" "")
2554 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2559 (define_insn "*arm_negsi2"
2560 [(set (match_operand:SI 0 "s_register_operand" "=r")
2561 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2563 "rsb%?\\t%0, %1, #0"
2564 [(set_attr "predicable" "yes")]
2567 (define_insn "*thumb_negsi2"
2568 [(set (match_operand:SI 0 "register_operand" "=l")
2569 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2572 [(set_attr "length" "2")]
2575 (define_expand "negsf2"
2576 [(set (match_operand:SF 0 "s_register_operand" "")
2577 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2578 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2582 (define_expand "negdf2"
2583 [(set (match_operand:DF 0 "s_register_operand" "")
2584 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2585 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2588 ;; abssi2 doesn't really clobber the condition codes if a different register
2589 ;; is being set. To keep things simple, assume during rtl manipulations that
2590 ;; it does, but tell the final scan operator the truth. Similarly for
2593 (define_expand "abssi2"
2595 [(set (match_operand:SI 0 "s_register_operand" "")
2596 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2597 (clobber (reg:CC CC_REGNUM))])]
2601 (define_insn "*arm_abssi2"
2602 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2603 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2604 (clobber (reg:CC CC_REGNUM))]
2607 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2608 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2609 [(set_attr "conds" "clob,*")
2610 (set_attr "shift" "1")
2611 ;; predicable can't be set based on the variant, so left as no
2612 (set_attr "length" "8")]
2615 (define_insn "*neg_abssi2"
2616 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2617 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2618 (clobber (reg:CC CC_REGNUM))]
2621 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2622 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2623 [(set_attr "conds" "clob,*")
2624 (set_attr "shift" "1")
2625 ;; predicable can't be set based on the variant, so left as no
2626 (set_attr "length" "8")]
2629 (define_expand "abssf2"
2630 [(set (match_operand:SF 0 "s_register_operand" "")
2631 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
2632 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2635 (define_expand "absdf2"
2636 [(set (match_operand:DF 0 "s_register_operand" "")
2637 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
2638 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2641 (define_expand "sqrtsf2"
2642 [(set (match_operand:SF 0 "s_register_operand" "")
2643 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
2644 "TARGET_ARM && TARGET_HARD_FLOAT"
2647 (define_expand "sqrtdf2"
2648 [(set (match_operand:DF 0 "s_register_operand" "")
2649 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
2650 "TARGET_ARM && TARGET_HARD_FLOAT"
2653 (define_insn_and_split "one_cmpldi2"
2654 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2655 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2658 "TARGET_ARM && reload_completed"
2659 [(set (match_dup 0) (not:SI (match_dup 1)))
2660 (set (match_dup 2) (not:SI (match_dup 3)))]
2663 operands[2] = gen_highpart (SImode, operands[0]);
2664 operands[0] = gen_lowpart (SImode, operands[0]);
2665 operands[3] = gen_highpart (SImode, operands[1]);
2666 operands[1] = gen_lowpart (SImode, operands[1]);
2668 [(set_attr "length" "8")
2669 (set_attr "predicable" "yes")]
2672 (define_expand "one_cmplsi2"
2673 [(set (match_operand:SI 0 "s_register_operand" "")
2674 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2679 (define_insn "*arm_one_cmplsi2"
2680 [(set (match_operand:SI 0 "s_register_operand" "=r")
2681 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
2684 [(set_attr "predicable" "yes")]
2687 (define_insn "*thumb_one_cmplsi2"
2688 [(set (match_operand:SI 0 "register_operand" "=l")
2689 (not:SI (match_operand:SI 1 "register_operand" "l")))]
2692 [(set_attr "length" "2")]
2695 (define_insn "*notsi_compare0"
2696 [(set (reg:CC_NOOV CC_REGNUM)
2697 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2699 (set (match_operand:SI 0 "s_register_operand" "=r")
2700 (not:SI (match_dup 1)))]
2703 [(set_attr "conds" "set")]
2706 (define_insn "*notsi_compare0_scratch"
2707 [(set (reg:CC_NOOV CC_REGNUM)
2708 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2710 (clobber (match_scratch:SI 0 "=r"))]
2713 [(set_attr "conds" "set")]
2716 ;; Fixed <--> Floating conversion insns
2718 (define_expand "floatsisf2"
2719 [(set (match_operand:SF 0 "s_register_operand" "")
2720 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
2721 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2725 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
2730 (define_expand "floatsidf2"
2731 [(set (match_operand:DF 0 "s_register_operand" "")
2732 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
2733 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2737 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
2742 (define_expand "fix_truncsfsi2"
2743 [(set (match_operand:SI 0 "s_register_operand" "")
2744 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
2745 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2749 if (!cirrus_fp_register (operands[0], SImode))
2750 operands[0] = force_reg (SImode, operands[0]);
2751 if (!cirrus_fp_register (operands[1], SFmode))
2752 operands[1] = force_reg (SFmode, operands[0]);
2753 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
2758 (define_expand "fix_truncdfsi2"
2759 [(set (match_operand:SI 0 "s_register_operand" "")
2760 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
2761 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2765 if (!cirrus_fp_register (operands[1], DFmode))
2766 operands[1] = force_reg (DFmode, operands[0]);
2767 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
2774 (define_expand "truncdfsf2"
2775 [(set (match_operand:SF 0 "s_register_operand" "")
2777 (match_operand:DF 1 "s_register_operand" "")))]
2778 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2782 ;; Zero and sign extension instructions.
2784 (define_insn "zero_extendsidi2"
2785 [(set (match_operand:DI 0 "s_register_operand" "=r")
2786 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2789 if (REGNO (operands[1])
2790 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2791 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2792 return \"mov%?\\t%R0, #0\";
2794 [(set_attr "length" "8")
2795 (set_attr "predicable" "yes")]
2798 (define_insn "zero_extendqidi2"
2799 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
2800 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2803 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
2804 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
2805 [(set_attr "length" "8")
2806 (set_attr "predicable" "yes")
2807 (set_attr "type" "*,load")
2808 (set_attr "pool_range" "*,4092")
2809 (set_attr "neg_pool_range" "*,4084")]
2812 (define_insn "extendsidi2"
2813 [(set (match_operand:DI 0 "s_register_operand" "=r")
2814 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2817 if (REGNO (operands[1])
2818 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2819 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2820 return \"mov%?\\t%R0, %Q0, asr #31\";
2822 [(set_attr "length" "8")
2823 (set_attr "shift" "1")
2824 (set_attr "predicable" "yes")]
2827 (define_expand "zero_extendhisi2"
2829 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2831 (set (match_operand:SI 0 "s_register_operand" "")
2832 (lshiftrt:SI (match_dup 2) (const_int 16)))]
2838 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2840 /* Note: We do not have to worry about TARGET_MMU_TRAPS
2841 here because the insn below will generate an LDRH instruction
2842 rather than an LDR instruction, so we cannot get an unaligned
2844 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2845 gen_rtx_ZERO_EXTEND (SImode,
2849 if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
2851 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
2854 if (!s_register_operand (operands[1], HImode))
2855 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2856 operands[1] = gen_lowpart (SImode, operands[1]);
2857 operands[2] = gen_reg_rtx (SImode);
2859 else /* TARGET_THUMB */
2861 if (GET_CODE (operands[1]) == MEM)
2865 tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
2866 tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
2873 if (!s_register_operand (operands[1], HImode))
2874 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2875 operands[1] = gen_lowpart (SImode, operands[1]);
2876 operands[2] = gen_reg_rtx (SImode);
2878 ops[0] = operands[2];
2879 ops[1] = operands[1];
2880 ops[2] = GEN_INT (16);
2882 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
2883 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
2885 ops[0] = operands[0];
2886 ops[1] = operands[2];
2887 ops[2] = GEN_INT (16);
2889 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
2890 gen_rtx_LSHIFTRT (SImode, ops[1],
2898 (define_insn "*thumb_zero_extendhisi2"
2899 [(set (match_operand:SI 0 "register_operand" "=l")
2900 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2903 rtx mem = XEXP (operands[1], 0);
2905 if (GET_CODE (mem) == CONST)
2906 mem = XEXP (mem, 0);
2908 if (GET_CODE (mem) == LABEL_REF)
2909 return \"ldr\\t%0, %1\";
2911 if (GET_CODE (mem) == PLUS)
2913 rtx a = XEXP (mem, 0);
2914 rtx b = XEXP (mem, 1);
2916 /* This can happen due to bugs in reload. */
2917 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
2920 ops[0] = operands[0];
2923 output_asm_insn (\"mov %0, %1\", ops);
2925 XEXP (mem, 0) = operands[0];
2928 else if ( GET_CODE (a) == LABEL_REF
2929 && GET_CODE (b) == CONST_INT)
2930 return \"ldr\\t%0, %1\";
2933 return \"ldrh\\t%0, %1\";
2935 [(set_attr "length" "4")
2936 (set_attr "type" "load")
2937 (set_attr "pool_range" "60")]
2940 (define_insn "*arm_zero_extendhisi2"
2941 [(set (match_operand:SI 0 "s_register_operand" "=r")
2942 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2943 "TARGET_ARM && arm_arch4"
2945 [(set_attr "type" "load")
2946 (set_attr "predicable" "yes")
2947 (set_attr "pool_range" "256")
2948 (set_attr "neg_pool_range" "244")]
2952 [(set (match_operand:SI 0 "s_register_operand" "")
2953 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2954 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2955 "TARGET_ARM && (!arm_arch4)"
2956 [(set (match_dup 2) (match_dup 1))
2957 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
2959 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
2965 [(set (match_operand:SI 0 "s_register_operand" "")
2966 (match_operator:SI 3 "shiftable_operator"
2967 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2968 (match_operand:SI 4 "s_register_operand" "")]))
2969 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2970 "TARGET_ARM && (!arm_arch4)"
2971 [(set (match_dup 2) (match_dup 1))
2974 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2976 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
2981 (define_expand "zero_extendqisi2"
2982 [(set (match_operand:SI 0 "s_register_operand" "")
2983 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
2986 if (GET_CODE (operands[1]) != MEM)
2990 emit_insn (gen_andsi3 (operands[0],
2991 gen_lowpart (SImode, operands[1]),
2994 else /* TARGET_THUMB */
2996 rtx temp = gen_reg_rtx (SImode);
2999 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3000 operands[1] = gen_lowpart (SImode, operands[1]);
3003 ops[1] = operands[1];
3004 ops[2] = GEN_INT (24);
3006 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3007 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3009 ops[0] = operands[0];
3011 ops[2] = GEN_INT (24);
3013 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3014 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3021 (define_insn "*thumb_zero_extendqisi2"
3022 [(set (match_operand:SI 0 "register_operand" "=l")
3023 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3026 [(set_attr "length" "2")
3027 (set_attr "type" "load")
3028 (set_attr "pool_range" "32")]
3031 (define_insn "*arm_zero_extendqisi2"
3032 [(set (match_operand:SI 0 "s_register_operand" "=r")
3033 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3035 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3036 [(set_attr "type" "load")
3037 (set_attr "predicable" "yes")
3038 (set_attr "pool_range" "4096")
3039 (set_attr "neg_pool_range" "4084")]
3043 [(set (match_operand:SI 0 "s_register_operand" "")
3044 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3045 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3046 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3047 [(set (match_dup 2) (match_dup 1))
3048 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3052 (define_insn "*compareqi_eq0"
3053 [(set (reg:CC_Z CC_REGNUM)
3054 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3058 [(set_attr "conds" "set")]
3061 (define_expand "extendhisi2"
3063 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3065 (set (match_operand:SI 0 "s_register_operand" "")
3066 (ashiftrt:SI (match_dup 2)
3071 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3073 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3074 here because the insn below will generate an LDRH instruction
3075 rather than an LDR instruction, so we cannot get an unaligned
3077 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3078 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3082 if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3084 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3087 if (!s_register_operand (operands[1], HImode))
3088 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3089 operands[1] = gen_lowpart (SImode, operands[1]);
3090 operands[2] = gen_reg_rtx (SImode);
3096 ops[0] = operands[2];
3097 ops[1] = operands[1];
3098 ops[2] = GEN_INT (16);
3100 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3101 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3103 ops[0] = operands[0];
3104 ops[1] = operands[2];
3105 ops[2] = GEN_INT (16);
3107 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3108 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3115 (define_insn "*thumb_extendhisi2_insn"
3116 [(set (match_operand:SI 0 "register_operand" "=l")
3117 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3118 (clobber (match_scratch:SI 2 "=&l"))]
3123 rtx mem = XEXP (operands[1], 0);
3125 /* This code used to try to use 'V', and fix the address only if it was
3126 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3127 range of QImode offsets, and offsettable_address_p does a QImode
3130 if (GET_CODE (mem) == CONST)
3131 mem = XEXP (mem, 0);
3133 if (GET_CODE (mem) == LABEL_REF)
3134 return \"ldr\\t%0, %1\";
3136 if (GET_CODE (mem) == PLUS)
3138 rtx a = XEXP (mem, 0);
3139 rtx b = XEXP (mem, 1);
3141 if (GET_CODE (a) == LABEL_REF
3142 && GET_CODE (b) == CONST_INT)
3143 return \"ldr\\t%0, %1\";
3145 if (GET_CODE (b) == REG)
3146 return \"ldrsh\\t%0, %1\";
3154 ops[2] = const0_rtx;
3157 if (GET_CODE (ops[1]) != REG)
3163 ops[0] = operands[0];
3164 ops[3] = operands[2];
3165 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3168 [(set_attr "length" "4")
3169 (set_attr "type" "load")
3170 (set_attr "pool_range" "1020")]
3173 (define_expand "extendhisi2_mem"
3174 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3176 (zero_extend:SI (match_dup 7)))
3177 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3178 (set (match_operand:SI 0 "" "")
3179 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3184 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3186 mem1 = gen_rtx_MEM (QImode, addr);
3187 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3188 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3189 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3190 operands[0] = gen_lowpart (SImode, operands[0]);
3192 operands[2] = gen_reg_rtx (SImode);
3193 operands[3] = gen_reg_rtx (SImode);
3194 operands[6] = gen_reg_rtx (SImode);
3197 if (BYTES_BIG_ENDIAN)
3199 operands[4] = operands[2];
3200 operands[5] = operands[3];
3204 operands[4] = operands[3];
3205 operands[5] = operands[2];
3210 (define_insn "*arm_extendhisi_insn"
3211 [(set (match_operand:SI 0 "s_register_operand" "=r")
3212 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3213 "TARGET_ARM && arm_arch4"
3215 [(set_attr "type" "load")
3216 (set_attr "predicable" "yes")
3217 (set_attr "pool_range" "256")
3218 (set_attr "neg_pool_range" "244")]
3222 [(set (match_operand:SI 0 "s_register_operand" "")
3223 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3224 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3225 "TARGET_ARM && (!arm_arch4)"
3226 [(set (match_dup 2) (match_dup 1))
3227 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3229 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3235 [(set (match_operand:SI 0 "s_register_operand" "")
3236 (match_operator:SI 3 "shiftable_operator"
3237 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3238 (match_operand:SI 4 "s_register_operand" "")]))
3239 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3240 "TARGET_ARM && (!arm_arch4)"
3241 [(set (match_dup 2) (match_dup 1))
3244 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3245 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3250 (define_expand "extendqihi2"
3252 (ashift:SI (match_operand:QI 1 "general_operand" "")
3254 (set (match_operand:HI 0 "s_register_operand" "")
3255 (ashiftrt:SI (match_dup 2)
3260 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3262 emit_insn (gen_rtx_SET (VOIDmode,
3264 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3267 if (!s_register_operand (operands[1], QImode))
3268 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3269 operands[0] = gen_lowpart (SImode, operands[0]);
3270 operands[1] = gen_lowpart (SImode, operands[1]);
3271 operands[2] = gen_reg_rtx (SImode);
3275 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3276 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3277 (define_insn "*extendqihi_insn"
3278 [(set (match_operand:HI 0 "s_register_operand" "=r")
3279 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3280 "TARGET_ARM && arm_arch4"
3282 /* If the address is invalid, this will split the instruction into two. */
3283 if (bad_signed_byte_operand (operands[1], VOIDmode))
3285 return \"ldr%?sb\\t%0, %1\";
3287 [(set_attr "type" "load")
3288 (set_attr "predicable" "yes")
3289 (set_attr "length" "8")
3290 (set_attr "pool_range" "256")
3291 (set_attr "neg_pool_range" "244")]
3295 [(set (match_operand:HI 0 "s_register_operand" "")
3296 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3297 "TARGET_ARM && arm_arch4 && reload_completed"
3298 [(set (match_dup 3) (match_dup 1))
3299 (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3302 HOST_WIDE_INT offset;
3304 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3305 operands[2] = gen_rtx_MEM (QImode, operands[3]);
3306 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3307 operands[1] = XEXP (operands[1], 0);
3308 if (GET_CODE (operands[1]) == PLUS
3309 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3310 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3311 || const_ok_for_arm (-offset)))
3313 HOST_WIDE_INT low = (offset > 0
3314 ? (offset & 0xff) : -((-offset) & 0xff));
3315 XEXP (operands[2], 0) = plus_constant (operands[3], low);
3316 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3318 /* Ensure the sum is in correct canonical form */
3319 else if (GET_CODE (operands[1]) == PLUS
3320 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3321 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3322 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3323 XEXP (operands[1], 1),
3324 XEXP (operands[1], 0));
3328 (define_expand "extendqisi2"
3330 (ashift:SI (match_operand:QI 1 "general_operand" "")
3332 (set (match_operand:SI 0 "s_register_operand" "")
3333 (ashiftrt:SI (match_dup 2)
3338 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3340 emit_insn (gen_rtx_SET (VOIDmode,
3342 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3345 if (!s_register_operand (operands[1], QImode))
3346 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3347 operands[1] = gen_lowpart (SImode, operands[1]);
3348 operands[2] = gen_reg_rtx (SImode);
3354 ops[0] = operands[2];
3355 ops[1] = operands[1];
3356 ops[2] = GEN_INT (24);
3358 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3359 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3361 ops[0] = operands[0];
3362 ops[1] = operands[2];
3363 ops[2] = GEN_INT (24);
3365 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3366 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3373 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3374 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3375 (define_insn "*arm_extendqisi_insn"
3376 [(set (match_operand:SI 0 "s_register_operand" "=r")
3377 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3378 "TARGET_ARM && arm_arch4"
3380 /* If the address is invalid, this will split the instruction into two. */
3381 if (bad_signed_byte_operand (operands[1], VOIDmode))
3383 return \"ldr%?sb\\t%0, %1\";
3385 [(set_attr "type" "load")
3386 (set_attr "predicable" "yes")
3387 (set_attr "length" "8")
3388 (set_attr "pool_range" "256")
3389 (set_attr "neg_pool_range" "244")]
3393 [(set (match_operand:SI 0 "s_register_operand" "")
3394 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3395 "TARGET_ARM && arm_arch4 && reload_completed"
3396 [(set (match_dup 0) (match_dup 1))
3397 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3400 HOST_WIDE_INT offset;
3402 operands[2] = gen_rtx_MEM (QImode, operands[0]);
3403 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3404 operands[1] = XEXP (operands[1], 0);
3405 if (GET_CODE (operands[1]) == PLUS
3406 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3407 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3408 || const_ok_for_arm (-offset)))
3410 HOST_WIDE_INT low = (offset > 0
3411 ? (offset & 0xff) : -((-offset) & 0xff));
3412 XEXP (operands[2], 0) = plus_constant (operands[0], low);
3413 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3415 /* Ensure the sum is in correct canonical form */
3416 else if (GET_CODE (operands[1]) == PLUS
3417 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3418 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3419 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3420 XEXP (operands[1], 1),
3421 XEXP (operands[1], 0));
3425 (define_insn "*thumb_extendqisi2_insn"
3426 [(set (match_operand:SI 0 "register_operand" "=l,l")
3427 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3432 rtx mem = XEXP (operands[1], 0);
3434 if (GET_CODE (mem) == CONST)
3435 mem = XEXP (mem, 0);
3437 if (GET_CODE (mem) == LABEL_REF)
3438 return \"ldr\\t%0, %1\";
3440 if (GET_CODE (mem) == PLUS
3441 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3442 return \"ldr\\t%0, %1\";
3444 if (which_alternative == 0)
3445 return \"ldrsb\\t%0, %1\";
3447 ops[0] = operands[0];
3449 if (GET_CODE (mem) == PLUS)
3451 rtx a = XEXP (mem, 0);
3452 rtx b = XEXP (mem, 1);
3457 if (GET_CODE (a) == REG)
3459 if (GET_CODE (b) == REG)
3460 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3461 else if (REGNO (a) == REGNO (ops[0]))
3463 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3464 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3465 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3468 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3470 else if (GET_CODE (b) != REG)
3474 if (REGNO (b) == REGNO (ops[0]))
3476 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3477 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3478 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3481 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3484 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3486 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3487 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3488 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3493 ops[2] = const0_rtx;
3495 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3499 [(set_attr "length" "2,6")
3500 (set_attr "type" "load,load")
3501 (set_attr "pool_range" "32,32")]
3504 (define_expand "extendsfdf2"
3505 [(set (match_operand:DF 0 "s_register_operand" "")
3506 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
3507 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3511 ;; Move insns (including loads and stores)
3513 ;; XXX Just some ideas about movti.
3514 ;; I don't think these are a good idea on the arm, there just aren't enough
3516 ;;(define_expand "loadti"
3517 ;; [(set (match_operand:TI 0 "s_register_operand" "")
3518 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
3521 ;;(define_expand "storeti"
3522 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3523 ;; (match_operand:TI 1 "s_register_operand" ""))]
3526 ;;(define_expand "movti"
3527 ;; [(set (match_operand:TI 0 "general_operand" "")
3528 ;; (match_operand:TI 1 "general_operand" ""))]
3534 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3535 ;; operands[1] = copy_to_reg (operands[1]);
3536 ;; if (GET_CODE (operands[0]) == MEM)
3537 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3538 ;; else if (GET_CODE (operands[1]) == MEM)
3539 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3543 ;; emit_insn (insn);
3547 ;; Recognize garbage generated above.
3550 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3551 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3555 ;; register mem = (which_alternative < 3);
3556 ;; register const char *template;
3558 ;; operands[mem] = XEXP (operands[mem], 0);
3559 ;; switch (which_alternative)
3561 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3562 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
3563 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
3564 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
3565 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
3566 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
3568 ;; output_asm_insn (template, operands);
3572 (define_expand "movdi"
3573 [(set (match_operand:DI 0 "general_operand" "")
3574 (match_operand:DI 1 "general_operand" ""))]
3579 if (!no_new_pseudos)
3581 if (GET_CODE (operands[0]) != REG)
3582 operands[1] = force_reg (DImode, operands[1]);
3588 (define_insn "*arm_movdi"
3589 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3590 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
3591 "TARGET_ARM && !TARGET_CIRRUS"
3593 return (output_move_double (operands));
3595 [(set_attr "length" "8")
3596 (set_attr "type" "*,load,store2")
3597 (set_attr "pool_range" "*,1020,*")
3598 (set_attr "neg_pool_range" "*,1008,*")]
3601 ;;; ??? This should have alternatives for constants.
3602 ;;; ??? This was originally identical to the movdf_insn pattern.
3603 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3604 ;;; thumb_reorg with a memory reference.
3605 (define_insn "*thumb_movdi_insn"
3606 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3607 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
3610 && ( register_operand (operands[0], DImode)
3611 || register_operand (operands[1], DImode))"
3614 switch (which_alternative)
3618 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3619 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
3620 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
3622 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3624 operands[1] = GEN_INT (- INTVAL (operands[1]));
3625 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3627 return \"ldmia\\t%1, {%0, %H0}\";
3629 return \"stmia\\t%0, {%1, %H1}\";
3631 return thumb_load_double_from_address (operands);
3633 operands[2] = gen_rtx (MEM, SImode,
3634 plus_constant (XEXP (operands[0], 0), 4));
3635 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3638 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3639 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
3640 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
3643 [(set_attr "length" "4,4,6,2,2,6,4,4")
3644 (set_attr "type" "*,*,*,load,store2,load,store2,*")
3645 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
3648 (define_expand "movsi"
3649 [(set (match_operand:SI 0 "general_operand" "")
3650 (match_operand:SI 1 "general_operand" ""))]
3655 /* Everything except mem = const or mem = mem can be done easily */
3656 if (GET_CODE (operands[0]) == MEM)
3657 operands[1] = force_reg (SImode, operands[1]);
3658 if (GET_CODE (operands[1]) == CONST_INT
3659 && !(const_ok_for_arm (INTVAL (operands[1]))
3660 || const_ok_for_arm (~INTVAL (operands[1]))))
3662 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3665 : preserve_subexpressions_p ()));
3669 else /* TARGET_THUMB.... */
3671 if (!no_new_pseudos)
3673 if (GET_CODE (operands[0]) != REG)
3674 operands[1] = force_reg (SImode, operands[1]);
3679 && (CONSTANT_P (operands[1])
3680 || symbol_mentioned_p (operands[1])
3681 || label_mentioned_p (operands[1])))
3682 operands[1] = legitimize_pic_address (operands[1], SImode,
3683 (no_new_pseudos ? operands[0] : 0));
3687 (define_insn "*arm_movsi_insn"
3688 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
3689 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
3691 && ( register_operand (operands[0], SImode)
3692 || register_operand (operands[1], SImode))"
3698 [(set_attr "type" "*,*,load,store1")
3699 (set_attr "predicable" "yes")
3700 (set_attr "pool_range" "*,*,4096,*")
3701 (set_attr "neg_pool_range" "*,*,4084,*")]
3705 [(set (match_operand:SI 0 "s_register_operand" "")
3706 (match_operand:SI 1 "const_int_operand" ""))]
3708 && (!(const_ok_for_arm (INTVAL (operands[1]))
3709 || const_ok_for_arm (~INTVAL (operands[1]))))"
3710 [(clobber (const_int 0))]
3712 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3718 (define_insn "*thumb_movsi_insn"
3719 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
3720 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
3722 && ( register_operand (operands[0], SImode)
3723 || register_operand (operands[1], SImode))"
3734 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
3735 (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
3736 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
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]), 'J')"
3743 [(set (match_dup 0) (match_dup 1))
3744 (set (match_dup 0) (neg:SI (match_dup 0)))]
3745 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
3749 [(set (match_operand:SI 0 "register_operand" "")
3750 (match_operand:SI 1 "const_int_operand" ""))]
3751 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
3752 [(set (match_dup 0) (match_dup 1))
3753 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
3756 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
3757 unsigned HOST_WIDE_INT mask = 0xff;
3760 for (i = 0; i < 25; i++)
3761 if ((val & (mask << i)) == val)
3764 /* Shouldn't happen, but we don't want to split if the shift is zero. */
3768 operands[1] = GEN_INT (val >> i);
3769 operands[2] = GEN_INT (i);
3773 ;; When generating pic, we need to load the symbol offset into a register.
3774 ;; So that the optimizer does not confuse this with a normal symbol load
3775 ;; we use an unspec. The offset will be loaded from a constant pool entry,
3776 ;; since that is the only type of relocation we can use.
3778 ;; The rather odd constraints on the following are to force reload to leave
3779 ;; the insn alone, and to force the minipool generation pass to then move
3780 ;; the GOT symbol to memory.
3782 (define_insn "pic_load_addr_arm"
3783 [(set (match_operand:SI 0 "s_register_operand" "=r")
3784 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3785 "TARGET_ARM && flag_pic"
3787 [(set_attr "type" "load")
3788 (set (attr "pool_range") (const_int 4096))
3789 (set (attr "neg_pool_range") (const_int 4084))]
3792 (define_insn "pic_load_addr_thumb"
3793 [(set (match_operand:SI 0 "s_register_operand" "=l")
3794 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3795 "TARGET_THUMB && flag_pic"
3797 [(set_attr "type" "load")
3798 (set (attr "pool_range") (const_int 1024))]
3801 ;; This variant is used for AOF assembly, since it needs to mention the
3802 ;; pic register in the rtl.
3803 (define_expand "pic_load_addr_based"
3804 [(set (match_operand:SI 0 "s_register_operand" "")
3805 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
3806 "TARGET_ARM && flag_pic"
3807 "operands[2] = pic_offset_table_rtx;"
3810 (define_insn "*pic_load_addr_based_insn"
3811 [(set (match_operand:SI 0 "s_register_operand" "=r")
3812 (unspec:SI [(match_operand 1 "" "")
3813 (match_operand 2 "s_register_operand" "r")]
3815 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
3817 #ifdef AOF_ASSEMBLER
3818 operands[1] = aof_pic_entry (operands[1]);
3820 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
3823 [(set_attr "type" "load")
3824 (set (attr "pool_range")
3825 (if_then_else (eq_attr "is_thumb" "yes")
3828 (set (attr "neg_pool_range")
3829 (if_then_else (eq_attr "is_thumb" "yes")
3834 (define_insn "pic_add_dot_plus_four"
3835 [(set (match_operand:SI 0 "register_operand" "+r")
3836 (unspec:SI [(plus:SI (match_dup 0)
3837 (const (plus:SI (pc) (const_int 4))))]
3839 (use (label_ref (match_operand 1 "" "")))]
3840 "TARGET_THUMB && flag_pic"
3842 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3843 CODE_LABEL_NUMBER (operands[1]));
3844 return \"add\\t%0, %|pc\";
3846 [(set_attr "length" "2")]
3849 (define_insn "pic_add_dot_plus_eight"
3850 [(set (match_operand:SI 0 "register_operand" "+r")
3851 (unspec:SI [(plus:SI (match_dup 0)
3852 (const (plus:SI (pc) (const_int 8))))]
3854 (use (label_ref (match_operand 1 "" "")))]
3855 "TARGET_ARM && flag_pic"
3857 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3858 CODE_LABEL_NUMBER (operands[1]));
3859 return \"add%?\\t%0, %|pc, %0\";
3861 [(set_attr "predicable" "yes")]
3864 (define_expand "builtin_setjmp_receiver"
3865 [(label_ref (match_operand 0 "" ""))]
3869 arm_finalize_pic (0);
3873 ;; If copying one reg to another we can set the condition codes according to
3874 ;; its value. Such a move is common after a return from subroutine and the
3875 ;; result is being tested against zero.
3877 (define_insn "*movsi_compare0"
3878 [(set (reg:CC CC_REGNUM)
3879 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
3881 (set (match_operand:SI 0 "s_register_operand" "=r,r")
3886 sub%?s\\t%0, %1, #0"
3887 [(set_attr "conds" "set")]
3890 ;; Subroutine to store a half word from a register into memory.
3891 ;; Operand 0 is the source register (HImode)
3892 ;; Operand 1 is the destination address in a register (SImode)
3894 ;; In both this routine and the next, we must be careful not to spill
3895 ;; a memory address of reg+large_const into a separate PLUS insn, since this
3896 ;; can generate unrecognizable rtl.
3898 (define_expand "storehi"
3899 [;; store the low byte
3900 (set (match_operand 1 "" "") (match_dup 3))
3901 ;; extract the high byte
3903 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
3904 ;; store the high byte
3905 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
3909 rtx op1 = operands[1];
3910 rtx addr = XEXP (op1, 0);
3911 enum rtx_code code = GET_CODE (addr);
3913 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
3915 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
3917 operands[4] = adjust_address (op1, QImode, 1);
3918 operands[1] = adjust_address (operands[1], QImode, 0);
3919 operands[3] = gen_lowpart (QImode, operands[0]);
3920 operands[0] = gen_lowpart (SImode, operands[0]);
3921 operands[2] = gen_reg_rtx (SImode);
3925 (define_expand "storehi_bigend"
3926 [(set (match_dup 4) (match_dup 3))
3928 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
3929 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 3))]
3933 rtx op1 = operands[1];
3934 rtx addr = XEXP (op1, 0);
3935 enum rtx_code code = GET_CODE (addr);
3937 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
3939 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
3941 operands[4] = adjust_address (op1, QImode, 1);
3942 operands[1] = adjust_address (operands[1], QImode, 0);
3943 operands[3] = gen_lowpart (QImode, operands[0]);
3944 operands[0] = gen_lowpart (SImode, operands[0]);
3945 operands[2] = gen_reg_rtx (SImode);
3949 ;; Subroutine to store a half word integer constant into memory.
3950 (define_expand "storeinthi"
3951 [(set (match_operand 0 "" "")
3952 (subreg:QI (match_operand 1 "" "") 0))
3953 (set (match_dup 3) (match_dup 2))]
3957 HOST_WIDE_INT value = INTVAL (operands[1]);
3958 rtx addr = XEXP (operands[0], 0);
3959 rtx op0 = operands[0];
3960 enum rtx_code code = GET_CODE (addr);
3962 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
3964 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
3966 operands[1] = gen_reg_rtx (SImode);
3967 if (BYTES_BIG_ENDIAN)
3969 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
3970 if ((value & 255) == ((value >> 8) & 255))
3971 operands[2] = operands[1];
3974 operands[2] = gen_reg_rtx (SImode);
3975 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
3980 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
3981 if ((value & 255) == ((value >> 8) & 255))
3982 operands[2] = operands[1];
3985 operands[2] = gen_reg_rtx (SImode);
3986 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
3990 operands[3] = adjust_address (op0, QImode, 1);
3991 operands[0] = adjust_address (operands[0], QImode, 0);
3992 operands[2] = gen_lowpart (QImode, operands[2]);
3996 (define_expand "storehi_single_op"
3997 [(set (match_operand:HI 0 "memory_operand" "")
3998 (match_operand:HI 1 "general_operand" ""))]
3999 "TARGET_ARM && arm_arch4"
4001 if (!s_register_operand (operands[1], HImode))
4002 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4006 (define_expand "movhi"
4007 [(set (match_operand:HI 0 "general_operand" "")
4008 (match_operand:HI 1 "general_operand" ""))]
4013 if (!no_new_pseudos)
4015 if (GET_CODE (operands[0]) == MEM)
4019 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4022 if (GET_CODE (operands[1]) == CONST_INT)
4023 emit_insn (gen_storeinthi (operands[0], operands[1]));
4026 if (GET_CODE (operands[1]) == MEM)
4027 operands[1] = force_reg (HImode, operands[1]);
4028 if (BYTES_BIG_ENDIAN)
4029 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4031 emit_insn (gen_storehi (operands[1], operands[0]));
4035 /* Sign extend a constant, and keep it in an SImode reg. */
4036 else if (GET_CODE (operands[1]) == CONST_INT)
4038 rtx reg = gen_reg_rtx (SImode);
4039 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4041 /* If the constant is already valid, leave it alone. */
4042 if (!const_ok_for_arm (val))
4044 /* If setting all the top bits will make the constant
4045 loadable in a single instruction, then set them.
4046 Otherwise, sign extend the number. */
4048 if (const_ok_for_arm (~(val | ~0xffff)))
4050 else if (val & 0x8000)
4054 emit_insn (gen_movsi (reg, GEN_INT (val)));
4055 operands[1] = gen_lowpart (HImode, reg);
4057 else if (arm_arch4 && !no_new_pseudos && optimize > 0
4058 && GET_CODE (operands[1]) == MEM)
4060 rtx reg = gen_reg_rtx (SImode);
4062 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4063 operands[1] = gen_lowpart (HImode, reg);
4065 else if (!arm_arch4)
4067 /* Note: We do not have to worry about TARGET_MMU_TRAPS
4068 for v4 and up architectures because LDRH instructions will
4069 be used to access the HI values, and these cannot generate
4070 unaligned word access faults in the MMU. */
4071 if (GET_CODE (operands[1]) == MEM)
4073 if (TARGET_MMU_TRAPS)
4076 rtx offset = const0_rtx;
4077 rtx reg = gen_reg_rtx (SImode);
4079 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4080 || (GET_CODE (base) == PLUS
4081 && (GET_CODE (offset = XEXP (base, 1))
4083 && ((INTVAL(offset) & 1) != 1)
4084 && GET_CODE (base = XEXP (base, 0)) == REG))
4085 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4087 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4090 new = gen_rtx_MEM (SImode,
4091 plus_constant (base, new_offset));
4092 MEM_COPY_ATTRIBUTES (new, operands[1]);
4093 emit_insn (gen_movsi (reg, new));
4094 if (((INTVAL (offset) & 2) != 0)
4095 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4097 rtx reg2 = gen_reg_rtx (SImode);
4099 emit_insn (gen_lshrsi3 (reg2, reg,
4105 emit_insn (gen_movhi_bytes (reg, operands[1]));
4107 operands[1] = gen_lowpart (HImode, reg);
4109 else if (BYTES_BIG_ENDIAN)
4112 rtx offset = const0_rtx;
4114 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4115 || (GET_CODE (base) == PLUS
4116 && (GET_CODE (offset = XEXP (base, 1))
4118 && GET_CODE (base = XEXP (base, 0)) == REG))
4119 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4121 rtx reg = gen_reg_rtx (SImode);
4124 if ((INTVAL (offset) & 2) == 2)
4126 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4127 new = gen_rtx_MEM (SImode,
4128 plus_constant (base,
4130 MEM_COPY_ATTRIBUTES (new, operands[1]);
4131 emit_insn (gen_movsi (reg, new));
4135 new = gen_rtx_MEM (SImode,
4136 XEXP (operands[1], 0));
4137 MEM_COPY_ATTRIBUTES (new, operands[1]);
4138 emit_insn (gen_rotated_loadsi (reg, new));
4141 operands[1] = gen_lowpart (HImode, reg);
4145 emit_insn (gen_movhi_bigend (operands[0],
4153 /* Handle loading a large integer during reload */
4154 else if (GET_CODE (operands[1]) == CONST_INT
4155 && !const_ok_for_arm (INTVAL (operands[1]))
4156 && !const_ok_for_arm (~INTVAL (operands[1])))
4158 /* Writing a constant to memory needs a scratch, which should
4159 be handled with SECONDARY_RELOADs. */
4160 if (GET_CODE (operands[0]) != REG)
4163 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4164 emit_insn (gen_movsi (operands[0], operands[1]));
4168 else /* TARGET_THUMB */
4170 if (!no_new_pseudos)
4172 if (GET_CODE (operands[0]) != REG)
4173 operands[1] = force_reg (HImode, operands[1]);
4175 /* ??? We shouldn't really get invalid addresses here, but this can
4176 happen if we are passed a SP (never OK for HImode/QImode) or
4177 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4178 HImode/QImode) relative address. */
4179 /* ??? This should perhaps be fixed elsewhere, for instance, in
4180 fixup_stack_1, by checking for other kinds of invalid addresses,
4181 e.g. a bare reference to a virtual register. This may confuse the
4182 alpha though, which must handle this case differently. */
4183 if (GET_CODE (operands[0]) == MEM
4184 && !memory_address_p (GET_MODE (operands[0]),
4185 XEXP (operands[0], 0)))
4187 = replace_equiv_address (operands[0],
4188 copy_to_reg (XEXP (operands[0], 0)));
4190 if (GET_CODE (operands[1]) == MEM
4191 && !memory_address_p (GET_MODE (operands[1]),
4192 XEXP (operands[1], 0)))
4194 = replace_equiv_address (operands[1],
4195 copy_to_reg (XEXP (operands[1], 0)));
4197 /* Handle loading a large integer during reload */
4198 else if (GET_CODE (operands[1]) == CONST_INT
4199 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4201 /* Writing a constant to memory needs a scratch, which should
4202 be handled with SECONDARY_RELOADs. */
4203 if (GET_CODE (operands[0]) != REG)
4206 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4207 emit_insn (gen_movsi (operands[0], operands[1]));
4214 (define_insn "*thumb_movhi_insn"
4215 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4216 (match_operand:HI 1 "general_operand" "l,mn,l,*h,*r,I"))]
4218 && ( register_operand (operands[0], HImode)
4219 || register_operand (operands[1], HImode))"
4221 switch (which_alternative)
4223 case 0: return \"add %0, %1, #0\";
4224 case 2: return \"strh %1, %0\";
4225 case 3: return \"mov %0, %1\";
4226 case 4: return \"mov %0, %1\";
4227 case 5: return \"mov %0, %1\";
4230 /* The stack pointer can end up being taken as an index register.
4231 Catch this case here and deal with it. */
4232 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4233 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4234 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4237 ops[0] = operands[0];
4238 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4240 output_asm_insn (\"mov %0, %1\", ops);
4242 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4245 return \"ldrh %0, %1\";
4247 [(set_attr "length" "2,4,2,2,2,2")
4248 (set_attr "type" "*,load,store1,*,*,*")
4249 (set_attr "pool_range" "*,64,*,*,*,*")]
4253 (define_insn "rotated_loadsi"
4254 [(set (match_operand:SI 0 "s_register_operand" "=r")
4255 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4257 "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4262 ops[0] = operands[0];
4263 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4264 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4267 [(set_attr "type" "load")
4268 (set_attr "predicable" "yes")]
4271 (define_expand "movhi_bytes"
4272 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4274 (zero_extend:SI (match_dup 6)))
4275 (set (match_operand:SI 0 "" "")
4276 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4281 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4283 mem1 = gen_rtx_MEM (QImode, addr);
4284 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4285 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4286 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4287 operands[0] = gen_lowpart (SImode, operands[0]);
4289 operands[2] = gen_reg_rtx (SImode);
4290 operands[3] = gen_reg_rtx (SImode);
4293 if (BYTES_BIG_ENDIAN)
4295 operands[4] = operands[2];
4296 operands[5] = operands[3];
4300 operands[4] = operands[3];
4301 operands[5] = operands[2];
4306 (define_expand "movhi_bigend"
4308 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4311 (ashiftrt:SI (match_dup 2) (const_int 16)))
4312 (set (match_operand:HI 0 "s_register_operand" "")
4313 (subreg:HI (match_dup 3) 0))]
4316 operands[2] = gen_reg_rtx (SImode);
4317 operands[3] = gen_reg_rtx (SImode);
4321 ;; Pattern to recognize insn generated default case above
4322 (define_insn "*movhi_insn_arch4"
4323 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4324 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4327 && (GET_CODE (operands[1]) != CONST_INT
4328 || const_ok_for_arm (INTVAL (operands[1]))
4329 || const_ok_for_arm (~INTVAL (operands[1])))"
4331 mov%?\\t%0, %1\\t%@ movhi
4332 mvn%?\\t%0, #%B1\\t%@ movhi
4333 str%?h\\t%1, %0\\t%@ movhi
4334 ldr%?h\\t%0, %1\\t%@ movhi"
4335 [(set_attr "type" "*,*,store1,load")
4336 (set_attr "predicable" "yes")
4337 (set_attr "pool_range" "*,*,*,256")
4338 (set_attr "neg_pool_range" "*,*,*,244")]
4341 (define_insn "*movhi_insn_littleend"
4342 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4343 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4346 && !BYTES_BIG_ENDIAN
4347 && !TARGET_MMU_TRAPS
4348 && (GET_CODE (operands[1]) != CONST_INT
4349 || const_ok_for_arm (INTVAL (operands[1]))
4350 || const_ok_for_arm (~INTVAL (operands[1])))"
4352 mov%?\\t%0, %1\\t%@ movhi
4353 mvn%?\\t%0, #%B1\\t%@ movhi
4354 ldr%?\\t%0, %1\\t%@ movhi"
4355 [(set_attr "type" "*,*,load")
4356 (set_attr "predicable" "yes")
4357 (set_attr "pool_range" "4096")
4358 (set_attr "neg_pool_range" "4084")]
4361 (define_insn "*movhi_insn_bigend"
4362 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4363 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4367 && !TARGET_MMU_TRAPS
4368 && (GET_CODE (operands[1]) != CONST_INT
4369 || const_ok_for_arm (INTVAL (operands[1]))
4370 || const_ok_for_arm (~INTVAL (operands[1])))"
4372 mov%?\\t%0, %1\\t%@ movhi
4373 mvn%?\\t%0, #%B1\\t%@ movhi
4374 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4375 [(set_attr "type" "*,*,load")
4376 (set_attr "predicable" "yes")
4377 (set_attr "length" "4,4,8")
4378 (set_attr "pool_range" "*,*,4092")
4379 (set_attr "neg_pool_range" "*,*,4084")]
4382 (define_insn "*loadhi_si_bigend"
4383 [(set (match_operand:SI 0 "s_register_operand" "=r")
4384 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
4388 && !TARGET_MMU_TRAPS"
4389 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4390 [(set_attr "type" "load")
4391 (set_attr "predicable" "yes")
4392 (set_attr "pool_range" "4096")
4393 (set_attr "neg_pool_range" "4084")]
4396 (define_insn "*movhi_bytes"
4397 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4398 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4399 "TARGET_ARM && TARGET_MMU_TRAPS"
4401 mov%?\\t%0, %1\\t%@ movhi
4402 mvn%?\\t%0, #%B1\\t%@ movhi"
4403 [(set_attr "predicable" "yes")]
4406 (define_insn "thumb_movhi_clobber"
4407 [(set (match_operand:HI 0 "memory_operand" "=m")
4408 (match_operand:HI 1 "register_operand" "l"))
4409 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4415 ;; We use a DImode scratch because we may occasionally need an additional
4416 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4417 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4418 (define_expand "reload_outhi"
4419 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4420 (match_operand:HI 1 "s_register_operand" "r")
4421 (match_operand:DI 2 "s_register_operand" "=&l")])]
4424 arm_reload_out_hi (operands);
4426 thumb_reload_out_hi (operands);
4431 (define_expand "reload_inhi"
4432 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4433 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4434 (match_operand:DI 2 "s_register_operand" "=&r")])]
4435 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4438 arm_reload_in_hi (operands);
4440 thumb_reload_out_hi (operands);
4444 (define_expand "movqi"
4445 [(set (match_operand:QI 0 "general_operand" "")
4446 (match_operand:QI 1 "general_operand" ""))]
4451 /* Everything except mem = const or mem = mem can be done easily */
4453 if (!no_new_pseudos)
4455 if (GET_CODE (operands[1]) == CONST_INT)
4457 rtx reg = gen_reg_rtx (SImode);
4459 emit_insn (gen_movsi (reg, operands[1]));
4460 operands[1] = gen_lowpart (QImode, reg);
4462 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4464 rtx reg = gen_reg_rtx (SImode);
4466 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4467 operands[1] = gen_lowpart (QImode, reg);
4469 if (GET_CODE (operands[0]) == MEM)
4470 operands[1] = force_reg (QImode, operands[1]);
4473 else /* TARGET_THUMB */
4475 if (!no_new_pseudos)
4477 if (GET_CODE (operands[0]) != REG)
4478 operands[1] = force_reg (QImode, operands[1]);
4480 /* ??? We shouldn't really get invalid addresses here, but this can
4481 happen if we are passed a SP (never OK for HImode/QImode) or
4482 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4483 HImode/QImode) relative address. */
4484 /* ??? This should perhaps be fixed elsewhere, for instance, in
4485 fixup_stack_1, by checking for other kinds of invalid addresses,
4486 e.g. a bare reference to a virtual register. This may confuse the
4487 alpha though, which must handle this case differently. */
4488 if (GET_CODE (operands[0]) == MEM
4489 && !memory_address_p (GET_MODE (operands[0]),
4490 XEXP (operands[0], 0)))
4492 = replace_equiv_address (operands[0],
4493 copy_to_reg (XEXP (operands[0], 0)));
4494 if (GET_CODE (operands[1]) == MEM
4495 && !memory_address_p (GET_MODE (operands[1]),
4496 XEXP (operands[1], 0)))
4498 = replace_equiv_address (operands[1],
4499 copy_to_reg (XEXP (operands[1], 0)));
4501 /* Handle loading a large integer during reload */
4502 else if (GET_CODE (operands[1]) == CONST_INT
4503 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4505 /* Writing a constant to memory needs a scratch, which should
4506 be handled with SECONDARY_RELOADs. */
4507 if (GET_CODE (operands[0]) != REG)
4510 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4511 emit_insn (gen_movsi (operands[0], operands[1]));
4519 (define_insn "*arm_movqi_insn"
4520 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4521 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4523 && ( register_operand (operands[0], QImode)
4524 || register_operand (operands[1], QImode))"
4530 [(set_attr "type" "*,*,load,store1")
4531 (set_attr "predicable" "yes")]
4534 (define_insn "*thumb_movqi_insn"
4535 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4536 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
4538 && ( register_operand (operands[0], QImode)
4539 || register_operand (operands[1], QImode))"
4547 [(set_attr "length" "2")
4548 (set_attr "type" "*,load,store1,*,*,*")
4549 (set_attr "pool_range" "*,32,*,*,*,*")]
4552 (define_expand "movsf"
4553 [(set (match_operand:SF 0 "general_operand" "")
4554 (match_operand:SF 1 "general_operand" ""))]
4559 if (GET_CODE (operands[0]) == MEM)
4560 operands[1] = force_reg (SFmode, operands[1]);
4562 else /* TARGET_THUMB */
4564 if (!no_new_pseudos)
4566 if (GET_CODE (operands[0]) != REG)
4567 operands[1] = force_reg (SFmode, operands[1]);
4574 [(set (match_operand:SF 0 "nonimmediate_operand" "")
4575 (match_operand:SF 1 "immediate_operand" ""))]
4577 && !TARGET_HARD_FLOAT
4579 && GET_CODE (operands[1]) == CONST_DOUBLE"
4580 [(set (match_dup 2) (match_dup 3))]
4582 operands[2] = gen_lowpart (SImode, operands[0]);
4583 operands[3] = gen_lowpart (SImode, operands[1]);
4584 if (operands[2] == 0 || operands[3] == 0)
4589 (define_insn "*arm_movsf_soft_insn"
4590 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4591 (match_operand:SF 1 "general_operand" "r,mE,r"))]
4594 && TARGET_SOFT_FLOAT
4595 && (GET_CODE (operands[0]) != MEM
4596 || register_operand (operands[1], SFmode))"
4599 ldr%?\\t%0, %1\\t%@ float
4600 str%?\\t%1, %0\\t%@ float"
4601 [(set_attr "length" "4,4,4")
4602 (set_attr "predicable" "yes")
4603 (set_attr "type" "*,load,store1")
4604 (set_attr "pool_range" "*,4096,*")
4605 (set_attr "neg_pool_range" "*,4084,*")]
4608 ;;; ??? This should have alternatives for constants.
4609 (define_insn "*thumb_movsf_insn"
4610 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4611 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
4613 && ( register_operand (operands[0], SFmode)
4614 || register_operand (operands[1], SFmode))"
4623 [(set_attr "length" "2")
4624 (set_attr "type" "*,load,store1,load,store1,*,*")
4625 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
4628 (define_expand "movdf"
4629 [(set (match_operand:DF 0 "general_operand" "")
4630 (match_operand:DF 1 "general_operand" ""))]
4635 if (GET_CODE (operands[0]) == MEM)
4636 operands[1] = force_reg (DFmode, operands[1]);
4638 else /* TARGET_THUMB */
4640 if (!no_new_pseudos)
4642 if (GET_CODE (operands[0]) != REG)
4643 operands[1] = force_reg (DFmode, operands[1]);
4649 ;; Reloading a df mode value stored in integer regs to memory can require a
4651 (define_expand "reload_outdf"
4652 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
4653 (match_operand:DF 1 "s_register_operand" "r")
4654 (match_operand:SI 2 "s_register_operand" "=&r")]
4658 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
4661 operands[2] = XEXP (operands[0], 0);
4662 else if (code == POST_INC || code == PRE_DEC)
4664 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
4665 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
4666 emit_insn (gen_movdi (operands[0], operands[1]));
4669 else if (code == PRE_INC)
4671 rtx reg = XEXP (XEXP (operands[0], 0), 0);
4673 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
4676 else if (code == POST_DEC)
4677 operands[2] = XEXP (XEXP (operands[0], 0), 0);
4679 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
4680 XEXP (XEXP (operands[0], 0), 1)));
4682 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
4685 if (code == POST_DEC)
4686 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
4692 (define_insn "*movdf_soft_insn"
4693 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
4694 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
4695 "TARGET_ARM && TARGET_SOFT_FLOAT
4698 "* return output_move_double (operands);"
4699 [(set_attr "length" "8,8,8")
4700 (set_attr "type" "*,load,store2")
4701 (set_attr "pool_range" "1020")
4702 (set_attr "neg_pool_range" "1008")]
4705 ;;; ??? This should have alternatives for constants.
4706 ;;; ??? This was originally identical to the movdi_insn pattern.
4707 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
4708 ;;; thumb_reorg with a memory reference.
4709 (define_insn "*thumb_movdf_insn"
4710 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
4711 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
4713 && ( register_operand (operands[0], DFmode)
4714 || register_operand (operands[1], DFmode))"
4716 switch (which_alternative)
4720 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4721 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4722 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4724 return \"ldmia\\t%1, {%0, %H0}\";
4726 return \"stmia\\t%0, {%1, %H1}\";
4728 return thumb_load_double_from_address (operands);
4730 operands[2] = gen_rtx (MEM, SImode,
4731 plus_constant (XEXP (operands[0], 0), 4));
4732 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4735 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4736 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4737 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4740 [(set_attr "length" "4,2,2,6,4,4")
4741 (set_attr "type" "*,load,store2,load,store2,*")
4742 (set_attr "pool_range" "*,*,*,1020,*,*")]
4746 ;; load- and store-multiple insns
4747 ;; The arm can load/store any set of registers, provided that they are in
4748 ;; ascending order; but that is beyond GCC so stick with what it knows.
4750 (define_expand "load_multiple"
4751 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
4752 (match_operand:SI 1 "" ""))
4753 (use (match_operand:SI 2 "" ""))])]
4756 /* Support only fixed point registers. */
4757 if (GET_CODE (operands[2]) != CONST_INT
4758 || INTVAL (operands[2]) > 14
4759 || INTVAL (operands[2]) < 2
4760 || GET_CODE (operands[1]) != MEM
4761 || GET_CODE (operands[0]) != REG
4762 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
4763 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
4767 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
4768 force_reg (SImode, XEXP (operands[1], 0)),
4769 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
4770 MEM_IN_STRUCT_P(operands[1]),
4771 MEM_SCALAR_P (operands[1]));
4775 ;; Load multiple with write-back
4777 (define_insn "*ldmsi_postinc4"
4778 [(match_parallel 0 "load_multiple_operation"
4779 [(set (match_operand:SI 1 "s_register_operand" "=r")
4780 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4782 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4783 (mem:SI (match_dup 2)))
4784 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4785 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
4786 (set (match_operand:SI 5 "arm_hard_register_operand" "")
4787 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
4788 (set (match_operand:SI 6 "arm_hard_register_operand" "")
4789 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
4790 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
4791 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
4792 [(set_attr "type" "load")
4793 (set_attr "predicable" "yes")]
4796 (define_insn "*ldmsi_postinc3"
4797 [(match_parallel 0 "load_multiple_operation"
4798 [(set (match_operand:SI 1 "s_register_operand" "=r")
4799 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4801 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4802 (mem:SI (match_dup 2)))
4803 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4804 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
4805 (set (match_operand:SI 5 "arm_hard_register_operand" "")
4806 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
4807 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4808 "ldm%?ia\\t%1!, {%3, %4, %5}"
4809 [(set_attr "type" "load")
4810 (set_attr "predicable" "yes")]
4813 (define_insn "*ldmsi_postinc2"
4814 [(match_parallel 0 "load_multiple_operation"
4815 [(set (match_operand:SI 1 "s_register_operand" "=r")
4816 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4818 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4819 (mem:SI (match_dup 2)))
4820 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4821 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
4822 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4823 "ldm%?ia\\t%1!, {%3, %4}"
4824 [(set_attr "type" "load")
4825 (set_attr "predicable" "yes")]
4828 ;; Ordinary load multiple
4830 (define_insn "*ldmsi4"
4831 [(match_parallel 0 "load_multiple_operation"
4832 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4833 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4834 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4835 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
4836 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4837 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
4838 (set (match_operand:SI 5 "arm_hard_register_operand" "")
4839 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
4840 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4841 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
4842 [(set_attr "type" "load")
4843 (set_attr "predicable" "yes")]
4846 (define_insn "*ldmsi3"
4847 [(match_parallel 0 "load_multiple_operation"
4848 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4849 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4850 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4851 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
4852 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4853 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
4854 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4855 "ldm%?ia\\t%1, {%2, %3, %4}"
4856 [(set_attr "type" "load")
4857 (set_attr "predicable" "yes")]
4860 (define_insn "*ldmsi2"
4861 [(match_parallel 0 "load_multiple_operation"
4862 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4863 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4864 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4865 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
4866 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
4867 "ldm%?ia\\t%1, {%2, %3}"
4868 [(set_attr "type" "load")
4869 (set_attr "predicable" "yes")]
4872 (define_expand "store_multiple"
4873 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
4874 (match_operand:SI 1 "" ""))
4875 (use (match_operand:SI 2 "" ""))])]
4878 /* Support only fixed point registers */
4879 if (GET_CODE (operands[2]) != CONST_INT
4880 || INTVAL (operands[2]) > 14
4881 || INTVAL (operands[2]) < 2
4882 || GET_CODE (operands[1]) != REG
4883 || GET_CODE (operands[0]) != MEM
4884 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
4885 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
4889 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
4890 force_reg (SImode, XEXP (operands[0], 0)),
4891 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
4892 MEM_IN_STRUCT_P(operands[0]),
4893 MEM_SCALAR_P (operands[0]));
4897 ;; Store multiple with write-back
4899 (define_insn "*stmsi_postinc4"
4900 [(match_parallel 0 "store_multiple_operation"
4901 [(set (match_operand:SI 1 "s_register_operand" "=r")
4902 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4904 (set (mem:SI (match_dup 2))
4905 (match_operand:SI 3 "arm_hard_register_operand" ""))
4906 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
4907 (match_operand:SI 4 "arm_hard_register_operand" ""))
4908 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
4909 (match_operand:SI 5 "arm_hard_register_operand" ""))
4910 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
4911 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
4912 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
4913 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
4914 [(set_attr "predicable" "yes")
4915 (set_attr "type" "store4")]
4918 (define_insn "*stmsi_postinc3"
4919 [(match_parallel 0 "store_multiple_operation"
4920 [(set (match_operand:SI 1 "s_register_operand" "=r")
4921 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4923 (set (mem:SI (match_dup 2))
4924 (match_operand:SI 3 "arm_hard_register_operand" ""))
4925 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
4926 (match_operand:SI 4 "arm_hard_register_operand" ""))
4927 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
4928 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
4929 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4930 "stm%?ia\\t%1!, {%3, %4, %5}"
4931 [(set_attr "predicable" "yes")
4932 (set_attr "type" "store3")]
4935 (define_insn "*stmsi_postinc2"
4936 [(match_parallel 0 "store_multiple_operation"
4937 [(set (match_operand:SI 1 "s_register_operand" "=r")
4938 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4940 (set (mem:SI (match_dup 2))
4941 (match_operand:SI 3 "arm_hard_register_operand" ""))
4942 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
4943 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
4944 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4945 "stm%?ia\\t%1!, {%3, %4}"
4946 [(set_attr "predicable" "yes")
4947 (set_attr "type" "store2")]
4950 ;; Ordinary store multiple
4952 (define_insn "*stmsi4"
4953 [(match_parallel 0 "store_multiple_operation"
4954 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
4955 (match_operand:SI 2 "arm_hard_register_operand" ""))
4956 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
4957 (match_operand:SI 3 "arm_hard_register_operand" ""))
4958 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
4959 (match_operand:SI 4 "arm_hard_register_operand" ""))
4960 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
4961 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
4962 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4963 "stm%?ia\\t%1, {%2, %3, %4, %5}"
4964 [(set_attr "predicable" "yes")
4965 (set_attr "type" "store4")]
4968 (define_insn "*stmsi3"
4969 [(match_parallel 0 "store_multiple_operation"
4970 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
4971 (match_operand:SI 2 "arm_hard_register_operand" ""))
4972 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
4973 (match_operand:SI 3 "arm_hard_register_operand" ""))
4974 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
4975 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
4976 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4977 "stm%?ia\\t%1, {%2, %3, %4}"
4978 [(set_attr "predicable" "yes")
4979 (set_attr "type" "store3")]
4982 (define_insn "*stmsi2"
4983 [(match_parallel 0 "store_multiple_operation"
4984 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
4985 (match_operand:SI 2 "arm_hard_register_operand" ""))
4986 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
4987 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
4988 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
4989 "stm%?ia\\t%1, {%2, %3}"
4990 [(set_attr "predicable" "yes")
4991 (set_attr "type" "store2")]
4994 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
4995 ;; We could let this apply for blocks of less than this, but it clobbers so
4996 ;; many registers that there is then probably a better way.
4998 (define_expand "movstrqi"
4999 [(match_operand:BLK 0 "general_operand" "")
5000 (match_operand:BLK 1 "general_operand" "")
5001 (match_operand:SI 2 "const_int_operand" "")
5002 (match_operand:SI 3 "const_int_operand" "")]
5007 if (arm_gen_movstrqi (operands))
5011 else /* TARGET_THUMB */
5013 if ( INTVAL (operands[3]) != 4
5014 || INTVAL (operands[2]) > 48)
5017 thumb_expand_movstrqi (operands);
5023 ;; Thumb block-move insns
5025 (define_insn "movmem12b"
5026 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5027 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5028 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5029 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5030 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5031 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5032 (set (match_operand:SI 0 "register_operand" "=l")
5033 (plus:SI (match_dup 2) (const_int 12)))
5034 (set (match_operand:SI 1 "register_operand" "=l")
5035 (plus:SI (match_dup 3) (const_int 12)))
5036 (clobber (match_scratch:SI 4 "=&l"))
5037 (clobber (match_scratch:SI 5 "=&l"))
5038 (clobber (match_scratch:SI 6 "=&l"))]
5040 "* return thumb_output_move_mem_multiple (3, operands);"
5041 [(set_attr "length" "4")
5042 ; This isn't entirely accurate... It loads as well, but in terms of
5043 ; scheduling the following insn it is better to consider it as a store
5044 (set_attr "type" "store3")]
5047 (define_insn "movmem8b"
5048 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5049 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5050 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5051 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5052 (set (match_operand:SI 0 "register_operand" "=l")
5053 (plus:SI (match_dup 2) (const_int 8)))
5054 (set (match_operand:SI 1 "register_operand" "=l")
5055 (plus:SI (match_dup 3) (const_int 8)))
5056 (clobber (match_scratch:SI 4 "=&l"))
5057 (clobber (match_scratch:SI 5 "=&l"))]
5059 "* return thumb_output_move_mem_multiple (2, operands);"
5060 [(set_attr "length" "4")
5061 ; This isn't entirely accurate... It loads as well, but in terms of
5062 ; scheduling the following insn it is better to consider it as a store
5063 (set_attr "type" "store2")]
5068 ;; Compare & branch insns
5069 ;; The range calcualations are based as follows:
5070 ;; For forward branches, the address calculation returns the address of
5071 ;; the next instruction. This is 2 beyond the branch instruction.
5072 ;; For backward branches, the address calculation returns the address of
5073 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5074 ;; instruction for the shortest sequence, and 4 before the branch instruction
5075 ;; if we have to jump around an unconditional branch.
5076 ;; To the basic branch range the PC offset must be added (this is +4).
5077 ;; So for forward branches we have
5078 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5079 ;; And for backward branches we have
5080 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5082 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5083 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5085 (define_insn "cbranchsi4"
5088 (match_operator 0 "arm_comparison_operator"
5089 [(match_operand:SI 1 "register_operand" "l,r")
5090 (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5091 (label_ref (match_operand 3 "" ""))
5095 output_asm_insn (\"cmp\\t%1, %2\", operands);
5096 switch (get_attr_length (insn))
5098 case 4: return \"b%d0\\t%l3\";
5099 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5100 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5103 [(set (attr "far_jump")
5105 (eq_attr "length" "8")
5106 (const_string "yes")
5107 (const_string "no")))
5108 (set (attr "length")
5110 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5111 (le (minus (match_dup 3) (pc)) (const_int 256)))
5114 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5115 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5120 (define_insn "*negated_cbranchsi4"
5123 (match_operator 0 "arm_comparison_operator"
5124 [(match_operand:SI 1 "register_operand" "l")
5125 (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5126 (label_ref (match_operand 3 "" ""))
5130 output_asm_insn (\"cmn\\t%1, %2\", operands);
5131 switch (get_attr_length (insn))
5133 case 4: return \"b%d0\\t%l3\";
5134 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5135 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5138 [(set (attr "far_jump")
5140 (eq_attr "length" "8")
5141 (const_string "yes")
5142 (const_string "no")))
5143 (set (attr "length")
5145 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5146 (le (minus (match_dup 3) (pc)) (const_int 256)))
5149 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5150 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5156 ;; Comparison and test insns
5158 (define_expand "cmpsi"
5159 [(match_operand:SI 0 "s_register_operand" "")
5160 (match_operand:SI 1 "arm_add_operand" "")]
5163 arm_compare_op0 = operands[0];
5164 arm_compare_op1 = operands[1];
5169 (define_expand "cmpsf"
5170 [(match_operand:SF 0 "s_register_operand" "")
5171 (match_operand:SF 1 "fpa_rhs_operand" "")]
5172 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5174 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
5175 operands[1] = force_reg (SFmode, operands[1]);
5177 arm_compare_op0 = operands[0];
5178 arm_compare_op1 = operands[1];
5183 (define_expand "cmpdf"
5184 [(match_operand:DF 0 "s_register_operand" "")
5185 (match_operand:DF 1 "fpa_rhs_operand" "")]
5186 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5188 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
5189 operands[1] = force_reg (DFmode, operands[1]);
5191 arm_compare_op0 = operands[0];
5192 arm_compare_op1 = operands[1];
5197 (define_insn "*arm_cmpsi_insn"
5198 [(set (reg:CC CC_REGNUM)
5199 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5200 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
5205 [(set_attr "conds" "set")]
5208 (define_insn "*cmpsi_shiftsi"
5209 [(set (reg:CC CC_REGNUM)
5210 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5211 (match_operator:SI 3 "shift_operator"
5212 [(match_operand:SI 1 "s_register_operand" "r")
5213 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
5216 [(set_attr "conds" "set")
5217 (set_attr "shift" "1")
5221 (define_insn "*cmpsi_shiftsi_swp"
5222 [(set (reg:CC_SWP CC_REGNUM)
5223 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5224 [(match_operand:SI 1 "s_register_operand" "r")
5225 (match_operand:SI 2 "reg_or_int_operand" "rM")])
5226 (match_operand:SI 0 "s_register_operand" "r")))]
5229 [(set_attr "conds" "set")
5230 (set_attr "shift" "1")
5234 (define_insn "*cmpsi_neg_shiftsi"
5235 [(set (reg:CC CC_REGNUM)
5236 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5237 (neg:SI (match_operator:SI 3 "shift_operator"
5238 [(match_operand:SI 1 "s_register_operand" "r")
5239 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5242 [(set_attr "conds" "set")
5243 (set_attr "shift" "1")
5247 ;; Cirrus SF compare instruction
5248 (define_insn "*cirrus_cmpsf"
5249 [(set (reg:CCFP CC_REGNUM)
5250 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
5251 (match_operand:SF 1 "cirrus_fp_register" "v")))]
5252 "TARGET_ARM && TARGET_CIRRUS"
5253 "cfcmps%?\\tr15, %V0, %V1"
5254 [(set_attr "type" "mav_farith")
5255 (set_attr "cirrus" "compare")]
5258 ;; Cirrus DF compare instruction
5259 (define_insn "*cirrus_cmpdf"
5260 [(set (reg:CCFP CC_REGNUM)
5261 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
5262 (match_operand:DF 1 "cirrus_fp_register" "v")))]
5263 "TARGET_ARM && TARGET_CIRRUS"
5264 "cfcmpd%?\\tr15, %V0, %V1"
5265 [(set_attr "type" "mav_farith")
5266 (set_attr "cirrus" "compare")]
5269 ;; Cirrus DI compare instruction
5270 (define_expand "cmpdi"
5271 [(match_operand:DI 0 "cirrus_fp_register" "")
5272 (match_operand:DI 1 "cirrus_fp_register" "")]
5273 "TARGET_ARM && TARGET_CIRRUS"
5275 arm_compare_op0 = operands[0];
5276 arm_compare_op1 = operands[1];
5280 (define_insn "*cirrus_cmpdi"
5281 [(set (reg:CC CC_REGNUM)
5282 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
5283 (match_operand:DI 1 "cirrus_fp_register" "v")))]
5284 "TARGET_ARM && TARGET_CIRRUS"
5285 "cfcmp64%?\\tr15, %V0, %V1"
5286 [(set_attr "type" "mav_farith")
5287 (set_attr "cirrus" "compare")]
5290 ; This insn allows redundant compares to be removed by cse, nothing should
5291 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5292 ; is deleted later on. The match_dup will match the mode here, so that
5293 ; mode changes of the condition codes aren't lost by this even though we don't
5294 ; specify what they are.
5296 (define_insn "*deleted_compare"
5297 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5299 "\\t%@ deleted compare"
5300 [(set_attr "conds" "set")
5301 (set_attr "length" "0")]
5305 ;; Conditional branch insns
5307 (define_expand "beq"
5309 (if_then_else (eq (match_dup 1) (const_int 0))
5310 (label_ref (match_operand 0 "" ""))
5313 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5316 (define_expand "bne"
5318 (if_then_else (ne (match_dup 1) (const_int 0))
5319 (label_ref (match_operand 0 "" ""))
5322 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5325 (define_expand "bgt"
5327 (if_then_else (gt (match_dup 1) (const_int 0))
5328 (label_ref (match_operand 0 "" ""))
5331 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5334 (define_expand "ble"
5336 (if_then_else (le (match_dup 1) (const_int 0))
5337 (label_ref (match_operand 0 "" ""))
5340 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5343 (define_expand "bge"
5345 (if_then_else (ge (match_dup 1) (const_int 0))
5346 (label_ref (match_operand 0 "" ""))
5349 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5352 (define_expand "blt"
5354 (if_then_else (lt (match_dup 1) (const_int 0))
5355 (label_ref (match_operand 0 "" ""))
5358 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5361 (define_expand "bgtu"
5363 (if_then_else (gtu (match_dup 1) (const_int 0))
5364 (label_ref (match_operand 0 "" ""))
5367 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5370 (define_expand "bleu"
5372 (if_then_else (leu (match_dup 1) (const_int 0))
5373 (label_ref (match_operand 0 "" ""))
5376 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5379 (define_expand "bgeu"
5381 (if_then_else (geu (match_dup 1) (const_int 0))
5382 (label_ref (match_operand 0 "" ""))
5385 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5388 (define_expand "bltu"
5390 (if_then_else (ltu (match_dup 1) (const_int 0))
5391 (label_ref (match_operand 0 "" ""))
5394 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5397 (define_expand "bunordered"
5399 (if_then_else (unordered (match_dup 1) (const_int 0))
5400 (label_ref (match_operand 0 "" ""))
5402 "TARGET_ARM && TARGET_HARD_FLOAT"
5403 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5407 (define_expand "bordered"
5409 (if_then_else (ordered (match_dup 1) (const_int 0))
5410 (label_ref (match_operand 0 "" ""))
5412 "TARGET_ARM && TARGET_HARD_FLOAT"
5413 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5417 (define_expand "bungt"
5419 (if_then_else (ungt (match_dup 1) (const_int 0))
5420 (label_ref (match_operand 0 "" ""))
5422 "TARGET_ARM && TARGET_HARD_FLOAT"
5423 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5426 (define_expand "bunlt"
5428 (if_then_else (unlt (match_dup 1) (const_int 0))
5429 (label_ref (match_operand 0 "" ""))
5431 "TARGET_ARM && TARGET_HARD_FLOAT"
5432 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5435 (define_expand "bunge"
5437 (if_then_else (unge (match_dup 1) (const_int 0))
5438 (label_ref (match_operand 0 "" ""))
5440 "TARGET_ARM && TARGET_HARD_FLOAT"
5441 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5444 (define_expand "bunle"
5446 (if_then_else (unle (match_dup 1) (const_int 0))
5447 (label_ref (match_operand 0 "" ""))
5449 "TARGET_ARM && TARGET_HARD_FLOAT"
5450 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5453 ;; The following two patterns need two branch instructions, since there is
5454 ;; no single instruction that will handle all cases.
5455 (define_expand "buneq"
5457 (if_then_else (uneq (match_dup 1) (const_int 0))
5458 (label_ref (match_operand 0 "" ""))
5460 "TARGET_ARM && TARGET_HARD_FLOAT"
5461 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
5464 (define_expand "bltgt"
5466 (if_then_else (ltgt (match_dup 1) (const_int 0))
5467 (label_ref (match_operand 0 "" ""))
5469 "TARGET_ARM && TARGET_HARD_FLOAT"
5470 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
5474 ;; Patterns to match conditional branch insns.
5477 ; Special pattern to match UNEQ.
5478 (define_insn "*arm_buneq"
5480 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5481 (label_ref (match_operand 0 "" ""))
5483 "TARGET_ARM && TARGET_HARD_FLOAT"
5485 if (arm_ccfsm_state != 0)
5488 return \"bvs\\t%l0\;beq\\t%l0\";
5490 [(set_attr "conds" "jump_clob")
5491 (set_attr "length" "8")]
5494 ; Special pattern to match LTGT.
5495 (define_insn "*arm_bltgt"
5497 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5498 (label_ref (match_operand 0 "" ""))
5500 "TARGET_ARM && TARGET_HARD_FLOAT"
5502 if (arm_ccfsm_state != 0)
5505 return \"bmi\\t%l0\;bgt\\t%l0\";
5507 [(set_attr "conds" "jump_clob")
5508 (set_attr "length" "8")]
5511 (define_insn "*arm_cond_branch"
5513 (if_then_else (match_operator 1 "arm_comparison_operator"
5514 [(match_operand 2 "cc_register" "") (const_int 0)])
5515 (label_ref (match_operand 0 "" ""))
5519 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5521 arm_ccfsm_state += 2;
5524 return \"b%d1\\t%l0\";
5526 [(set_attr "conds" "use")]
5529 ; Special pattern to match reversed UNEQ.
5530 (define_insn "*arm_buneq_reversed"
5532 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5534 (label_ref (match_operand 0 "" ""))))]
5535 "TARGET_ARM && TARGET_HARD_FLOAT"
5537 if (arm_ccfsm_state != 0)
5540 return \"bmi\\t%l0\;bgt\\t%l0\";
5542 [(set_attr "conds" "jump_clob")
5543 (set_attr "length" "8")]
5546 ; Special pattern to match reversed LTGT.
5547 (define_insn "*arm_bltgt_reversed"
5549 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5551 (label_ref (match_operand 0 "" ""))))]
5552 "TARGET_ARM && TARGET_HARD_FLOAT"
5554 if (arm_ccfsm_state != 0)
5557 return \"bvs\\t%l0\;beq\\t%l0\";
5559 [(set_attr "conds" "jump_clob")
5560 (set_attr "length" "8")]
5563 (define_insn "*arm_cond_branch_reversed"
5565 (if_then_else (match_operator 1 "arm_comparison_operator"
5566 [(match_operand 2 "cc_register" "") (const_int 0)])
5568 (label_ref (match_operand 0 "" ""))))]
5571 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5573 arm_ccfsm_state += 2;
5576 return \"b%D1\\t%l0\";
5578 [(set_attr "conds" "use")]
5585 (define_expand "seq"
5586 [(set (match_operand:SI 0 "s_register_operand" "")
5587 (eq:SI (match_dup 1) (const_int 0)))]
5589 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5592 (define_expand "sne"
5593 [(set (match_operand:SI 0 "s_register_operand" "")
5594 (ne:SI (match_dup 1) (const_int 0)))]
5596 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5599 (define_expand "sgt"
5600 [(set (match_operand:SI 0 "s_register_operand" "")
5601 (gt:SI (match_dup 1) (const_int 0)))]
5603 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5606 (define_expand "sle"
5607 [(set (match_operand:SI 0 "s_register_operand" "")
5608 (le:SI (match_dup 1) (const_int 0)))]
5610 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5613 (define_expand "sge"
5614 [(set (match_operand:SI 0 "s_register_operand" "")
5615 (ge:SI (match_dup 1) (const_int 0)))]
5617 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5620 (define_expand "slt"
5621 [(set (match_operand:SI 0 "s_register_operand" "")
5622 (lt:SI (match_dup 1) (const_int 0)))]
5624 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5627 (define_expand "sgtu"
5628 [(set (match_operand:SI 0 "s_register_operand" "")
5629 (gtu:SI (match_dup 1) (const_int 0)))]
5631 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5634 (define_expand "sleu"
5635 [(set (match_operand:SI 0 "s_register_operand" "")
5636 (leu:SI (match_dup 1) (const_int 0)))]
5638 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5641 (define_expand "sgeu"
5642 [(set (match_operand:SI 0 "s_register_operand" "")
5643 (geu:SI (match_dup 1) (const_int 0)))]
5645 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5648 (define_expand "sltu"
5649 [(set (match_operand:SI 0 "s_register_operand" "")
5650 (ltu:SI (match_dup 1) (const_int 0)))]
5652 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5655 (define_expand "sunordered"
5656 [(set (match_operand:SI 0 "s_register_operand" "")
5657 (unordered:SI (match_dup 1) (const_int 0)))]
5658 "TARGET_ARM && TARGET_HARD_FLOAT"
5659 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5663 (define_expand "sordered"
5664 [(set (match_operand:SI 0 "s_register_operand" "")
5665 (ordered:SI (match_dup 1) (const_int 0)))]
5666 "TARGET_ARM && TARGET_HARD_FLOAT"
5667 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5671 (define_expand "sungt"
5672 [(set (match_operand:SI 0 "s_register_operand" "")
5673 (ungt:SI (match_dup 1) (const_int 0)))]
5674 "TARGET_ARM && TARGET_HARD_FLOAT"
5675 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
5679 (define_expand "sunge"
5680 [(set (match_operand:SI 0 "s_register_operand" "")
5681 (unge:SI (match_dup 1) (const_int 0)))]
5682 "TARGET_ARM && TARGET_HARD_FLOAT"
5683 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
5687 (define_expand "sunlt"
5688 [(set (match_operand:SI 0 "s_register_operand" "")
5689 (unlt:SI (match_dup 1) (const_int 0)))]
5690 "TARGET_ARM && TARGET_HARD_FLOAT"
5691 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
5695 (define_expand "sunle"
5696 [(set (match_operand:SI 0 "s_register_operand" "")
5697 (unle:SI (match_dup 1) (const_int 0)))]
5698 "TARGET_ARM && TARGET_HARD_FLOAT"
5699 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
5703 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
5704 ;;; simple ARM instructions.
5706 ; (define_expand "suneq"
5707 ; [(set (match_operand:SI 0 "s_register_operand" "")
5708 ; (uneq:SI (match_dup 1) (const_int 0)))]
5709 ; "TARGET_ARM && TARGET_HARD_FLOAT"
5713 ; (define_expand "sltgt"
5714 ; [(set (match_operand:SI 0 "s_register_operand" "")
5715 ; (ltgt:SI (match_dup 1) (const_int 0)))]
5716 ; "TARGET_ARM && TARGET_HARD_FLOAT"
5720 (define_insn "*mov_scc"
5721 [(set (match_operand:SI 0 "s_register_operand" "=r")
5722 (match_operator:SI 1 "arm_comparison_operator"
5723 [(match_operand 2 "cc_register" "") (const_int 0)]))]
5725 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
5726 [(set_attr "conds" "use")
5727 (set_attr "length" "8")]
5730 (define_insn "*mov_negscc"
5731 [(set (match_operand:SI 0 "s_register_operand" "=r")
5732 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
5733 [(match_operand 2 "cc_register" "") (const_int 0)])))]
5735 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
5736 [(set_attr "conds" "use")
5737 (set_attr "length" "8")]
5740 (define_insn "*mov_notscc"
5741 [(set (match_operand:SI 0 "s_register_operand" "=r")
5742 (not:SI (match_operator:SI 1 "arm_comparison_operator"
5743 [(match_operand 2 "cc_register" "") (const_int 0)])))]
5745 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
5746 [(set_attr "conds" "use")
5747 (set_attr "length" "8")]
5751 ;; Conditional move insns
5753 (define_expand "movsicc"
5754 [(set (match_operand:SI 0 "s_register_operand" "")
5755 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
5756 (match_operand:SI 2 "arm_not_operand" "")
5757 (match_operand:SI 3 "arm_not_operand" "")))]
5761 enum rtx_code code = GET_CODE (operands[1]);
5764 if (code == UNEQ || code == LTGT)
5767 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
5768 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
5772 (define_expand "movsfcc"
5773 [(set (match_operand:SF 0 "s_register_operand" "")
5774 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
5775 (match_operand:SF 2 "s_register_operand" "")
5776 (match_operand:SF 3 "nonmemory_operand" "")))]
5780 enum rtx_code code = GET_CODE (operands[1]);
5783 if (code == UNEQ || code == LTGT)
5786 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
5787 Otherwise, ensure it is a valid FP add operand */
5788 if ((!TARGET_HARD_FLOAT)
5789 || (!fpa_add_operand (operands[3], SFmode)))
5790 operands[3] = force_reg (SFmode, operands[3]);
5792 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
5793 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
5797 (define_expand "movdfcc"
5798 [(set (match_operand:DF 0 "s_register_operand" "")
5799 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
5800 (match_operand:DF 2 "s_register_operand" "")
5801 (match_operand:DF 3 "fpa_add_operand" "")))]
5802 "TARGET_ARM && TARGET_HARD_FLOAT"
5805 enum rtx_code code = GET_CODE (operands[1]);
5808 if (code == UNEQ || code == LTGT)
5811 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
5812 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
5816 (define_insn "*movsicc_insn"
5817 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
5819 (match_operator 3 "arm_comparison_operator"
5820 [(match_operand 4 "cc_register" "") (const_int 0)])
5821 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
5822 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
5829 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
5830 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
5831 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
5832 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
5833 [(set_attr "length" "4,4,4,4,8,8,8,8")
5834 (set_attr "conds" "use")]
5837 (define_insn "*movsfcc_soft_insn"
5838 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
5839 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
5840 [(match_operand 4 "cc_register" "") (const_int 0)])
5841 (match_operand:SF 1 "s_register_operand" "0,r")
5842 (match_operand:SF 2 "s_register_operand" "r,0")))]
5843 "TARGET_ARM && TARGET_SOFT_FLOAT"
5847 [(set_attr "conds" "use")]
5851 ;; Jump and linkage insns
5853 (define_expand "jump"
5855 (label_ref (match_operand 0 "" "")))]
5860 (define_insn "*arm_jump"
5862 (label_ref (match_operand 0 "" "")))]
5866 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5868 arm_ccfsm_state += 2;
5871 return \"b%?\\t%l0\";
5874 [(set_attr "predicable" "yes")]
5877 (define_insn "*thumb_jump"
5879 (label_ref (match_operand 0 "" "")))]
5882 if (get_attr_length (insn) == 2)
5884 return \"bl\\t%l0\\t%@ far jump\";
5886 [(set (attr "far_jump")
5888 (eq_attr "length" "4")
5889 (const_string "yes")
5890 (const_string "no")))
5891 (set (attr "length")
5893 (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
5894 (le (minus (match_dup 0) (pc)) (const_int 2044)))
5899 (define_expand "call"
5900 [(parallel [(call (match_operand 0 "memory_operand" "")
5901 (match_operand 1 "general_operand" ""))
5902 (use (match_operand 2 "" ""))
5903 (clobber (reg:SI LR_REGNUM))])]
5909 /* In an untyped call, we can get NULL for operand 2. */
5910 if (operands[2] == NULL_RTX)
5911 operands[2] = const0_rtx;
5913 /* This is to decide if we should generate indirect calls by loading the
5914 32 bit address of the callee into a register before performing the
5915 branch and link. operand[2] encodes the long_call/short_call
5916 attribute of the function being called. This attribute is set whenever
5917 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
5918 is used, and the short_call attribute can also be set if function is
5919 declared as static or if it has already been defined in the current
5920 compilation unit. See arm.c and arm.h for info about this. The third
5921 parameter to arm_is_longcall_p is used to tell it which pattern
5923 callee = XEXP (operands[0], 0);
5925 if (GET_CODE (callee) != REG
5926 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
5927 XEXP (operands[0], 0) = force_reg (Pmode, callee);
5931 (define_insn "*call_reg"
5932 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
5933 (match_operand 1 "" ""))
5934 (use (match_operand 2 "" ""))
5935 (clobber (reg:SI LR_REGNUM))]
5938 return output_call (operands);
5940 ;; length is worst case, normally it is only two
5941 [(set_attr "length" "12")
5942 (set_attr "type" "call")]
5945 (define_insn "*call_mem"
5946 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
5947 (match_operand 1 "" ""))
5948 (use (match_operand 2 "" ""))
5949 (clobber (reg:SI LR_REGNUM))]
5952 return output_call_mem (operands);
5954 [(set_attr "length" "12")
5955 (set_attr "type" "call")]
5958 (define_insn "*call_indirect"
5959 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
5960 (match_operand 1 "" ""))
5961 (use (match_operand 2 "" ""))
5962 (clobber (reg:SI LR_REGNUM))]
5966 if (TARGET_CALLER_INTERWORKING)
5967 return \"bl\\t%__interwork_call_via_%0\";
5969 return \"bl\\t%__call_via_%0\";
5971 [(set_attr "type" "call")]
5974 (define_insn "*call_value_indirect"
5975 [(set (match_operand 0 "" "=l")
5976 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
5977 (match_operand 2 "" "")))
5978 (use (match_operand 3 "" ""))
5979 (clobber (reg:SI LR_REGNUM))]
5983 if (TARGET_CALLER_INTERWORKING)
5984 return \"bl\\t%__interwork_call_via_%1\";
5986 return \"bl\\t%__call_via_%1\";
5988 [(set_attr "type" "call")]
5991 (define_expand "call_value"
5992 [(parallel [(set (match_operand 0 "" "")
5993 (call (match_operand 1 "memory_operand" "")
5994 (match_operand 2 "general_operand" "")))
5995 (use (match_operand 3 "" ""))
5996 (clobber (reg:SI LR_REGNUM))])]
6000 rtx callee = XEXP (operands[1], 0);
6002 /* In an untyped call, we can get NULL for operand 2. */
6003 if (operands[3] == 0)
6004 operands[3] = const0_rtx;
6006 /* See the comment in define_expand \"call\". */
6007 if (GET_CODE (callee) != REG
6008 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6009 XEXP (operands[1], 0) = force_reg (Pmode, callee);
6013 (define_insn "*call_value_reg"
6014 [(set (match_operand 0 "" "=r,f,v")
6015 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r,r"))
6016 (match_operand 2 "" "")))
6017 (use (match_operand 3 "" ""))
6018 (clobber (reg:SI LR_REGNUM))]
6021 return output_call (&operands[1]);
6023 [(set_attr "length" "12")
6024 (set_attr "type" "call")]
6027 (define_insn "*call_value_mem"
6028 [(set (match_operand 0 "" "=r,f,v")
6029 (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m,m"))
6030 (match_operand 2 "" "")))
6031 (use (match_operand 3 "" ""))
6032 (clobber (reg:SI LR_REGNUM))]
6033 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6035 return output_call_mem (&operands[1]);
6037 [(set_attr "length" "12")
6038 (set_attr "type" "call")]
6041 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6042 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6044 (define_insn "*call_symbol"
6045 [(call (mem:SI (match_operand:SI 0 "" "X"))
6046 (match_operand 1 "" ""))
6047 (use (match_operand 2 "" ""))
6048 (clobber (reg:SI LR_REGNUM))]
6050 && (GET_CODE (operands[0]) == SYMBOL_REF)
6051 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6054 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6056 [(set_attr "type" "call")]
6059 (define_insn "*call_value_symbol"
6060 [(set (match_operand 0 "s_register_operand" "=r,f,v")
6061 (call (mem:SI (match_operand:SI 1 "" "X,X,X"))
6062 (match_operand:SI 2 "" "")))
6063 (use (match_operand 3 "" ""))
6064 (clobber (reg:SI LR_REGNUM))]
6066 && (GET_CODE (operands[1]) == SYMBOL_REF)
6067 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6070 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6072 [(set_attr "type" "call")]
6075 (define_insn "*call_insn"
6076 [(call (mem:SI (match_operand:SI 0 "" "X"))
6077 (match_operand:SI 1 "" ""))
6078 (use (match_operand 2 "" ""))
6079 (clobber (reg:SI LR_REGNUM))]
6081 && GET_CODE (operands[0]) == SYMBOL_REF
6082 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6084 [(set_attr "length" "4")
6085 (set_attr "type" "call")]
6088 (define_insn "*call_value_insn"
6089 [(set (match_operand 0 "register_operand" "=l")
6090 (call (mem:SI (match_operand 1 "" "X"))
6091 (match_operand 2 "" "")))
6092 (use (match_operand 3 "" ""))
6093 (clobber (reg:SI LR_REGNUM))]
6095 && GET_CODE (operands[1]) == SYMBOL_REF
6096 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6098 [(set_attr "length" "4")
6099 (set_attr "type" "call")]
6102 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6103 (define_expand "sibcall"
6104 [(parallel [(call (match_operand 0 "memory_operand" "")
6105 (match_operand 1 "general_operand" ""))
6107 (use (match_operand 2 "" ""))])]
6111 if (operands[2] == NULL_RTX)
6112 operands[2] = const0_rtx;
6116 (define_expand "sibcall_value"
6117 [(parallel [(set (match_operand 0 "register_operand" "")
6118 (call (match_operand 1 "memory_operand" "")
6119 (match_operand 2 "general_operand" "")))
6121 (use (match_operand 3 "" ""))])]
6125 if (operands[3] == NULL_RTX)
6126 operands[3] = const0_rtx;
6130 (define_insn "*sibcall_insn"
6131 [(call (mem:SI (match_operand:SI 0 "" "X"))
6132 (match_operand 1 "" ""))
6134 (use (match_operand 2 "" ""))]
6135 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6137 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6139 [(set_attr "type" "call")]
6142 (define_insn "*sibcall_value_insn"
6143 [(set (match_operand 0 "s_register_operand" "=r,f,v")
6144 (call (mem:SI (match_operand:SI 1 "" "X,X,X"))
6145 (match_operand 2 "" "")))
6147 (use (match_operand 3 "" ""))]
6148 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6150 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6152 [(set_attr "type" "call")]
6155 ;; Often the return insn will be the same as loading from memory, so set attr
6156 (define_insn "return"
6158 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6161 if (arm_ccfsm_state == 2)
6163 arm_ccfsm_state += 2;
6166 return output_return_instruction (const_true_rtx, TRUE, FALSE);
6168 [(set_attr "type" "load")
6169 (set_attr "predicable" "yes")]
6172 (define_insn "*cond_return"
6174 (if_then_else (match_operator 0 "arm_comparison_operator"
6175 [(match_operand 1 "cc_register" "") (const_int 0)])
6178 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6181 if (arm_ccfsm_state == 2)
6183 arm_ccfsm_state += 2;
6186 return output_return_instruction (operands[0], TRUE, FALSE);
6188 [(set_attr "conds" "use")
6189 (set_attr "type" "load")]
6192 (define_insn "*cond_return_inverted"
6194 (if_then_else (match_operator 0 "arm_comparison_operator"
6195 [(match_operand 1 "cc_register" "") (const_int 0)])
6198 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6201 if (arm_ccfsm_state == 2)
6203 arm_ccfsm_state += 2;
6206 return output_return_instruction (operands[0], TRUE, TRUE);
6208 [(set_attr "conds" "use")
6209 (set_attr "type" "load")]
6212 ;; Generate a sequence of instructions to determine if the processor is
6213 ;; in 26-bit or 32-bit mode, and return the appropriate return address
6216 (define_expand "return_addr_mask"
6218 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6220 (set (match_operand:SI 0 "s_register_operand" "")
6221 (if_then_else:SI (eq (match_dup 1) (const_int 0))
6223 (const_int 67108860)))] ; 0x03fffffc
6226 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
6229 (define_insn "*check_arch2"
6230 [(set (match_operand:CC_NOOV 0 "cc_register" "")
6231 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6234 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
6235 [(set_attr "length" "8")
6236 (set_attr "conds" "set")]
6239 ;; Call subroutine returning any type.
6241 (define_expand "untyped_call"
6242 [(parallel [(call (match_operand 0 "" "")
6244 (match_operand 1 "" "")
6245 (match_operand 2 "" "")])]
6251 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6253 for (i = 0; i < XVECLEN (operands[2], 0); i++)
6255 rtx set = XVECEXP (operands[2], 0, i);
6257 emit_move_insn (SET_DEST (set), SET_SRC (set));
6260 /* The optimizer does not know that the call sets the function value
6261 registers we stored in the result block. We avoid problems by
6262 claiming that all hard registers are used and clobbered at this
6264 emit_insn (gen_blockage ());
6270 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6271 ;; all of memory. This blocks insns from being moved across this point.
6273 (define_insn "blockage"
6274 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6277 [(set_attr "length" "0")
6278 (set_attr "type" "block")]
6281 (define_expand "casesi"
6282 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6283 (match_operand:SI 1 "const_int_operand" "") ; lower bound
6284 (match_operand:SI 2 "const_int_operand" "") ; total range
6285 (match_operand:SI 3 "" "") ; table label
6286 (match_operand:SI 4 "" "")] ; Out of range label
6291 if (operands[1] != const0_rtx)
6293 reg = gen_reg_rtx (SImode);
6295 emit_insn (gen_addsi3 (reg, operands[0],
6296 GEN_INT (-INTVAL (operands[1]))));
6300 if (!const_ok_for_arm (INTVAL (operands[2])))
6301 operands[2] = force_reg (SImode, operands[2]);
6303 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6309 ;; The USE in this pattern is needed to tell flow analysis that this is
6310 ;; a CASESI insn. It has no other purpose.
6311 (define_insn "casesi_internal"
6312 [(parallel [(set (pc)
6314 (leu (match_operand:SI 0 "s_register_operand" "r")
6315 (match_operand:SI 1 "arm_rhs_operand" "rI"))
6316 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6317 (label_ref (match_operand 2 "" ""))))
6318 (label_ref (match_operand 3 "" ""))))
6319 (clobber (reg:CC CC_REGNUM))
6320 (use (label_ref (match_dup 2)))])]
6324 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6325 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6327 [(set_attr "conds" "clob")
6328 (set_attr "length" "12")]
6331 (define_expand "indirect_jump"
6333 (match_operand:SI 0 "s_register_operand" ""))]
6338 (define_insn "*arm_indirect_jump"
6340 (match_operand:SI 0 "s_register_operand" "r"))]
6342 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6343 [(set_attr "predicable" "yes")]
6346 ;; Although not supported by the define_expand above,
6347 ;; cse/combine may generate this form.
6348 (define_insn "*load_indirect_jump"
6350 (match_operand:SI 0 "memory_operand" "m"))]
6352 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6353 [(set_attr "type" "load")
6354 (set_attr "pool_range" "4096")
6355 (set_attr "neg_pool_range" "4084")
6356 (set_attr "predicable" "yes")]
6359 (define_insn "*thumb_indirect_jump"
6361 (match_operand:SI 0 "register_operand" "l*r"))]
6364 [(set_attr "conds" "clob")
6365 (set_attr "length" "2")]
6376 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6377 return \"mov\\tr8, r8\";
6379 [(set (attr "length")
6380 (if_then_else (eq_attr "is_thumb" "yes")
6386 ;; Patterns to allow combination of arithmetic, cond code and shifts
6388 (define_insn "*arith_shiftsi"
6389 [(set (match_operand:SI 0 "s_register_operand" "=r")
6390 (match_operator:SI 1 "shiftable_operator"
6391 [(match_operator:SI 3 "shift_operator"
6392 [(match_operand:SI 4 "s_register_operand" "r")
6393 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6394 (match_operand:SI 2 "s_register_operand" "r")]))]
6396 "%i1%?\\t%0, %2, %4%S3"
6397 [(set_attr "predicable" "yes")
6398 (set_attr "shift" "4")
6402 (define_insn "*arith_shiftsi_compare0"
6403 [(set (reg:CC_NOOV CC_REGNUM)
6404 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6405 [(match_operator:SI 3 "shift_operator"
6406 [(match_operand:SI 4 "s_register_operand" "r")
6407 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6408 (match_operand:SI 2 "s_register_operand" "r")])
6410 (set (match_operand:SI 0 "s_register_operand" "=r")
6411 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6414 "%i1%?s\\t%0, %2, %4%S3"
6415 [(set_attr "conds" "set")
6416 (set_attr "shift" "4")
6420 (define_insn "*arith_shiftsi_compare0_scratch"
6421 [(set (reg:CC_NOOV CC_REGNUM)
6422 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6423 [(match_operator:SI 3 "shift_operator"
6424 [(match_operand:SI 4 "s_register_operand" "r")
6425 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6426 (match_operand:SI 2 "s_register_operand" "r")])
6428 (clobber (match_scratch:SI 0 "=r"))]
6430 "%i1%?s\\t%0, %2, %4%S3"
6431 [(set_attr "conds" "set")
6432 (set_attr "shift" "4")
6436 (define_insn "*sub_shiftsi"
6437 [(set (match_operand:SI 0 "s_register_operand" "=r")
6438 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6439 (match_operator:SI 2 "shift_operator"
6440 [(match_operand:SI 3 "s_register_operand" "r")
6441 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
6443 "sub%?\\t%0, %1, %3%S2"
6444 [(set_attr "predicable" "yes")
6445 (set_attr "shift" "3")
6449 (define_insn "*sub_shiftsi_compare0"
6450 [(set (reg:CC_NOOV CC_REGNUM)
6452 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6453 (match_operator:SI 2 "shift_operator"
6454 [(match_operand:SI 3 "s_register_operand" "r")
6455 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6457 (set (match_operand:SI 0 "s_register_operand" "=r")
6458 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6461 "sub%?s\\t%0, %1, %3%S2"
6462 [(set_attr "conds" "set")
6463 (set_attr "shift" "3")
6467 (define_insn "*sub_shiftsi_compare0_scratch"
6468 [(set (reg:CC_NOOV CC_REGNUM)
6470 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6471 (match_operator:SI 2 "shift_operator"
6472 [(match_operand:SI 3 "s_register_operand" "r")
6473 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6475 (clobber (match_scratch:SI 0 "=r"))]
6477 "sub%?s\\t%0, %1, %3%S2"
6478 [(set_attr "conds" "set")
6479 (set_attr "shift" "3")
6485 (define_insn "*and_scc"
6486 [(set (match_operand:SI 0 "s_register_operand" "=r")
6487 (and:SI (match_operator:SI 1 "arm_comparison_operator"
6488 [(match_operand 3 "cc_register" "") (const_int 0)])
6489 (match_operand:SI 2 "s_register_operand" "r")))]
6491 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
6492 [(set_attr "conds" "use")
6493 (set_attr "length" "8")]
6496 (define_insn "*ior_scc"
6497 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6498 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
6499 [(match_operand 3 "cc_register" "") (const_int 0)])
6500 (match_operand:SI 1 "s_register_operand" "0,?r")))]
6504 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
6505 [(set_attr "conds" "use")
6506 (set_attr "length" "4,8")]
6509 (define_insn "*compare_scc"
6510 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6511 (match_operator:SI 1 "arm_comparison_operator"
6512 [(match_operand:SI 2 "s_register_operand" "r,r")
6513 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
6514 (clobber (reg:CC CC_REGNUM))]
6517 if (operands[3] == const0_rtx)
6519 if (GET_CODE (operands[1]) == LT)
6520 return \"mov\\t%0, %2, lsr #31\";
6522 if (GET_CODE (operands[1]) == GE)
6523 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
6525 if (GET_CODE (operands[1]) == EQ)
6526 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
6529 if (GET_CODE (operands[1]) == NE)
6531 if (which_alternative == 1)
6532 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
6533 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
6535 if (which_alternative == 1)
6536 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
6538 output_asm_insn (\"cmp\\t%2, %3\", operands);
6539 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
6541 [(set_attr "conds" "clob")
6542 (set_attr "length" "12")]
6545 (define_insn "*cond_move"
6546 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
6547 (if_then_else:SI (match_operator 3 "equality_operator"
6548 [(match_operator 4 "arm_comparison_operator"
6549 [(match_operand 5 "cc_register" "") (const_int 0)])
6551 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
6552 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
6555 if (GET_CODE (operands[3]) == NE)
6557 if (which_alternative != 1)
6558 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
6559 if (which_alternative != 0)
6560 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
6563 if (which_alternative != 0)
6564 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6565 if (which_alternative != 1)
6566 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
6569 [(set_attr "conds" "use")
6570 (set_attr "length" "4,4,8")]
6573 (define_insn "*cond_arith"
6574 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6575 (match_operator:SI 5 "shiftable_operator"
6576 [(match_operator:SI 4 "arm_comparison_operator"
6577 [(match_operand:SI 2 "s_register_operand" "r,r")
6578 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
6579 (match_operand:SI 1 "s_register_operand" "0,?r")]))
6580 (clobber (reg:CC CC_REGNUM))]
6583 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
6584 return \"%i5\\t%0, %1, %2, lsr #31\";
6586 output_asm_insn (\"cmp\\t%2, %3\", operands);
6587 if (GET_CODE (operands[5]) == AND)
6588 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
6589 else if (GET_CODE (operands[5]) == MINUS)
6590 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
6591 else if (which_alternative != 0)
6592 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6593 return \"%i5%d4\\t%0, %1, #1\";
6595 [(set_attr "conds" "clob")
6596 (set_attr "length" "12")]
6599 (define_insn "*cond_sub"
6600 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6601 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
6602 (match_operator:SI 4 "arm_comparison_operator"
6603 [(match_operand:SI 2 "s_register_operand" "r,r")
6604 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
6605 (clobber (reg:CC CC_REGNUM))]
6608 output_asm_insn (\"cmp\\t%2, %3\", operands);
6609 if (which_alternative != 0)
6610 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6611 return \"sub%d4\\t%0, %1, #1\";
6613 [(set_attr "conds" "clob")
6614 (set_attr "length" "8,12")]
6617 (define_insn "*cmp_ite0"
6618 [(set (match_operand 6 "dominant_cc_register" "")
6621 (match_operator 4 "arm_comparison_operator"
6622 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6623 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6624 (match_operator:SI 5 "arm_comparison_operator"
6625 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6626 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
6632 static const char * const opcodes[4][2] =
6634 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
6635 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
6636 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
6637 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
6638 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
6639 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
6640 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
6641 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
6644 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
6646 return opcodes[which_alternative][swap];
6648 [(set_attr "conds" "set")
6649 (set_attr "length" "8")]
6652 (define_insn "*cmp_ite1"
6653 [(set (match_operand 6 "dominant_cc_register" "")
6656 (match_operator 4 "arm_comparison_operator"
6657 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6658 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6659 (match_operator:SI 5 "arm_comparison_operator"
6660 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6661 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
6667 static const char * const opcodes[4][2] =
6669 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
6670 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
6671 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
6672 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
6673 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
6674 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
6675 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
6676 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
6679 comparison_dominates_p (GET_CODE (operands[5]),
6680 reverse_condition (GET_CODE (operands[4])));
6682 return opcodes[which_alternative][swap];
6684 [(set_attr "conds" "set")
6685 (set_attr "length" "8")]
6688 (define_insn "*cmp_and"
6689 [(set (match_operand 6 "dominant_cc_register" "")
6692 (match_operator 4 "arm_comparison_operator"
6693 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6694 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6695 (match_operator:SI 5 "arm_comparison_operator"
6696 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6697 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
6702 static const char *const opcodes[4][2] =
6704 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
6705 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
6706 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
6707 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
6708 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
6709 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
6710 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
6711 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
6714 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
6716 return opcodes[which_alternative][swap];
6718 [(set_attr "conds" "set")
6719 (set_attr "predicable" "no")
6720 (set_attr "length" "8")]
6723 (define_insn "*cmp_ior"
6724 [(set (match_operand 6 "dominant_cc_register" "")
6727 (match_operator 4 "arm_comparison_operator"
6728 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6729 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6730 (match_operator:SI 5 "arm_comparison_operator"
6731 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6732 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
6737 static const char *const opcodes[4][2] =
6739 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
6740 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
6741 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
6742 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
6743 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
6744 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
6745 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
6746 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
6749 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
6751 return opcodes[which_alternative][swap];
6754 [(set_attr "conds" "set")
6755 (set_attr "length" "8")]
6758 (define_insn_and_split "*ior_scc_scc"
6759 [(set (match_operand:SI 0 "s_register_operand" "=r")
6760 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
6761 [(match_operand:SI 1 "s_register_operand" "r")
6762 (match_operand:SI 2 "arm_add_operand" "rIL")])
6763 (match_operator:SI 6 "arm_comparison_operator"
6764 [(match_operand:SI 4 "s_register_operand" "r")
6765 (match_operand:SI 5 "arm_add_operand" "rIL")])))
6766 (clobber (reg:CC CC_REGNUM))]
6768 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
6771 "TARGET_ARM && reload_completed"
6775 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6776 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
6778 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
6780 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
6783 [(set_attr "conds" "clob")
6784 (set_attr "length" "16")])
6786 ; If the above pattern is followed by a CMP insn, then the compare is
6787 ; redundant, since we can rework the conditional instruction that follows.
6788 (define_insn_and_split "*ior_scc_scc_cmp"
6789 [(set (match_operand 0 "dominant_cc_register" "")
6790 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
6791 [(match_operand:SI 1 "s_register_operand" "r")
6792 (match_operand:SI 2 "arm_add_operand" "rIL")])
6793 (match_operator:SI 6 "arm_comparison_operator"
6794 [(match_operand:SI 4 "s_register_operand" "r")
6795 (match_operand:SI 5 "arm_add_operand" "rIL")]))
6797 (set (match_operand:SI 7 "s_register_operand" "=r")
6798 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6799 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
6802 "TARGET_ARM && reload_completed"
6806 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6807 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
6809 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
6811 [(set_attr "conds" "set")
6812 (set_attr "length" "16")])
6814 (define_insn_and_split "*and_scc_scc"
6815 [(set (match_operand:SI 0 "s_register_operand" "=r")
6816 (and:SI (match_operator:SI 3 "arm_comparison_operator"
6817 [(match_operand:SI 1 "s_register_operand" "r")
6818 (match_operand:SI 2 "arm_add_operand" "rIL")])
6819 (match_operator:SI 6 "arm_comparison_operator"
6820 [(match_operand:SI 4 "s_register_operand" "r")
6821 (match_operand:SI 5 "arm_add_operand" "rIL")])))
6822 (clobber (reg:CC CC_REGNUM))]
6824 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
6827 "TARGET_ARM && reload_completed
6828 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
6833 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6834 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
6836 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
6838 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
6841 [(set_attr "conds" "clob")
6842 (set_attr "length" "16")])
6844 ; If the above pattern is followed by a CMP insn, then the compare is
6845 ; redundant, since we can rework the conditional instruction that follows.
6846 (define_insn_and_split "*and_scc_scc_cmp"
6847 [(set (match_operand 0 "dominant_cc_register" "")
6848 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
6849 [(match_operand:SI 1 "s_register_operand" "r")
6850 (match_operand:SI 2 "arm_add_operand" "rIL")])
6851 (match_operator:SI 6 "arm_comparison_operator"
6852 [(match_operand:SI 4 "s_register_operand" "r")
6853 (match_operand:SI 5 "arm_add_operand" "rIL")]))
6855 (set (match_operand:SI 7 "s_register_operand" "=r")
6856 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6857 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
6860 "TARGET_ARM && reload_completed"
6864 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6865 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
6867 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
6869 [(set_attr "conds" "set")
6870 (set_attr "length" "16")])
6872 ;; If there is no dominance in the comparison, then we can still save an
6873 ;; instruction in the AND case, since we can know that the second compare
6874 ;; need only zero the value if false (if true, then the value is already
6876 (define_insn_and_split "*and_scc_scc_nodom"
6877 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
6878 (and:SI (match_operator:SI 3 "arm_comparison_operator"
6879 [(match_operand:SI 1 "s_register_operand" "r,r,0")
6880 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
6881 (match_operator:SI 6 "arm_comparison_operator"
6882 [(match_operand:SI 4 "s_register_operand" "r,r,r")
6883 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
6884 (clobber (reg:CC CC_REGNUM))]
6886 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
6889 "TARGET_ARM && reload_completed"
6890 [(parallel [(set (match_dup 0)
6891 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
6892 (clobber (reg:CC CC_REGNUM))])
6893 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
6895 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
6898 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
6899 operands[4], operands[5]),
6901 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
6903 [(set_attr "conds" "clob")
6904 (set_attr "length" "20")])
6906 (define_insn "*negscc"
6907 [(set (match_operand:SI 0 "s_register_operand" "=r")
6908 (neg:SI (match_operator 3 "arm_comparison_operator"
6909 [(match_operand:SI 1 "s_register_operand" "r")
6910 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
6911 (clobber (reg:CC CC_REGNUM))]
6914 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
6915 return \"mov\\t%0, %1, asr #31\";
6917 if (GET_CODE (operands[3]) == NE)
6918 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
6920 if (GET_CODE (operands[3]) == GT)
6921 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
6923 output_asm_insn (\"cmp\\t%1, %2\", operands);
6924 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
6925 return \"mvn%d3\\t%0, #0\";
6927 [(set_attr "conds" "clob")
6928 (set_attr "length" "12")]
6931 (define_insn "movcond"
6932 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
6934 (match_operator 5 "arm_comparison_operator"
6935 [(match_operand:SI 3 "s_register_operand" "r,r,r")
6936 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
6937 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
6938 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
6939 (clobber (reg:CC CC_REGNUM))]
6942 if (GET_CODE (operands[5]) == LT
6943 && (operands[4] == const0_rtx))
6945 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
6947 if (operands[2] == const0_rtx)
6948 return \"and\\t%0, %1, %3, asr #31\";
6949 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
6951 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
6953 if (operands[1] == const0_rtx)
6954 return \"bic\\t%0, %2, %3, asr #31\";
6955 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
6957 /* The only case that falls through to here is when both ops 1 & 2
6961 if (GET_CODE (operands[5]) == GE
6962 && (operands[4] == const0_rtx))
6964 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
6966 if (operands[2] == const0_rtx)
6967 return \"bic\\t%0, %1, %3, asr #31\";
6968 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
6970 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
6972 if (operands[1] == const0_rtx)
6973 return \"and\\t%0, %2, %3, asr #31\";
6974 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
6976 /* The only case that falls through to here is when both ops 1 & 2
6979 if (GET_CODE (operands[4]) == CONST_INT
6980 && !const_ok_for_arm (INTVAL (operands[4])))
6981 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
6983 output_asm_insn (\"cmp\\t%3, %4\", operands);
6984 if (which_alternative != 0)
6985 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
6986 if (which_alternative != 1)
6987 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
6990 [(set_attr "conds" "clob")
6991 (set_attr "length" "8,8,12")]
6994 (define_insn "*ifcompare_plus_move"
6995 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6996 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
6997 [(match_operand:SI 4 "s_register_operand" "r,r")
6998 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7000 (match_operand:SI 2 "s_register_operand" "r,r")
7001 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7002 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7003 (clobber (reg:CC CC_REGNUM))]
7006 [(set_attr "conds" "clob")
7007 (set_attr "length" "8,12")]
7010 (define_insn "*if_plus_move"
7011 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7013 (match_operator 4 "arm_comparison_operator"
7014 [(match_operand 5 "cc_register" "") (const_int 0)])
7016 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7017 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7018 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7022 sub%d4\\t%0, %2, #%n3
7023 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7024 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7025 [(set_attr "conds" "use")
7026 (set_attr "length" "4,4,8,8")
7027 (set_attr "type" "*,*,*,*")]
7030 (define_insn "*ifcompare_move_plus"
7031 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7032 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7033 [(match_operand:SI 4 "s_register_operand" "r,r")
7034 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7035 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7037 (match_operand:SI 2 "s_register_operand" "r,r")
7038 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7039 (clobber (reg:CC CC_REGNUM))]
7042 [(set_attr "conds" "clob")
7043 (set_attr "length" "8,12")]
7046 (define_insn "*if_move_plus"
7047 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7049 (match_operator 4 "arm_comparison_operator"
7050 [(match_operand 5 "cc_register" "") (const_int 0)])
7051 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7053 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7054 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7058 sub%D4\\t%0, %2, #%n3
7059 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7060 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7061 [(set_attr "conds" "use")
7062 (set_attr "length" "4,4,8,8")
7063 (set_attr "type" "*,*,*,*")]
7066 (define_insn "*ifcompare_arith_arith"
7067 [(set (match_operand:SI 0 "s_register_operand" "=r")
7068 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7069 [(match_operand:SI 5 "s_register_operand" "r")
7070 (match_operand:SI 6 "arm_add_operand" "rIL")])
7071 (match_operator:SI 8 "shiftable_operator"
7072 [(match_operand:SI 1 "s_register_operand" "r")
7073 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7074 (match_operator:SI 7 "shiftable_operator"
7075 [(match_operand:SI 3 "s_register_operand" "r")
7076 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7077 (clobber (reg:CC CC_REGNUM))]
7080 [(set_attr "conds" "clob")
7081 (set_attr "length" "12")]
7084 (define_insn "*if_arith_arith"
7085 [(set (match_operand:SI 0 "s_register_operand" "=r")
7086 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7087 [(match_operand 8 "cc_register" "") (const_int 0)])
7088 (match_operator:SI 6 "shiftable_operator"
7089 [(match_operand:SI 1 "s_register_operand" "r")
7090 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7091 (match_operator:SI 7 "shiftable_operator"
7092 [(match_operand:SI 3 "s_register_operand" "r")
7093 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7095 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7096 [(set_attr "conds" "use")
7097 (set_attr "length" "8")]
7100 (define_insn "*ifcompare_arith_move"
7101 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7102 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7103 [(match_operand:SI 2 "s_register_operand" "r,r")
7104 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7105 (match_operator:SI 7 "shiftable_operator"
7106 [(match_operand:SI 4 "s_register_operand" "r,r")
7107 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7108 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7109 (clobber (reg:CC CC_REGNUM))]
7112 /* If we have an operation where (op x 0) is the identity operation and
7113 the conditional operator is LT or GE and we are comparing against zero and
7114 everything is in registers then we can do this in two instructions */
7115 if (operands[3] == const0_rtx
7116 && GET_CODE (operands[7]) != AND
7117 && GET_CODE (operands[5]) == REG
7118 && GET_CODE (operands[1]) == REG
7119 && REGNO (operands[1]) == REGNO (operands[4])
7120 && REGNO (operands[4]) != REGNO (operands[0]))
7122 if (GET_CODE (operands[6]) == LT)
7123 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7124 else if (GET_CODE (operands[6]) == GE)
7125 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7127 if (GET_CODE (operands[3]) == CONST_INT
7128 && !const_ok_for_arm (INTVAL (operands[3])))
7129 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7131 output_asm_insn (\"cmp\\t%2, %3\", operands);
7132 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7133 if (which_alternative != 0)
7134 return \"mov%D6\\t%0, %1\";
7137 [(set_attr "conds" "clob")
7138 (set_attr "length" "8,12")]
7141 (define_insn "*if_arith_move"
7142 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7143 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7144 [(match_operand 6 "cc_register" "") (const_int 0)])
7145 (match_operator:SI 5 "shiftable_operator"
7146 [(match_operand:SI 2 "s_register_operand" "r,r")
7147 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7148 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7152 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7153 [(set_attr "conds" "use")
7154 (set_attr "length" "4,8")
7155 (set_attr "type" "*,*")]
7158 (define_insn "*ifcompare_move_arith"
7159 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7160 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7161 [(match_operand:SI 4 "s_register_operand" "r,r")
7162 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7163 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7164 (match_operator:SI 7 "shiftable_operator"
7165 [(match_operand:SI 2 "s_register_operand" "r,r")
7166 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7167 (clobber (reg:CC CC_REGNUM))]
7170 /* If we have an operation where (op x 0) is the identity operation and
7171 the conditional operator is LT or GE and we are comparing against zero and
7172 everything is in registers then we can do this in two instructions */
7173 if (operands[5] == const0_rtx
7174 && GET_CODE (operands[7]) != AND
7175 && GET_CODE (operands[3]) == REG
7176 && GET_CODE (operands[1]) == REG
7177 && REGNO (operands[1]) == REGNO (operands[2])
7178 && REGNO (operands[2]) != REGNO (operands[0]))
7180 if (GET_CODE (operands[6]) == GE)
7181 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7182 else if (GET_CODE (operands[6]) == LT)
7183 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7186 if (GET_CODE (operands[5]) == CONST_INT
7187 && !const_ok_for_arm (INTVAL (operands[5])))
7188 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7190 output_asm_insn (\"cmp\\t%4, %5\", operands);
7192 if (which_alternative != 0)
7193 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7194 return \"%I7%D6\\t%0, %2, %3\";
7196 [(set_attr "conds" "clob")
7197 (set_attr "length" "8,12")]
7200 (define_insn "*if_move_arith"
7201 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7203 (match_operator 4 "arm_comparison_operator"
7204 [(match_operand 6 "cc_register" "") (const_int 0)])
7205 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7206 (match_operator:SI 5 "shiftable_operator"
7207 [(match_operand:SI 2 "s_register_operand" "r,r")
7208 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7212 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7213 [(set_attr "conds" "use")
7214 (set_attr "length" "4,8")
7215 (set_attr "type" "*,*")]
7218 (define_insn "*ifcompare_move_not"
7219 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7221 (match_operator 5 "arm_comparison_operator"
7222 [(match_operand:SI 3 "s_register_operand" "r,r")
7223 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7224 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7226 (match_operand:SI 2 "s_register_operand" "r,r"))))
7227 (clobber (reg:CC CC_REGNUM))]
7230 [(set_attr "conds" "clob")
7231 (set_attr "length" "8,12")]
7234 (define_insn "*if_move_not"
7235 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7237 (match_operator 4 "arm_comparison_operator"
7238 [(match_operand 3 "cc_register" "") (const_int 0)])
7239 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7240 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7244 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7245 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7246 [(set_attr "conds" "use")
7247 (set_attr "length" "4,8,8")]
7250 (define_insn "*ifcompare_not_move"
7251 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7253 (match_operator 5 "arm_comparison_operator"
7254 [(match_operand:SI 3 "s_register_operand" "r,r")
7255 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7257 (match_operand:SI 2 "s_register_operand" "r,r"))
7258 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7259 (clobber (reg:CC CC_REGNUM))]
7262 [(set_attr "conds" "clob")
7263 (set_attr "length" "8,12")]
7266 (define_insn "*if_not_move"
7267 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7269 (match_operator 4 "arm_comparison_operator"
7270 [(match_operand 3 "cc_register" "") (const_int 0)])
7271 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7272 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7276 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7277 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7278 [(set_attr "conds" "use")
7279 (set_attr "length" "4,8,8")]
7282 (define_insn "*ifcompare_shift_move"
7283 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7285 (match_operator 6 "arm_comparison_operator"
7286 [(match_operand:SI 4 "s_register_operand" "r,r")
7287 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7288 (match_operator:SI 7 "shift_operator"
7289 [(match_operand:SI 2 "s_register_operand" "r,r")
7290 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7291 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7292 (clobber (reg:CC CC_REGNUM))]
7295 [(set_attr "conds" "clob")
7296 (set_attr "length" "8,12")]
7299 (define_insn "*if_shift_move"
7300 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7302 (match_operator 5 "arm_comparison_operator"
7303 [(match_operand 6 "cc_register" "") (const_int 0)])
7304 (match_operator:SI 4 "shift_operator"
7305 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7306 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7307 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7311 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7312 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7313 [(set_attr "conds" "use")
7314 (set_attr "shift" "2")
7315 (set_attr "length" "4,8,8")]
7318 (define_insn "*ifcompare_move_shift"
7319 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7321 (match_operator 6 "arm_comparison_operator"
7322 [(match_operand:SI 4 "s_register_operand" "r,r")
7323 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7324 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7325 (match_operator:SI 7 "shift_operator"
7326 [(match_operand:SI 2 "s_register_operand" "r,r")
7327 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7328 (clobber (reg:CC CC_REGNUM))]
7331 [(set_attr "conds" "clob")
7332 (set_attr "length" "8,12")]
7335 (define_insn "*if_move_shift"
7336 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7338 (match_operator 5 "arm_comparison_operator"
7339 [(match_operand 6 "cc_register" "") (const_int 0)])
7340 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7341 (match_operator:SI 4 "shift_operator"
7342 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7343 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7347 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7348 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7349 [(set_attr "conds" "use")
7350 (set_attr "shift" "2")
7351 (set_attr "length" "4,8,8")]
7354 (define_insn "*ifcompare_shift_shift"
7355 [(set (match_operand:SI 0 "s_register_operand" "=r")
7357 (match_operator 7 "arm_comparison_operator"
7358 [(match_operand:SI 5 "s_register_operand" "r")
7359 (match_operand:SI 6 "arm_add_operand" "rIL")])
7360 (match_operator:SI 8 "shift_operator"
7361 [(match_operand:SI 1 "s_register_operand" "r")
7362 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7363 (match_operator:SI 9 "shift_operator"
7364 [(match_operand:SI 3 "s_register_operand" "r")
7365 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7366 (clobber (reg:CC CC_REGNUM))]
7369 [(set_attr "conds" "clob")
7370 (set_attr "length" "12")]
7373 (define_insn "*if_shift_shift"
7374 [(set (match_operand:SI 0 "s_register_operand" "=r")
7376 (match_operator 5 "arm_comparison_operator"
7377 [(match_operand 8 "cc_register" "") (const_int 0)])
7378 (match_operator:SI 6 "shift_operator"
7379 [(match_operand:SI 1 "s_register_operand" "r")
7380 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7381 (match_operator:SI 7 "shift_operator"
7382 [(match_operand:SI 3 "s_register_operand" "r")
7383 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7385 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7386 [(set_attr "conds" "use")
7387 (set_attr "shift" "1")
7388 (set_attr "length" "8")]
7391 (define_insn "*ifcompare_not_arith"
7392 [(set (match_operand:SI 0 "s_register_operand" "=r")
7394 (match_operator 6 "arm_comparison_operator"
7395 [(match_operand:SI 4 "s_register_operand" "r")
7396 (match_operand:SI 5 "arm_add_operand" "rIL")])
7397 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7398 (match_operator:SI 7 "shiftable_operator"
7399 [(match_operand:SI 2 "s_register_operand" "r")
7400 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7401 (clobber (reg:CC CC_REGNUM))]
7404 [(set_attr "conds" "clob")
7405 (set_attr "length" "12")]
7408 (define_insn "*if_not_arith"
7409 [(set (match_operand:SI 0 "s_register_operand" "=r")
7411 (match_operator 5 "arm_comparison_operator"
7412 [(match_operand 4 "cc_register" "") (const_int 0)])
7413 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7414 (match_operator:SI 6 "shiftable_operator"
7415 [(match_operand:SI 2 "s_register_operand" "r")
7416 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7418 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7419 [(set_attr "conds" "use")
7420 (set_attr "length" "8")]
7423 (define_insn "*ifcompare_arith_not"
7424 [(set (match_operand:SI 0 "s_register_operand" "=r")
7426 (match_operator 6 "arm_comparison_operator"
7427 [(match_operand:SI 4 "s_register_operand" "r")
7428 (match_operand:SI 5 "arm_add_operand" "rIL")])
7429 (match_operator:SI 7 "shiftable_operator"
7430 [(match_operand:SI 2 "s_register_operand" "r")
7431 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7432 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7433 (clobber (reg:CC CC_REGNUM))]
7436 [(set_attr "conds" "clob")
7437 (set_attr "length" "12")]
7440 (define_insn "*if_arith_not"
7441 [(set (match_operand:SI 0 "s_register_operand" "=r")
7443 (match_operator 5 "arm_comparison_operator"
7444 [(match_operand 4 "cc_register" "") (const_int 0)])
7445 (match_operator:SI 6 "shiftable_operator"
7446 [(match_operand:SI 2 "s_register_operand" "r")
7447 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7448 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7450 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7451 [(set_attr "conds" "use")
7452 (set_attr "length" "8")]
7455 (define_insn "*ifcompare_neg_move"
7456 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7458 (match_operator 5 "arm_comparison_operator"
7459 [(match_operand:SI 3 "s_register_operand" "r,r")
7460 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7461 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7462 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7463 (clobber (reg:CC CC_REGNUM))]
7466 [(set_attr "conds" "clob")
7467 (set_attr "length" "8,12")]
7470 (define_insn "*if_neg_move"
7471 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7473 (match_operator 4 "arm_comparison_operator"
7474 [(match_operand 3 "cc_register" "") (const_int 0)])
7475 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7476 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7480 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7481 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
7482 [(set_attr "conds" "use")
7483 (set_attr "length" "4,8,8")]
7486 (define_insn "*ifcompare_move_neg"
7487 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7489 (match_operator 5 "arm_comparison_operator"
7490 [(match_operand:SI 3 "s_register_operand" "r,r")
7491 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7492 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7493 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
7494 (clobber (reg:CC CC_REGNUM))]
7497 [(set_attr "conds" "clob")
7498 (set_attr "length" "8,12")]
7501 (define_insn "*if_move_neg"
7502 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7504 (match_operator 4 "arm_comparison_operator"
7505 [(match_operand 3 "cc_register" "") (const_int 0)])
7506 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7507 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7511 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
7512 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
7513 [(set_attr "conds" "use")
7514 (set_attr "length" "4,8,8")]
7517 (define_insn "*arith_adjacentmem"
7518 [(set (match_operand:SI 0 "s_register_operand" "=r")
7519 (match_operator:SI 1 "shiftable_operator"
7520 [(match_operand:SI 2 "memory_operand" "m")
7521 (match_operand:SI 3 "memory_operand" "m")]))
7522 (clobber (match_scratch:SI 4 "=r"))]
7523 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
7528 int val1 = 0, val2 = 0;
7530 if (REGNO (operands[0]) > REGNO (operands[4]))
7532 ldm[1] = operands[4];
7533 ldm[2] = operands[0];
7537 ldm[1] = operands[0];
7538 ldm[2] = operands[4];
7540 if (GET_CODE (XEXP (operands[2], 0)) != REG)
7541 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
7542 if (GET_CODE (XEXP (operands[3], 0)) != REG)
7543 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
7544 arith[0] = operands[0];
7545 arith[3] = operands[1];
7559 ldm[0] = ops[0] = operands[4];
7560 ops[1] = XEXP (XEXP (operands[2], 0), 0);
7561 ops[2] = XEXP (XEXP (operands[2], 0), 1);
7562 output_add_immediate (ops);
7564 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7566 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7570 ldm[0] = XEXP (operands[3], 0);
7572 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7574 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7578 ldm[0] = XEXP (operands[2], 0);
7580 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7582 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7584 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
7587 [(set_attr "length" "12")
7588 (set_attr "predicable" "yes")
7589 (set_attr "type" "load")]
7592 ;; the arm can support extended pre-inc instructions
7594 ;; In all these cases, we use operands 0 and 1 for the register being
7595 ;; incremented because those are the operands that local-alloc will
7596 ;; tie and these are the pair most likely to be tieable (and the ones
7597 ;; that will benefit the most).
7599 ;; We reject the frame pointer if it occurs anywhere in these patterns since
7600 ;; elimination will cause too many headaches.
7602 (define_insn "*strqi_preinc"
7603 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7604 (match_operand:SI 2 "index_operand" "rJ")))
7605 (match_operand:QI 3 "s_register_operand" "r"))
7606 (set (match_operand:SI 0 "s_register_operand" "=r")
7607 (plus:SI (match_dup 1) (match_dup 2)))]
7609 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7610 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7611 && (GET_CODE (operands[2]) != REG
7612 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7613 "str%?b\\t%3, [%0, %2]!"
7614 [(set_attr "type" "store1")
7615 (set_attr "predicable" "yes")]
7618 (define_insn "*strqi_predec"
7619 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7620 (match_operand:SI 2 "s_register_operand" "r")))
7621 (match_operand:QI 3 "s_register_operand" "r"))
7622 (set (match_operand:SI 0 "s_register_operand" "=r")
7623 (minus:SI (match_dup 1) (match_dup 2)))]
7625 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7626 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7627 && (GET_CODE (operands[2]) != REG
7628 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7629 "str%?b\\t%3, [%0, -%2]!"
7630 [(set_attr "type" "store1")
7631 (set_attr "predicable" "yes")]
7634 (define_insn "*loadqi_preinc"
7635 [(set (match_operand:QI 3 "s_register_operand" "=r")
7636 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7637 (match_operand:SI 2 "index_operand" "rJ"))))
7638 (set (match_operand:SI 0 "s_register_operand" "=r")
7639 (plus:SI (match_dup 1) (match_dup 2)))]
7641 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7642 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7643 && (GET_CODE (operands[2]) != REG
7644 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7645 "ldr%?b\\t%3, [%0, %2]!"
7646 [(set_attr "type" "load")
7647 (set_attr "predicable" "yes")]
7650 (define_insn "*loadqi_predec"
7651 [(set (match_operand:QI 3 "s_register_operand" "=r")
7652 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7653 (match_operand:SI 2 "s_register_operand" "r"))))
7654 (set (match_operand:SI 0 "s_register_operand" "=r")
7655 (minus:SI (match_dup 1) (match_dup 2)))]
7657 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7658 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7659 && (GET_CODE (operands[2]) != REG
7660 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7661 "ldr%?b\\t%3, [%0, -%2]!"
7662 [(set_attr "type" "load")
7663 (set_attr "predicable" "yes")]
7666 (define_insn "*loadqisi_preinc"
7667 [(set (match_operand:SI 3 "s_register_operand" "=r")
7669 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7670 (match_operand:SI 2 "index_operand" "rJ")))))
7671 (set (match_operand:SI 0 "s_register_operand" "=r")
7672 (plus:SI (match_dup 1) (match_dup 2)))]
7674 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7675 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7676 && (GET_CODE (operands[2]) != REG
7677 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7678 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
7679 [(set_attr "type" "load")
7680 (set_attr "predicable" "yes")]
7683 (define_insn "*loadqisi_predec"
7684 [(set (match_operand:SI 3 "s_register_operand" "=r")
7686 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7687 (match_operand:SI 2 "s_register_operand" "r")))))
7688 (set (match_operand:SI 0 "s_register_operand" "=r")
7689 (minus:SI (match_dup 1) (match_dup 2)))]
7691 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7692 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7693 && (GET_CODE (operands[2]) != REG
7694 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7695 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
7696 [(set_attr "type" "load")
7697 (set_attr "predicable" "yes")]
7700 (define_insn "*strsi_preinc"
7701 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7702 (match_operand:SI 2 "index_operand" "rJ")))
7703 (match_operand:SI 3 "s_register_operand" "r"))
7704 (set (match_operand:SI 0 "s_register_operand" "=r")
7705 (plus:SI (match_dup 1) (match_dup 2)))]
7707 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7708 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7709 && (GET_CODE (operands[2]) != REG
7710 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7711 "str%?\\t%3, [%0, %2]!"
7712 [(set_attr "type" "store1")
7713 (set_attr "predicable" "yes")]
7716 (define_insn "*strsi_predec"
7717 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7718 (match_operand:SI 2 "s_register_operand" "r")))
7719 (match_operand:SI 3 "s_register_operand" "r"))
7720 (set (match_operand:SI 0 "s_register_operand" "=r")
7721 (minus:SI (match_dup 1) (match_dup 2)))]
7723 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7724 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7725 && (GET_CODE (operands[2]) != REG
7726 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7727 "str%?\\t%3, [%0, -%2]!"
7728 [(set_attr "type" "store1")
7729 (set_attr "predicable" "yes")]
7732 (define_insn "*loadsi_preinc"
7733 [(set (match_operand:SI 3 "s_register_operand" "=r")
7734 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7735 (match_operand:SI 2 "index_operand" "rJ"))))
7736 (set (match_operand:SI 0 "s_register_operand" "=r")
7737 (plus:SI (match_dup 1) (match_dup 2)))]
7739 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7740 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7741 && (GET_CODE (operands[2]) != REG
7742 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7743 "ldr%?\\t%3, [%0, %2]!"
7744 [(set_attr "type" "load")
7745 (set_attr "predicable" "yes")]
7748 (define_insn "*loadsi_predec"
7749 [(set (match_operand:SI 3 "s_register_operand" "=r")
7750 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7751 (match_operand:SI 2 "s_register_operand" "r"))))
7752 (set (match_operand:SI 0 "s_register_operand" "=r")
7753 (minus:SI (match_dup 1) (match_dup 2)))]
7755 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7756 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7757 && (GET_CODE (operands[2]) != REG
7758 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7759 "ldr%?\\t%3, [%0, -%2]!"
7760 [(set_attr "type" "load")
7761 (set_attr "predicable" "yes")]
7764 (define_insn "*loadhi_preinc"
7765 [(set (match_operand:HI 3 "s_register_operand" "=r")
7766 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7767 (match_operand:SI 2 "index_operand" "rJ"))))
7768 (set (match_operand:SI 0 "s_register_operand" "=r")
7769 (plus:SI (match_dup 1) (match_dup 2)))]
7771 && !BYTES_BIG_ENDIAN
7772 && !TARGET_MMU_TRAPS
7774 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7775 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7776 && (GET_CODE (operands[2]) != REG
7777 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7778 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
7779 [(set_attr "type" "load")
7780 (set_attr "predicable" "yes")]
7783 (define_insn "*loadhi_predec"
7784 [(set (match_operand:HI 3 "s_register_operand" "=r")
7785 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7786 (match_operand:SI 2 "s_register_operand" "r"))))
7787 (set (match_operand:SI 0 "s_register_operand" "=r")
7788 (minus:SI (match_dup 1) (match_dup 2)))]
7790 && !BYTES_BIG_ENDIAN
7791 && !TARGET_MMU_TRAPS
7793 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7794 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7795 && (GET_CODE (operands[2]) != REG
7796 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7797 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
7798 [(set_attr "type" "load")
7799 (set_attr "predicable" "yes")]
7802 (define_insn "*strqi_shiftpreinc"
7803 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
7804 [(match_operand:SI 3 "s_register_operand" "r")
7805 (match_operand:SI 4 "const_shift_operand" "n")])
7806 (match_operand:SI 1 "s_register_operand" "0")))
7807 (match_operand:QI 5 "s_register_operand" "r"))
7808 (set (match_operand:SI 0 "s_register_operand" "=r")
7809 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7812 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7813 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7814 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7815 "str%?b\\t%5, [%0, %3%S2]!"
7816 [(set_attr "type" "store1")
7817 (set_attr "predicable" "yes")]
7820 (define_insn "*strqi_shiftpredec"
7821 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7822 (match_operator:SI 2 "shift_operator"
7823 [(match_operand:SI 3 "s_register_operand" "r")
7824 (match_operand:SI 4 "const_shift_operand" "n")])))
7825 (match_operand:QI 5 "s_register_operand" "r"))
7826 (set (match_operand:SI 0 "s_register_operand" "=r")
7827 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7830 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7831 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7832 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7833 "str%?b\\t%5, [%0, -%3%S2]!"
7834 [(set_attr "type" "store1")
7835 (set_attr "predicable" "yes")]
7838 (define_insn "*loadqi_shiftpreinc"
7839 [(set (match_operand:QI 5 "s_register_operand" "=r")
7840 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
7841 [(match_operand:SI 3 "s_register_operand" "r")
7842 (match_operand:SI 4 "const_shift_operand" "n")])
7843 (match_operand:SI 1 "s_register_operand" "0"))))
7844 (set (match_operand:SI 0 "s_register_operand" "=r")
7845 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7848 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7849 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7850 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7851 "ldr%?b\\t%5, [%0, %3%S2]!"
7852 [(set_attr "type" "load")
7853 (set_attr "predicable" "yes")]
7856 (define_insn "*loadqi_shiftpredec"
7857 [(set (match_operand:QI 5 "s_register_operand" "=r")
7858 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7859 (match_operator:SI 2 "shift_operator"
7860 [(match_operand:SI 3 "s_register_operand" "r")
7861 (match_operand:SI 4 "const_shift_operand" "n")]))))
7862 (set (match_operand:SI 0 "s_register_operand" "=r")
7863 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7866 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7867 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7868 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7869 "ldr%?b\\t%5, [%0, -%3%S2]!"
7870 [(set_attr "type" "load")
7871 (set_attr "predicable" "yes")]
7874 (define_insn "*strsi_shiftpreinc"
7875 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
7876 [(match_operand:SI 3 "s_register_operand" "r")
7877 (match_operand:SI 4 "const_shift_operand" "n")])
7878 (match_operand:SI 1 "s_register_operand" "0")))
7879 (match_operand:SI 5 "s_register_operand" "r"))
7880 (set (match_operand:SI 0 "s_register_operand" "=r")
7881 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7884 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7885 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7886 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7887 "str%?\\t%5, [%0, %3%S2]!"
7888 [(set_attr "type" "store1")
7889 (set_attr "predicable" "yes")]
7892 (define_insn "*strsi_shiftpredec"
7893 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7894 (match_operator:SI 2 "shift_operator"
7895 [(match_operand:SI 3 "s_register_operand" "r")
7896 (match_operand:SI 4 "const_shift_operand" "n")])))
7897 (match_operand:SI 5 "s_register_operand" "r"))
7898 (set (match_operand:SI 0 "s_register_operand" "=r")
7899 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7902 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7903 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7904 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7905 "str%?\\t%5, [%0, -%3%S2]!"
7906 [(set_attr "type" "store1")
7907 (set_attr "predicable" "yes")]
7910 (define_insn "*loadsi_shiftpreinc"
7911 [(set (match_operand:SI 5 "s_register_operand" "=r")
7912 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
7913 [(match_operand:SI 3 "s_register_operand" "r")
7914 (match_operand:SI 4 "const_shift_operand" "n")])
7915 (match_operand:SI 1 "s_register_operand" "0"))))
7916 (set (match_operand:SI 0 "s_register_operand" "=r")
7917 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7920 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7921 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7922 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7923 "ldr%?\\t%5, [%0, %3%S2]!"
7924 [(set_attr "type" "load")
7925 (set_attr "predicable" "yes")]
7928 (define_insn "*loadsi_shiftpredec"
7929 [(set (match_operand:SI 5 "s_register_operand" "=r")
7930 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7931 (match_operator:SI 2 "shift_operator"
7932 [(match_operand:SI 3 "s_register_operand" "r")
7933 (match_operand:SI 4 "const_shift_operand" "n")]))))
7934 (set (match_operand:SI 0 "s_register_operand" "=r")
7935 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7938 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7939 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7940 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7941 "ldr%?\\t%5, [%0, -%3%S2]!"
7942 [(set_attr "type" "load")
7943 (set_attr "predicable" "yes")])
7945 (define_insn "*loadhi_shiftpreinc"
7946 [(set (match_operand:HI 5 "s_register_operand" "=r")
7947 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
7948 [(match_operand:SI 3 "s_register_operand" "r")
7949 (match_operand:SI 4 "const_shift_operand" "n")])
7950 (match_operand:SI 1 "s_register_operand" "0"))))
7951 (set (match_operand:SI 0 "s_register_operand" "=r")
7952 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7955 && !BYTES_BIG_ENDIAN
7956 && !TARGET_MMU_TRAPS
7958 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7959 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7960 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7961 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
7962 [(set_attr "type" "load")
7963 (set_attr "predicable" "yes")]
7966 (define_insn "*loadhi_shiftpredec"
7967 [(set (match_operand:HI 5 "s_register_operand" "=r")
7968 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7969 (match_operator:SI 2 "shift_operator"
7970 [(match_operand:SI 3 "s_register_operand" "r")
7971 (match_operand:SI 4 "const_shift_operand" "n")]))))
7972 (set (match_operand:SI 0 "s_register_operand" "=r")
7973 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7976 && !BYTES_BIG_ENDIAN
7977 && !TARGET_MMU_TRAPS
7979 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7980 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7981 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7982 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
7983 [(set_attr "type" "load")
7984 (set_attr "predicable" "yes")]
7987 ; It can also support extended post-inc expressions, but combine doesn't
7989 ; It doesn't seem worth adding peepholes for anything but the most common
7990 ; cases since, unlike combine, the increment must immediately follow the load
7991 ; for this pattern to match.
7992 ; We must watch to see that the source/destination register isn't also the
7993 ; same as the base address register, and that if the index is a register,
7994 ; that it is not the same as the base address register. In such cases the
7995 ; instruction that we would generate would have UNPREDICTABLE behavior so
7999 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8000 (match_operand:QI 2 "s_register_operand" "r"))
8002 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8004 && (REGNO (operands[2]) != REGNO (operands[0]))
8005 && (GET_CODE (operands[1]) != REG
8006 || (REGNO (operands[1]) != REGNO (operands[0])))"
8007 "str%?b\\t%2, [%0], %1"
8011 [(set (match_operand:QI 0 "s_register_operand" "=r")
8012 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8014 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8016 && REGNO (operands[0]) != REGNO(operands[1])
8017 && (GET_CODE (operands[2]) != REG
8018 || REGNO(operands[0]) != REGNO (operands[2]))"
8019 "ldr%?b\\t%0, [%1], %2"
8023 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8024 (match_operand:SI 2 "s_register_operand" "r"))
8026 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8028 && (REGNO (operands[2]) != REGNO (operands[0]))
8029 && (GET_CODE (operands[1]) != REG
8030 || (REGNO (operands[1]) != REGNO (operands[0])))"
8031 "str%?\\t%2, [%0], %1"
8035 [(set (match_operand:HI 0 "s_register_operand" "=r")
8036 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8038 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8040 && !BYTES_BIG_ENDIAN
8041 && !TARGET_MMU_TRAPS
8043 && REGNO (operands[0]) != REGNO(operands[1])
8044 && (GET_CODE (operands[2]) != REG
8045 || REGNO(operands[0]) != REGNO (operands[2]))"
8046 "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8050 [(set (match_operand:SI 0 "s_register_operand" "=r")
8051 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8053 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8055 && REGNO (operands[0]) != REGNO(operands[1])
8056 && (GET_CODE (operands[2]) != REG
8057 || REGNO(operands[0]) != REGNO (operands[2]))"
8058 "ldr%?\\t%0, [%1], %2"
8062 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8063 (match_operand:SI 1 "index_operand" "rJ")))
8064 (match_operand:QI 2 "s_register_operand" "r"))
8065 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8067 && (REGNO (operands[2]) != REGNO (operands[0]))
8068 && (GET_CODE (operands[1]) != REG
8069 || (REGNO (operands[1]) != REGNO (operands[0])))"
8070 "str%?b\\t%2, [%0, %1]!"
8074 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8075 [(match_operand:SI 0 "s_register_operand" "r")
8076 (match_operand:SI 1 "const_int_operand" "n")])
8077 (match_operand:SI 2 "s_register_operand" "+r")))
8078 (match_operand:QI 3 "s_register_operand" "r"))
8079 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8082 && (REGNO (operands[3]) != REGNO (operands[2]))
8083 && (REGNO (operands[0]) != REGNO (operands[2]))"
8084 "str%?b\\t%3, [%2, %0%S4]!"
8087 ; This pattern is never tried by combine, so do it as a peephole
8090 [(set (match_operand:SI 0 "s_register_operand" "")
8091 (match_operand:SI 1 "s_register_operand" ""))
8092 (set (reg:CC CC_REGNUM)
8093 (compare:CC (match_dup 1) (const_int 0)))]
8096 || (!cirrus_fp_register (operands[0], SImode)
8097 && !cirrus_fp_register (operands[1], SImode)))
8099 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8100 (set (match_dup 0) (match_dup 1))])]
8104 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8105 ; reversed, check that the memory references aren't volatile.
8108 [(set (match_operand:SI 0 "s_register_operand" "=r")
8109 (match_operand:SI 4 "memory_operand" "m"))
8110 (set (match_operand:SI 1 "s_register_operand" "=r")
8111 (match_operand:SI 5 "memory_operand" "m"))
8112 (set (match_operand:SI 2 "s_register_operand" "=r")
8113 (match_operand:SI 6 "memory_operand" "m"))
8114 (set (match_operand:SI 3 "s_register_operand" "=r")
8115 (match_operand:SI 7 "memory_operand" "m"))]
8116 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8118 return emit_ldm_seq (operands, 4);
8123 [(set (match_operand:SI 0 "s_register_operand" "=r")
8124 (match_operand:SI 3 "memory_operand" "m"))
8125 (set (match_operand:SI 1 "s_register_operand" "=r")
8126 (match_operand:SI 4 "memory_operand" "m"))
8127 (set (match_operand:SI 2 "s_register_operand" "=r")
8128 (match_operand:SI 5 "memory_operand" "m"))]
8129 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8131 return emit_ldm_seq (operands, 3);
8136 [(set (match_operand:SI 0 "s_register_operand" "=r")
8137 (match_operand:SI 2 "memory_operand" "m"))
8138 (set (match_operand:SI 1 "s_register_operand" "=r")
8139 (match_operand:SI 3 "memory_operand" "m"))]
8140 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8142 return emit_ldm_seq (operands, 2);
8147 [(set (match_operand:SI 4 "memory_operand" "=m")
8148 (match_operand:SI 0 "s_register_operand" "r"))
8149 (set (match_operand:SI 5 "memory_operand" "=m")
8150 (match_operand:SI 1 "s_register_operand" "r"))
8151 (set (match_operand:SI 6 "memory_operand" "=m")
8152 (match_operand:SI 2 "s_register_operand" "r"))
8153 (set (match_operand:SI 7 "memory_operand" "=m")
8154 (match_operand:SI 3 "s_register_operand" "r"))]
8155 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8157 return emit_stm_seq (operands, 4);
8162 [(set (match_operand:SI 3 "memory_operand" "=m")
8163 (match_operand:SI 0 "s_register_operand" "r"))
8164 (set (match_operand:SI 4 "memory_operand" "=m")
8165 (match_operand:SI 1 "s_register_operand" "r"))
8166 (set (match_operand:SI 5 "memory_operand" "=m")
8167 (match_operand:SI 2 "s_register_operand" "r"))]
8168 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8170 return emit_stm_seq (operands, 3);
8175 [(set (match_operand:SI 2 "memory_operand" "=m")
8176 (match_operand:SI 0 "s_register_operand" "r"))
8177 (set (match_operand:SI 3 "memory_operand" "=m")
8178 (match_operand:SI 1 "s_register_operand" "r"))]
8179 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8181 return emit_stm_seq (operands, 2);
8186 [(set (match_operand:SI 0 "s_register_operand" "")
8187 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8189 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8190 [(match_operand:SI 3 "s_register_operand" "")
8191 (match_operand:SI 4 "arm_rhs_operand" "")]))))
8192 (clobber (match_operand:SI 5 "s_register_operand" ""))]
8194 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8195 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8200 ;; This split can be used because CC_Z mode implies that the following
8201 ;; branch will be an equality, or an unsigned inequality, so the sign
8202 ;; extension is not needed.
8205 [(set (reg:CC_Z CC_REGNUM)
8207 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8209 (match_operand 1 "const_int_operand" "")))
8210 (clobber (match_scratch:SI 2 ""))]
8212 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8213 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8214 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8215 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8217 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8221 (define_expand "prologue"
8222 [(clobber (const_int 0))]
8225 arm_expand_prologue ();
8227 thumb_expand_prologue ();
8232 (define_expand "epilogue"
8233 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8237 thumb_expand_epilogue ();
8238 else if (USE_RETURN_INSN (FALSE))
8240 emit_jump_insn (gen_return ());
8243 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8245 gen_rtx_RETURN (VOIDmode)),
8251 ;; Note - although unspec_volatile's USE all hard registers,
8252 ;; USEs are ignored after relaod has completed. Thus we need
8253 ;; to add an unspec of the link register to ensure that flow
8254 ;; does not think that it is unused by the sibcall branch that
8255 ;; will replace the standard function epilogue.
8256 (define_insn "sibcall_epilogue"
8257 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
8258 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
8261 if (USE_RETURN_INSN (FALSE))
8262 return output_return_instruction (const_true_rtx, FALSE, FALSE);
8263 return arm_output_epilogue (FALSE);
8265 ;; Length is absolute worst case
8266 [(set_attr "length" "44")
8267 (set_attr "type" "block")
8268 ;; We don't clobber the conditions, but the potential length of this
8269 ;; operation is sufficient to make conditionalizing the sequence
8270 ;; unlikely to be profitable.
8271 (set_attr "conds" "clob")]
8274 (define_insn "*epilogue_insns"
8275 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8279 return arm_output_epilogue (TRUE);
8280 else /* TARGET_THUMB */
8281 return thumb_unexpanded_epilogue ();
8283 ; Length is absolute worst case
8284 [(set_attr "length" "44")
8285 (set_attr "type" "block")
8286 ;; We don't clobber the conditions, but the potential length of this
8287 ;; operation is sufficient to make conditionalizing the sequence
8288 ;; unlikely to be profitable.
8289 (set_attr "conds" "clob")]
8292 (define_expand "eh_epilogue"
8293 [(use (match_operand:SI 0 "register_operand" ""))
8294 (use (match_operand:SI 1 "register_operand" ""))
8295 (use (match_operand:SI 2 "register_operand" ""))]
8299 cfun->machine->eh_epilogue_sp_ofs = operands[1];
8300 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8302 rtx ra = gen_rtx_REG (Pmode, 2);
8304 emit_move_insn (ra, operands[2]);
8307 /* This is a hack -- we may have crystalized the function type too
8309 cfun->machine->func_type = 0;
8313 ;; This split is only used during output to reduce the number of patterns
8314 ;; that need assembler instructions adding to them. We allowed the setting
8315 ;; of the conditions to be implicit during rtl generation so that
8316 ;; the conditional compare patterns would work. However this conflicts to
8317 ;; some extent with the conditional data operations, so we have to split them
8321 [(set (match_operand:SI 0 "s_register_operand" "")
8322 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8323 [(match_operand 2 "" "") (match_operand 3 "" "")])
8325 (match_operand 4 "" "")))
8326 (clobber (reg:CC CC_REGNUM))]
8327 "TARGET_ARM && reload_completed"
8328 [(set (match_dup 5) (match_dup 6))
8329 (cond_exec (match_dup 7)
8330 (set (match_dup 0) (match_dup 4)))]
8333 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8334 operands[2], operands[3]);
8335 enum rtx_code rc = GET_CODE (operands[1]);
8337 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8338 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8339 if (mode == CCFPmode || mode == CCFPEmode)
8340 rc = reverse_condition_maybe_unordered (rc);
8342 rc = reverse_condition (rc);
8344 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8349 [(set (match_operand:SI 0 "s_register_operand" "")
8350 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8351 [(match_operand 2 "" "") (match_operand 3 "" "")])
8352 (match_operand 4 "" "")
8354 (clobber (reg:CC CC_REGNUM))]
8355 "TARGET_ARM && reload_completed"
8356 [(set (match_dup 5) (match_dup 6))
8357 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8358 (set (match_dup 0) (match_dup 4)))]
8361 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8362 operands[2], operands[3]);
8364 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8365 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8370 [(set (match_operand:SI 0 "s_register_operand" "")
8371 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8372 [(match_operand 2 "" "") (match_operand 3 "" "")])
8373 (match_operand 4 "" "")
8374 (match_operand 5 "" "")))
8375 (clobber (reg:CC CC_REGNUM))]
8376 "TARGET_ARM && reload_completed"
8377 [(set (match_dup 6) (match_dup 7))
8378 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8379 (set (match_dup 0) (match_dup 4)))
8380 (cond_exec (match_dup 8)
8381 (set (match_dup 0) (match_dup 5)))]
8384 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8385 operands[2], operands[3]);
8386 enum rtx_code rc = GET_CODE (operands[1]);
8388 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8389 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8390 if (mode == CCFPmode || mode == CCFPEmode)
8391 rc = reverse_condition_maybe_unordered (rc);
8393 rc = reverse_condition (rc);
8395 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8400 [(set (match_operand:SI 0 "s_register_operand" "")
8401 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8402 [(match_operand:SI 2 "s_register_operand" "")
8403 (match_operand:SI 3 "arm_add_operand" "")])
8404 (match_operand:SI 4 "arm_rhs_operand" "")
8406 (match_operand:SI 5 "s_register_operand" ""))))
8407 (clobber (reg:CC CC_REGNUM))]
8408 "TARGET_ARM && reload_completed"
8409 [(set (match_dup 6) (match_dup 7))
8410 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8411 (set (match_dup 0) (match_dup 4)))
8412 (cond_exec (match_dup 8)
8413 (set (match_dup 0) (not:SI (match_dup 5))))]
8416 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8417 operands[2], operands[3]);
8418 enum rtx_code rc = GET_CODE (operands[1]);
8420 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8421 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8422 if (mode == CCFPmode || mode == CCFPEmode)
8423 rc = reverse_condition_maybe_unordered (rc);
8425 rc = reverse_condition (rc);
8427 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8431 (define_insn "*cond_move_not"
8432 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8433 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8434 [(match_operand 3 "cc_register" "") (const_int 0)])
8435 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8437 (match_operand:SI 2 "s_register_operand" "r,r"))))]
8441 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8442 [(set_attr "conds" "use")
8443 (set_attr "length" "4,8")]
8446 ;; The next two patterns occur when an AND operation is followed by a
8447 ;; scc insn sequence
8449 (define_insn "*sign_extract_onebit"
8450 [(set (match_operand:SI 0 "s_register_operand" "=r")
8451 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8453 (match_operand:SI 2 "const_int_operand" "n")))
8454 (clobber (reg:CC CC_REGNUM))]
8457 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8458 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8459 return \"mvnne\\t%0, #0\";
8461 [(set_attr "conds" "clob")
8462 (set_attr "length" "8")]
8465 (define_insn "*not_signextract_onebit"
8466 [(set (match_operand:SI 0 "s_register_operand" "=r")
8468 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8470 (match_operand:SI 2 "const_int_operand" "n"))))
8471 (clobber (reg:CC CC_REGNUM))]
8474 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8475 output_asm_insn (\"tst\\t%1, %2\", operands);
8476 output_asm_insn (\"mvneq\\t%0, #0\", operands);
8477 return \"movne\\t%0, #0\";
8479 [(set_attr "conds" "clob")
8480 (set_attr "length" "12")]
8483 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
8484 ;; expressions. For simplicity, the first register is also in the unspec
8486 (define_insn "*push_multi"
8487 [(match_parallel 2 "multi_register_push"
8488 [(set (match_operand:BLK 0 "memory_operand" "=m")
8489 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8490 UNSPEC_PUSH_MULT))])]
8494 int num_saves = XVECLEN (operands[2], 0);
8496 /* For the StrongARM at least it is faster to
8497 use STR to store only a single register. */
8499 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8505 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
8507 for (i = 1; i < num_saves; i++)
8509 strcat (pattern, \", %|\");
8511 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
8514 strcat (pattern, \"}\");
8515 output_asm_insn (pattern, operands);
8520 [(set_attr "type" "store4")]
8523 (define_insn "stack_tie"
8524 [(set (mem:BLK (scratch))
8525 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
8526 (match_operand:SI 1 "s_register_operand" "r")]
8530 [(set_attr "length" "0")]
8533 ;; Similarly for the floating point registers
8534 (define_insn "*push_fp_multi"
8535 [(match_parallel 2 "multi_register_push"
8536 [(set (match_operand:BLK 0 "memory_operand" "=m")
8537 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
8538 UNSPEC_PUSH_MULT))])]
8544 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
8545 output_asm_insn (pattern, operands);
8548 [(set_attr "type" "f_store")]
8551 ;; Special patterns for dealing with the constant pool
8553 (define_insn "align_4"
8554 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
8557 assemble_align (32);
8562 (define_insn "consttable_end"
8563 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
8566 making_const_table = FALSE;
8571 (define_insn "consttable_1"
8572 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
8575 making_const_table = TRUE;
8576 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
8580 [(set_attr "length" "4")]
8583 (define_insn "consttable_2"
8584 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
8587 making_const_table = TRUE;
8588 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
8592 [(set_attr "length" "4")]
8595 (define_insn "consttable_4"
8596 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
8600 making_const_table = TRUE;
8601 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8606 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8607 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8611 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
8616 [(set_attr "length" "4")]
8619 (define_insn "consttable_8"
8620 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
8624 making_const_table = TRUE;
8625 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8630 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8631 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8635 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
8640 [(set_attr "length" "8")]
8643 ;; Miscellaneous Thumb patterns
8645 (define_expand "tablejump"
8646 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
8647 (use (label_ref (match_operand 1 "" "")))])]
8652 /* Hopefully, CSE will eliminate this copy. */
8653 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
8654 rtx reg2 = gen_reg_rtx (SImode);
8656 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
8662 (define_insn "*thumb_tablejump"
8663 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
8664 (use (label_ref (match_operand 1 "" "")))]
8667 [(set_attr "length" "2")]
8672 (define_insn "clzsi2"
8673 [(set (match_operand:SI 0 "s_register_operand" "=r")
8674 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
8675 "TARGET_ARM && arm_arch5"
8677 [(set_attr "predicable" "yes")])
8679 (define_expand "ffssi2"
8680 [(set (match_operand:SI 0 "s_register_operand" "")
8681 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
8682 "TARGET_ARM && arm_arch5"
8687 t1 = gen_reg_rtx (SImode);
8688 t2 = gen_reg_rtx (SImode);
8689 t3 = gen_reg_rtx (SImode);
8691 emit_insn (gen_negsi2 (t1, operands[1]));
8692 emit_insn (gen_andsi3 (t2, operands[1], t1));
8693 emit_insn (gen_clzsi2 (t3, t2));
8694 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
8699 (define_expand "ctzsi2"
8700 [(set (match_operand:SI 0 "s_register_operand" "")
8701 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
8702 "TARGET_ARM && arm_arch5"
8707 t1 = gen_reg_rtx (SImode);
8708 t2 = gen_reg_rtx (SImode);
8709 t3 = gen_reg_rtx (SImode);
8711 emit_insn (gen_negsi2 (t1, operands[1]));
8712 emit_insn (gen_andsi3 (t2, operands[1], t1));
8713 emit_insn (gen_clzsi2 (t3, t2));
8714 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
8719 ;; V5E instructions.
8721 (define_insn "prefetch"
8722 [(prefetch (match_operand:SI 0 "address_operand" "p")
8723 (match_operand:SI 1 "" "")
8724 (match_operand:SI 2 "" ""))]
8725 "TARGET_ARM && arm_arch5e"
8728 ;; General predication pattern
8731 [(match_operator 0 "arm_comparison_operator"
8732 [(match_operand 1 "cc_register" "")
8738 (define_insn "prologue_use"
8739 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
8741 "%@ %0 needed for prologue"
8744 ;; Load the FPA co-processor patterns
8746 ;; Load the Maverick co-processor patterns
8747 (include "cirrus.md")