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.
78 (UNSPEC_WSHUFH 8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
79 (UNSPEC_WACC 9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
80 (UNSPEC_TMOVMSK 10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
81 (UNSPEC_WSAD 11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
82 (UNSPEC_WSADZ 12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
83 (UNSPEC_WMACS 13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
84 (UNSPEC_WMACU 14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
85 (UNSPEC_WMACSZ 15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
86 (UNSPEC_WMACUZ 16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
87 (UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
88 (UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
89 (UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
93 ;; UNSPEC_VOLATILE Usage:
96 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
98 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
99 ; instruction epilogue sequence that isn't expanded
100 ; into normal RTL. Used for both normal and sibcall
102 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
103 ; for inlined constants.
104 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
106 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
108 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
110 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
112 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
114 (VUNSPEC_TMRC 8) ; Used by the iWMMXt TMRC instruction.
115 (VUNSPEC_TMCR 9) ; Used by the iWMMXt TMCR instruction.
116 (VUNSPEC_ALIGN8 10) ; 8-byte alignment version of VUNSPEC_ALIGN
117 (VUNSPEC_WCMP_EQ 11) ; Used by the iWMMXt WCMPEQ instructions
118 (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
119 (VUNSPEC_WCMP_GT 13) ; Used by the iwMMXT WCMPGT instructions
123 ;;---------------------------------------------------------------------------
126 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
127 ; generating ARM code. This is used to control the length of some insn
128 ; patterns that share the same RTL in both ARM and Thumb code.
129 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
131 ; PROG_MODE attribute is used to determine whether condition codes are
132 ; clobbered by a call insn: they are if in prog32 mode. This is controlled
133 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
134 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
136 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
137 ; scheduling decisions for the load unit and the multiplier.
138 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
140 ;; Operand number of an input operand that is shifted. Zero if the
141 ;; given instruction does not shift one of its input operands.
142 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
143 (define_attr "shift" "" (const_int 0))
145 ; Floating Point Unit. If we only have floating point emulation, then there
146 ; is no point in scheduling the floating point insns. (Well, for best
147 ; performance we should try and group them together).
148 (define_attr "fpu" "softfpa,fpa,fpe2,fpe3,maverick"
149 (const (symbol_ref "arm_fpu_attr")))
151 ; LENGTH of an instruction (in bytes)
152 (define_attr "length" "" (const_int 4))
154 ; POOL_RANGE is how far away from a constant pool entry that this insn
155 ; can be placed. If the distance is zero, then this insn will never
156 ; reference the pool.
157 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
158 ; before its address.
159 (define_attr "pool_range" "" (const_int 0))
160 (define_attr "neg_pool_range" "" (const_int 0))
162 ; An assembler sequence may clobber the condition codes without us knowing.
163 ; If such an insn references the pool, then we have no way of knowing how,
164 ; so use the most conservative value for pool_range.
165 (define_asm_attributes
166 [(set_attr "conds" "clob")
167 (set_attr "length" "4")
168 (set_attr "pool_range" "250")])
170 ; TYPE attribute is used to detect floating point instructions which, if
171 ; running on a co-processor can run in parallel with other, basic instructions
172 ; If write-buffer scheduling is enabled then it can also be used in the
173 ; scheduling of writes.
175 ; Classification of each insn
176 ; normal any data instruction that doesn't hit memory or fp regs
177 ; mult a multiply instruction
178 ; block blockage insn, this blocks all functional units
179 ; float a floating point arithmetic operation (subject to expansion)
180 ; fdivd DFmode floating point division
181 ; fdivs SFmode floating point division
182 ; fmul Floating point multiply
183 ; ffmul Fast floating point multiply
184 ; farith Floating point arithmetic (4 cycle)
185 ; ffarith Fast floating point arithmetic (2 cycle)
186 ; float_em a floating point arithmetic operation that is normally emulated
187 ; even on a machine with an fpa.
188 ; f_load a floating point load from memory
189 ; f_store a floating point store to memory
190 ; f_mem_r a transfer of a floating point register to a real reg via mem
191 ; r_mem_f the reverse of f_mem_r
192 ; f_2_r fast transfer float to arm (no memory needed)
193 ; r_2_f fast transfer arm to float
194 ; call a subroutine call
195 ; load any load from memory
196 ; store1 store 1 word to memory from arm registers
197 ; store2 store 2 words
198 ; store3 store 3 words
199 ; store4 store 4 words
200 ; Additions for Cirrus Maverick co-processor:
201 ; mav_farith Floating point arithmetic (4 cycle)
202 ; mav_dmult Double multiplies (7 cycle)
205 "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"
206 (const_string "normal"))
208 ; Load scheduling, set from the arm_ld_sched variable
209 ; initialized by arm_override_options()
210 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
212 ; condition codes: this one is used by final_prescan_insn to speed up
213 ; conditionalizing instructions. It saves having to scan the rtl to see if
214 ; it uses or alters the condition codes.
216 ; USE means that the condition codes are used by the insn in the process of
217 ; outputting code, this means (at present) that we can't use the insn in
220 ; SET means that the purpose of the insn is to set the condition codes in a
221 ; well defined manner.
223 ; CLOB means that the condition codes are altered in an undefined manner, if
224 ; they are altered at all
226 ; JUMP_CLOB is used when the condition cannot be represented by a single
227 ; instruction (UNEQ and LTGT). These cannot be predicated.
229 ; NOCOND means that the condition codes are neither altered nor affect the
230 ; output of this insn
232 (define_attr "conds" "use,set,clob,jump_clob,nocond"
233 (if_then_else (eq_attr "type" "call")
234 (if_then_else (eq_attr "prog_mode" "prog32")
235 (const_string "clob") (const_string "nocond"))
236 (const_string "nocond")))
238 ; Predicable means that the insn can be conditionally executed based on
239 ; an automatically added predicate (additional patterns are generated by
240 ; gen...). We default to 'no' because no Thumb patterns match this rule
241 ; and not all ARM patterns do.
242 (define_attr "predicable" "no,yes" (const_string "no"))
244 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
245 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
246 ; suffer blockages enough to warrant modelling this (and it can adversely
247 ; affect the schedule).
248 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
250 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
251 ; to stall the processor. Used with model_wbuf above.
252 (define_attr "write_conflict" "no,yes"
253 (if_then_else (eq_attr "type"
254 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
256 (const_string "no")))
258 ; Classify the insns into those that take one cycle and those that take more
259 ; than one on the main cpu execution unit.
260 (define_attr "core_cycles" "single,multi"
261 (if_then_else (eq_attr "type"
262 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
263 (const_string "single")
264 (const_string "multi")))
266 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
267 ;; distant label. Only applicable to Thumb code.
268 (define_attr "far_jump" "yes,no" (const_string "no"))
270 (define_automaton "arm")
274 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
276 ; The write buffer on some of the arm6 processors is hard to model exactly.
277 ; There is room in the buffer for up to two addresses and up to eight words
278 ; of memory, but the two needn't be split evenly. When writing the two
279 ; addresses are fully pipelined. However, a read from memory that is not
280 ; currently in the cache will block until the writes have completed.
281 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
282 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
283 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
284 ; cycle to add as well.
285 (define_cpu_unit "write_buf" "arm")
287 ;; Write blockage unit
289 ; The write_blockage unit models (partially), the fact that reads will stall
290 ; until the write buffer empties.
291 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
292 ; so we don't model them here
293 (define_cpu_unit "write_blockage" "arm")
297 (define_cpu_unit "core" "arm")
299 (define_insn_reservation "r_mem_f_wbuf" 5
300 (and (eq_attr "model_wbuf" "yes")
301 (eq_attr "type" "r_mem_f"))
304 (define_insn_reservation "store1_wbuf" 5
305 (and (eq_attr "model_wbuf" "yes")
306 (eq_attr "type" "store1"))
307 "core+write_buf*3+write_blockage*5")
309 (define_insn_reservation "store2_wbuf" 7
310 (and (eq_attr "model_wbuf" "yes")
311 (eq_attr "type" "store2"))
312 "core+write_buf*4+write_blockage*7")
314 (define_insn_reservation "store3_wbuf" 9
315 (and (eq_attr "model_wbuf" "yes")
316 (eq_attr "type" "store3"))
317 "core+write_buf*5+write_blockage*9")
319 (define_insn_reservation "store4_wbuf" 11
320 (and (eq_attr "model_wbuf" "yes")
321 (eq_attr "type" "store4"))
322 "core+write_buf*6+write_blockage*11")
324 (define_insn_reservation "store2" 3
325 (and (eq_attr "model_wbuf" "no")
326 (eq_attr "type" "store2"))
329 (define_insn_reservation "store3" 4
330 (and (eq_attr "model_wbuf" "no")
331 (eq_attr "type" "store3"))
334 (define_insn_reservation "store4" 5
335 (and (eq_attr "model_wbuf" "no")
336 (eq_attr "type" "store4"))
339 (define_insn_reservation "store1_ldsched" 1
340 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1"))
343 (define_insn_reservation "load_ldsched_xscale" 3
344 (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
345 (eq_attr "is_xscale" "yes"))
348 (define_insn_reservation "load_ldsched" 2
349 (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
350 (eq_attr "is_xscale" "no"))
353 (define_insn_reservation "load_or_store" 2
354 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1"))
357 (define_insn_reservation "mult" 16
358 (and (eq_attr "ldsched" "no") (eq_attr "type" "mult"))
361 (define_insn_reservation "mult_ldsched_strongarm" 3
362 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
363 (eq_attr "type" "mult"))
366 (define_insn_reservation "mult_ldsched" 4
367 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
368 (eq_attr "type" "mult"))
371 (define_insn_reservation "multi_cycle" 32
372 (and (eq_attr "core_cycles" "multi")
373 (eq_attr "type" "!mult,load,store1,store2,store3,store4"))
376 (define_insn_reservation "single_cycle" 1
377 (eq_attr "core_cycles" "single")
381 ;;---------------------------------------------------------------------------
386 ;; Note: For DImode insns, there is normally no reason why operands should
387 ;; not be in the same register, what we don't want is for something being
388 ;; written to partially overlap something that is an input.
389 ;; Cirrus 64bit additions should not be split because we have a native
390 ;; 64bit addition instructions.
392 (define_expand "adddi3"
394 [(set (match_operand:DI 0 "s_register_operand" "")
395 (plus:DI (match_operand:DI 1 "s_register_operand" "")
396 (match_operand:DI 2 "s_register_operand" "")))
397 (clobber (reg:CC CC_REGNUM))])]
402 if (!cirrus_fp_register (operands[0], DImode))
403 operands[0] = force_reg (DImode, operands[0]);
404 if (!cirrus_fp_register (operands[1], DImode))
405 operands[1] = force_reg (DImode, operands[1]);
406 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
412 if (GET_CODE (operands[1]) != REG)
413 operands[1] = force_reg (SImode, operands[1]);
414 if (GET_CODE (operands[2]) != REG)
415 operands[2] = force_reg (SImode, operands[2]);
420 (define_insn "*thumb_adddi3"
421 [(set (match_operand:DI 0 "register_operand" "=l")
422 (plus:DI (match_operand:DI 1 "register_operand" "%0")
423 (match_operand:DI 2 "register_operand" "l")))
424 (clobber (reg:CC CC_REGNUM))
427 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
428 [(set_attr "length" "4")]
431 (define_insn_and_split "*arm_adddi3"
432 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
433 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
434 (match_operand:DI 2 "s_register_operand" "r, 0")))
435 (clobber (reg:CC CC_REGNUM))]
436 "TARGET_ARM && !TARGET_CIRRUS"
438 "TARGET_ARM && reload_completed"
439 [(parallel [(set (reg:CC_C CC_REGNUM)
440 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
442 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
443 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
444 (plus:SI (match_dup 4) (match_dup 5))))]
447 operands[3] = gen_highpart (SImode, operands[0]);
448 operands[0] = gen_lowpart (SImode, operands[0]);
449 operands[4] = gen_highpart (SImode, operands[1]);
450 operands[1] = gen_lowpart (SImode, operands[1]);
451 operands[5] = gen_highpart (SImode, operands[2]);
452 operands[2] = gen_lowpart (SImode, operands[2]);
454 [(set_attr "conds" "clob")
455 (set_attr "length" "8")]
458 (define_insn_and_split "*adddi_sesidi_di"
459 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
460 (plus:DI (sign_extend:DI
461 (match_operand:SI 2 "s_register_operand" "r,r"))
462 (match_operand:DI 1 "s_register_operand" "r,0")))
463 (clobber (reg:CC CC_REGNUM))]
464 "TARGET_ARM && !TARGET_CIRRUS"
466 "TARGET_ARM && reload_completed"
467 [(parallel [(set (reg:CC_C CC_REGNUM)
468 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
470 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
471 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
472 (plus:SI (ashiftrt:SI (match_dup 2)
477 operands[3] = gen_highpart (SImode, operands[0]);
478 operands[0] = gen_lowpart (SImode, operands[0]);
479 operands[4] = gen_highpart (SImode, operands[1]);
480 operands[1] = gen_lowpart (SImode, operands[1]);
481 operands[2] = gen_lowpart (SImode, operands[2]);
483 [(set_attr "conds" "clob")
484 (set_attr "length" "8")]
487 (define_insn_and_split "*adddi_zesidi_di"
488 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
489 (plus:DI (zero_extend:DI
490 (match_operand:SI 2 "s_register_operand" "r,r"))
491 (match_operand:DI 1 "s_register_operand" "r,0")))
492 (clobber (reg:CC CC_REGNUM))]
493 "TARGET_ARM && !TARGET_CIRRUS"
495 "TARGET_ARM && reload_completed"
496 [(parallel [(set (reg:CC_C CC_REGNUM)
497 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
499 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
500 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
501 (plus:SI (match_dup 4) (const_int 0))))]
504 operands[3] = gen_highpart (SImode, operands[0]);
505 operands[0] = gen_lowpart (SImode, operands[0]);
506 operands[4] = gen_highpart (SImode, operands[1]);
507 operands[1] = gen_lowpart (SImode, operands[1]);
508 operands[2] = gen_lowpart (SImode, operands[2]);
510 [(set_attr "conds" "clob")
511 (set_attr "length" "8")]
514 (define_expand "addsi3"
515 [(set (match_operand:SI 0 "s_register_operand" "")
516 (plus:SI (match_operand:SI 1 "s_register_operand" "")
517 (match_operand:SI 2 "reg_or_int_operand" "")))]
520 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
522 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
524 (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
530 ; If there is a scratch available, this will be faster than synthesizing the
533 [(match_scratch:SI 3 "r")
534 (set (match_operand:SI 0 "s_register_operand" "")
535 (plus:SI (match_operand:SI 1 "s_register_operand" "")
536 (match_operand:SI 2 "const_int_operand" "")))]
538 !(const_ok_for_arm (INTVAL (operands[2]))
539 || const_ok_for_arm (-INTVAL (operands[2])))
540 && const_ok_for_arm (~INTVAL (operands[2]))"
541 [(set (match_dup 3) (match_dup 2))
542 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
546 (define_insn_and_split "*arm_addsi3"
547 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
548 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
549 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
556 GET_CODE (operands[2]) == CONST_INT
557 && !(const_ok_for_arm (INTVAL (operands[2]))
558 || const_ok_for_arm (-INTVAL (operands[2])))"
559 [(clobber (const_int 0))]
561 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
565 [(set_attr "length" "4,4,16")
566 (set_attr "predicable" "yes")]
569 ;; Register group 'k' is a single register group containing only the stack
570 ;; register. Trying to reload it will always fail catastrophically,
571 ;; so never allow those alternatives to match if reloading is needed.
573 (define_insn "*thumb_addsi3"
574 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
575 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
576 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
579 static const char * const asms[] =
581 \"add\\t%0, %0, %2\",
582 \"sub\\t%0, %0, #%n2\",
583 \"add\\t%0, %1, %2\",
584 \"add\\t%0, %0, %2\",
585 \"add\\t%0, %0, %2\",
586 \"add\\t%0, %1, %2\",
589 if ((which_alternative == 2 || which_alternative == 6)
590 && GET_CODE (operands[2]) == CONST_INT
591 && INTVAL (operands[2]) < 0)
592 return \"sub\\t%0, %1, #%n2\";
593 return asms[which_alternative];
595 [(set_attr "length" "2")]
598 ;; Reloading and elimination of the frame pointer can
599 ;; sometimes cause this optimization to be missed.
601 [(set (match_operand:SI 0 "register_operand" "")
602 (match_operand:SI 1 "const_int_operand" ""))
604 (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
606 && REGNO (operands[2]) == STACK_POINTER_REGNUM
607 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
608 && (INTVAL (operands[1]) & 3) == 0"
609 [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
613 (define_insn "*addsi3_compare0"
614 [(set (reg:CC_NOOV CC_REGNUM)
616 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
617 (match_operand:SI 2 "arm_add_operand" "rI,L"))
619 (set (match_operand:SI 0 "s_register_operand" "=r,r")
620 (plus:SI (match_dup 1) (match_dup 2)))]
624 sub%?s\\t%0, %1, #%n2"
625 [(set_attr "conds" "set")]
628 (define_insn "*addsi3_compare0_scratch"
629 [(set (reg:CC_NOOV CC_REGNUM)
631 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
632 (match_operand:SI 1 "arm_add_operand" "rI,L"))
638 [(set_attr "conds" "set")]
641 ;; These patterns are the same ones as the two regular addsi3_compare0
642 ;; patterns, except we write them slightly different - the combiner
643 ;; tends to generate them this way.
644 (define_insn "*addsi3_compare0_for_combiner"
645 [(set (reg:CC CC_REGNUM)
647 (match_operand:SI 1 "s_register_operand" "r,r")
648 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
649 (set (match_operand:SI 0 "s_register_operand" "=r,r")
650 (plus:SI (match_dup 1) (match_dup 2)))]
654 sub%?s\\t%0, %1, #%n2"
655 [(set_attr "conds" "set")]
658 (define_insn "*addsi3_compare0_scratch_for_combiner"
659 [(set (reg:CC CC_REGNUM)
661 (match_operand:SI 0 "s_register_operand" "r,r")
662 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
667 [(set_attr "conds" "set")]
670 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
671 ;; addend is a constant.
672 (define_insn "*cmpsi2_addneg"
673 [(set (reg:CC CC_REGNUM)
675 (match_operand:SI 1 "s_register_operand" "r,r")
676 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
677 (set (match_operand:SI 0 "s_register_operand" "=r,r")
678 (plus:SI (match_dup 1)
679 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
680 "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
683 add%?s\\t%0, %1, #%n2"
684 [(set_attr "conds" "set")]
687 ;; Convert the sequence
689 ;; cmn rd, #1 (equivalent to cmp rd, #-1)
693 ;; bcs dest ((unsigned)rn >= 1)
694 ;; similarly for the beq variant using bcc.
695 ;; This is a common looping idiom (while (n--))
697 [(set (match_operand:SI 0 "s_register_operand" "")
698 (plus:SI (match_operand:SI 1 "s_register_operand" "")
700 (set (match_operand 2 "cc_register" "")
701 (compare (match_dup 0) (const_int -1)))
703 (if_then_else (match_operator 3 "equality_operator"
704 [(match_dup 2) (const_int 0)])
705 (match_operand 4 "" "")
706 (match_operand 5 "" "")))]
707 "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
711 (match_dup 1) (const_int 1)))
712 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
714 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
717 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
718 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
721 operands[2], const0_rtx);"
724 ;; The next four insns work because they compare the result with one of
725 ;; the operands, and we know that the use of the condition code is
726 ;; either GEU or LTU, so we can use the carry flag from the addition
727 ;; instead of doing the compare a second time.
728 (define_insn "*addsi3_compare_op1"
729 [(set (reg:CC_C CC_REGNUM)
731 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
732 (match_operand:SI 2 "arm_add_operand" "rI,L"))
734 (set (match_operand:SI 0 "s_register_operand" "=r,r")
735 (plus:SI (match_dup 1) (match_dup 2)))]
739 sub%?s\\t%0, %1, #%n2"
740 [(set_attr "conds" "set")]
743 (define_insn "*addsi3_compare_op2"
744 [(set (reg:CC_C CC_REGNUM)
746 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
747 (match_operand:SI 2 "arm_add_operand" "rI,L"))
749 (set (match_operand:SI 0 "s_register_operand" "=r,r")
750 (plus:SI (match_dup 1) (match_dup 2)))]
754 sub%?s\\t%0, %1, #%n2"
755 [(set_attr "conds" "set")]
758 (define_insn "*compare_addsi2_op0"
759 [(set (reg:CC_C CC_REGNUM)
761 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
762 (match_operand:SI 1 "arm_add_operand" "rI,L"))
768 [(set_attr "conds" "set")]
771 (define_insn "*compare_addsi2_op1"
772 [(set (reg:CC_C CC_REGNUM)
774 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
775 (match_operand:SI 1 "arm_add_operand" "rI,L"))
781 [(set_attr "conds" "set")]
784 (define_insn "*addsi3_carryin"
785 [(set (match_operand:SI 0 "s_register_operand" "=r")
786 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
787 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
788 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
791 [(set_attr "conds" "use")]
794 (define_insn "*addsi3_carryin_shift"
795 [(set (match_operand:SI 0 "s_register_operand" "")
796 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
798 (match_operator:SI 2 "shift_operator"
799 [(match_operand:SI 3 "s_register_operand" "")
800 (match_operand:SI 4 "reg_or_int_operand" "")])
801 (match_operand:SI 1 "s_register_operand" ""))))]
803 "adc%?\\t%0, %1, %3%S2"
804 [(set_attr "conds" "use")]
807 (define_insn "*addsi3_carryin_alt1"
808 [(set (match_operand:SI 0 "s_register_operand" "=r")
809 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
810 (match_operand:SI 2 "arm_rhs_operand" "rI"))
811 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
814 [(set_attr "conds" "use")]
817 (define_insn "*addsi3_carryin_alt2"
818 [(set (match_operand:SI 0 "s_register_operand" "=r")
819 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
820 (match_operand:SI 1 "s_register_operand" "r"))
821 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
824 [(set_attr "conds" "use")]
827 (define_insn "*addsi3_carryin_alt3"
828 [(set (match_operand:SI 0 "s_register_operand" "=r")
829 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
830 (match_operand:SI 2 "arm_rhs_operand" "rI"))
831 (match_operand:SI 1 "s_register_operand" "r")))]
834 [(set_attr "conds" "use")]
837 (define_insn "incscc"
838 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
839 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
840 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
841 (match_operand:SI 1 "s_register_operand" "0,?r")))]
845 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
846 [(set_attr "conds" "use")
847 (set_attr "length" "4,8")]
850 (define_expand "addsf3"
851 [(set (match_operand:SF 0 "s_register_operand" "")
852 (plus:SF (match_operand:SF 1 "s_register_operand" "")
853 (match_operand:SF 2 "fpa_add_operand" "")))]
854 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
857 && !cirrus_fp_register (operands[2], SFmode))
858 operands[2] = force_reg (SFmode, operands[2]);
861 (define_expand "adddf3"
862 [(set (match_operand:DF 0 "s_register_operand" "")
863 (plus:DF (match_operand:DF 1 "s_register_operand" "")
864 (match_operand:DF 2 "fpa_add_operand" "")))]
865 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
868 && !cirrus_fp_register (operands[2], DFmode))
869 operands[2] = force_reg (DFmode, operands[2]);
872 (define_expand "subdi3"
874 [(set (match_operand:DI 0 "s_register_operand" "")
875 (minus:DI (match_operand:DI 1 "s_register_operand" "")
876 (match_operand:DI 2 "s_register_operand" "")))
877 (clobber (reg:CC CC_REGNUM))])]
882 && cirrus_fp_register (operands[0], DImode)
883 && cirrus_fp_register (operands[1], DImode))
885 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
891 if (GET_CODE (operands[1]) != REG)
892 operands[1] = force_reg (SImode, operands[1]);
893 if (GET_CODE (operands[2]) != REG)
894 operands[2] = force_reg (SImode, operands[2]);
899 (define_insn "*arm_subdi3"
900 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
901 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
902 (match_operand:DI 2 "s_register_operand" "r,0,0")))
903 (clobber (reg:CC CC_REGNUM))]
905 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
906 [(set_attr "conds" "clob")
907 (set_attr "length" "8")]
910 (define_insn "*thumb_subdi3"
911 [(set (match_operand:DI 0 "register_operand" "=l")
912 (minus:DI (match_operand:DI 1 "register_operand" "0")
913 (match_operand:DI 2 "register_operand" "l")))
914 (clobber (reg:CC CC_REGNUM))]
916 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
917 [(set_attr "length" "4")]
920 (define_insn "*subdi_di_zesidi"
921 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
922 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
924 (match_operand:SI 2 "s_register_operand" "r,r"))))
925 (clobber (reg:CC CC_REGNUM))]
927 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
928 [(set_attr "conds" "clob")
929 (set_attr "length" "8")]
932 (define_insn "*subdi_di_sesidi"
933 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
934 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
936 (match_operand:SI 2 "s_register_operand" "r,r"))))
937 (clobber (reg:CC CC_REGNUM))]
939 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
940 [(set_attr "conds" "clob")
941 (set_attr "length" "8")]
944 (define_insn "*subdi_zesidi_di"
945 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
946 (minus:DI (zero_extend:DI
947 (match_operand:SI 2 "s_register_operand" "r,r"))
948 (match_operand:DI 1 "s_register_operand" "?r,0")))
949 (clobber (reg:CC CC_REGNUM))]
951 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
952 [(set_attr "conds" "clob")
953 (set_attr "length" "8")]
956 (define_insn "*subdi_sesidi_di"
957 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
958 (minus:DI (sign_extend:DI
959 (match_operand:SI 2 "s_register_operand" "r,r"))
960 (match_operand:DI 1 "s_register_operand" "?r,0")))
961 (clobber (reg:CC CC_REGNUM))]
963 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
964 [(set_attr "conds" "clob")
965 (set_attr "length" "8")]
968 (define_insn "*subdi_zesidi_zesidi"
969 [(set (match_operand:DI 0 "s_register_operand" "=r")
970 (minus:DI (zero_extend:DI
971 (match_operand:SI 1 "s_register_operand" "r"))
973 (match_operand:SI 2 "s_register_operand" "r"))))
974 (clobber (reg:CC CC_REGNUM))]
976 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
977 [(set_attr "conds" "clob")
978 (set_attr "length" "8")]
981 (define_expand "subsi3"
982 [(set (match_operand:SI 0 "s_register_operand" "")
983 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
984 (match_operand:SI 2 "s_register_operand" "")))]
987 if (GET_CODE (operands[1]) == CONST_INT)
991 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
994 : preserve_subexpressions_p ()));
997 else /* TARGET_THUMB */
998 operands[1] = force_reg (SImode, operands[1]);
1003 (define_insn "*thumb_subsi3_insn"
1004 [(set (match_operand:SI 0 "register_operand" "=l")
1005 (minus:SI (match_operand:SI 1 "register_operand" "l")
1006 (match_operand:SI 2 "register_operand" "l")))]
1009 [(set_attr "length" "2")]
1012 (define_insn_and_split "*arm_subsi3_insn"
1013 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1014 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
1015 (match_operand:SI 2 "s_register_operand" "r,r")))]
1021 && GET_CODE (operands[1]) == CONST_INT
1022 && !const_ok_for_arm (INTVAL (operands[1]))"
1023 [(clobber (const_int 0))]
1025 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1029 [(set_attr "length" "4,16")
1030 (set_attr "predicable" "yes")]
1034 [(match_scratch:SI 3 "r")
1035 (set (match_operand:SI 0 "s_register_operand" "")
1036 (minus:SI (match_operand:SI 1 "const_int_operand" "")
1037 (match_operand:SI 2 "s_register_operand" "")))]
1039 && !const_ok_for_arm (INTVAL (operands[1]))
1040 && const_ok_for_arm (~INTVAL (operands[1]))"
1041 [(set (match_dup 3) (match_dup 1))
1042 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1046 (define_insn "*subsi3_compare0"
1047 [(set (reg:CC_NOOV CC_REGNUM)
1049 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1050 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1052 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1053 (minus:SI (match_dup 1) (match_dup 2)))]
1057 rsb%?s\\t%0, %2, %1"
1058 [(set_attr "conds" "set")]
1061 (define_insn "decscc"
1062 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1063 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1064 (match_operator:SI 2 "arm_comparison_operator"
1065 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1069 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1070 [(set_attr "conds" "use")
1071 (set_attr "length" "*,8")]
1074 (define_expand "subsf3"
1075 [(set (match_operand:SF 0 "s_register_operand" "")
1076 (minus:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1077 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1078 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1082 if (!cirrus_fp_register (operands[1], SFmode))
1083 operands[1] = force_reg (SFmode, operands[1]);
1084 if (!cirrus_fp_register (operands[2], SFmode))
1085 operands[2] = force_reg (SFmode, operands[2]);
1089 (define_expand "subdf3"
1090 [(set (match_operand:DF 0 "s_register_operand" "")
1091 (minus:DF (match_operand:DF 1 "fpa_rhs_operand" "")
1092 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1093 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1097 if (!cirrus_fp_register (operands[1], DFmode))
1098 operands[1] = force_reg (DFmode, operands[1]);
1099 if (!cirrus_fp_register (operands[2], DFmode))
1100 operands[2] = force_reg (DFmode, operands[2]);
1105 ;; Multiplication insns
1107 (define_expand "mulsi3"
1108 [(set (match_operand:SI 0 "s_register_operand" "")
1109 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1110 (match_operand:SI 1 "s_register_operand" "")))]
1115 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1116 (define_insn "*arm_mulsi3"
1117 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1118 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1119 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1121 "mul%?\\t%0, %2, %1"
1122 [(set_attr "type" "mult")
1123 (set_attr "predicable" "yes")]
1126 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1127 ; 1 and 2; are the same, because reload will make operand 0 match
1128 ; operand 1 without realizing that this conflicts with operand 2. We fix
1129 ; this by adding another alternative to match this case, and then `reload'
1130 ; it ourselves. This alternative must come first.
1131 (define_insn "*thumb_mulsi3"
1132 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1133 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1134 (match_operand:SI 2 "register_operand" "l,l,l")))]
1137 if (which_alternative < 2)
1138 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1140 return \"mul\\t%0, %0, %2\";
1142 [(set_attr "length" "4,4,2")
1143 (set_attr "type" "mult")]
1146 (define_insn "*mulsi3_compare0"
1147 [(set (reg:CC_NOOV CC_REGNUM)
1148 (compare:CC_NOOV (mult:SI
1149 (match_operand:SI 2 "s_register_operand" "r,r")
1150 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1152 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1153 (mult:SI (match_dup 2) (match_dup 1)))]
1154 "TARGET_ARM && !arm_arch_xscale"
1155 "mul%?s\\t%0, %2, %1"
1156 [(set_attr "conds" "set")
1157 (set_attr "type" "mult")]
1160 (define_insn "*mulsi_compare0_scratch"
1161 [(set (reg:CC_NOOV CC_REGNUM)
1162 (compare:CC_NOOV (mult:SI
1163 (match_operand:SI 2 "s_register_operand" "r,r")
1164 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1166 (clobber (match_scratch:SI 0 "=&r,&r"))]
1167 "TARGET_ARM && !arm_arch_xscale"
1168 "mul%?s\\t%0, %2, %1"
1169 [(set_attr "conds" "set")
1170 (set_attr "type" "mult")]
1173 ;; Unnamed templates to match MLA instruction.
1175 (define_insn "*mulsi3addsi"
1176 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1178 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1179 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1180 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1182 "mla%?\\t%0, %2, %1, %3"
1183 [(set_attr "type" "mult")
1184 (set_attr "predicable" "yes")]
1187 (define_insn "*mulsi3addsi_compare0"
1188 [(set (reg:CC_NOOV CC_REGNUM)
1191 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1192 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1193 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1195 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1196 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1198 "TARGET_ARM && !arm_arch_xscale"
1199 "mla%?s\\t%0, %2, %1, %3"
1200 [(set_attr "conds" "set")
1201 (set_attr "type" "mult")]
1204 (define_insn "*mulsi3addsi_compare0_scratch"
1205 [(set (reg:CC_NOOV CC_REGNUM)
1208 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1209 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1210 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1212 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1213 "TARGET_ARM && !arm_arch_xscale"
1214 "mla%?s\\t%0, %2, %1, %3"
1215 [(set_attr "conds" "set")
1216 (set_attr "type" "mult")]
1219 ;; Unnamed template to match long long multiply-accumlate (smlal)
1221 (define_insn "*mulsidi3adddi"
1222 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1225 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1226 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1227 (match_operand:DI 1 "s_register_operand" "0")))]
1228 "TARGET_ARM && arm_fast_multiply"
1229 "smlal%?\\t%Q0, %R0, %3, %2"
1230 [(set_attr "type" "mult")
1231 (set_attr "predicable" "yes")]
1234 (define_insn "mulsidi3"
1235 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1237 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1238 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1239 "TARGET_ARM && arm_fast_multiply"
1240 "smull%?\\t%Q0, %R0, %1, %2"
1241 [(set_attr "type" "mult")
1242 (set_attr "predicable" "yes")]
1245 (define_insn "umulsidi3"
1246 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1248 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1249 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1250 "TARGET_ARM && arm_fast_multiply"
1251 "umull%?\\t%Q0, %R0, %1, %2"
1252 [(set_attr "type" "mult")
1253 (set_attr "predicable" "yes")]
1256 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1258 (define_insn "*umulsidi3adddi"
1259 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1262 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1263 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1264 (match_operand:DI 1 "s_register_operand" "0")))]
1265 "TARGET_ARM && arm_fast_multiply"
1266 "umlal%?\\t%Q0, %R0, %3, %2"
1267 [(set_attr "type" "mult")
1268 (set_attr "predicable" "yes")]
1271 (define_insn "smulsi3_highpart"
1272 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1276 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1277 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1279 (clobber (match_scratch:SI 3 "=&r,&r"))]
1280 "TARGET_ARM && arm_fast_multiply"
1281 "smull%?\\t%3, %0, %2, %1"
1282 [(set_attr "type" "mult")
1283 (set_attr "predicable" "yes")]
1286 (define_insn "umulsi3_highpart"
1287 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1291 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1292 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1294 (clobber (match_scratch:SI 3 "=&r,&r"))]
1295 "TARGET_ARM && arm_fast_multiply"
1296 "umull%?\\t%3, %0, %2, %1"
1297 [(set_attr "type" "mult")
1298 (set_attr "predicable" "yes")]
1301 (define_insn "mulhisi3"
1302 [(set (match_operand:SI 0 "s_register_operand" "=r")
1303 (mult:SI (sign_extend:SI
1304 (match_operand:HI 1 "s_register_operand" "%r"))
1306 (match_operand:HI 2 "s_register_operand" "r"))))]
1307 "TARGET_ARM && arm_arch5e"
1308 "smulbb%?\\t%0, %1, %2"
1309 [(set_attr "type" "mult")
1310 (set_attr "predicable" "yes")]
1313 (define_insn "*mulhisi3tb"
1314 [(set (match_operand:SI 0 "s_register_operand" "=r")
1315 (mult:SI (ashiftrt:SI
1316 (match_operand:SI 1 "s_register_operand" "r")
1319 (match_operand:HI 2 "s_register_operand" "r"))))]
1320 "TARGET_ARM && arm_arch5e"
1321 "smultb%?\\t%0, %1, %2"
1322 [(set_attr "type" "mult")
1323 (set_attr "predicable" "yes")]
1326 (define_insn "*mulhisi3bt"
1327 [(set (match_operand:SI 0 "s_register_operand" "=r")
1328 (mult:SI (sign_extend:SI
1329 (match_operand:HI 1 "s_register_operand" "r"))
1331 (match_operand:SI 2 "s_register_operand" "r")
1333 "TARGET_ARM && arm_arch5e"
1334 "smulbt%?\\t%0, %1, %2"
1335 [(set_attr "type" "mult")
1336 (set_attr "predicable" "yes")]
1339 (define_insn "*mulhisi3tt"
1340 [(set (match_operand:SI 0 "s_register_operand" "=r")
1341 (mult:SI (ashiftrt:SI
1342 (match_operand:SI 1 "s_register_operand" "r")
1345 (match_operand:SI 2 "s_register_operand" "r")
1347 "TARGET_ARM && arm_arch5e"
1348 "smultt%?\\t%0, %1, %2"
1349 [(set_attr "type" "mult")
1350 (set_attr "predicable" "yes")]
1353 (define_insn "*mulhisi3addsi"
1354 [(set (match_operand:SI 0 "s_register_operand" "=r")
1355 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1356 (mult:SI (sign_extend:SI
1357 (match_operand:HI 2 "s_register_operand" "%r"))
1359 (match_operand:HI 3 "s_register_operand" "r")))))]
1360 "TARGET_ARM && arm_arch5e"
1361 "smlabb%?\\t%0, %2, %3, %1"
1362 [(set_attr "type" "mult")
1363 (set_attr "predicable" "yes")]
1366 (define_insn "*mulhidi3adddi"
1367 [(set (match_operand:DI 0 "s_register_operand" "=r")
1369 (match_operand:DI 1 "s_register_operand" "0")
1370 (mult:DI (sign_extend:DI
1371 (match_operand:HI 2 "s_register_operand" "%r"))
1373 (match_operand:HI 3 "s_register_operand" "r")))))]
1374 "TARGET_ARM && arm_arch5e"
1375 "smlalbb%?\\t%Q0, %R0, %2, %3"
1376 [(set_attr "type" "mult")
1377 (set_attr "predicable" "yes")])
1379 (define_expand "mulsf3"
1380 [(set (match_operand:SF 0 "s_register_operand" "")
1381 (mult:SF (match_operand:SF 1 "s_register_operand" "")
1382 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1383 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1386 && !cirrus_fp_register (operands[2], SFmode))
1387 operands[2] = force_reg (SFmode, operands[2]);
1390 (define_expand "muldf3"
1391 [(set (match_operand:DF 0 "s_register_operand" "")
1392 (mult:DF (match_operand:DF 1 "s_register_operand" "")
1393 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1394 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1397 && !cirrus_fp_register (operands[2], DFmode))
1398 operands[2] = force_reg (DFmode, operands[2]);
1403 (define_expand "divsf3"
1404 [(set (match_operand:SF 0 "s_register_operand" "")
1405 (div:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1406 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1407 "TARGET_ARM && TARGET_HARD_FLOAT"
1410 (define_expand "divdf3"
1411 [(set (match_operand:DF 0 "s_register_operand" "")
1412 (div:DF (match_operand:DF 1 "fpa_rhs_operand" "")
1413 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1414 "TARGET_ARM && TARGET_HARD_FLOAT"
1419 (define_expand "modsf3"
1420 [(set (match_operand:SF 0 "s_register_operand" "")
1421 (mod:SF (match_operand:SF 1 "s_register_operand" "")
1422 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1423 "TARGET_ARM && TARGET_HARD_FLOAT"
1426 (define_expand "moddf3"
1427 [(set (match_operand:DF 0 "s_register_operand" "")
1428 (mod:DF (match_operand:DF 1 "s_register_operand" "")
1429 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1430 "TARGET_ARM && TARGET_HARD_FLOAT"
1433 ;; Boolean and,ior,xor insns
1435 ;; Split up double word logical operations
1437 ;; Split up simple DImode logical operations. Simply perform the logical
1438 ;; operation on the upper and lower halves of the registers.
1440 [(set (match_operand:DI 0 "s_register_operand" "")
1441 (match_operator:DI 6 "logical_binary_operator"
1442 [(match_operand:DI 1 "s_register_operand" "")
1443 (match_operand:DI 2 "s_register_operand" "")]))]
1444 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1445 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1446 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1449 operands[3] = gen_highpart (SImode, operands[0]);
1450 operands[0] = gen_lowpart (SImode, operands[0]);
1451 operands[4] = gen_highpart (SImode, operands[1]);
1452 operands[1] = gen_lowpart (SImode, operands[1]);
1453 operands[5] = gen_highpart (SImode, operands[2]);
1454 operands[2] = gen_lowpart (SImode, operands[2]);
1459 [(set (match_operand:DI 0 "s_register_operand" "")
1460 (match_operator:DI 6 "logical_binary_operator"
1461 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1462 (match_operand:DI 1 "s_register_operand" "")]))]
1463 "TARGET_ARM && reload_completed"
1464 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1465 (set (match_dup 3) (match_op_dup:SI 6
1466 [(ashiftrt:SI (match_dup 2) (const_int 31))
1470 operands[3] = gen_highpart (SImode, operands[0]);
1471 operands[0] = gen_lowpart (SImode, operands[0]);
1472 operands[4] = gen_highpart (SImode, operands[1]);
1473 operands[1] = gen_lowpart (SImode, operands[1]);
1474 operands[5] = gen_highpart (SImode, operands[2]);
1475 operands[2] = gen_lowpart (SImode, operands[2]);
1479 ;; The zero extend of operand 2 means we can just copy the high part of
1480 ;; operand1 into operand0.
1482 [(set (match_operand:DI 0 "s_register_operand" "")
1484 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1485 (match_operand:DI 1 "s_register_operand" "")))]
1486 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1487 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1488 (set (match_dup 3) (match_dup 4))]
1491 operands[4] = gen_highpart (SImode, operands[1]);
1492 operands[3] = gen_highpart (SImode, operands[0]);
1493 operands[0] = gen_lowpart (SImode, operands[0]);
1494 operands[1] = gen_lowpart (SImode, operands[1]);
1498 ;; The zero extend of operand 2 means we can just copy the high part of
1499 ;; operand1 into operand0.
1501 [(set (match_operand:DI 0 "s_register_operand" "")
1503 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1504 (match_operand:DI 1 "s_register_operand" "")))]
1505 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1506 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1507 (set (match_dup 3) (match_dup 4))]
1510 operands[4] = gen_highpart (SImode, operands[1]);
1511 operands[3] = gen_highpart (SImode, operands[0]);
1512 operands[0] = gen_lowpart (SImode, operands[0]);
1513 operands[1] = gen_lowpart (SImode, operands[1]);
1517 (define_insn "anddi3"
1518 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1519 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1520 (match_operand:DI 2 "s_register_operand" "r,r")))]
1521 "TARGET_ARM && ! TARGET_IWMMXT"
1523 [(set_attr "length" "8")]
1526 (define_insn_and_split "*anddi_zesidi_di"
1527 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1528 (and:DI (zero_extend:DI
1529 (match_operand:SI 2 "s_register_operand" "r,r"))
1530 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1533 "TARGET_ARM && reload_completed"
1534 ; The zero extend of operand 2 clears the high word of the output
1536 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1537 (set (match_dup 3) (const_int 0))]
1540 operands[3] = gen_highpart (SImode, operands[0]);
1541 operands[0] = gen_lowpart (SImode, operands[0]);
1542 operands[1] = gen_lowpart (SImode, operands[1]);
1544 [(set_attr "length" "8")]
1547 (define_insn "*anddi_sesdi_di"
1548 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1549 (and:DI (sign_extend:DI
1550 (match_operand:SI 2 "s_register_operand" "r,r"))
1551 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1554 [(set_attr "length" "8")]
1557 (define_expand "andsi3"
1558 [(set (match_operand:SI 0 "s_register_operand" "")
1559 (and:SI (match_operand:SI 1 "s_register_operand" "")
1560 (match_operand:SI 2 "reg_or_int_operand" "")))]
1565 if (GET_CODE (operands[2]) == CONST_INT)
1567 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1570 ? 0 : preserve_subexpressions_p ()));
1574 else /* TARGET_THUMB */
1576 if (GET_CODE (operands[2]) != CONST_INT)
1577 operands[2] = force_reg (SImode, operands[2]);
1582 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1584 operands[2] = force_reg (SImode,
1585 GEN_INT (~INTVAL (operands[2])));
1587 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1592 for (i = 9; i <= 31; i++)
1594 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1596 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1600 else if ((((HOST_WIDE_INT) 1) << i) - 1
1601 == ~INTVAL (operands[2]))
1603 rtx shift = GEN_INT (i);
1604 rtx reg = gen_reg_rtx (SImode);
1606 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1607 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1613 operands[2] = force_reg (SImode, operands[2]);
1619 (define_insn_and_split "*arm_andsi3_insn"
1620 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1621 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1622 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1626 bic%?\\t%0, %1, #%B2
1629 && GET_CODE (operands[2]) == CONST_INT
1630 && !(const_ok_for_arm (INTVAL (operands[2]))
1631 || const_ok_for_arm (~INTVAL (operands[2])))"
1632 [(clobber (const_int 0))]
1634 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1638 [(set_attr "length" "4,4,16")
1639 (set_attr "predicable" "yes")]
1642 (define_insn "*thumb_andsi3_insn"
1643 [(set (match_operand:SI 0 "register_operand" "=l")
1644 (and:SI (match_operand:SI 1 "register_operand" "%0")
1645 (match_operand:SI 2 "register_operand" "l")))]
1648 [(set_attr "length" "2")]
1651 (define_insn "*andsi3_compare0"
1652 [(set (reg:CC_NOOV CC_REGNUM)
1654 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1655 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1657 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1658 (and:SI (match_dup 1) (match_dup 2)))]
1662 bic%?s\\t%0, %1, #%B2"
1663 [(set_attr "conds" "set")]
1666 (define_insn "*andsi3_compare0_scratch"
1667 [(set (reg:CC_NOOV CC_REGNUM)
1669 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1670 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1672 (clobber (match_scratch:SI 2 "=X,r"))]
1676 bic%?s\\t%2, %0, #%B1"
1677 [(set_attr "conds" "set")]
1680 (define_insn "*zeroextractsi_compare0_scratch"
1681 [(set (reg:CC_NOOV CC_REGNUM)
1682 (compare:CC_NOOV (zero_extract:SI
1683 (match_operand:SI 0 "s_register_operand" "r")
1684 (match_operand 1 "const_int_operand" "n")
1685 (match_operand 2 "const_int_operand" "n"))
1688 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1689 && INTVAL (operands[1]) > 0
1690 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1691 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1693 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1694 << INTVAL (operands[2]));
1695 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1698 [(set_attr "conds" "set")]
1701 (define_insn "*ne_zeroextractsi"
1702 [(set (match_operand:SI 0 "s_register_operand" "=r")
1703 (ne:SI (zero_extract:SI
1704 (match_operand:SI 1 "s_register_operand" "r")
1705 (match_operand:SI 2 "const_int_operand" "n")
1706 (match_operand:SI 3 "const_int_operand" "n"))
1708 (clobber (reg:CC CC_REGNUM))]
1710 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1711 && INTVAL (operands[2]) > 0
1712 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1713 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1715 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1716 << INTVAL (operands[3]));
1717 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1718 return \"movne\\t%0, #1\";
1720 [(set_attr "conds" "clob")
1721 (set_attr "length" "8")]
1725 [(set (match_operand:SI 0 "s_register_operand" "")
1726 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1727 (match_operand:SI 2 "const_int_operand" "")
1728 (match_operand:SI 3 "const_int_operand" "")))
1729 (clobber (match_operand:SI 4 "s_register_operand" ""))]
1731 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1732 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1734 HOST_WIDE_INT temp = INTVAL (operands[2]);
1736 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1737 operands[3] = GEN_INT (32 - temp);
1742 [(set (match_operand:SI 0 "s_register_operand" "")
1743 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1744 (match_operand:SI 2 "const_int_operand" "")
1745 (match_operand:SI 3 "const_int_operand" "")))]
1747 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1748 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1750 HOST_WIDE_INT temp = INTVAL (operands[2]);
1752 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1753 operands[3] = GEN_INT (32 - temp);
1757 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1758 ;;; represented by the bitfield, then this will produce incorrect results.
1759 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1760 ;;; which have a real bit-field insert instruction, the truncation happens
1761 ;;; in the bit-field insert instruction itself. Since arm does not have a
1762 ;;; bit-field insert instruction, we would have to emit code here to truncate
1763 ;;; the value before we insert. This loses some of the advantage of having
1764 ;;; this insv pattern, so this pattern needs to be reevalutated.
1766 (define_expand "insv"
1767 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1768 (match_operand:SI 1 "general_operand" "")
1769 (match_operand:SI 2 "general_operand" ""))
1770 (match_operand:SI 3 "reg_or_int_operand" ""))]
1774 int start_bit = INTVAL (operands[2]);
1775 int width = INTVAL (operands[1]);
1776 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1777 rtx target, subtarget;
1779 target = operands[0];
1780 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1781 subreg as the final target. */
1782 if (GET_CODE (target) == SUBREG)
1784 subtarget = gen_reg_rtx (SImode);
1785 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1786 < GET_MODE_SIZE (SImode))
1787 target = SUBREG_REG (target);
1792 if (GET_CODE (operands[3]) == CONST_INT)
1794 /* Since we are inserting a known constant, we may be able to
1795 reduce the number of bits that we have to clear so that
1796 the mask becomes simple. */
1797 /* ??? This code does not check to see if the new mask is actually
1798 simpler. It may not be. */
1799 rtx op1 = gen_reg_rtx (SImode);
1800 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1801 start of this pattern. */
1802 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1803 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1805 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1806 emit_insn (gen_iorsi3 (subtarget, op1,
1807 GEN_INT (op3_value << start_bit)));
1809 else if (start_bit == 0
1810 && !(const_ok_for_arm (mask)
1811 || const_ok_for_arm (~mask)))
1813 /* A Trick, since we are setting the bottom bits in the word,
1814 we can shift operand[3] up, operand[0] down, OR them together
1815 and rotate the result back again. This takes 3 insns, and
1816 the third might be mergeable into another op. */
1817 /* The shift up copes with the possibility that operand[3] is
1818 wider than the bitfield. */
1819 rtx op0 = gen_reg_rtx (SImode);
1820 rtx op1 = gen_reg_rtx (SImode);
1822 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1823 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1824 emit_insn (gen_iorsi3 (op1, op1, op0));
1825 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1827 else if ((width + start_bit == 32)
1828 && !(const_ok_for_arm (mask)
1829 || const_ok_for_arm (~mask)))
1831 /* Similar trick, but slightly less efficient. */
1833 rtx op0 = gen_reg_rtx (SImode);
1834 rtx op1 = gen_reg_rtx (SImode);
1836 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1837 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1838 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1839 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1843 rtx op0 = GEN_INT (mask);
1844 rtx op1 = gen_reg_rtx (SImode);
1845 rtx op2 = gen_reg_rtx (SImode);
1847 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1849 rtx tmp = gen_reg_rtx (SImode);
1851 emit_insn (gen_movsi (tmp, op0));
1855 /* Mask out any bits in operand[3] that are not needed. */
1856 emit_insn (gen_andsi3 (op1, operands[3], op0));
1858 if (GET_CODE (op0) == CONST_INT
1859 && (const_ok_for_arm (mask << start_bit)
1860 || const_ok_for_arm (~(mask << start_bit))))
1862 op0 = GEN_INT (~(mask << start_bit));
1863 emit_insn (gen_andsi3 (op2, operands[0], op0));
1867 if (GET_CODE (op0) == CONST_INT)
1869 rtx tmp = gen_reg_rtx (SImode);
1871 emit_insn (gen_movsi (tmp, op0));
1876 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1878 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1882 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1884 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1887 if (subtarget != target)
1889 /* If TARGET is still a SUBREG, then it must be wider than a word,
1890 so we must be careful only to set the subword we were asked to. */
1891 if (GET_CODE (target) == SUBREG)
1892 emit_move_insn (target, subtarget);
1894 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1901 ; constants for op 2 will never be given to these patterns.
1902 (define_insn_and_split "*anddi_notdi_di"
1903 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1904 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1905 (match_operand:DI 2 "s_register_operand" "0,r")))]
1908 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1909 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1910 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1913 operands[3] = gen_highpart (SImode, operands[0]);
1914 operands[0] = gen_lowpart (SImode, operands[0]);
1915 operands[4] = gen_highpart (SImode, operands[1]);
1916 operands[1] = gen_lowpart (SImode, operands[1]);
1917 operands[5] = gen_highpart (SImode, operands[2]);
1918 operands[2] = gen_lowpart (SImode, operands[2]);
1920 [(set_attr "length" "8")
1921 (set_attr "predicable" "yes")]
1924 (define_insn_and_split "*anddi_notzesidi_di"
1925 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1926 (and:DI (not:DI (zero_extend:DI
1927 (match_operand:SI 2 "s_register_operand" "r,r")))
1928 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1931 bic%?\\t%Q0, %Q1, %2
1933 ; (not (zero_extend ...)) allows us to just copy the high word from
1934 ; operand1 to operand0.
1937 && operands[0] != operands[1]"
1938 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1939 (set (match_dup 3) (match_dup 4))]
1942 operands[3] = gen_highpart (SImode, operands[0]);
1943 operands[0] = gen_lowpart (SImode, operands[0]);
1944 operands[4] = gen_highpart (SImode, operands[1]);
1945 operands[1] = gen_lowpart (SImode, operands[1]);
1947 [(set_attr "length" "4,8")
1948 (set_attr "predicable" "yes")]
1951 (define_insn_and_split "*anddi_notsesidi_di"
1952 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1953 (and:DI (not:DI (sign_extend:DI
1954 (match_operand:SI 2 "s_register_operand" "r,r")))
1955 (match_operand:DI 1 "s_register_operand" "0,r")))]
1958 "TARGET_ARM && reload_completed"
1959 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1960 (set (match_dup 3) (and:SI (not:SI
1961 (ashiftrt:SI (match_dup 2) (const_int 31)))
1965 operands[3] = gen_highpart (SImode, operands[0]);
1966 operands[0] = gen_lowpart (SImode, operands[0]);
1967 operands[4] = gen_highpart (SImode, operands[1]);
1968 operands[1] = gen_lowpart (SImode, operands[1]);
1970 [(set_attr "length" "8")
1971 (set_attr "predicable" "yes")]
1974 (define_insn "andsi_notsi_si"
1975 [(set (match_operand:SI 0 "s_register_operand" "=r")
1976 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1977 (match_operand:SI 1 "s_register_operand" "r")))]
1979 "bic%?\\t%0, %1, %2"
1980 [(set_attr "predicable" "yes")]
1983 (define_insn "bicsi3"
1984 [(set (match_operand:SI 0 "register_operand" "=l")
1985 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
1986 (match_operand:SI 2 "register_operand" "0")))]
1989 [(set_attr "length" "2")]
1992 (define_insn "andsi_not_shiftsi_si"
1993 [(set (match_operand:SI 0 "s_register_operand" "=r")
1994 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
1995 [(match_operand:SI 2 "s_register_operand" "r")
1996 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
1997 (match_operand:SI 1 "s_register_operand" "r")))]
1999 "bic%?\\t%0, %1, %2%S4"
2000 [(set_attr "predicable" "yes")
2001 (set_attr "shift" "2")
2005 (define_insn "*andsi_notsi_si_compare0"
2006 [(set (reg:CC_NOOV CC_REGNUM)
2008 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2009 (match_operand:SI 1 "s_register_operand" "r"))
2011 (set (match_operand:SI 0 "s_register_operand" "=r")
2012 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2014 "bic%?s\\t%0, %1, %2"
2015 [(set_attr "conds" "set")]
2018 (define_insn "*andsi_notsi_si_compare0_scratch"
2019 [(set (reg:CC_NOOV CC_REGNUM)
2021 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2022 (match_operand:SI 1 "s_register_operand" "r"))
2024 (clobber (match_scratch:SI 0 "=r"))]
2026 "bic%?s\\t%0, %1, %2"
2027 [(set_attr "conds" "set")]
2030 (define_insn "iordi3"
2031 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2032 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2033 (match_operand:DI 2 "s_register_operand" "r,r")))]
2034 "TARGET_ARM && ! TARGET_IWMMXT"
2036 [(set_attr "length" "8")
2037 (set_attr "predicable" "yes")]
2040 (define_insn "*iordi_zesidi_di"
2041 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2042 (ior:DI (zero_extend:DI
2043 (match_operand:SI 2 "s_register_operand" "r,r"))
2044 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2047 orr%?\\t%Q0, %Q1, %2
2049 [(set_attr "length" "4,8")
2050 (set_attr "predicable" "yes")]
2053 (define_insn "*iordi_sesidi_di"
2054 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2055 (ior:DI (sign_extend:DI
2056 (match_operand:SI 2 "s_register_operand" "r,r"))
2057 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2060 [(set_attr "length" "8")
2061 (set_attr "predicable" "yes")]
2064 (define_expand "iorsi3"
2065 [(set (match_operand:SI 0 "s_register_operand" "")
2066 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2067 (match_operand:SI 2 "reg_or_int_operand" "")))]
2070 if (GET_CODE (operands[2]) == CONST_INT)
2074 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2077 ? 0 : preserve_subexpressions_p ()));
2080 else /* TARGET_THUMB */
2081 operands [2] = force_reg (SImode, operands [2]);
2086 (define_insn_and_split "*arm_iorsi3"
2087 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2088 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2089 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2095 && GET_CODE (operands[2]) == CONST_INT
2096 && !const_ok_for_arm (INTVAL (operands[2]))"
2097 [(clobber (const_int 0))]
2099 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2103 [(set_attr "length" "4,16")
2104 (set_attr "predicable" "yes")]
2107 (define_insn "*thumb_iorsi3"
2108 [(set (match_operand:SI 0 "register_operand" "=l")
2109 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2110 (match_operand:SI 2 "register_operand" "l")))]
2113 [(set_attr "length" "2")]
2117 [(match_scratch:SI 3 "r")
2118 (set (match_operand:SI 0 "s_register_operand" "")
2119 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2120 (match_operand:SI 2 "const_int_operand" "")))]
2122 && !const_ok_for_arm (INTVAL (operands[2]))
2123 && const_ok_for_arm (~INTVAL (operands[2]))"
2124 [(set (match_dup 3) (match_dup 2))
2125 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2129 (define_insn "*iorsi3_compare0"
2130 [(set (reg:CC_NOOV CC_REGNUM)
2131 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2132 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2134 (set (match_operand:SI 0 "s_register_operand" "=r")
2135 (ior:SI (match_dup 1) (match_dup 2)))]
2137 "orr%?s\\t%0, %1, %2"
2138 [(set_attr "conds" "set")]
2141 (define_insn "*iorsi3_compare0_scratch"
2142 [(set (reg:CC_NOOV CC_REGNUM)
2143 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2144 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2146 (clobber (match_scratch:SI 0 "=r"))]
2148 "orr%?s\\t%0, %1, %2"
2149 [(set_attr "conds" "set")]
2152 (define_insn "xordi3"
2153 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2154 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2155 (match_operand:DI 2 "s_register_operand" "r,r")))]
2156 "TARGET_ARM && !TARGET_IWMMXT"
2158 [(set_attr "length" "8")
2159 (set_attr "predicable" "yes")]
2162 (define_insn "*xordi_zesidi_di"
2163 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2164 (xor:DI (zero_extend:DI
2165 (match_operand:SI 2 "s_register_operand" "r,r"))
2166 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2169 eor%?\\t%Q0, %Q1, %2
2171 [(set_attr "length" "4,8")
2172 (set_attr "predicable" "yes")]
2175 (define_insn "*xordi_sesidi_di"
2176 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2177 (xor:DI (sign_extend:DI
2178 (match_operand:SI 2 "s_register_operand" "r,r"))
2179 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2182 [(set_attr "length" "8")
2183 (set_attr "predicable" "yes")]
2186 (define_expand "xorsi3"
2187 [(set (match_operand:SI 0 "s_register_operand" "")
2188 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2189 (match_operand:SI 2 "arm_rhs_operand" "")))]
2192 if (GET_CODE (operands[2]) == CONST_INT)
2193 operands[2] = force_reg (SImode, operands[2]);
2197 (define_insn "*arm_xorsi3"
2198 [(set (match_operand:SI 0 "s_register_operand" "=r")
2199 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2200 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2202 "eor%?\\t%0, %1, %2"
2203 [(set_attr "predicable" "yes")]
2206 (define_insn "*thumb_xorsi3"
2207 [(set (match_operand:SI 0 "register_operand" "=l")
2208 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2209 (match_operand:SI 2 "register_operand" "l")))]
2212 [(set_attr "length" "2")]
2215 (define_insn "*xorsi3_compare0"
2216 [(set (reg:CC_NOOV CC_REGNUM)
2217 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2218 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2220 (set (match_operand:SI 0 "s_register_operand" "=r")
2221 (xor:SI (match_dup 1) (match_dup 2)))]
2223 "eor%?s\\t%0, %1, %2"
2224 [(set_attr "conds" "set")]
2227 (define_insn "*xorsi3_compare0_scratch"
2228 [(set (reg:CC_NOOV CC_REGNUM)
2229 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2230 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2234 [(set_attr "conds" "set")]
2237 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2238 ; (NOT D) we can sometimes merge the final NOT into one of the following
2242 [(set (match_operand:SI 0 "s_register_operand" "")
2243 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2244 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2245 (match_operand:SI 3 "arm_rhs_operand" "")))
2246 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2248 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2249 (not:SI (match_dup 3))))
2250 (set (match_dup 0) (not:SI (match_dup 4)))]
2254 (define_insn "*andsi_iorsi3_notsi"
2255 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2256 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2257 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2258 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2260 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2261 [(set_attr "length" "8")
2262 (set_attr "predicable" "yes")]
2267 ;; Minimum and maximum insns
2269 (define_insn "smaxsi3"
2270 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2271 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2272 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2273 (clobber (reg:CC CC_REGNUM))]
2276 cmp\\t%1, %2\;movlt\\t%0, %2
2277 cmp\\t%1, %2\;movge\\t%0, %1
2278 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2279 [(set_attr "conds" "clob")
2280 (set_attr "length" "8,8,12")]
2283 (define_insn "sminsi3"
2284 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2285 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2286 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2287 (clobber (reg:CC CC_REGNUM))]
2290 cmp\\t%1, %2\;movge\\t%0, %2
2291 cmp\\t%1, %2\;movlt\\t%0, %1
2292 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2293 [(set_attr "conds" "clob")
2294 (set_attr "length" "8,8,12")]
2297 (define_insn "umaxsi3"
2298 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2299 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2300 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2301 (clobber (reg:CC CC_REGNUM))]
2304 cmp\\t%1, %2\;movcc\\t%0, %2
2305 cmp\\t%1, %2\;movcs\\t%0, %1
2306 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2307 [(set_attr "conds" "clob")
2308 (set_attr "length" "8,8,12")]
2311 (define_insn "uminsi3"
2312 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2313 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2314 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2315 (clobber (reg:CC CC_REGNUM))]
2318 cmp\\t%1, %2\;movcs\\t%0, %2
2319 cmp\\t%1, %2\;movcc\\t%0, %1
2320 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2321 [(set_attr "conds" "clob")
2322 (set_attr "length" "8,8,12")]
2325 (define_insn "*store_minmaxsi"
2326 [(set (match_operand:SI 0 "memory_operand" "=m")
2327 (match_operator:SI 3 "minmax_operator"
2328 [(match_operand:SI 1 "s_register_operand" "r")
2329 (match_operand:SI 2 "s_register_operand" "r")]))
2330 (clobber (reg:CC CC_REGNUM))]
2333 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2335 output_asm_insn (\"cmp\\t%1, %2\", operands);
2336 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2337 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2340 [(set_attr "conds" "clob")
2341 (set_attr "length" "12")
2342 (set_attr "type" "store1")]
2345 ; Reject the frame pointer in operand[1], since reloading this after
2346 ; it has been eliminated can cause carnage.
2347 (define_insn "*minmax_arithsi"
2348 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2349 (match_operator:SI 4 "shiftable_operator"
2350 [(match_operator:SI 5 "minmax_operator"
2351 [(match_operand:SI 2 "s_register_operand" "r,r")
2352 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2353 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2354 (clobber (reg:CC CC_REGNUM))]
2356 && (GET_CODE (operands[1]) != REG
2357 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2358 && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2361 enum rtx_code code = GET_CODE (operands[4]);
2363 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2365 output_asm_insn (\"cmp\\t%2, %3\", operands);
2366 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2367 if (which_alternative != 0 || operands[3] != const0_rtx
2368 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2369 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2372 [(set_attr "conds" "clob")
2373 (set_attr "length" "12")]
2377 ;; Shift and rotation insns
2379 (define_expand "ashlsi3"
2380 [(set (match_operand:SI 0 "s_register_operand" "")
2381 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2382 (match_operand:SI 2 "arm_rhs_operand" "")))]
2385 if (GET_CODE (operands[2]) == CONST_INT
2386 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2388 emit_insn (gen_movsi (operands[0], const0_rtx));
2394 (define_insn "*thumb_ashlsi3"
2395 [(set (match_operand:SI 0 "register_operand" "=l,l")
2396 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2397 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2400 [(set_attr "length" "2")]
2403 (define_expand "ashrsi3"
2404 [(set (match_operand:SI 0 "s_register_operand" "")
2405 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2406 (match_operand:SI 2 "arm_rhs_operand" "")))]
2409 if (GET_CODE (operands[2]) == CONST_INT
2410 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2411 operands[2] = GEN_INT (31);
2415 (define_insn "*thumb_ashrsi3"
2416 [(set (match_operand:SI 0 "register_operand" "=l,l")
2417 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2418 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2421 [(set_attr "length" "2")]
2424 (define_expand "lshrsi3"
2425 [(set (match_operand:SI 0 "s_register_operand" "")
2426 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2427 (match_operand:SI 2 "arm_rhs_operand" "")))]
2430 if (GET_CODE (operands[2]) == CONST_INT
2431 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2433 emit_insn (gen_movsi (operands[0], const0_rtx));
2439 (define_insn "*thumb_lshrsi3"
2440 [(set (match_operand:SI 0 "register_operand" "=l,l")
2441 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2442 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2445 [(set_attr "length" "2")]
2448 (define_expand "rotlsi3"
2449 [(set (match_operand:SI 0 "s_register_operand" "")
2450 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2451 (match_operand:SI 2 "reg_or_int_operand" "")))]
2454 if (GET_CODE (operands[2]) == CONST_INT)
2455 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2458 rtx reg = gen_reg_rtx (SImode);
2459 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2465 (define_expand "rotrsi3"
2466 [(set (match_operand:SI 0 "s_register_operand" "")
2467 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2468 (match_operand:SI 2 "arm_rhs_operand" "")))]
2473 if (GET_CODE (operands[2]) == CONST_INT
2474 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2475 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2477 else /* TARGET_THUMB */
2479 if (GET_CODE (operands [2]) == CONST_INT)
2480 operands [2] = force_reg (SImode, operands[2]);
2485 (define_insn "*thumb_rotrsi3"
2486 [(set (match_operand:SI 0 "register_operand" "=l")
2487 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2488 (match_operand:SI 2 "register_operand" "l")))]
2491 [(set_attr "length" "2")]
2494 (define_expand "ashldi3"
2495 [(set (match_operand:DI 0 "s_register_operand" "")
2496 (ashift:DI (match_operand:DI 1 "general_operand" "")
2497 (match_operand:SI 2 "general_operand" "")))]
2498 "TARGET_ARM && (TARGET_IWMMXT || TARGET_CIRRUS)"
2500 if (! s_register_operand (operands[1], DImode))
2501 operands[1] = copy_to_mode_reg (DImode, operands[1]);
2502 if (! s_register_operand (operands[2], SImode))
2503 operands[2] = copy_to_mode_reg (SImode, operands[2]);
2507 (define_insn "*arm_shiftsi3"
2508 [(set (match_operand:SI 0 "s_register_operand" "=r")
2509 (match_operator:SI 3 "shift_operator"
2510 [(match_operand:SI 1 "s_register_operand" "r")
2511 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2514 [(set_attr "predicable" "yes")
2515 (set_attr "shift" "1")
2519 (define_insn "*shiftsi3_compare0"
2520 [(set (reg:CC_NOOV CC_REGNUM)
2521 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2522 [(match_operand:SI 1 "s_register_operand" "r")
2523 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2525 (set (match_operand:SI 0 "s_register_operand" "=r")
2526 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2528 "mov%?s\\t%0, %1%S3"
2529 [(set_attr "conds" "set")
2530 (set_attr "shift" "1")
2534 (define_insn "*shiftsi3_compare0_scratch"
2535 [(set (reg:CC_NOOV CC_REGNUM)
2536 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2537 [(match_operand:SI 1 "s_register_operand" "r")
2538 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2540 (clobber (match_scratch:SI 0 "=r"))]
2542 "mov%?s\\t%0, %1%S3"
2543 [(set_attr "conds" "set")
2544 (set_attr "shift" "1")
2548 (define_insn "*notsi_shiftsi"
2549 [(set (match_operand:SI 0 "s_register_operand" "=r")
2550 (not:SI (match_operator:SI 3 "shift_operator"
2551 [(match_operand:SI 1 "s_register_operand" "r")
2552 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2555 [(set_attr "predicable" "yes")
2556 (set_attr "shift" "1")
2560 (define_insn "*notsi_shiftsi_compare0"
2561 [(set (reg:CC_NOOV CC_REGNUM)
2562 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2563 [(match_operand:SI 1 "s_register_operand" "r")
2564 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2566 (set (match_operand:SI 0 "s_register_operand" "=r")
2567 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2569 "mvn%?s\\t%0, %1%S3"
2570 [(set_attr "conds" "set")
2571 (set_attr "shift" "1")
2575 (define_insn "*not_shiftsi_compare0_scratch"
2576 [(set (reg:CC_NOOV CC_REGNUM)
2577 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2578 [(match_operand:SI 1 "s_register_operand" "r")
2579 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2581 (clobber (match_scratch:SI 0 "=r"))]
2583 "mvn%?s\\t%0, %1%S3"
2584 [(set_attr "conds" "set")
2585 (set_attr "shift" "1")
2589 ;; We don't really have extzv, but defining this using shifts helps
2590 ;; to reduce register pressure later on.
2592 (define_expand "extzv"
2594 (ashift:SI (match_operand:SI 1 "register_operand" "")
2595 (match_operand:SI 2 "const_int_operand" "")))
2596 (set (match_operand:SI 0 "register_operand" "")
2597 (lshiftrt:SI (match_dup 4)
2598 (match_operand:SI 3 "const_int_operand" "")))]
2602 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2603 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2605 operands[3] = GEN_INT (rshift);
2609 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2613 operands[2] = GEN_INT (lshift);
2614 operands[4] = gen_reg_rtx (SImode);
2619 ;; Unary arithmetic insns
2621 (define_expand "negdi2"
2623 [(set (match_operand:DI 0 "s_register_operand" "")
2624 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2625 (clobber (reg:CC CC_REGNUM))])]
2630 if (GET_CODE (operands[1]) != REG)
2631 operands[1] = force_reg (SImode, operands[1]);
2636 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2637 ;; The second alternative is to allow the common case of a *full* overlap.
2638 (define_insn "*arm_negdi2"
2639 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2640 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2641 (clobber (reg:CC CC_REGNUM))]
2643 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2644 [(set_attr "conds" "clob")
2645 (set_attr "length" "8")]
2648 (define_insn "*thumb_negdi2"
2649 [(set (match_operand:DI 0 "register_operand" "=&l")
2650 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2651 (clobber (reg:CC CC_REGNUM))]
2653 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2654 [(set_attr "length" "6")]
2657 (define_expand "negsi2"
2658 [(set (match_operand:SI 0 "s_register_operand" "")
2659 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2664 (define_insn "*arm_negsi2"
2665 [(set (match_operand:SI 0 "s_register_operand" "=r")
2666 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2668 "rsb%?\\t%0, %1, #0"
2669 [(set_attr "predicable" "yes")]
2672 (define_insn "*thumb_negsi2"
2673 [(set (match_operand:SI 0 "register_operand" "=l")
2674 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2677 [(set_attr "length" "2")]
2680 (define_expand "negsf2"
2681 [(set (match_operand:SF 0 "s_register_operand" "")
2682 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2683 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2687 (define_expand "negdf2"
2688 [(set (match_operand:DF 0 "s_register_operand" "")
2689 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2690 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2693 ;; abssi2 doesn't really clobber the condition codes if a different register
2694 ;; is being set. To keep things simple, assume during rtl manipulations that
2695 ;; it does, but tell the final scan operator the truth. Similarly for
2698 (define_expand "abssi2"
2700 [(set (match_operand:SI 0 "s_register_operand" "")
2701 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2702 (clobber (reg:CC CC_REGNUM))])]
2706 (define_insn "*arm_abssi2"
2707 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2708 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2709 (clobber (reg:CC CC_REGNUM))]
2712 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2713 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2714 [(set_attr "conds" "clob,*")
2715 (set_attr "shift" "1")
2716 ;; predicable can't be set based on the variant, so left as no
2717 (set_attr "length" "8")]
2720 (define_insn "*neg_abssi2"
2721 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2722 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2723 (clobber (reg:CC CC_REGNUM))]
2726 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2727 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2728 [(set_attr "conds" "clob,*")
2729 (set_attr "shift" "1")
2730 ;; predicable can't be set based on the variant, so left as no
2731 (set_attr "length" "8")]
2734 (define_expand "abssf2"
2735 [(set (match_operand:SF 0 "s_register_operand" "")
2736 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
2737 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2740 (define_expand "absdf2"
2741 [(set (match_operand:DF 0 "s_register_operand" "")
2742 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
2743 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2746 (define_expand "sqrtsf2"
2747 [(set (match_operand:SF 0 "s_register_operand" "")
2748 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
2749 "TARGET_ARM && TARGET_HARD_FLOAT"
2752 (define_expand "sqrtdf2"
2753 [(set (match_operand:DF 0 "s_register_operand" "")
2754 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
2755 "TARGET_ARM && TARGET_HARD_FLOAT"
2758 (define_insn_and_split "one_cmpldi2"
2759 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2760 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2763 "TARGET_ARM && reload_completed"
2764 [(set (match_dup 0) (not:SI (match_dup 1)))
2765 (set (match_dup 2) (not:SI (match_dup 3)))]
2768 operands[2] = gen_highpart (SImode, operands[0]);
2769 operands[0] = gen_lowpart (SImode, operands[0]);
2770 operands[3] = gen_highpart (SImode, operands[1]);
2771 operands[1] = gen_lowpart (SImode, operands[1]);
2773 [(set_attr "length" "8")
2774 (set_attr "predicable" "yes")]
2777 (define_expand "one_cmplsi2"
2778 [(set (match_operand:SI 0 "s_register_operand" "")
2779 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2784 (define_insn "*arm_one_cmplsi2"
2785 [(set (match_operand:SI 0 "s_register_operand" "=r")
2786 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
2789 [(set_attr "predicable" "yes")]
2792 (define_insn "*thumb_one_cmplsi2"
2793 [(set (match_operand:SI 0 "register_operand" "=l")
2794 (not:SI (match_operand:SI 1 "register_operand" "l")))]
2797 [(set_attr "length" "2")]
2800 (define_insn "*notsi_compare0"
2801 [(set (reg:CC_NOOV CC_REGNUM)
2802 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2804 (set (match_operand:SI 0 "s_register_operand" "=r")
2805 (not:SI (match_dup 1)))]
2808 [(set_attr "conds" "set")]
2811 (define_insn "*notsi_compare0_scratch"
2812 [(set (reg:CC_NOOV CC_REGNUM)
2813 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2815 (clobber (match_scratch:SI 0 "=r"))]
2818 [(set_attr "conds" "set")]
2821 ;; Fixed <--> Floating conversion insns
2823 (define_expand "floatsisf2"
2824 [(set (match_operand:SF 0 "s_register_operand" "")
2825 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
2826 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2830 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
2835 (define_expand "floatsidf2"
2836 [(set (match_operand:DF 0 "s_register_operand" "")
2837 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
2838 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2842 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
2847 (define_expand "fix_truncsfsi2"
2848 [(set (match_operand:SI 0 "s_register_operand" "")
2849 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
2850 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2854 if (!cirrus_fp_register (operands[0], SImode))
2855 operands[0] = force_reg (SImode, operands[0]);
2856 if (!cirrus_fp_register (operands[1], SFmode))
2857 operands[1] = force_reg (SFmode, operands[0]);
2858 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
2863 (define_expand "fix_truncdfsi2"
2864 [(set (match_operand:SI 0 "s_register_operand" "")
2865 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
2866 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2870 if (!cirrus_fp_register (operands[1], DFmode))
2871 operands[1] = force_reg (DFmode, operands[0]);
2872 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
2879 (define_expand "truncdfsf2"
2880 [(set (match_operand:SF 0 "s_register_operand" "")
2882 (match_operand:DF 1 "s_register_operand" "")))]
2883 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2887 ;; Zero and sign extension instructions.
2889 (define_insn "zero_extendsidi2"
2890 [(set (match_operand:DI 0 "s_register_operand" "=r")
2891 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2894 if (REGNO (operands[1])
2895 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2896 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2897 return \"mov%?\\t%R0, #0\";
2899 [(set_attr "length" "8")
2900 (set_attr "predicable" "yes")]
2903 (define_insn "zero_extendqidi2"
2904 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
2905 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2908 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
2909 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
2910 [(set_attr "length" "8")
2911 (set_attr "predicable" "yes")
2912 (set_attr "type" "*,load")
2913 (set_attr "pool_range" "*,4092")
2914 (set_attr "neg_pool_range" "*,4084")]
2917 (define_insn "extendsidi2"
2918 [(set (match_operand:DI 0 "s_register_operand" "=r")
2919 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2922 if (REGNO (operands[1])
2923 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2924 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2925 return \"mov%?\\t%R0, %Q0, asr #31\";
2927 [(set_attr "length" "8")
2928 (set_attr "shift" "1")
2929 (set_attr "predicable" "yes")]
2932 (define_expand "zero_extendhisi2"
2934 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2936 (set (match_operand:SI 0 "s_register_operand" "")
2937 (lshiftrt:SI (match_dup 2) (const_int 16)))]
2943 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2945 /* Note: We do not have to worry about TARGET_MMU_TRAPS
2946 here because the insn below will generate an LDRH instruction
2947 rather than an LDR instruction, so we cannot get an unaligned
2949 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2950 gen_rtx_ZERO_EXTEND (SImode,
2954 if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
2956 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
2959 if (!s_register_operand (operands[1], HImode))
2960 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2961 operands[1] = gen_lowpart (SImode, operands[1]);
2962 operands[2] = gen_reg_rtx (SImode);
2964 else /* TARGET_THUMB */
2966 if (GET_CODE (operands[1]) == MEM)
2970 tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
2971 tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
2978 if (!s_register_operand (operands[1], HImode))
2979 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2980 operands[1] = gen_lowpart (SImode, operands[1]);
2981 operands[2] = gen_reg_rtx (SImode);
2983 ops[0] = operands[2];
2984 ops[1] = operands[1];
2985 ops[2] = GEN_INT (16);
2987 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
2988 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
2990 ops[0] = operands[0];
2991 ops[1] = operands[2];
2992 ops[2] = GEN_INT (16);
2994 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
2995 gen_rtx_LSHIFTRT (SImode, ops[1],
3003 (define_insn "*thumb_zero_extendhisi2"
3004 [(set (match_operand:SI 0 "register_operand" "=l")
3005 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3008 rtx mem = XEXP (operands[1], 0);
3010 if (GET_CODE (mem) == CONST)
3011 mem = XEXP (mem, 0);
3013 if (GET_CODE (mem) == LABEL_REF)
3014 return \"ldr\\t%0, %1\";
3016 if (GET_CODE (mem) == PLUS)
3018 rtx a = XEXP (mem, 0);
3019 rtx b = XEXP (mem, 1);
3021 /* This can happen due to bugs in reload. */
3022 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3025 ops[0] = operands[0];
3028 output_asm_insn (\"mov %0, %1\", ops);
3030 XEXP (mem, 0) = operands[0];
3033 else if ( GET_CODE (a) == LABEL_REF
3034 && GET_CODE (b) == CONST_INT)
3035 return \"ldr\\t%0, %1\";
3038 return \"ldrh\\t%0, %1\";
3040 [(set_attr "length" "4")
3041 (set_attr "type" "load")
3042 (set_attr "pool_range" "60")]
3045 (define_insn "*arm_zero_extendhisi2"
3046 [(set (match_operand:SI 0 "s_register_operand" "=r")
3047 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3048 "TARGET_ARM && arm_arch4"
3050 [(set_attr "type" "load")
3051 (set_attr "predicable" "yes")
3052 (set_attr "pool_range" "256")
3053 (set_attr "neg_pool_range" "244")]
3057 [(set (match_operand:SI 0 "s_register_operand" "")
3058 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3059 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3060 "TARGET_ARM && (!arm_arch4)"
3061 [(set (match_dup 2) (match_dup 1))
3062 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3064 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3070 [(set (match_operand:SI 0 "s_register_operand" "")
3071 (match_operator:SI 3 "shiftable_operator"
3072 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3073 (match_operand:SI 4 "s_register_operand" "")]))
3074 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3075 "TARGET_ARM && (!arm_arch4)"
3076 [(set (match_dup 2) (match_dup 1))
3079 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3081 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3086 (define_expand "zero_extendqisi2"
3087 [(set (match_operand:SI 0 "s_register_operand" "")
3088 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3091 if (GET_CODE (operands[1]) != MEM)
3095 emit_insn (gen_andsi3 (operands[0],
3096 gen_lowpart (SImode, operands[1]),
3099 else /* TARGET_THUMB */
3101 rtx temp = gen_reg_rtx (SImode);
3104 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3105 operands[1] = gen_lowpart (SImode, operands[1]);
3108 ops[1] = operands[1];
3109 ops[2] = GEN_INT (24);
3111 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3112 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3114 ops[0] = operands[0];
3116 ops[2] = GEN_INT (24);
3118 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3119 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3126 (define_insn "*thumb_zero_extendqisi2"
3127 [(set (match_operand:SI 0 "register_operand" "=l")
3128 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3131 [(set_attr "length" "2")
3132 (set_attr "type" "load")
3133 (set_attr "pool_range" "32")]
3136 (define_insn "*arm_zero_extendqisi2"
3137 [(set (match_operand:SI 0 "s_register_operand" "=r")
3138 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3140 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3141 [(set_attr "type" "load")
3142 (set_attr "predicable" "yes")
3143 (set_attr "pool_range" "4096")
3144 (set_attr "neg_pool_range" "4084")]
3148 [(set (match_operand:SI 0 "s_register_operand" "")
3149 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3150 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3151 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3152 [(set (match_dup 2) (match_dup 1))
3153 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3157 (define_insn "*compareqi_eq0"
3158 [(set (reg:CC_Z CC_REGNUM)
3159 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3163 [(set_attr "conds" "set")]
3166 (define_expand "extendhisi2"
3168 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3170 (set (match_operand:SI 0 "s_register_operand" "")
3171 (ashiftrt:SI (match_dup 2)
3176 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3178 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3179 here because the insn below will generate an LDRH instruction
3180 rather than an LDR instruction, so we cannot get an unaligned
3182 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3183 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3187 if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3189 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3192 if (!s_register_operand (operands[1], HImode))
3193 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3194 operands[1] = gen_lowpart (SImode, operands[1]);
3195 operands[2] = gen_reg_rtx (SImode);
3201 ops[0] = operands[2];
3202 ops[1] = operands[1];
3203 ops[2] = GEN_INT (16);
3205 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3206 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3208 ops[0] = operands[0];
3209 ops[1] = operands[2];
3210 ops[2] = GEN_INT (16);
3212 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3213 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3220 (define_insn "*thumb_extendhisi2_insn"
3221 [(set (match_operand:SI 0 "register_operand" "=l")
3222 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3223 (clobber (match_scratch:SI 2 "=&l"))]
3228 rtx mem = XEXP (operands[1], 0);
3230 /* This code used to try to use 'V', and fix the address only if it was
3231 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3232 range of QImode offsets, and offsettable_address_p does a QImode
3235 if (GET_CODE (mem) == CONST)
3236 mem = XEXP (mem, 0);
3238 if (GET_CODE (mem) == LABEL_REF)
3239 return \"ldr\\t%0, %1\";
3241 if (GET_CODE (mem) == PLUS)
3243 rtx a = XEXP (mem, 0);
3244 rtx b = XEXP (mem, 1);
3246 if (GET_CODE (a) == LABEL_REF
3247 && GET_CODE (b) == CONST_INT)
3248 return \"ldr\\t%0, %1\";
3250 if (GET_CODE (b) == REG)
3251 return \"ldrsh\\t%0, %1\";
3259 ops[2] = const0_rtx;
3262 if (GET_CODE (ops[1]) != REG)
3268 ops[0] = operands[0];
3269 ops[3] = operands[2];
3270 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3273 [(set_attr "length" "4")
3274 (set_attr "type" "load")
3275 (set_attr "pool_range" "1020")]
3278 (define_expand "extendhisi2_mem"
3279 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3281 (zero_extend:SI (match_dup 7)))
3282 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3283 (set (match_operand:SI 0 "" "")
3284 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3289 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3291 mem1 = gen_rtx_MEM (QImode, addr);
3292 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3293 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3294 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3295 operands[0] = gen_lowpart (SImode, operands[0]);
3297 operands[2] = gen_reg_rtx (SImode);
3298 operands[3] = gen_reg_rtx (SImode);
3299 operands[6] = gen_reg_rtx (SImode);
3302 if (BYTES_BIG_ENDIAN)
3304 operands[4] = operands[2];
3305 operands[5] = operands[3];
3309 operands[4] = operands[3];
3310 operands[5] = operands[2];
3315 (define_insn "*arm_extendhisi_insn"
3316 [(set (match_operand:SI 0 "s_register_operand" "=r")
3317 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3318 "TARGET_ARM && arm_arch4"
3320 [(set_attr "type" "load")
3321 (set_attr "predicable" "yes")
3322 (set_attr "pool_range" "256")
3323 (set_attr "neg_pool_range" "244")]
3327 [(set (match_operand:SI 0 "s_register_operand" "")
3328 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3329 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3330 "TARGET_ARM && (!arm_arch4)"
3331 [(set (match_dup 2) (match_dup 1))
3332 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3334 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3340 [(set (match_operand:SI 0 "s_register_operand" "")
3341 (match_operator:SI 3 "shiftable_operator"
3342 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3343 (match_operand:SI 4 "s_register_operand" "")]))
3344 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3345 "TARGET_ARM && (!arm_arch4)"
3346 [(set (match_dup 2) (match_dup 1))
3349 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3350 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3355 (define_expand "extendqihi2"
3357 (ashift:SI (match_operand:QI 1 "general_operand" "")
3359 (set (match_operand:HI 0 "s_register_operand" "")
3360 (ashiftrt:SI (match_dup 2)
3365 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3367 emit_insn (gen_rtx_SET (VOIDmode,
3369 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3372 if (!s_register_operand (operands[1], QImode))
3373 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3374 operands[0] = gen_lowpart (SImode, operands[0]);
3375 operands[1] = gen_lowpart (SImode, operands[1]);
3376 operands[2] = gen_reg_rtx (SImode);
3380 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3381 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3382 (define_insn "*extendqihi_insn"
3383 [(set (match_operand:HI 0 "s_register_operand" "=r")
3384 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3385 "TARGET_ARM && arm_arch4"
3387 /* If the address is invalid, this will split the instruction into two. */
3388 if (bad_signed_byte_operand (operands[1], VOIDmode))
3390 return \"ldr%?sb\\t%0, %1\";
3392 [(set_attr "type" "load")
3393 (set_attr "predicable" "yes")
3394 (set_attr "length" "8")
3395 (set_attr "pool_range" "256")
3396 (set_attr "neg_pool_range" "244")]
3400 [(set (match_operand:HI 0 "s_register_operand" "")
3401 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3402 "TARGET_ARM && arm_arch4 && reload_completed"
3403 [(set (match_dup 3) (match_dup 1))
3404 (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3407 HOST_WIDE_INT offset;
3409 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3410 operands[2] = gen_rtx_MEM (QImode, operands[3]);
3411 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3412 operands[1] = XEXP (operands[1], 0);
3413 if (GET_CODE (operands[1]) == PLUS
3414 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3415 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3416 || const_ok_for_arm (-offset)))
3418 HOST_WIDE_INT low = (offset > 0
3419 ? (offset & 0xff) : -((-offset) & 0xff));
3420 XEXP (operands[2], 0) = plus_constant (operands[3], low);
3421 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3423 /* Ensure the sum is in correct canonical form */
3424 else if (GET_CODE (operands[1]) == PLUS
3425 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3426 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3427 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3428 XEXP (operands[1], 1),
3429 XEXP (operands[1], 0));
3433 (define_expand "extendqisi2"
3435 (ashift:SI (match_operand:QI 1 "general_operand" "")
3437 (set (match_operand:SI 0 "s_register_operand" "")
3438 (ashiftrt:SI (match_dup 2)
3443 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3445 emit_insn (gen_rtx_SET (VOIDmode,
3447 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3450 if (!s_register_operand (operands[1], QImode))
3451 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3452 operands[1] = gen_lowpart (SImode, operands[1]);
3453 operands[2] = gen_reg_rtx (SImode);
3459 ops[0] = operands[2];
3460 ops[1] = operands[1];
3461 ops[2] = GEN_INT (24);
3463 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3464 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3466 ops[0] = operands[0];
3467 ops[1] = operands[2];
3468 ops[2] = GEN_INT (24);
3470 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3471 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3478 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3479 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3480 (define_insn "*arm_extendqisi_insn"
3481 [(set (match_operand:SI 0 "s_register_operand" "=r")
3482 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3483 "TARGET_ARM && arm_arch4"
3485 /* If the address is invalid, this will split the instruction into two. */
3486 if (bad_signed_byte_operand (operands[1], VOIDmode))
3488 return \"ldr%?sb\\t%0, %1\";
3490 [(set_attr "type" "load")
3491 (set_attr "predicable" "yes")
3492 (set_attr "length" "8")
3493 (set_attr "pool_range" "256")
3494 (set_attr "neg_pool_range" "244")]
3498 [(set (match_operand:SI 0 "s_register_operand" "")
3499 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3500 "TARGET_ARM && arm_arch4 && reload_completed"
3501 [(set (match_dup 0) (match_dup 1))
3502 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3505 HOST_WIDE_INT offset;
3507 operands[2] = gen_rtx_MEM (QImode, operands[0]);
3508 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3509 operands[1] = XEXP (operands[1], 0);
3510 if (GET_CODE (operands[1]) == PLUS
3511 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3512 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3513 || const_ok_for_arm (-offset)))
3515 HOST_WIDE_INT low = (offset > 0
3516 ? (offset & 0xff) : -((-offset) & 0xff));
3517 XEXP (operands[2], 0) = plus_constant (operands[0], low);
3518 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3520 /* Ensure the sum is in correct canonical form */
3521 else if (GET_CODE (operands[1]) == PLUS
3522 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3523 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3524 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3525 XEXP (operands[1], 1),
3526 XEXP (operands[1], 0));
3530 (define_insn "*thumb_extendqisi2_insn"
3531 [(set (match_operand:SI 0 "register_operand" "=l,l")
3532 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3537 rtx mem = XEXP (operands[1], 0);
3539 if (GET_CODE (mem) == CONST)
3540 mem = XEXP (mem, 0);
3542 if (GET_CODE (mem) == LABEL_REF)
3543 return \"ldr\\t%0, %1\";
3545 if (GET_CODE (mem) == PLUS
3546 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3547 return \"ldr\\t%0, %1\";
3549 if (which_alternative == 0)
3550 return \"ldrsb\\t%0, %1\";
3552 ops[0] = operands[0];
3554 if (GET_CODE (mem) == PLUS)
3556 rtx a = XEXP (mem, 0);
3557 rtx b = XEXP (mem, 1);
3562 if (GET_CODE (a) == REG)
3564 if (GET_CODE (b) == REG)
3565 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3566 else if (REGNO (a) == REGNO (ops[0]))
3568 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3569 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3570 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3573 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3575 else if (GET_CODE (b) != REG)
3579 if (REGNO (b) == REGNO (ops[0]))
3581 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3582 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3583 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3586 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3589 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3591 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3592 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3593 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3598 ops[2] = const0_rtx;
3600 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3604 [(set_attr "length" "2,6")
3605 (set_attr "type" "load,load")
3606 (set_attr "pool_range" "32,32")]
3609 (define_expand "extendsfdf2"
3610 [(set (match_operand:DF 0 "s_register_operand" "")
3611 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
3612 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3616 ;; Move insns (including loads and stores)
3618 ;; XXX Just some ideas about movti.
3619 ;; I don't think these are a good idea on the arm, there just aren't enough
3621 ;;(define_expand "loadti"
3622 ;; [(set (match_operand:TI 0 "s_register_operand" "")
3623 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
3626 ;;(define_expand "storeti"
3627 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3628 ;; (match_operand:TI 1 "s_register_operand" ""))]
3631 ;;(define_expand "movti"
3632 ;; [(set (match_operand:TI 0 "general_operand" "")
3633 ;; (match_operand:TI 1 "general_operand" ""))]
3639 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3640 ;; operands[1] = copy_to_reg (operands[1]);
3641 ;; if (GET_CODE (operands[0]) == MEM)
3642 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3643 ;; else if (GET_CODE (operands[1]) == MEM)
3644 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3648 ;; emit_insn (insn);
3652 ;; Recognize garbage generated above.
3655 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3656 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3660 ;; register mem = (which_alternative < 3);
3661 ;; register const char *template;
3663 ;; operands[mem] = XEXP (operands[mem], 0);
3664 ;; switch (which_alternative)
3666 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3667 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
3668 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
3669 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
3670 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
3671 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
3673 ;; output_asm_insn (template, operands);
3677 (define_expand "movdi"
3678 [(set (match_operand:DI 0 "general_operand" "")
3679 (match_operand:DI 1 "general_operand" ""))]
3684 if (!no_new_pseudos)
3686 if (GET_CODE (operands[0]) != REG)
3687 operands[1] = force_reg (DImode, operands[1]);
3693 (define_insn "*arm_movdi"
3694 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3695 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
3696 "TARGET_ARM && !TARGET_CIRRUS && ! TARGET_IWMMXT"
3698 return (output_move_double (operands));
3700 [(set_attr "length" "8")
3701 (set_attr "type" "*,load,store2")
3702 (set_attr "pool_range" "*,1020,*")
3703 (set_attr "neg_pool_range" "*,1008,*")]
3706 ;;; ??? This should have alternatives for constants.
3707 ;;; ??? This was originally identical to the movdf_insn pattern.
3708 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3709 ;;; thumb_reorg with a memory reference.
3710 (define_insn "*thumb_movdi_insn"
3711 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3712 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
3715 && ( register_operand (operands[0], DImode)
3716 || register_operand (operands[1], DImode))"
3719 switch (which_alternative)
3723 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3724 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
3725 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
3727 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3729 operands[1] = GEN_INT (- INTVAL (operands[1]));
3730 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3732 return \"ldmia\\t%1, {%0, %H0}\";
3734 return \"stmia\\t%0, {%1, %H1}\";
3736 return thumb_load_double_from_address (operands);
3738 operands[2] = gen_rtx (MEM, SImode,
3739 plus_constant (XEXP (operands[0], 0), 4));
3740 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3743 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3744 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
3745 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
3748 [(set_attr "length" "4,4,6,2,2,6,4,4")
3749 (set_attr "type" "*,*,*,load,store2,load,store2,*")
3750 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
3753 (define_expand "movsi"
3754 [(set (match_operand:SI 0 "general_operand" "")
3755 (match_operand:SI 1 "general_operand" ""))]
3760 /* Everything except mem = const or mem = mem can be done easily */
3761 if (GET_CODE (operands[0]) == MEM)
3762 operands[1] = force_reg (SImode, operands[1]);
3763 if (GET_CODE (operands[1]) == CONST_INT
3764 && !(const_ok_for_arm (INTVAL (operands[1]))
3765 || const_ok_for_arm (~INTVAL (operands[1]))))
3767 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3770 : preserve_subexpressions_p ()));
3774 else /* TARGET_THUMB.... */
3776 if (!no_new_pseudos)
3778 if (GET_CODE (operands[0]) != REG)
3779 operands[1] = force_reg (SImode, operands[1]);
3784 && (CONSTANT_P (operands[1])
3785 || symbol_mentioned_p (operands[1])
3786 || label_mentioned_p (operands[1])))
3787 operands[1] = legitimize_pic_address (operands[1], SImode,
3788 (no_new_pseudos ? operands[0] : 0));
3792 (define_insn "*arm_movsi_insn"
3793 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
3794 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
3795 "TARGET_ARM && ! TARGET_IWMMXT
3796 && ( register_operand (operands[0], SImode)
3797 || register_operand (operands[1], SImode))"
3803 [(set_attr "type" "*,*,load,store1")
3804 (set_attr "predicable" "yes")
3805 (set_attr "pool_range" "*,*,4096,*")
3806 (set_attr "neg_pool_range" "*,*,4084,*")]
3810 [(set (match_operand:SI 0 "s_register_operand" "")
3811 (match_operand:SI 1 "const_int_operand" ""))]
3813 && (!(const_ok_for_arm (INTVAL (operands[1]))
3814 || const_ok_for_arm (~INTVAL (operands[1]))))"
3815 [(clobber (const_int 0))]
3817 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3823 (define_insn "*thumb_movsi_insn"
3824 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
3825 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
3827 && ( register_operand (operands[0], SImode)
3828 || register_operand (operands[1], SImode))"
3839 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
3840 (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
3841 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
3845 [(set (match_operand:SI 0 "register_operand" "")
3846 (match_operand:SI 1 "const_int_operand" ""))]
3847 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
3848 [(set (match_dup 0) (match_dup 1))
3849 (set (match_dup 0) (neg:SI (match_dup 0)))]
3850 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
3854 [(set (match_operand:SI 0 "register_operand" "")
3855 (match_operand:SI 1 "const_int_operand" ""))]
3856 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
3857 [(set (match_dup 0) (match_dup 1))
3858 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
3861 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
3862 unsigned HOST_WIDE_INT mask = 0xff;
3865 for (i = 0; i < 25; i++)
3866 if ((val & (mask << i)) == val)
3869 /* Shouldn't happen, but we don't want to split if the shift is zero. */
3873 operands[1] = GEN_INT (val >> i);
3874 operands[2] = GEN_INT (i);
3878 ;; When generating pic, we need to load the symbol offset into a register.
3879 ;; So that the optimizer does not confuse this with a normal symbol load
3880 ;; we use an unspec. The offset will be loaded from a constant pool entry,
3881 ;; since that is the only type of relocation we can use.
3883 ;; The rather odd constraints on the following are to force reload to leave
3884 ;; the insn alone, and to force the minipool generation pass to then move
3885 ;; the GOT symbol to memory.
3887 (define_insn "pic_load_addr_arm"
3888 [(set (match_operand:SI 0 "s_register_operand" "=r")
3889 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3890 "TARGET_ARM && flag_pic"
3892 [(set_attr "type" "load")
3893 (set (attr "pool_range") (const_int 4096))
3894 (set (attr "neg_pool_range") (const_int 4084))]
3897 (define_insn "pic_load_addr_thumb"
3898 [(set (match_operand:SI 0 "s_register_operand" "=l")
3899 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3900 "TARGET_THUMB && flag_pic"
3902 [(set_attr "type" "load")
3903 (set (attr "pool_range") (const_int 1024))]
3906 ;; This variant is used for AOF assembly, since it needs to mention the
3907 ;; pic register in the rtl.
3908 (define_expand "pic_load_addr_based"
3909 [(set (match_operand:SI 0 "s_register_operand" "")
3910 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
3911 "TARGET_ARM && flag_pic"
3912 "operands[2] = pic_offset_table_rtx;"
3915 (define_insn "*pic_load_addr_based_insn"
3916 [(set (match_operand:SI 0 "s_register_operand" "=r")
3917 (unspec:SI [(match_operand 1 "" "")
3918 (match_operand 2 "s_register_operand" "r")]
3920 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
3922 #ifdef AOF_ASSEMBLER
3923 operands[1] = aof_pic_entry (operands[1]);
3925 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
3928 [(set_attr "type" "load")
3929 (set (attr "pool_range")
3930 (if_then_else (eq_attr "is_thumb" "yes")
3933 (set (attr "neg_pool_range")
3934 (if_then_else (eq_attr "is_thumb" "yes")
3939 (define_insn "pic_add_dot_plus_four"
3940 [(set (match_operand:SI 0 "register_operand" "+r")
3941 (unspec:SI [(plus:SI (match_dup 0)
3942 (const (plus:SI (pc) (const_int 4))))]
3944 (use (label_ref (match_operand 1 "" "")))]
3945 "TARGET_THUMB && flag_pic"
3947 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3948 CODE_LABEL_NUMBER (operands[1]));
3949 return \"add\\t%0, %|pc\";
3951 [(set_attr "length" "2")]
3954 (define_insn "pic_add_dot_plus_eight"
3955 [(set (match_operand:SI 0 "register_operand" "+r")
3956 (unspec:SI [(plus:SI (match_dup 0)
3957 (const (plus:SI (pc) (const_int 8))))]
3959 (use (label_ref (match_operand 1 "" "")))]
3960 "TARGET_ARM && flag_pic"
3962 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3963 CODE_LABEL_NUMBER (operands[1]));
3964 return \"add%?\\t%0, %|pc, %0\";
3966 [(set_attr "predicable" "yes")]
3969 (define_expand "builtin_setjmp_receiver"
3970 [(label_ref (match_operand 0 "" ""))]
3974 arm_finalize_pic (0);
3978 ;; If copying one reg to another we can set the condition codes according to
3979 ;; its value. Such a move is common after a return from subroutine and the
3980 ;; result is being tested against zero.
3982 (define_insn "*movsi_compare0"
3983 [(set (reg:CC CC_REGNUM)
3984 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
3986 (set (match_operand:SI 0 "s_register_operand" "=r,r")
3991 sub%?s\\t%0, %1, #0"
3992 [(set_attr "conds" "set")]
3995 ;; Subroutine to store a half word from a register into memory.
3996 ;; Operand 0 is the source register (HImode)
3997 ;; Operand 1 is the destination address in a register (SImode)
3999 ;; In both this routine and the next, we must be careful not to spill
4000 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4001 ;; can generate unrecognizable rtl.
4003 (define_expand "storehi"
4004 [;; store the low byte
4005 (set (match_operand 1 "" "") (match_dup 3))
4006 ;; extract the high byte
4008 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4009 ;; store the high byte
4010 (set (match_dup 4) (match_dup 5))]
4014 rtx op1 = operands[1];
4015 rtx addr = XEXP (op1, 0);
4016 enum rtx_code code = GET_CODE (addr);
4018 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4020 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4022 operands[4] = adjust_address (op1, QImode, 1);
4023 operands[1] = adjust_address (operands[1], QImode, 0);
4024 operands[3] = gen_lowpart (QImode, operands[0]);
4025 operands[0] = gen_lowpart (SImode, operands[0]);
4026 operands[2] = gen_reg_rtx (SImode);
4027 operands[5] = gen_lowpart (QImode, operands[2]);
4031 (define_expand "storehi_bigend"
4032 [(set (match_dup 4) (match_dup 3))
4034 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4035 (set (match_operand 1 "" "") (match_dup 5))]
4039 rtx op1 = operands[1];
4040 rtx addr = XEXP (op1, 0);
4041 enum rtx_code code = GET_CODE (addr);
4043 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4045 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4047 operands[4] = adjust_address (op1, QImode, 1);
4048 operands[1] = adjust_address (operands[1], QImode, 0);
4049 operands[3] = gen_lowpart (QImode, operands[0]);
4050 operands[0] = gen_lowpart (SImode, operands[0]);
4051 operands[2] = gen_reg_rtx (SImode);
4052 operands[5] = gen_lowpart (QImode, operands[2]);
4056 ;; Subroutine to store a half word integer constant into memory.
4057 (define_expand "storeinthi"
4058 [(set (match_operand 0 "" "")
4059 (match_operand 1 "" ""))
4060 (set (match_dup 3) (match_dup 2))]
4064 HOST_WIDE_INT value = INTVAL (operands[1]);
4065 rtx addr = XEXP (operands[0], 0);
4066 rtx op0 = operands[0];
4067 enum rtx_code code = GET_CODE (addr);
4069 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4071 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4073 operands[1] = gen_reg_rtx (SImode);
4074 if (BYTES_BIG_ENDIAN)
4076 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4077 if ((value & 255) == ((value >> 8) & 255))
4078 operands[2] = operands[1];
4081 operands[2] = gen_reg_rtx (SImode);
4082 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4087 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4088 if ((value & 255) == ((value >> 8) & 255))
4089 operands[2] = operands[1];
4092 operands[2] = gen_reg_rtx (SImode);
4093 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4097 operands[3] = adjust_address (op0, QImode, 1);
4098 operands[0] = adjust_address (operands[0], QImode, 0);
4099 operands[2] = gen_lowpart (QImode, operands[2]);
4100 operands[1] = gen_lowpart (QImode, operands[1]);
4104 (define_expand "storehi_single_op"
4105 [(set (match_operand:HI 0 "memory_operand" "")
4106 (match_operand:HI 1 "general_operand" ""))]
4107 "TARGET_ARM && arm_arch4"
4109 if (!s_register_operand (operands[1], HImode))
4110 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4114 (define_expand "movhi"
4115 [(set (match_operand:HI 0 "general_operand" "")
4116 (match_operand:HI 1 "general_operand" ""))]
4121 if (!no_new_pseudos)
4123 if (GET_CODE (operands[0]) == MEM)
4127 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4130 if (GET_CODE (operands[1]) == CONST_INT)
4131 emit_insn (gen_storeinthi (operands[0], operands[1]));
4134 if (GET_CODE (operands[1]) == MEM)
4135 operands[1] = force_reg (HImode, operands[1]);
4136 if (BYTES_BIG_ENDIAN)
4137 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4139 emit_insn (gen_storehi (operands[1], operands[0]));
4143 /* Sign extend a constant, and keep it in an SImode reg. */
4144 else if (GET_CODE (operands[1]) == CONST_INT)
4146 rtx reg = gen_reg_rtx (SImode);
4147 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4149 /* If the constant is already valid, leave it alone. */
4150 if (!const_ok_for_arm (val))
4152 /* If setting all the top bits will make the constant
4153 loadable in a single instruction, then set them.
4154 Otherwise, sign extend the number. */
4156 if (const_ok_for_arm (~(val | ~0xffff)))
4158 else if (val & 0x8000)
4162 emit_insn (gen_movsi (reg, GEN_INT (val)));
4163 operands[1] = gen_lowpart (HImode, reg);
4165 else if (arm_arch4 && !no_new_pseudos && optimize > 0
4166 && GET_CODE (operands[1]) == MEM)
4168 rtx reg = gen_reg_rtx (SImode);
4170 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4171 operands[1] = gen_lowpart (HImode, reg);
4173 else if (!arm_arch4)
4175 /* Note: We do not have to worry about TARGET_MMU_TRAPS
4176 for v4 and up architectures because LDRH instructions will
4177 be used to access the HI values, and these cannot generate
4178 unaligned word access faults in the MMU. */
4179 if (GET_CODE (operands[1]) == MEM)
4181 if (TARGET_MMU_TRAPS)
4184 rtx offset = const0_rtx;
4185 rtx reg = gen_reg_rtx (SImode);
4187 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4188 || (GET_CODE (base) == PLUS
4189 && (GET_CODE (offset = XEXP (base, 1))
4191 && ((INTVAL(offset) & 1) != 1)
4192 && GET_CODE (base = XEXP (base, 0)) == REG))
4193 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4195 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4198 new = gen_rtx_MEM (SImode,
4199 plus_constant (base, new_offset));
4200 MEM_COPY_ATTRIBUTES (new, operands[1]);
4201 emit_insn (gen_movsi (reg, new));
4202 if (((INTVAL (offset) & 2) != 0)
4203 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4205 rtx reg2 = gen_reg_rtx (SImode);
4207 emit_insn (gen_lshrsi3 (reg2, reg,
4213 emit_insn (gen_movhi_bytes (reg, operands[1]));
4215 operands[1] = gen_lowpart (HImode, reg);
4217 else if (BYTES_BIG_ENDIAN)
4220 rtx offset = const0_rtx;
4222 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4223 || (GET_CODE (base) == PLUS
4224 && (GET_CODE (offset = XEXP (base, 1))
4226 && GET_CODE (base = XEXP (base, 0)) == REG))
4227 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4229 rtx reg = gen_reg_rtx (SImode);
4232 if ((INTVAL (offset) & 2) == 2)
4234 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4235 new = gen_rtx_MEM (SImode,
4236 plus_constant (base,
4238 MEM_COPY_ATTRIBUTES (new, operands[1]);
4239 emit_insn (gen_movsi (reg, new));
4243 new = gen_rtx_MEM (SImode,
4244 XEXP (operands[1], 0));
4245 MEM_COPY_ATTRIBUTES (new, operands[1]);
4246 emit_insn (gen_rotated_loadsi (reg, new));
4249 operands[1] = gen_lowpart (HImode, reg);
4253 emit_insn (gen_movhi_bigend (operands[0],
4261 /* Handle loading a large integer during reload */
4262 else if (GET_CODE (operands[1]) == CONST_INT
4263 && !const_ok_for_arm (INTVAL (operands[1]))
4264 && !const_ok_for_arm (~INTVAL (operands[1])))
4266 /* Writing a constant to memory needs a scratch, which should
4267 be handled with SECONDARY_RELOADs. */
4268 if (GET_CODE (operands[0]) != REG)
4271 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4272 emit_insn (gen_movsi (operands[0], operands[1]));
4276 else /* TARGET_THUMB */
4278 if (!no_new_pseudos)
4280 if (GET_CODE (operands[0]) != REG)
4281 operands[1] = force_reg (HImode, operands[1]);
4283 /* ??? We shouldn't really get invalid addresses here, but this can
4284 happen if we are passed a SP (never OK for HImode/QImode) or
4285 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4286 HImode/QImode) relative address. */
4287 /* ??? This should perhaps be fixed elsewhere, for instance, in
4288 fixup_stack_1, by checking for other kinds of invalid addresses,
4289 e.g. a bare reference to a virtual register. This may confuse the
4290 alpha though, which must handle this case differently. */
4291 if (GET_CODE (operands[0]) == MEM
4292 && !memory_address_p (GET_MODE (operands[0]),
4293 XEXP (operands[0], 0)))
4295 = replace_equiv_address (operands[0],
4296 copy_to_reg (XEXP (operands[0], 0)));
4298 if (GET_CODE (operands[1]) == MEM
4299 && !memory_address_p (GET_MODE (operands[1]),
4300 XEXP (operands[1], 0)))
4302 = replace_equiv_address (operands[1],
4303 copy_to_reg (XEXP (operands[1], 0)));
4305 /* Handle loading a large integer during reload */
4306 else if (GET_CODE (operands[1]) == CONST_INT
4307 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4309 /* Writing a constant to memory needs a scratch, which should
4310 be handled with SECONDARY_RELOADs. */
4311 if (GET_CODE (operands[0]) != REG)
4314 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4315 emit_insn (gen_movsi (operands[0], operands[1]));
4322 (define_insn "*thumb_movhi_insn"
4323 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4324 (match_operand:HI 1 "general_operand" "l,mn,l,*h,*r,I"))]
4326 && ( register_operand (operands[0], HImode)
4327 || register_operand (operands[1], HImode))"
4329 switch (which_alternative)
4331 case 0: return \"add %0, %1, #0\";
4332 case 2: return \"strh %1, %0\";
4333 case 3: return \"mov %0, %1\";
4334 case 4: return \"mov %0, %1\";
4335 case 5: return \"mov %0, %1\";
4338 /* The stack pointer can end up being taken as an index register.
4339 Catch this case here and deal with it. */
4340 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4341 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4342 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4345 ops[0] = operands[0];
4346 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4348 output_asm_insn (\"mov %0, %1\", ops);
4350 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4353 return \"ldrh %0, %1\";
4355 [(set_attr "length" "2,4,2,2,2,2")
4356 (set_attr "type" "*,load,store1,*,*,*")
4357 (set_attr "pool_range" "*,64,*,*,*,*")]
4361 (define_insn "rotated_loadsi"
4362 [(set (match_operand:SI 0 "s_register_operand" "=r")
4363 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4365 "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4370 ops[0] = operands[0];
4371 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4372 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4375 [(set_attr "type" "load")
4376 (set_attr "predicable" "yes")]
4379 (define_expand "movhi_bytes"
4380 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4382 (zero_extend:SI (match_dup 6)))
4383 (set (match_operand:SI 0 "" "")
4384 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4389 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4391 mem1 = gen_rtx_MEM (QImode, addr);
4392 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4393 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4394 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4395 operands[0] = gen_lowpart (SImode, operands[0]);
4397 operands[2] = gen_reg_rtx (SImode);
4398 operands[3] = gen_reg_rtx (SImode);
4401 if (BYTES_BIG_ENDIAN)
4403 operands[4] = operands[2];
4404 operands[5] = operands[3];
4408 operands[4] = operands[3];
4409 operands[5] = operands[2];
4414 (define_expand "movhi_bigend"
4416 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4419 (ashiftrt:SI (match_dup 2) (const_int 16)))
4420 (set (match_operand:HI 0 "s_register_operand" "")
4424 operands[2] = gen_reg_rtx (SImode);
4425 operands[3] = gen_reg_rtx (SImode);
4426 operands[4] = gen_lowpart (HImode, operands[3]);
4430 ;; Pattern to recognize insn generated default case above
4431 (define_insn "*movhi_insn_arch4"
4432 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4433 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4436 && (GET_CODE (operands[1]) != CONST_INT
4437 || const_ok_for_arm (INTVAL (operands[1]))
4438 || const_ok_for_arm (~INTVAL (operands[1])))"
4440 mov%?\\t%0, %1\\t%@ movhi
4441 mvn%?\\t%0, #%B1\\t%@ movhi
4442 str%?h\\t%1, %0\\t%@ movhi
4443 ldr%?h\\t%0, %1\\t%@ movhi"
4444 [(set_attr "type" "*,*,store1,load")
4445 (set_attr "predicable" "yes")
4446 (set_attr "pool_range" "*,*,*,256")
4447 (set_attr "neg_pool_range" "*,*,*,244")]
4450 (define_insn "*movhi_insn_littleend"
4451 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4452 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4455 && !BYTES_BIG_ENDIAN
4456 && !TARGET_MMU_TRAPS
4457 && (GET_CODE (operands[1]) != CONST_INT
4458 || const_ok_for_arm (INTVAL (operands[1]))
4459 || const_ok_for_arm (~INTVAL (operands[1])))"
4461 mov%?\\t%0, %1\\t%@ movhi
4462 mvn%?\\t%0, #%B1\\t%@ movhi
4463 ldr%?\\t%0, %1\\t%@ movhi"
4464 [(set_attr "type" "*,*,load")
4465 (set_attr "predicable" "yes")
4466 (set_attr "pool_range" "4096")
4467 (set_attr "neg_pool_range" "4084")]
4470 (define_insn "*movhi_insn_bigend"
4471 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4472 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4476 && !TARGET_MMU_TRAPS
4477 && (GET_CODE (operands[1]) != CONST_INT
4478 || const_ok_for_arm (INTVAL (operands[1]))
4479 || const_ok_for_arm (~INTVAL (operands[1])))"
4481 mov%?\\t%0, %1\\t%@ movhi
4482 mvn%?\\t%0, #%B1\\t%@ movhi
4483 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4484 [(set_attr "type" "*,*,load")
4485 (set_attr "predicable" "yes")
4486 (set_attr "length" "4,4,8")
4487 (set_attr "pool_range" "*,*,4092")
4488 (set_attr "neg_pool_range" "*,*,4084")]
4491 (define_insn "*loadhi_si_bigend"
4492 [(set (match_operand:SI 0 "s_register_operand" "=r")
4493 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
4497 && !TARGET_MMU_TRAPS"
4498 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4499 [(set_attr "type" "load")
4500 (set_attr "predicable" "yes")
4501 (set_attr "pool_range" "4096")
4502 (set_attr "neg_pool_range" "4084")]
4505 (define_insn "*movhi_bytes"
4506 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4507 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4508 "TARGET_ARM && TARGET_MMU_TRAPS"
4510 mov%?\\t%0, %1\\t%@ movhi
4511 mvn%?\\t%0, #%B1\\t%@ movhi"
4512 [(set_attr "predicable" "yes")]
4515 (define_insn "thumb_movhi_clobber"
4516 [(set (match_operand:HI 0 "memory_operand" "=m")
4517 (match_operand:HI 1 "register_operand" "l"))
4518 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4524 ;; We use a DImode scratch because we may occasionally need an additional
4525 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4526 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4527 (define_expand "reload_outhi"
4528 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4529 (match_operand:HI 1 "s_register_operand" "r")
4530 (match_operand:DI 2 "s_register_operand" "=&l")])]
4533 arm_reload_out_hi (operands);
4535 thumb_reload_out_hi (operands);
4540 (define_expand "reload_inhi"
4541 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4542 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4543 (match_operand:DI 2 "s_register_operand" "=&r")])]
4544 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4547 arm_reload_in_hi (operands);
4549 thumb_reload_out_hi (operands);
4553 (define_expand "movqi"
4554 [(set (match_operand:QI 0 "general_operand" "")
4555 (match_operand:QI 1 "general_operand" ""))]
4560 /* Everything except mem = const or mem = mem can be done easily */
4562 if (!no_new_pseudos)
4564 if (GET_CODE (operands[1]) == CONST_INT)
4566 rtx reg = gen_reg_rtx (SImode);
4568 emit_insn (gen_movsi (reg, operands[1]));
4569 operands[1] = gen_lowpart (QImode, reg);
4571 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4573 rtx reg = gen_reg_rtx (SImode);
4575 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4576 operands[1] = gen_lowpart (QImode, reg);
4578 if (GET_CODE (operands[0]) == MEM)
4579 operands[1] = force_reg (QImode, operands[1]);
4582 else /* TARGET_THUMB */
4584 if (!no_new_pseudos)
4586 if (GET_CODE (operands[0]) != REG)
4587 operands[1] = force_reg (QImode, operands[1]);
4589 /* ??? We shouldn't really get invalid addresses here, but this can
4590 happen if we are passed a SP (never OK for HImode/QImode) or
4591 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4592 HImode/QImode) relative address. */
4593 /* ??? This should perhaps be fixed elsewhere, for instance, in
4594 fixup_stack_1, by checking for other kinds of invalid addresses,
4595 e.g. a bare reference to a virtual register. This may confuse the
4596 alpha though, which must handle this case differently. */
4597 if (GET_CODE (operands[0]) == MEM
4598 && !memory_address_p (GET_MODE (operands[0]),
4599 XEXP (operands[0], 0)))
4601 = replace_equiv_address (operands[0],
4602 copy_to_reg (XEXP (operands[0], 0)));
4603 if (GET_CODE (operands[1]) == MEM
4604 && !memory_address_p (GET_MODE (operands[1]),
4605 XEXP (operands[1], 0)))
4607 = replace_equiv_address (operands[1],
4608 copy_to_reg (XEXP (operands[1], 0)));
4610 /* Handle loading a large integer during reload */
4611 else if (GET_CODE (operands[1]) == CONST_INT
4612 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4614 /* Writing a constant to memory needs a scratch, which should
4615 be handled with SECONDARY_RELOADs. */
4616 if (GET_CODE (operands[0]) != REG)
4619 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4620 emit_insn (gen_movsi (operands[0], operands[1]));
4628 (define_insn "*arm_movqi_insn"
4629 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4630 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4632 && ( register_operand (operands[0], QImode)
4633 || register_operand (operands[1], QImode))"
4639 [(set_attr "type" "*,*,load,store1")
4640 (set_attr "predicable" "yes")]
4643 (define_insn "*thumb_movqi_insn"
4644 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4645 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
4647 && ( register_operand (operands[0], QImode)
4648 || register_operand (operands[1], QImode))"
4656 [(set_attr "length" "2")
4657 (set_attr "type" "*,load,store1,*,*,*")
4658 (set_attr "pool_range" "*,32,*,*,*,*")]
4661 (define_expand "movsf"
4662 [(set (match_operand:SF 0 "general_operand" "")
4663 (match_operand:SF 1 "general_operand" ""))]
4668 if (GET_CODE (operands[0]) == MEM)
4669 operands[1] = force_reg (SFmode, operands[1]);
4671 else /* TARGET_THUMB */
4673 if (!no_new_pseudos)
4675 if (GET_CODE (operands[0]) != REG)
4676 operands[1] = force_reg (SFmode, operands[1]);
4683 [(set (match_operand:SF 0 "nonimmediate_operand" "")
4684 (match_operand:SF 1 "immediate_operand" ""))]
4686 && !TARGET_HARD_FLOAT
4688 && GET_CODE (operands[1]) == CONST_DOUBLE"
4689 [(set (match_dup 2) (match_dup 3))]
4691 operands[2] = gen_lowpart (SImode, operands[0]);
4692 operands[3] = gen_lowpart (SImode, operands[1]);
4693 if (operands[2] == 0 || operands[3] == 0)
4698 (define_insn "*arm_movsf_soft_insn"
4699 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4700 (match_operand:SF 1 "general_operand" "r,mE,r"))]
4703 && TARGET_SOFT_FLOAT
4704 && (GET_CODE (operands[0]) != MEM
4705 || register_operand (operands[1], SFmode))"
4708 ldr%?\\t%0, %1\\t%@ float
4709 str%?\\t%1, %0\\t%@ float"
4710 [(set_attr "length" "4,4,4")
4711 (set_attr "predicable" "yes")
4712 (set_attr "type" "*,load,store1")
4713 (set_attr "pool_range" "*,4096,*")
4714 (set_attr "neg_pool_range" "*,4084,*")]
4717 ;;; ??? This should have alternatives for constants.
4718 (define_insn "*thumb_movsf_insn"
4719 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4720 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
4722 && ( register_operand (operands[0], SFmode)
4723 || register_operand (operands[1], SFmode))"
4732 [(set_attr "length" "2")
4733 (set_attr "type" "*,load,store1,load,store1,*,*")
4734 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
4737 (define_expand "movdf"
4738 [(set (match_operand:DF 0 "general_operand" "")
4739 (match_operand:DF 1 "general_operand" ""))]
4744 if (GET_CODE (operands[0]) == MEM)
4745 operands[1] = force_reg (DFmode, operands[1]);
4747 else /* TARGET_THUMB */
4749 if (!no_new_pseudos)
4751 if (GET_CODE (operands[0]) != REG)
4752 operands[1] = force_reg (DFmode, operands[1]);
4758 ;; Reloading a df mode value stored in integer regs to memory can require a
4760 (define_expand "reload_outdf"
4761 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
4762 (match_operand:DF 1 "s_register_operand" "r")
4763 (match_operand:SI 2 "s_register_operand" "=&r")]
4767 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
4770 operands[2] = XEXP (operands[0], 0);
4771 else if (code == POST_INC || code == PRE_DEC)
4773 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
4774 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
4775 emit_insn (gen_movdi (operands[0], operands[1]));
4778 else if (code == PRE_INC)
4780 rtx reg = XEXP (XEXP (operands[0], 0), 0);
4782 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
4785 else if (code == POST_DEC)
4786 operands[2] = XEXP (XEXP (operands[0], 0), 0);
4788 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
4789 XEXP (XEXP (operands[0], 0), 1)));
4791 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
4794 if (code == POST_DEC)
4795 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
4801 (define_insn "*movdf_soft_insn"
4802 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
4803 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
4804 "TARGET_ARM && TARGET_SOFT_FLOAT
4807 "* return output_move_double (operands);"
4808 [(set_attr "length" "8,8,8")
4809 (set_attr "type" "*,load,store2")
4810 (set_attr "pool_range" "1020")
4811 (set_attr "neg_pool_range" "1008")]
4814 ;;; ??? This should have alternatives for constants.
4815 ;;; ??? This was originally identical to the movdi_insn pattern.
4816 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
4817 ;;; thumb_reorg with a memory reference.
4818 (define_insn "*thumb_movdf_insn"
4819 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
4820 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
4822 && ( register_operand (operands[0], DFmode)
4823 || register_operand (operands[1], DFmode))"
4825 switch (which_alternative)
4829 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4830 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4831 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4833 return \"ldmia\\t%1, {%0, %H0}\";
4835 return \"stmia\\t%0, {%1, %H1}\";
4837 return thumb_load_double_from_address (operands);
4839 operands[2] = gen_rtx (MEM, SImode,
4840 plus_constant (XEXP (operands[0], 0), 4));
4841 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4844 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4845 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4846 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4849 [(set_attr "length" "4,2,2,6,4,4")
4850 (set_attr "type" "*,load,store2,load,store2,*")
4851 (set_attr "pool_range" "*,*,*,1020,*,*")]
4855 (define_expand "movv2si"
4856 [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
4857 (match_operand:V2SI 1 "general_operand" ""))]
4858 "TARGET_REALLY_IWMMXT"
4862 (define_expand "movv4hi"
4863 [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
4864 (match_operand:V4HI 1 "general_operand" ""))]
4865 "TARGET_REALLY_IWMMXT"
4869 (define_expand "movv8qi"
4870 [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
4871 (match_operand:V8QI 1 "general_operand" ""))]
4872 "TARGET_REALLY_IWMMXT"
4877 ;; load- and store-multiple insns
4878 ;; The arm can load/store any set of registers, provided that they are in
4879 ;; ascending order; but that is beyond GCC so stick with what it knows.
4881 (define_expand "load_multiple"
4882 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
4883 (match_operand:SI 1 "" ""))
4884 (use (match_operand:SI 2 "" ""))])]
4887 /* Support only fixed point registers. */
4888 if (GET_CODE (operands[2]) != CONST_INT
4889 || INTVAL (operands[2]) > 14
4890 || INTVAL (operands[2]) < 2
4891 || GET_CODE (operands[1]) != MEM
4892 || GET_CODE (operands[0]) != REG
4893 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
4894 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
4898 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
4899 force_reg (SImode, XEXP (operands[1], 0)),
4900 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
4901 MEM_IN_STRUCT_P(operands[1]),
4902 MEM_SCALAR_P (operands[1]));
4906 ;; Load multiple with write-back
4908 (define_insn "*ldmsi_postinc4"
4909 [(match_parallel 0 "load_multiple_operation"
4910 [(set (match_operand:SI 1 "s_register_operand" "=r")
4911 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4913 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4914 (mem:SI (match_dup 2)))
4915 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4916 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
4917 (set (match_operand:SI 5 "arm_hard_register_operand" "")
4918 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
4919 (set (match_operand:SI 6 "arm_hard_register_operand" "")
4920 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
4921 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
4922 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
4923 [(set_attr "type" "load")
4924 (set_attr "predicable" "yes")]
4927 (define_insn "*ldmsi_postinc3"
4928 [(match_parallel 0 "load_multiple_operation"
4929 [(set (match_operand:SI 1 "s_register_operand" "=r")
4930 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4932 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4933 (mem:SI (match_dup 2)))
4934 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4935 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
4936 (set (match_operand:SI 5 "arm_hard_register_operand" "")
4937 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
4938 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4939 "ldm%?ia\\t%1!, {%3, %4, %5}"
4940 [(set_attr "type" "load")
4941 (set_attr "predicable" "yes")]
4944 (define_insn "*ldmsi_postinc2"
4945 [(match_parallel 0 "load_multiple_operation"
4946 [(set (match_operand:SI 1 "s_register_operand" "=r")
4947 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4949 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4950 (mem:SI (match_dup 2)))
4951 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4952 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
4953 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4954 "ldm%?ia\\t%1!, {%3, %4}"
4955 [(set_attr "type" "load")
4956 (set_attr "predicable" "yes")]
4959 ;; Ordinary load multiple
4961 (define_insn "*ldmsi4"
4962 [(match_parallel 0 "load_multiple_operation"
4963 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4964 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4965 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4966 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
4967 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4968 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
4969 (set (match_operand:SI 5 "arm_hard_register_operand" "")
4970 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
4971 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4972 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
4973 [(set_attr "type" "load")
4974 (set_attr "predicable" "yes")]
4977 (define_insn "*ldmsi3"
4978 [(match_parallel 0 "load_multiple_operation"
4979 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4980 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4981 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4982 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
4983 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4984 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
4985 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4986 "ldm%?ia\\t%1, {%2, %3, %4}"
4987 [(set_attr "type" "load")
4988 (set_attr "predicable" "yes")]
4991 (define_insn "*ldmsi2"
4992 [(match_parallel 0 "load_multiple_operation"
4993 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4994 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4995 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4996 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
4997 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
4998 "ldm%?ia\\t%1, {%2, %3}"
4999 [(set_attr "type" "load")
5000 (set_attr "predicable" "yes")]
5003 (define_expand "store_multiple"
5004 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5005 (match_operand:SI 1 "" ""))
5006 (use (match_operand:SI 2 "" ""))])]
5009 /* Support only fixed point registers */
5010 if (GET_CODE (operands[2]) != CONST_INT
5011 || INTVAL (operands[2]) > 14
5012 || INTVAL (operands[2]) < 2
5013 || GET_CODE (operands[1]) != REG
5014 || GET_CODE (operands[0]) != MEM
5015 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5016 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5020 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5021 force_reg (SImode, XEXP (operands[0], 0)),
5022 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5023 MEM_IN_STRUCT_P(operands[0]),
5024 MEM_SCALAR_P (operands[0]));
5028 ;; Store multiple with write-back
5030 (define_insn "*stmsi_postinc4"
5031 [(match_parallel 0 "store_multiple_operation"
5032 [(set (match_operand:SI 1 "s_register_operand" "=r")
5033 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5035 (set (mem:SI (match_dup 2))
5036 (match_operand:SI 3 "arm_hard_register_operand" ""))
5037 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5038 (match_operand:SI 4 "arm_hard_register_operand" ""))
5039 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5040 (match_operand:SI 5 "arm_hard_register_operand" ""))
5041 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5042 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5043 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5044 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5045 [(set_attr "predicable" "yes")
5046 (set_attr "type" "store4")]
5049 (define_insn "*stmsi_postinc3"
5050 [(match_parallel 0 "store_multiple_operation"
5051 [(set (match_operand:SI 1 "s_register_operand" "=r")
5052 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5054 (set (mem:SI (match_dup 2))
5055 (match_operand:SI 3 "arm_hard_register_operand" ""))
5056 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5057 (match_operand:SI 4 "arm_hard_register_operand" ""))
5058 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5059 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5060 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5061 "stm%?ia\\t%1!, {%3, %4, %5}"
5062 [(set_attr "predicable" "yes")
5063 (set_attr "type" "store3")]
5066 (define_insn "*stmsi_postinc2"
5067 [(match_parallel 0 "store_multiple_operation"
5068 [(set (match_operand:SI 1 "s_register_operand" "=r")
5069 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5071 (set (mem:SI (match_dup 2))
5072 (match_operand:SI 3 "arm_hard_register_operand" ""))
5073 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5074 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5075 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5076 "stm%?ia\\t%1!, {%3, %4}"
5077 [(set_attr "predicable" "yes")
5078 (set_attr "type" "store2")]
5081 ;; Ordinary store multiple
5083 (define_insn "*stmsi4"
5084 [(match_parallel 0 "store_multiple_operation"
5085 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5086 (match_operand:SI 2 "arm_hard_register_operand" ""))
5087 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5088 (match_operand:SI 3 "arm_hard_register_operand" ""))
5089 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5090 (match_operand:SI 4 "arm_hard_register_operand" ""))
5091 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5092 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5093 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5094 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5095 [(set_attr "predicable" "yes")
5096 (set_attr "type" "store4")]
5099 (define_insn "*stmsi3"
5100 [(match_parallel 0 "store_multiple_operation"
5101 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5102 (match_operand:SI 2 "arm_hard_register_operand" ""))
5103 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5104 (match_operand:SI 3 "arm_hard_register_operand" ""))
5105 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5106 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5107 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5108 "stm%?ia\\t%1, {%2, %3, %4}"
5109 [(set_attr "predicable" "yes")
5110 (set_attr "type" "store3")]
5113 (define_insn "*stmsi2"
5114 [(match_parallel 0 "store_multiple_operation"
5115 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5116 (match_operand:SI 2 "arm_hard_register_operand" ""))
5117 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5118 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5119 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5120 "stm%?ia\\t%1, {%2, %3}"
5121 [(set_attr "predicable" "yes")
5122 (set_attr "type" "store2")]
5125 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5126 ;; We could let this apply for blocks of less than this, but it clobbers so
5127 ;; many registers that there is then probably a better way.
5129 (define_expand "movstrqi"
5130 [(match_operand:BLK 0 "general_operand" "")
5131 (match_operand:BLK 1 "general_operand" "")
5132 (match_operand:SI 2 "const_int_operand" "")
5133 (match_operand:SI 3 "const_int_operand" "")]
5138 if (arm_gen_movstrqi (operands))
5142 else /* TARGET_THUMB */
5144 if ( INTVAL (operands[3]) != 4
5145 || INTVAL (operands[2]) > 48)
5148 thumb_expand_movstrqi (operands);
5154 ;; Thumb block-move insns
5156 (define_insn "movmem12b"
5157 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5158 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5159 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5160 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5161 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5162 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5163 (set (match_operand:SI 0 "register_operand" "=l")
5164 (plus:SI (match_dup 2) (const_int 12)))
5165 (set (match_operand:SI 1 "register_operand" "=l")
5166 (plus:SI (match_dup 3) (const_int 12)))
5167 (clobber (match_scratch:SI 4 "=&l"))
5168 (clobber (match_scratch:SI 5 "=&l"))
5169 (clobber (match_scratch:SI 6 "=&l"))]
5171 "* return thumb_output_move_mem_multiple (3, operands);"
5172 [(set_attr "length" "4")
5173 ; This isn't entirely accurate... It loads as well, but in terms of
5174 ; scheduling the following insn it is better to consider it as a store
5175 (set_attr "type" "store3")]
5178 (define_insn "movmem8b"
5179 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5180 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5181 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5182 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5183 (set (match_operand:SI 0 "register_operand" "=l")
5184 (plus:SI (match_dup 2) (const_int 8)))
5185 (set (match_operand:SI 1 "register_operand" "=l")
5186 (plus:SI (match_dup 3) (const_int 8)))
5187 (clobber (match_scratch:SI 4 "=&l"))
5188 (clobber (match_scratch:SI 5 "=&l"))]
5190 "* return thumb_output_move_mem_multiple (2, operands);"
5191 [(set_attr "length" "4")
5192 ; This isn't entirely accurate... It loads as well, but in terms of
5193 ; scheduling the following insn it is better to consider it as a store
5194 (set_attr "type" "store2")]
5199 ;; Compare & branch insns
5200 ;; The range calculations are based as follows:
5201 ;; For forward branches, the address calculation returns the address of
5202 ;; the next instruction. This is 2 beyond the branch instruction.
5203 ;; For backward branches, the address calculation returns the address of
5204 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5205 ;; instruction for the shortest sequence, and 4 before the branch instruction
5206 ;; if we have to jump around an unconditional branch.
5207 ;; To the basic branch range the PC offset must be added (this is +4).
5208 ;; So for forward branches we have
5209 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5210 ;; And for backward branches we have
5211 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5213 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5214 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5216 (define_expand "cbranchsi4"
5217 [(set (pc) (if_then_else
5218 (match_operator 0 "arm_comparison_operator"
5219 [(match_operand:SI 1 "s_register_operand" "")
5220 (match_operand:SI 2 "nonmemory_operand" "")])
5221 (label_ref (match_operand 3 "" ""))
5225 if (thumb_cmpneg_operand (operands[2], SImode))
5227 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5228 operands[3], operands[0]));
5231 if (!thumb_cmp_operand (operands[2], SImode))
5232 operands[2] = force_reg (SImode, operands[2]);
5235 (define_insn "*cbranchsi4_insn"
5236 [(set (pc) (if_then_else
5237 (match_operator 0 "arm_comparison_operator"
5238 [(match_operand:SI 1 "s_register_operand" "l,*h")
5239 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5240 (label_ref (match_operand 3 "" ""))
5244 output_asm_insn (\"cmp\\t%1, %2\", operands);
5246 switch (get_attr_length (insn))
5248 case 4: return \"b%d0\\t%l3\";
5249 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5250 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5253 [(set (attr "far_jump")
5255 (eq_attr "length" "8")
5256 (const_string "yes")
5257 (const_string "no")))
5258 (set (attr "length")
5260 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5261 (le (minus (match_dup 3) (pc)) (const_int 256)))
5264 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5265 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5270 (define_insn "cbranchsi4_scratch"
5271 [(set (pc) (if_then_else
5272 (match_operator 4 "arm_comparison_operator"
5273 [(match_operand:SI 1 "s_register_operand" "l,0")
5274 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5275 (label_ref (match_operand 3 "" ""))
5277 (clobber (match_scratch:SI 0 "=l,l"))]
5280 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5282 switch (get_attr_length (insn))
5284 case 4: return \"b%d4\\t%l3\";
5285 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5286 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5289 [(set (attr "far_jump")
5291 (eq_attr "length" "8")
5292 (const_string "yes")
5293 (const_string "no")))
5294 (set (attr "length")
5296 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5297 (le (minus (match_dup 3) (pc)) (const_int 256)))
5300 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5301 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5305 (define_insn "*movsi_cbranchsi4"
5308 (match_operator 3 "arm_comparison_operator"
5309 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5311 (label_ref (match_operand 2 "" ""))
5313 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5317 if (which_alternative == 0)
5318 output_asm_insn (\"cmp\t%0, #0\", operands);
5319 else if (which_alternative == 1)
5320 output_asm_insn (\"sub\t%0, %1, #0\", operands);
5323 output_asm_insn (\"cmp\t%1, #0\", operands);
5324 if (which_alternative == 2)
5325 output_asm_insn (\"mov\t%0, %1\", operands);
5327 output_asm_insn (\"str\t%1, %0\", operands);
5329 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5331 case 4: return \"b%d3\\t%l2\";
5332 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5333 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5336 [(set (attr "far_jump")
5338 (ior (and (gt (symbol_ref ("which_alternative"))
5340 (eq_attr "length" "8"))
5341 (eq_attr "length" "10"))
5342 (const_string "yes")
5343 (const_string "no")))
5344 (set (attr "length")
5346 (le (symbol_ref ("which_alternative"))
5349 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5350 (le (minus (match_dup 2) (pc)) (const_int 256)))
5353 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5354 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5358 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5359 (le (minus (match_dup 2) (pc)) (const_int 256)))
5362 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5363 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5368 (define_insn "*negated_cbranchsi4"
5371 (match_operator 0 "arm_comparison_operator"
5372 [(match_operand:SI 1 "s_register_operand" "l")
5373 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5374 (label_ref (match_operand 3 "" ""))
5378 output_asm_insn (\"cmn\\t%1, %2\", operands);
5379 switch (get_attr_length (insn))
5381 case 4: return \"b%d0\\t%l3\";
5382 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5383 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5386 [(set (attr "far_jump")
5388 (eq_attr "length" "8")
5389 (const_string "yes")
5390 (const_string "no")))
5391 (set (attr "length")
5393 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5394 (le (minus (match_dup 3) (pc)) (const_int 256)))
5397 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5398 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5403 (define_insn "*tbit_cbranch"
5406 (match_operator 0 "equality_operator"
5407 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5409 (match_operand:SI 2 "const_int_operand" "i"))
5411 (label_ref (match_operand 3 "" ""))
5413 (clobber (match_scratch:SI 4 "=l"))]
5418 op[0] = operands[4];
5419 op[1] = operands[1];
5420 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5422 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5423 switch (get_attr_length (insn))
5425 case 4: return \"b%d0\\t%l3\";
5426 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5427 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5430 [(set (attr "far_jump")
5432 (eq_attr "length" "8")
5433 (const_string "yes")
5434 (const_string "no")))
5435 (set (attr "length")
5437 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5438 (le (minus (match_dup 3) (pc)) (const_int 256)))
5441 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5442 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5447 (define_insn "*tstsi3_cbranch"
5450 (match_operator 3 "equality_operator"
5451 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5452 (match_operand:SI 1 "s_register_operand" "l"))
5454 (label_ref (match_operand 2 "" ""))
5459 output_asm_insn (\"tst\\t%0, %1\", operands);
5460 switch (get_attr_length (insn))
5462 case 4: return \"b%d3\\t%l2\";
5463 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5464 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5467 [(set (attr "far_jump")
5469 (eq_attr "length" "8")
5470 (const_string "yes")
5471 (const_string "no")))
5472 (set (attr "length")
5474 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5475 (le (minus (match_dup 2) (pc)) (const_int 256)))
5478 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5479 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5484 (define_insn "*andsi3_cbranch"
5487 (match_operator 5 "equality_operator"
5488 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5489 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5491 (label_ref (match_operand 4 "" ""))
5493 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5494 (and:SI (match_dup 2) (match_dup 3)))
5495 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5499 if (which_alternative == 0)
5500 output_asm_insn (\"and\\t%0, %3\", operands);
5501 else if (which_alternative == 1)
5503 output_asm_insn (\"and\\t%1, %3\", operands);
5504 output_asm_insn (\"mov\\t%0, %1\", operands);
5508 output_asm_insn (\"and\\t%1, %3\", operands);
5509 output_asm_insn (\"str\\t%1, %0\", operands);
5512 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5514 case 4: return \"b%d5\\t%l4\";
5515 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5516 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5519 [(set (attr "far_jump")
5521 (ior (and (eq (symbol_ref ("which_alternative"))
5523 (eq_attr "length" "8"))
5524 (eq_attr "length" "10"))
5525 (const_string "yes")
5526 (const_string "no")))
5527 (set (attr "length")
5529 (eq (symbol_ref ("which_alternative"))
5532 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5533 (le (minus (match_dup 4) (pc)) (const_int 256)))
5536 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5537 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5541 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5542 (le (minus (match_dup 4) (pc)) (const_int 256)))
5545 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5546 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5551 (define_insn "*orrsi3_cbranch_scratch"
5554 (match_operator 4 "equality_operator"
5555 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
5556 (match_operand:SI 2 "s_register_operand" "l"))
5558 (label_ref (match_operand 3 "" ""))
5560 (clobber (match_scratch:SI 0 "=l"))]
5564 output_asm_insn (\"orr\\t%0, %2\", operands);
5565 switch (get_attr_length (insn))
5567 case 4: return \"b%d4\\t%l3\";
5568 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5569 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5572 [(set (attr "far_jump")
5574 (eq_attr "length" "8")
5575 (const_string "yes")
5576 (const_string "no")))
5577 (set (attr "length")
5579 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5580 (le (minus (match_dup 3) (pc)) (const_int 256)))
5583 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5584 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5589 (define_insn "*orrsi3_cbranch"
5592 (match_operator 5 "equality_operator"
5593 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5594 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5596 (label_ref (match_operand 4 "" ""))
5598 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5599 (ior:SI (match_dup 2) (match_dup 3)))
5600 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5604 if (which_alternative == 0)
5605 output_asm_insn (\"orr\\t%0, %3\", operands);
5606 else if (which_alternative == 1)
5608 output_asm_insn (\"orr\\t%1, %3\", operands);
5609 output_asm_insn (\"mov\\t%0, %1\", operands);
5613 output_asm_insn (\"orr\\t%1, %3\", operands);
5614 output_asm_insn (\"str\\t%1, %0\", operands);
5617 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5619 case 4: return \"b%d5\\t%l4\";
5620 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5621 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5624 [(set (attr "far_jump")
5626 (ior (and (eq (symbol_ref ("which_alternative"))
5628 (eq_attr "length" "8"))
5629 (eq_attr "length" "10"))
5630 (const_string "yes")
5631 (const_string "no")))
5632 (set (attr "length")
5634 (eq (symbol_ref ("which_alternative"))
5637 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5638 (le (minus (match_dup 4) (pc)) (const_int 256)))
5641 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5642 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5646 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5647 (le (minus (match_dup 4) (pc)) (const_int 256)))
5650 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5651 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5656 (define_insn "*xorsi3_cbranch_scratch"
5659 (match_operator 4 "equality_operator"
5660 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
5661 (match_operand:SI 2 "s_register_operand" "l"))
5663 (label_ref (match_operand 3 "" ""))
5665 (clobber (match_scratch:SI 0 "=l"))]
5669 output_asm_insn (\"eor\\t%0, %2\", operands);
5670 switch (get_attr_length (insn))
5672 case 4: return \"b%d4\\t%l3\";
5673 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5674 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5677 [(set (attr "far_jump")
5679 (eq_attr "length" "8")
5680 (const_string "yes")
5681 (const_string "no")))
5682 (set (attr "length")
5684 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5685 (le (minus (match_dup 3) (pc)) (const_int 256)))
5688 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5689 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5694 (define_insn "*xorsi3_cbranch"
5697 (match_operator 5 "equality_operator"
5698 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5699 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5701 (label_ref (match_operand 4 "" ""))
5703 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5704 (xor:SI (match_dup 2) (match_dup 3)))
5705 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5709 if (which_alternative == 0)
5710 output_asm_insn (\"eor\\t%0, %3\", operands);
5711 else if (which_alternative == 1)
5713 output_asm_insn (\"eor\\t%1, %3\", operands);
5714 output_asm_insn (\"mov\\t%0, %1\", operands);
5718 output_asm_insn (\"eor\\t%1, %3\", operands);
5719 output_asm_insn (\"str\\t%1, %0\", operands);
5722 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5724 case 4: return \"b%d5\\t%l4\";
5725 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5726 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5729 [(set (attr "far_jump")
5731 (ior (and (eq (symbol_ref ("which_alternative"))
5733 (eq_attr "length" "8"))
5734 (eq_attr "length" "10"))
5735 (const_string "yes")
5736 (const_string "no")))
5737 (set (attr "length")
5739 (eq (symbol_ref ("which_alternative"))
5742 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5743 (le (minus (match_dup 4) (pc)) (const_int 256)))
5746 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5747 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5751 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5752 (le (minus (match_dup 4) (pc)) (const_int 256)))
5755 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5756 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5761 (define_insn "*bicsi3_cbranch_scratch"
5764 (match_operator 4 "equality_operator"
5765 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
5766 (match_operand:SI 1 "s_register_operand" "0"))
5768 (label_ref (match_operand 3 "" ""))
5770 (clobber (match_scratch:SI 0 "=l"))]
5774 output_asm_insn (\"bic\\t%0, %2\", operands);
5775 switch (get_attr_length (insn))
5777 case 4: return \"b%d4\\t%l3\";
5778 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5779 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5782 [(set (attr "far_jump")
5784 (eq_attr "length" "8")
5785 (const_string "yes")
5786 (const_string "no")))
5787 (set (attr "length")
5789 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5790 (le (minus (match_dup 3) (pc)) (const_int 256)))
5793 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5794 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5799 (define_insn "*bicsi3_cbranch"
5802 (match_operator 5 "equality_operator"
5803 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5804 (match_operand:SI 2 "s_register_operand" "0,1,1,1"))
5806 (label_ref (match_operand 4 "" ""))
5808 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5809 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
5810 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5814 if (which_alternative == 0)
5815 output_asm_insn (\"bic\\t%0, %3\", operands);
5816 else if (which_alternative == 1)
5818 output_asm_insn (\"bic\\t%1, %3\", operands);
5819 output_asm_insn (\"mov\\t%0, %1\", operands);
5823 output_asm_insn (\"bic\\t%1, %3\", operands);
5824 output_asm_insn (\"str\\t%1, %0\", operands);
5827 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5829 case 4: return \"b%d5\\t%l4\";
5830 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5831 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5834 [(set (attr "far_jump")
5836 (ior (and (eq (symbol_ref ("which_alternative"))
5838 (eq_attr "length" "8"))
5839 (eq_attr "length" "10"))
5840 (const_string "yes")
5841 (const_string "no")))
5842 (set (attr "length")
5844 (eq (symbol_ref ("which_alternative"))
5847 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5848 (le (minus (match_dup 4) (pc)) (const_int 256)))
5851 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5852 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5856 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5857 (le (minus (match_dup 4) (pc)) (const_int 256)))
5860 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5861 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5866 (define_insn "*cbranchne_decr1"
5868 (if_then_else (match_operator 3 "equality_operator"
5869 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
5871 (label_ref (match_operand 4 "" ""))
5873 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5874 (plus:SI (match_dup 2) (const_int -1)))
5875 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5880 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
5882 VOIDmode, operands[2], const1_rtx);
5883 cond[1] = operands[4];
5885 if (which_alternative == 0)
5886 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
5887 else if (which_alternative == 1)
5889 /* We must provide an alternative for a hi reg because reload
5890 cannot handle output reloads on a jump instruction, but we
5891 can't subtract into that. Fortunately a mov from lo to hi
5892 does not clobber the condition codes. */
5893 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
5894 output_asm_insn (\"mov\\t%0, %1\", operands);
5898 /* Similarly, but the target is memory. */
5899 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
5900 output_asm_insn (\"str\\t%1, %0\", operands);
5903 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5906 output_asm_insn (\"b%d0\\t%l1\", cond);
5909 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
5910 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
5912 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
5913 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5917 [(set (attr "far_jump")
5919 (ior (and (eq (symbol_ref ("which_alternative"))
5921 (eq_attr "length" "8"))
5922 (eq_attr "length" "10"))
5923 (const_string "yes")
5924 (const_string "no")))
5925 (set_attr_alternative "length"
5929 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5930 (le (minus (match_dup 4) (pc)) (const_int 256)))
5933 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5934 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5939 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5940 (le (minus (match_dup 4) (pc)) (const_int 256)))
5943 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5944 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5949 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5950 (le (minus (match_dup 4) (pc)) (const_int 256)))
5953 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5954 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5959 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5960 (le (minus (match_dup 4) (pc)) (const_int 256)))
5963 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5964 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5969 (define_insn "*addsi3_cbranch"
5972 (match_operator 4 "comparison_operator"
5974 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
5975 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
5977 (label_ref (match_operand 5 "" ""))
5980 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
5981 (plus:SI (match_dup 2) (match_dup 3)))
5982 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
5984 && (GET_CODE (operands[4]) == EQ
5985 || GET_CODE (operands[4]) == NE
5986 || GET_CODE (operands[4]) == GE
5987 || GET_CODE (operands[4]) == LT)"
5993 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
5994 cond[1] = operands[2];
5995 cond[2] = operands[3];
5997 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
5998 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6000 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6002 if (which_alternative >= 3
6003 && which_alternative < 4)
6004 output_asm_insn (\"mov\\t%0, %1\", operands);
6005 else if (which_alternative >= 4)
6006 output_asm_insn (\"str\\t%1, %0\", operands);
6008 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6011 return \"b%d4\\t%l5\";
6013 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6015 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6019 [(set (attr "far_jump")
6021 (ior (and (lt (symbol_ref ("which_alternative"))
6023 (eq_attr "length" "8"))
6024 (eq_attr "length" "10"))
6025 (const_string "yes")
6026 (const_string "no")))
6027 (set (attr "length")
6029 (lt (symbol_ref ("which_alternative"))
6032 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6033 (le (minus (match_dup 5) (pc)) (const_int 256)))
6036 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6037 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6041 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6042 (le (minus (match_dup 5) (pc)) (const_int 256)))
6045 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6046 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6051 (define_insn "*addsi3_cbranch_scratch"
6054 (match_operator 3 "comparison_operator"
6056 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6057 (match_operand:SI 2 "reg_or_int_operand" "J,l,I,L"))
6059 (label_ref (match_operand 4 "" ""))
6061 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6063 && (GET_CODE (operands[3]) == EQ
6064 || GET_CODE (operands[3]) == NE
6065 || GET_CODE (operands[3]) == GE
6066 || GET_CODE (operands[3]) == LT)"
6069 switch (which_alternative)
6072 output_asm_insn (\"cmp\t%1, #%n2\", operands);
6075 output_asm_insn (\"cmn\t%1, %2\", operands);
6078 output_asm_insn (\"add\t%0, %1, %2\", operands);
6081 output_asm_insn (\"add\t%0, %0, %2\", operands);
6085 switch (get_attr_length (insn))
6088 return \"b%d3\\t%l4\";
6090 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6092 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6096 [(set (attr "far_jump")
6098 (eq_attr "length" "8")
6099 (const_string "yes")
6100 (const_string "no")))
6101 (set (attr "length")
6103 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6104 (le (minus (match_dup 4) (pc)) (const_int 256)))
6107 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6108 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6113 (define_insn "*subsi3_cbranch"
6116 (match_operator 4 "comparison_operator"
6118 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6119 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6121 (label_ref (match_operand 5 "" ""))
6123 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6124 (minus:SI (match_dup 2) (match_dup 3)))
6125 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6127 && (GET_CODE (operands[4]) == EQ
6128 || GET_CODE (operands[4]) == NE
6129 || GET_CODE (operands[4]) == GE
6130 || GET_CODE (operands[4]) == LT)"
6133 if (which_alternative == 0)
6134 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6135 else if (which_alternative == 1)
6137 /* We must provide an alternative for a hi reg because reload
6138 cannot handle output reloads on a jump instruction, but we
6139 can't subtract into that. Fortunately a mov from lo to hi
6140 does not clobber the condition codes. */
6141 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6142 output_asm_insn (\"mov\\t%0, %1\", operands);
6146 /* Similarly, but the target is memory. */
6147 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6148 output_asm_insn (\"str\\t%1, %0\", operands);
6151 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6154 return \"b%d4\\t%l5\";
6156 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6158 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6162 [(set (attr "far_jump")
6164 (ior (and (eq (symbol_ref ("which_alternative"))
6166 (eq_attr "length" "8"))
6167 (eq_attr "length" "10"))
6168 (const_string "yes")
6169 (const_string "no")))
6170 (set (attr "length")
6172 (eq (symbol_ref ("which_alternative"))
6175 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6176 (le (minus (match_dup 5) (pc)) (const_int 256)))
6179 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6180 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6184 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6185 (le (minus (match_dup 5) (pc)) (const_int 256)))
6188 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6189 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6194 (define_insn "*subsi3_cbranch_scratch"
6197 (match_operator 0 "arm_comparison_operator"
6198 [(minus:SI (match_operand:SI 1 "register_operand" "l")
6199 (match_operand:SI 2 "nonmemory_operand" "l"))
6201 (label_ref (match_operand 3 "" ""))
6204 && (GET_CODE (operands[0]) == EQ
6205 || GET_CODE (operands[0]) == NE
6206 || GET_CODE (operands[0]) == GE
6207 || GET_CODE (operands[0]) == LT)"
6209 output_asm_insn (\"cmp\\t%1, %2\", operands);
6210 switch (get_attr_length (insn))
6212 case 4: return \"b%d0\\t%l3\";
6213 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6214 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6217 [(set (attr "far_jump")
6219 (eq_attr "length" "8")
6220 (const_string "yes")
6221 (const_string "no")))
6222 (set (attr "length")
6224 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6225 (le (minus (match_dup 3) (pc)) (const_int 256)))
6228 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6229 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6234 ;; Comparison and test insns
6236 (define_expand "cmpsi"
6237 [(match_operand:SI 0 "s_register_operand" "")
6238 (match_operand:SI 1 "arm_add_operand" "")]
6241 arm_compare_op0 = operands[0];
6242 arm_compare_op1 = operands[1];
6247 (define_expand "cmpsf"
6248 [(match_operand:SF 0 "s_register_operand" "")
6249 (match_operand:SF 1 "fpa_rhs_operand" "")]
6250 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
6252 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
6253 operands[1] = force_reg (SFmode, operands[1]);
6255 arm_compare_op0 = operands[0];
6256 arm_compare_op1 = operands[1];
6261 (define_expand "cmpdf"
6262 [(match_operand:DF 0 "s_register_operand" "")
6263 (match_operand:DF 1 "fpa_rhs_operand" "")]
6264 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
6266 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
6267 operands[1] = force_reg (DFmode, operands[1]);
6269 arm_compare_op0 = operands[0];
6270 arm_compare_op1 = operands[1];
6275 (define_insn "*arm_cmpsi_insn"
6276 [(set (reg:CC CC_REGNUM)
6277 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6278 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
6283 [(set_attr "conds" "set")]
6286 (define_insn "*cmpsi_shiftsi"
6287 [(set (reg:CC CC_REGNUM)
6288 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6289 (match_operator:SI 3 "shift_operator"
6290 [(match_operand:SI 1 "s_register_operand" "r")
6291 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
6294 [(set_attr "conds" "set")
6295 (set_attr "shift" "1")
6299 (define_insn "*cmpsi_shiftsi_swp"
6300 [(set (reg:CC_SWP CC_REGNUM)
6301 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6302 [(match_operand:SI 1 "s_register_operand" "r")
6303 (match_operand:SI 2 "reg_or_int_operand" "rM")])
6304 (match_operand:SI 0 "s_register_operand" "r")))]
6307 [(set_attr "conds" "set")
6308 (set_attr "shift" "1")
6312 (define_insn "*cmpsi_neg_shiftsi"
6313 [(set (reg:CC CC_REGNUM)
6314 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6315 (neg:SI (match_operator:SI 3 "shift_operator"
6316 [(match_operand:SI 1 "s_register_operand" "r")
6317 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
6320 [(set_attr "conds" "set")
6321 (set_attr "shift" "1")
6325 ;; Cirrus SF compare instruction
6326 (define_insn "*cirrus_cmpsf"
6327 [(set (reg:CCFP CC_REGNUM)
6328 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6329 (match_operand:SF 1 "cirrus_fp_register" "v")))]
6330 "TARGET_ARM && TARGET_CIRRUS"
6331 "cfcmps%?\\tr15, %V0, %V1"
6332 [(set_attr "type" "mav_farith")
6333 (set_attr "cirrus" "compare")]
6336 ;; Cirrus DF compare instruction
6337 (define_insn "*cirrus_cmpdf"
6338 [(set (reg:CCFP CC_REGNUM)
6339 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6340 (match_operand:DF 1 "cirrus_fp_register" "v")))]
6341 "TARGET_ARM && TARGET_CIRRUS"
6342 "cfcmpd%?\\tr15, %V0, %V1"
6343 [(set_attr "type" "mav_farith")
6344 (set_attr "cirrus" "compare")]
6347 ;; Cirrus DI compare instruction
6348 (define_expand "cmpdi"
6349 [(match_operand:DI 0 "cirrus_fp_register" "")
6350 (match_operand:DI 1 "cirrus_fp_register" "")]
6351 "TARGET_ARM && TARGET_CIRRUS"
6353 arm_compare_op0 = operands[0];
6354 arm_compare_op1 = operands[1];
6358 (define_insn "*cirrus_cmpdi"
6359 [(set (reg:CC CC_REGNUM)
6360 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6361 (match_operand:DI 1 "cirrus_fp_register" "v")))]
6362 "TARGET_ARM && TARGET_CIRRUS"
6363 "cfcmp64%?\\tr15, %V0, %V1"
6364 [(set_attr "type" "mav_farith")
6365 (set_attr "cirrus" "compare")]
6368 ; This insn allows redundant compares to be removed by cse, nothing should
6369 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6370 ; is deleted later on. The match_dup will match the mode here, so that
6371 ; mode changes of the condition codes aren't lost by this even though we don't
6372 ; specify what they are.
6374 (define_insn "*deleted_compare"
6375 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6377 "\\t%@ deleted compare"
6378 [(set_attr "conds" "set")
6379 (set_attr "length" "0")]
6383 ;; Conditional branch insns
6385 (define_expand "beq"
6387 (if_then_else (eq (match_dup 1) (const_int 0))
6388 (label_ref (match_operand 0 "" ""))
6391 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6394 (define_expand "bne"
6396 (if_then_else (ne (match_dup 1) (const_int 0))
6397 (label_ref (match_operand 0 "" ""))
6400 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6403 (define_expand "bgt"
6405 (if_then_else (gt (match_dup 1) (const_int 0))
6406 (label_ref (match_operand 0 "" ""))
6409 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6412 (define_expand "ble"
6414 (if_then_else (le (match_dup 1) (const_int 0))
6415 (label_ref (match_operand 0 "" ""))
6418 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6421 (define_expand "bge"
6423 (if_then_else (ge (match_dup 1) (const_int 0))
6424 (label_ref (match_operand 0 "" ""))
6427 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6430 (define_expand "blt"
6432 (if_then_else (lt (match_dup 1) (const_int 0))
6433 (label_ref (match_operand 0 "" ""))
6436 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6439 (define_expand "bgtu"
6441 (if_then_else (gtu (match_dup 1) (const_int 0))
6442 (label_ref (match_operand 0 "" ""))
6445 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6448 (define_expand "bleu"
6450 (if_then_else (leu (match_dup 1) (const_int 0))
6451 (label_ref (match_operand 0 "" ""))
6454 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6457 (define_expand "bgeu"
6459 (if_then_else (geu (match_dup 1) (const_int 0))
6460 (label_ref (match_operand 0 "" ""))
6463 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6466 (define_expand "bltu"
6468 (if_then_else (ltu (match_dup 1) (const_int 0))
6469 (label_ref (match_operand 0 "" ""))
6472 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6475 (define_expand "bunordered"
6477 (if_then_else (unordered (match_dup 1) (const_int 0))
6478 (label_ref (match_operand 0 "" ""))
6480 "TARGET_ARM && TARGET_HARD_FLOAT"
6481 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6485 (define_expand "bordered"
6487 (if_then_else (ordered (match_dup 1) (const_int 0))
6488 (label_ref (match_operand 0 "" ""))
6490 "TARGET_ARM && TARGET_HARD_FLOAT"
6491 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6495 (define_expand "bungt"
6497 (if_then_else (ungt (match_dup 1) (const_int 0))
6498 (label_ref (match_operand 0 "" ""))
6500 "TARGET_ARM && TARGET_HARD_FLOAT"
6501 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6504 (define_expand "bunlt"
6506 (if_then_else (unlt (match_dup 1) (const_int 0))
6507 (label_ref (match_operand 0 "" ""))
6509 "TARGET_ARM && TARGET_HARD_FLOAT"
6510 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6513 (define_expand "bunge"
6515 (if_then_else (unge (match_dup 1) (const_int 0))
6516 (label_ref (match_operand 0 "" ""))
6518 "TARGET_ARM && TARGET_HARD_FLOAT"
6519 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6522 (define_expand "bunle"
6524 (if_then_else (unle (match_dup 1) (const_int 0))
6525 (label_ref (match_operand 0 "" ""))
6527 "TARGET_ARM && TARGET_HARD_FLOAT"
6528 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6531 ;; The following two patterns need two branch instructions, since there is
6532 ;; no single instruction that will handle all cases.
6533 (define_expand "buneq"
6535 (if_then_else (uneq (match_dup 1) (const_int 0))
6536 (label_ref (match_operand 0 "" ""))
6538 "TARGET_ARM && TARGET_HARD_FLOAT"
6539 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6542 (define_expand "bltgt"
6544 (if_then_else (ltgt (match_dup 1) (const_int 0))
6545 (label_ref (match_operand 0 "" ""))
6547 "TARGET_ARM && TARGET_HARD_FLOAT"
6548 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6552 ;; Patterns to match conditional branch insns.
6555 ; Special pattern to match UNEQ.
6556 (define_insn "*arm_buneq"
6558 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6559 (label_ref (match_operand 0 "" ""))
6561 "TARGET_ARM && TARGET_HARD_FLOAT"
6563 if (arm_ccfsm_state != 0)
6566 return \"bvs\\t%l0\;beq\\t%l0\";
6568 [(set_attr "conds" "jump_clob")
6569 (set_attr "length" "8")]
6572 ; Special pattern to match LTGT.
6573 (define_insn "*arm_bltgt"
6575 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6576 (label_ref (match_operand 0 "" ""))
6578 "TARGET_ARM && TARGET_HARD_FLOAT"
6580 if (arm_ccfsm_state != 0)
6583 return \"bmi\\t%l0\;bgt\\t%l0\";
6585 [(set_attr "conds" "jump_clob")
6586 (set_attr "length" "8")]
6589 (define_insn "*arm_cond_branch"
6591 (if_then_else (match_operator 1 "arm_comparison_operator"
6592 [(match_operand 2 "cc_register" "") (const_int 0)])
6593 (label_ref (match_operand 0 "" ""))
6597 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6599 arm_ccfsm_state += 2;
6602 return \"b%d1\\t%l0\";
6604 [(set_attr "conds" "use")]
6607 ; Special pattern to match reversed UNEQ.
6608 (define_insn "*arm_buneq_reversed"
6610 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6612 (label_ref (match_operand 0 "" ""))))]
6613 "TARGET_ARM && TARGET_HARD_FLOAT"
6615 if (arm_ccfsm_state != 0)
6618 return \"bmi\\t%l0\;bgt\\t%l0\";
6620 [(set_attr "conds" "jump_clob")
6621 (set_attr "length" "8")]
6624 ; Special pattern to match reversed LTGT.
6625 (define_insn "*arm_bltgt_reversed"
6627 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6629 (label_ref (match_operand 0 "" ""))))]
6630 "TARGET_ARM && TARGET_HARD_FLOAT"
6632 if (arm_ccfsm_state != 0)
6635 return \"bvs\\t%l0\;beq\\t%l0\";
6637 [(set_attr "conds" "jump_clob")
6638 (set_attr "length" "8")]
6641 (define_insn "*arm_cond_branch_reversed"
6643 (if_then_else (match_operator 1 "arm_comparison_operator"
6644 [(match_operand 2 "cc_register" "") (const_int 0)])
6646 (label_ref (match_operand 0 "" ""))))]
6649 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6651 arm_ccfsm_state += 2;
6654 return \"b%D1\\t%l0\";
6656 [(set_attr "conds" "use")]
6663 (define_expand "seq"
6664 [(set (match_operand:SI 0 "s_register_operand" "")
6665 (eq:SI (match_dup 1) (const_int 0)))]
6667 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6670 (define_expand "sne"
6671 [(set (match_operand:SI 0 "s_register_operand" "")
6672 (ne:SI (match_dup 1) (const_int 0)))]
6674 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6677 (define_expand "sgt"
6678 [(set (match_operand:SI 0 "s_register_operand" "")
6679 (gt:SI (match_dup 1) (const_int 0)))]
6681 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6684 (define_expand "sle"
6685 [(set (match_operand:SI 0 "s_register_operand" "")
6686 (le:SI (match_dup 1) (const_int 0)))]
6688 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6691 (define_expand "sge"
6692 [(set (match_operand:SI 0 "s_register_operand" "")
6693 (ge:SI (match_dup 1) (const_int 0)))]
6695 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6698 (define_expand "slt"
6699 [(set (match_operand:SI 0 "s_register_operand" "")
6700 (lt:SI (match_dup 1) (const_int 0)))]
6702 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6705 (define_expand "sgtu"
6706 [(set (match_operand:SI 0 "s_register_operand" "")
6707 (gtu:SI (match_dup 1) (const_int 0)))]
6709 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6712 (define_expand "sleu"
6713 [(set (match_operand:SI 0 "s_register_operand" "")
6714 (leu:SI (match_dup 1) (const_int 0)))]
6716 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6719 (define_expand "sgeu"
6720 [(set (match_operand:SI 0 "s_register_operand" "")
6721 (geu:SI (match_dup 1) (const_int 0)))]
6723 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6726 (define_expand "sltu"
6727 [(set (match_operand:SI 0 "s_register_operand" "")
6728 (ltu:SI (match_dup 1) (const_int 0)))]
6730 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6733 (define_expand "sunordered"
6734 [(set (match_operand:SI 0 "s_register_operand" "")
6735 (unordered:SI (match_dup 1) (const_int 0)))]
6736 "TARGET_ARM && TARGET_HARD_FLOAT"
6737 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6741 (define_expand "sordered"
6742 [(set (match_operand:SI 0 "s_register_operand" "")
6743 (ordered:SI (match_dup 1) (const_int 0)))]
6744 "TARGET_ARM && TARGET_HARD_FLOAT"
6745 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6749 (define_expand "sungt"
6750 [(set (match_operand:SI 0 "s_register_operand" "")
6751 (ungt:SI (match_dup 1) (const_int 0)))]
6752 "TARGET_ARM && TARGET_HARD_FLOAT"
6753 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6757 (define_expand "sunge"
6758 [(set (match_operand:SI 0 "s_register_operand" "")
6759 (unge:SI (match_dup 1) (const_int 0)))]
6760 "TARGET_ARM && TARGET_HARD_FLOAT"
6761 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6765 (define_expand "sunlt"
6766 [(set (match_operand:SI 0 "s_register_operand" "")
6767 (unlt:SI (match_dup 1) (const_int 0)))]
6768 "TARGET_ARM && TARGET_HARD_FLOAT"
6769 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6773 (define_expand "sunle"
6774 [(set (match_operand:SI 0 "s_register_operand" "")
6775 (unle:SI (match_dup 1) (const_int 0)))]
6776 "TARGET_ARM && TARGET_HARD_FLOAT"
6777 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6781 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6782 ;;; simple ARM instructions.
6784 ; (define_expand "suneq"
6785 ; [(set (match_operand:SI 0 "s_register_operand" "")
6786 ; (uneq:SI (match_dup 1) (const_int 0)))]
6787 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6791 ; (define_expand "sltgt"
6792 ; [(set (match_operand:SI 0 "s_register_operand" "")
6793 ; (ltgt:SI (match_dup 1) (const_int 0)))]
6794 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6798 (define_insn "*mov_scc"
6799 [(set (match_operand:SI 0 "s_register_operand" "=r")
6800 (match_operator:SI 1 "arm_comparison_operator"
6801 [(match_operand 2 "cc_register" "") (const_int 0)]))]
6803 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6804 [(set_attr "conds" "use")
6805 (set_attr "length" "8")]
6808 (define_insn "*mov_negscc"
6809 [(set (match_operand:SI 0 "s_register_operand" "=r")
6810 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
6811 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6813 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6814 [(set_attr "conds" "use")
6815 (set_attr "length" "8")]
6818 (define_insn "*mov_notscc"
6819 [(set (match_operand:SI 0 "s_register_operand" "=r")
6820 (not:SI (match_operator:SI 1 "arm_comparison_operator"
6821 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6823 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6824 [(set_attr "conds" "use")
6825 (set_attr "length" "8")]
6829 ;; Conditional move insns
6831 (define_expand "movsicc"
6832 [(set (match_operand:SI 0 "s_register_operand" "")
6833 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6834 (match_operand:SI 2 "arm_not_operand" "")
6835 (match_operand:SI 3 "arm_not_operand" "")))]
6839 enum rtx_code code = GET_CODE (operands[1]);
6842 if (code == UNEQ || code == LTGT)
6845 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6846 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6850 (define_expand "movsfcc"
6851 [(set (match_operand:SF 0 "s_register_operand" "")
6852 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6853 (match_operand:SF 2 "s_register_operand" "")
6854 (match_operand:SF 3 "nonmemory_operand" "")))]
6858 enum rtx_code code = GET_CODE (operands[1]);
6861 if (code == UNEQ || code == LTGT)
6864 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
6865 Otherwise, ensure it is a valid FP add operand */
6866 if ((!TARGET_HARD_FLOAT)
6867 || (!fpa_add_operand (operands[3], SFmode)))
6868 operands[3] = force_reg (SFmode, operands[3]);
6870 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6871 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6875 (define_expand "movdfcc"
6876 [(set (match_operand:DF 0 "s_register_operand" "")
6877 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6878 (match_operand:DF 2 "s_register_operand" "")
6879 (match_operand:DF 3 "fpa_add_operand" "")))]
6880 "TARGET_ARM && TARGET_HARD_FLOAT"
6883 enum rtx_code code = GET_CODE (operands[1]);
6886 if (code == UNEQ || code == LTGT)
6889 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6890 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6894 (define_insn "*movsicc_insn"
6895 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6897 (match_operator 3 "arm_comparison_operator"
6898 [(match_operand 4 "cc_register" "") (const_int 0)])
6899 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6900 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6907 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6908 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6909 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6910 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6911 [(set_attr "length" "4,4,4,4,8,8,8,8")
6912 (set_attr "conds" "use")]
6915 (define_insn "*movsfcc_soft_insn"
6916 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6917 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
6918 [(match_operand 4 "cc_register" "") (const_int 0)])
6919 (match_operand:SF 1 "s_register_operand" "0,r")
6920 (match_operand:SF 2 "s_register_operand" "r,0")))]
6921 "TARGET_ARM && TARGET_SOFT_FLOAT"
6925 [(set_attr "conds" "use")]
6929 ;; Jump and linkage insns
6931 (define_expand "jump"
6933 (label_ref (match_operand 0 "" "")))]
6938 (define_insn "*arm_jump"
6940 (label_ref (match_operand 0 "" "")))]
6944 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6946 arm_ccfsm_state += 2;
6949 return \"b%?\\t%l0\";
6952 [(set_attr "predicable" "yes")]
6955 (define_insn "*thumb_jump"
6957 (label_ref (match_operand 0 "" "")))]
6960 if (get_attr_length (insn) == 2)
6962 return \"bl\\t%l0\\t%@ far jump\";
6964 [(set (attr "far_jump")
6966 (eq_attr "length" "4")
6967 (const_string "yes")
6968 (const_string "no")))
6969 (set (attr "length")
6971 (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6972 (le (minus (match_dup 0) (pc)) (const_int 2044)))
6977 (define_expand "call"
6978 [(parallel [(call (match_operand 0 "memory_operand" "")
6979 (match_operand 1 "general_operand" ""))
6980 (use (match_operand 2 "" ""))
6981 (clobber (reg:SI LR_REGNUM))])]
6987 /* In an untyped call, we can get NULL for operand 2. */
6988 if (operands[2] == NULL_RTX)
6989 operands[2] = const0_rtx;
6991 /* This is to decide if we should generate indirect calls by loading the
6992 32 bit address of the callee into a register before performing the
6993 branch and link. operand[2] encodes the long_call/short_call
6994 attribute of the function being called. This attribute is set whenever
6995 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6996 is used, and the short_call attribute can also be set if function is
6997 declared as static or if it has already been defined in the current
6998 compilation unit. See arm.c and arm.h for info about this. The third
6999 parameter to arm_is_longcall_p is used to tell it which pattern
7001 callee = XEXP (operands[0], 0);
7003 if (GET_CODE (callee) != REG
7004 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7005 XEXP (operands[0], 0) = force_reg (Pmode, callee);
7009 (define_insn "*call_reg"
7010 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7011 (match_operand 1 "" ""))
7012 (use (match_operand 2 "" ""))
7013 (clobber (reg:SI LR_REGNUM))]
7016 return output_call (operands);
7018 ;; length is worst case, normally it is only two
7019 [(set_attr "length" "12")
7020 (set_attr "type" "call")]
7023 (define_insn "*call_mem"
7024 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7025 (match_operand 1 "" ""))
7026 (use (match_operand 2 "" ""))
7027 (clobber (reg:SI LR_REGNUM))]
7030 return output_call_mem (operands);
7032 [(set_attr "length" "12")
7033 (set_attr "type" "call")]
7036 (define_insn "*call_indirect"
7037 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7038 (match_operand 1 "" ""))
7039 (use (match_operand 2 "" ""))
7040 (clobber (reg:SI LR_REGNUM))]
7044 if (TARGET_CALLER_INTERWORKING)
7045 return \"bl\\t%__interwork_call_via_%0\";
7047 return \"bl\\t%__call_via_%0\";
7049 [(set_attr "type" "call")]
7052 (define_insn "*call_value_indirect"
7053 [(set (match_operand 0 "" "")
7054 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7055 (match_operand 2 "" "")))
7056 (use (match_operand 3 "" ""))
7057 (clobber (reg:SI LR_REGNUM))]
7061 if (TARGET_CALLER_INTERWORKING)
7062 return \"bl\\t%__interwork_call_via_%1\";
7064 return \"bl\\t%__call_via_%1\";
7066 [(set_attr "type" "call")]
7069 (define_expand "call_value"
7070 [(parallel [(set (match_operand 0 "" "")
7071 (call (match_operand 1 "memory_operand" "")
7072 (match_operand 2 "general_operand" "")))
7073 (use (match_operand 3 "" ""))
7074 (clobber (reg:SI LR_REGNUM))])]
7078 rtx callee = XEXP (operands[1], 0);
7080 /* In an untyped call, we can get NULL for operand 2. */
7081 if (operands[3] == 0)
7082 operands[3] = const0_rtx;
7084 /* See the comment in define_expand \"call\". */
7085 if (GET_CODE (callee) != REG
7086 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7087 XEXP (operands[1], 0) = force_reg (Pmode, callee);
7091 (define_insn "*call_value_reg"
7092 [(set (match_operand 0 "" "")
7093 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7094 (match_operand 2 "" "")))
7095 (use (match_operand 3 "" ""))
7096 (clobber (reg:SI LR_REGNUM))]
7099 return output_call (&operands[1]);
7101 [(set_attr "length" "12")
7102 (set_attr "type" "call")]
7105 (define_insn "*call_value_mem"
7106 [(set (match_operand 0 "" "")
7107 (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7108 (match_operand 2 "" "")))
7109 (use (match_operand 3 "" ""))
7110 (clobber (reg:SI LR_REGNUM))]
7111 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7113 return output_call_mem (&operands[1]);
7115 [(set_attr "length" "12")
7116 (set_attr "type" "call")]
7119 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7120 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7122 (define_insn "*call_symbol"
7123 [(call (mem:SI (match_operand:SI 0 "" ""))
7124 (match_operand 1 "" ""))
7125 (use (match_operand 2 "" ""))
7126 (clobber (reg:SI LR_REGNUM))]
7128 && (GET_CODE (operands[0]) == SYMBOL_REF)
7129 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7132 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7134 [(set_attr "type" "call")]
7137 (define_insn "*call_value_symbol"
7138 [(set (match_operand 0 "s_register_operand" "")
7139 (call (mem:SI (match_operand:SI 1 "" ""))
7140 (match_operand:SI 2 "" "")))
7141 (use (match_operand 3 "" ""))
7142 (clobber (reg:SI LR_REGNUM))]
7144 && (GET_CODE (operands[1]) == SYMBOL_REF)
7145 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7148 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7150 [(set_attr "type" "call")]
7153 (define_insn "*call_insn"
7154 [(call (mem:SI (match_operand:SI 0 "" ""))
7155 (match_operand:SI 1 "" ""))
7156 (use (match_operand 2 "" ""))
7157 (clobber (reg:SI LR_REGNUM))]
7159 && GET_CODE (operands[0]) == SYMBOL_REF
7160 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7162 [(set_attr "length" "4")
7163 (set_attr "type" "call")]
7166 (define_insn "*call_value_insn"
7167 [(set (match_operand 0 "register_operand" "")
7168 (call (mem:SI (match_operand 1 "" ""))
7169 (match_operand 2 "" "")))
7170 (use (match_operand 3 "" ""))
7171 (clobber (reg:SI LR_REGNUM))]
7173 && GET_CODE (operands[1]) == SYMBOL_REF
7174 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7176 [(set_attr "length" "4")
7177 (set_attr "type" "call")]
7180 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7181 (define_expand "sibcall"
7182 [(parallel [(call (match_operand 0 "memory_operand" "")
7183 (match_operand 1 "general_operand" ""))
7185 (use (match_operand 2 "" ""))])]
7189 if (operands[2] == NULL_RTX)
7190 operands[2] = const0_rtx;
7194 (define_expand "sibcall_value"
7195 [(parallel [(set (match_operand 0 "register_operand" "")
7196 (call (match_operand 1 "memory_operand" "")
7197 (match_operand 2 "general_operand" "")))
7199 (use (match_operand 3 "" ""))])]
7203 if (operands[3] == NULL_RTX)
7204 operands[3] = const0_rtx;
7208 (define_insn "*sibcall_insn"
7209 [(call (mem:SI (match_operand:SI 0 "" "X"))
7210 (match_operand 1 "" ""))
7212 (use (match_operand 2 "" ""))]
7213 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7215 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7217 [(set_attr "type" "call")]
7220 (define_insn "*sibcall_value_insn"
7221 [(set (match_operand 0 "s_register_operand" "")
7222 (call (mem:SI (match_operand:SI 1 "" "X"))
7223 (match_operand 2 "" "")))
7225 (use (match_operand 3 "" ""))]
7226 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7228 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7230 [(set_attr "type" "call")]
7233 ;; Often the return insn will be the same as loading from memory, so set attr
7234 (define_insn "return"
7236 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7239 if (arm_ccfsm_state == 2)
7241 arm_ccfsm_state += 2;
7244 return output_return_instruction (const_true_rtx, TRUE, FALSE);
7246 [(set_attr "type" "load")
7247 (set_attr "length" "12")
7248 (set_attr "predicable" "yes")]
7251 (define_insn "*cond_return"
7253 (if_then_else (match_operator 0 "arm_comparison_operator"
7254 [(match_operand 1 "cc_register" "") (const_int 0)])
7257 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7260 if (arm_ccfsm_state == 2)
7262 arm_ccfsm_state += 2;
7265 return output_return_instruction (operands[0], TRUE, FALSE);
7267 [(set_attr "conds" "use")
7268 (set_attr "length" "12")
7269 (set_attr "type" "load")]
7272 (define_insn "*cond_return_inverted"
7274 (if_then_else (match_operator 0 "arm_comparison_operator"
7275 [(match_operand 1 "cc_register" "") (const_int 0)])
7278 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7281 if (arm_ccfsm_state == 2)
7283 arm_ccfsm_state += 2;
7286 return output_return_instruction (operands[0], TRUE, TRUE);
7288 [(set_attr "conds" "use")
7289 (set_attr "type" "load")]
7292 ;; Generate a sequence of instructions to determine if the processor is
7293 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7296 (define_expand "return_addr_mask"
7298 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7300 (set (match_operand:SI 0 "s_register_operand" "")
7301 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7303 (const_int 67108860)))] ; 0x03fffffc
7306 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7309 (define_insn "*check_arch2"
7310 [(set (match_operand:CC_NOOV 0 "cc_register" "")
7311 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7314 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7315 [(set_attr "length" "8")
7316 (set_attr "conds" "set")]
7319 ;; Call subroutine returning any type.
7321 (define_expand "untyped_call"
7322 [(parallel [(call (match_operand 0 "" "")
7324 (match_operand 1 "" "")
7325 (match_operand 2 "" "")])]
7331 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
7333 for (i = 0; i < XVECLEN (operands[2], 0); i++)
7335 rtx set = XVECEXP (operands[2], 0, i);
7337 emit_move_insn (SET_DEST (set), SET_SRC (set));
7340 /* The optimizer does not know that the call sets the function value
7341 registers we stored in the result block. We avoid problems by
7342 claiming that all hard registers are used and clobbered at this
7344 emit_insn (gen_blockage ());
7350 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7351 ;; all of memory. This blocks insns from being moved across this point.
7353 (define_insn "blockage"
7354 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7357 [(set_attr "length" "0")
7358 (set_attr "type" "block")]
7361 (define_expand "casesi"
7362 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
7363 (match_operand:SI 1 "const_int_operand" "") ; lower bound
7364 (match_operand:SI 2 "const_int_operand" "") ; total range
7365 (match_operand:SI 3 "" "") ; table label
7366 (match_operand:SI 4 "" "")] ; Out of range label
7371 if (operands[1] != const0_rtx)
7373 reg = gen_reg_rtx (SImode);
7375 emit_insn (gen_addsi3 (reg, operands[0],
7376 GEN_INT (-INTVAL (operands[1]))));
7380 if (!const_ok_for_arm (INTVAL (operands[2])))
7381 operands[2] = force_reg (SImode, operands[2]);
7383 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7389 ;; The USE in this pattern is needed to tell flow analysis that this is
7390 ;; a CASESI insn. It has no other purpose.
7391 (define_insn "casesi_internal"
7392 [(parallel [(set (pc)
7394 (leu (match_operand:SI 0 "s_register_operand" "r")
7395 (match_operand:SI 1 "arm_rhs_operand" "rI"))
7396 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7397 (label_ref (match_operand 2 "" ""))))
7398 (label_ref (match_operand 3 "" ""))))
7399 (clobber (reg:CC CC_REGNUM))
7400 (use (label_ref (match_dup 2)))])]
7404 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
7405 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
7407 [(set_attr "conds" "clob")
7408 (set_attr "length" "12")]
7411 (define_expand "indirect_jump"
7413 (match_operand:SI 0 "s_register_operand" ""))]
7418 (define_insn "*arm_indirect_jump"
7420 (match_operand:SI 0 "s_register_operand" "r"))]
7422 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
7423 [(set_attr "predicable" "yes")]
7426 ;; Although not supported by the define_expand above,
7427 ;; cse/combine may generate this form.
7428 (define_insn "*load_indirect_jump"
7430 (match_operand:SI 0 "memory_operand" "m"))]
7432 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
7433 [(set_attr "type" "load")
7434 (set_attr "pool_range" "4096")
7435 (set_attr "neg_pool_range" "4084")
7436 (set_attr "predicable" "yes")]
7439 (define_insn "*thumb_indirect_jump"
7441 (match_operand:SI 0 "register_operand" "l*r"))]
7444 [(set_attr "conds" "clob")
7445 (set_attr "length" "2")]
7456 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
7457 return \"mov\\tr8, r8\";
7459 [(set (attr "length")
7460 (if_then_else (eq_attr "is_thumb" "yes")
7466 ;; Patterns to allow combination of arithmetic, cond code and shifts
7468 (define_insn "*arith_shiftsi"
7469 [(set (match_operand:SI 0 "s_register_operand" "=r")
7470 (match_operator:SI 1 "shiftable_operator"
7471 [(match_operator:SI 3 "shift_operator"
7472 [(match_operand:SI 4 "s_register_operand" "r")
7473 (match_operand:SI 5 "reg_or_int_operand" "rI")])
7474 (match_operand:SI 2 "s_register_operand" "r")]))]
7476 "%i1%?\\t%0, %2, %4%S3"
7477 [(set_attr "predicable" "yes")
7478 (set_attr "shift" "4")
7482 (define_insn "*arith_shiftsi_compare0"
7483 [(set (reg:CC_NOOV CC_REGNUM)
7484 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7485 [(match_operator:SI 3 "shift_operator"
7486 [(match_operand:SI 4 "s_register_operand" "r")
7487 (match_operand:SI 5 "reg_or_int_operand" "rI")])
7488 (match_operand:SI 2 "s_register_operand" "r")])
7490 (set (match_operand:SI 0 "s_register_operand" "=r")
7491 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7494 "%i1%?s\\t%0, %2, %4%S3"
7495 [(set_attr "conds" "set")
7496 (set_attr "shift" "4")
7500 (define_insn "*arith_shiftsi_compare0_scratch"
7501 [(set (reg:CC_NOOV CC_REGNUM)
7502 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7503 [(match_operator:SI 3 "shift_operator"
7504 [(match_operand:SI 4 "s_register_operand" "r")
7505 (match_operand:SI 5 "reg_or_int_operand" "rI")])
7506 (match_operand:SI 2 "s_register_operand" "r")])
7508 (clobber (match_scratch:SI 0 "=r"))]
7510 "%i1%?s\\t%0, %2, %4%S3"
7511 [(set_attr "conds" "set")
7512 (set_attr "shift" "4")
7516 (define_insn "*sub_shiftsi"
7517 [(set (match_operand:SI 0 "s_register_operand" "=r")
7518 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7519 (match_operator:SI 2 "shift_operator"
7520 [(match_operand:SI 3 "s_register_operand" "r")
7521 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7523 "sub%?\\t%0, %1, %3%S2"
7524 [(set_attr "predicable" "yes")
7525 (set_attr "shift" "3")
7529 (define_insn "*sub_shiftsi_compare0"
7530 [(set (reg:CC_NOOV CC_REGNUM)
7532 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7533 (match_operator:SI 2 "shift_operator"
7534 [(match_operand:SI 3 "s_register_operand" "r")
7535 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7537 (set (match_operand:SI 0 "s_register_operand" "=r")
7538 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7541 "sub%?s\\t%0, %1, %3%S2"
7542 [(set_attr "conds" "set")
7543 (set_attr "shift" "3")
7547 (define_insn "*sub_shiftsi_compare0_scratch"
7548 [(set (reg:CC_NOOV CC_REGNUM)
7550 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7551 (match_operator:SI 2 "shift_operator"
7552 [(match_operand:SI 3 "s_register_operand" "r")
7553 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7555 (clobber (match_scratch:SI 0 "=r"))]
7557 "sub%?s\\t%0, %1, %3%S2"
7558 [(set_attr "conds" "set")
7559 (set_attr "shift" "3")
7565 (define_insn "*and_scc"
7566 [(set (match_operand:SI 0 "s_register_operand" "=r")
7567 (and:SI (match_operator:SI 1 "arm_comparison_operator"
7568 [(match_operand 3 "cc_register" "") (const_int 0)])
7569 (match_operand:SI 2 "s_register_operand" "r")))]
7571 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7572 [(set_attr "conds" "use")
7573 (set_attr "length" "8")]
7576 (define_insn "*ior_scc"
7577 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7578 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
7579 [(match_operand 3 "cc_register" "") (const_int 0)])
7580 (match_operand:SI 1 "s_register_operand" "0,?r")))]
7584 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7585 [(set_attr "conds" "use")
7586 (set_attr "length" "4,8")]
7589 (define_insn "*compare_scc"
7590 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7591 (match_operator:SI 1 "arm_comparison_operator"
7592 [(match_operand:SI 2 "s_register_operand" "r,r")
7593 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7594 (clobber (reg:CC CC_REGNUM))]
7597 if (operands[3] == const0_rtx)
7599 if (GET_CODE (operands[1]) == LT)
7600 return \"mov\\t%0, %2, lsr #31\";
7602 if (GET_CODE (operands[1]) == GE)
7603 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7605 if (GET_CODE (operands[1]) == EQ)
7606 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
7609 if (GET_CODE (operands[1]) == NE)
7611 if (which_alternative == 1)
7612 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7613 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7615 if (which_alternative == 1)
7616 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7618 output_asm_insn (\"cmp\\t%2, %3\", operands);
7619 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7621 [(set_attr "conds" "clob")
7622 (set_attr "length" "12")]
7625 (define_insn "*cond_move"
7626 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7627 (if_then_else:SI (match_operator 3 "equality_operator"
7628 [(match_operator 4 "arm_comparison_operator"
7629 [(match_operand 5 "cc_register" "") (const_int 0)])
7631 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7632 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7635 if (GET_CODE (operands[3]) == NE)
7637 if (which_alternative != 1)
7638 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7639 if (which_alternative != 0)
7640 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7643 if (which_alternative != 0)
7644 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7645 if (which_alternative != 1)
7646 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7649 [(set_attr "conds" "use")
7650 (set_attr "length" "4,4,8")]
7653 (define_insn "*cond_arith"
7654 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7655 (match_operator:SI 5 "shiftable_operator"
7656 [(match_operator:SI 4 "arm_comparison_operator"
7657 [(match_operand:SI 2 "s_register_operand" "r,r")
7658 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7659 (match_operand:SI 1 "s_register_operand" "0,?r")]))
7660 (clobber (reg:CC CC_REGNUM))]
7663 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7664 return \"%i5\\t%0, %1, %2, lsr #31\";
7666 output_asm_insn (\"cmp\\t%2, %3\", operands);
7667 if (GET_CODE (operands[5]) == AND)
7668 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7669 else if (GET_CODE (operands[5]) == MINUS)
7670 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7671 else if (which_alternative != 0)
7672 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7673 return \"%i5%d4\\t%0, %1, #1\";
7675 [(set_attr "conds" "clob")
7676 (set_attr "length" "12")]
7679 (define_insn "*cond_sub"
7680 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7681 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7682 (match_operator:SI 4 "arm_comparison_operator"
7683 [(match_operand:SI 2 "s_register_operand" "r,r")
7684 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7685 (clobber (reg:CC CC_REGNUM))]
7688 output_asm_insn (\"cmp\\t%2, %3\", operands);
7689 if (which_alternative != 0)
7690 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7691 return \"sub%d4\\t%0, %1, #1\";
7693 [(set_attr "conds" "clob")
7694 (set_attr "length" "8,12")]
7697 (define_insn "*cmp_ite0"
7698 [(set (match_operand 6 "dominant_cc_register" "")
7701 (match_operator 4 "arm_comparison_operator"
7702 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7703 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7704 (match_operator:SI 5 "arm_comparison_operator"
7705 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7706 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7712 static const char * const opcodes[4][2] =
7714 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7715 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7716 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7717 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7718 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7719 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7720 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7721 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7724 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7726 return opcodes[which_alternative][swap];
7728 [(set_attr "conds" "set")
7729 (set_attr "length" "8")]
7732 (define_insn "*cmp_ite1"
7733 [(set (match_operand 6 "dominant_cc_register" "")
7736 (match_operator 4 "arm_comparison_operator"
7737 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7738 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7739 (match_operator:SI 5 "arm_comparison_operator"
7740 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7741 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7747 static const char * const opcodes[4][2] =
7749 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7750 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7751 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7752 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7753 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7754 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7755 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7756 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7759 comparison_dominates_p (GET_CODE (operands[5]),
7760 reverse_condition (GET_CODE (operands[4])));
7762 return opcodes[which_alternative][swap];
7764 [(set_attr "conds" "set")
7765 (set_attr "length" "8")]
7768 (define_insn "*cmp_and"
7769 [(set (match_operand 6 "dominant_cc_register" "")
7772 (match_operator 4 "arm_comparison_operator"
7773 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7774 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7775 (match_operator:SI 5 "arm_comparison_operator"
7776 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7777 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7782 static const char *const opcodes[4][2] =
7784 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7785 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7786 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7787 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7788 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7789 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7790 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7791 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7794 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7796 return opcodes[which_alternative][swap];
7798 [(set_attr "conds" "set")
7799 (set_attr "predicable" "no")
7800 (set_attr "length" "8")]
7803 (define_insn "*cmp_ior"
7804 [(set (match_operand 6 "dominant_cc_register" "")
7807 (match_operator 4 "arm_comparison_operator"
7808 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7809 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7810 (match_operator:SI 5 "arm_comparison_operator"
7811 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7812 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7817 static const char *const opcodes[4][2] =
7819 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7820 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7821 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7822 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7823 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7824 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7825 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7826 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7829 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7831 return opcodes[which_alternative][swap];
7834 [(set_attr "conds" "set")
7835 (set_attr "length" "8")]
7838 (define_insn_and_split "*ior_scc_scc"
7839 [(set (match_operand:SI 0 "s_register_operand" "=r")
7840 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
7841 [(match_operand:SI 1 "s_register_operand" "r")
7842 (match_operand:SI 2 "arm_add_operand" "rIL")])
7843 (match_operator:SI 6 "arm_comparison_operator"
7844 [(match_operand:SI 4 "s_register_operand" "r")
7845 (match_operand:SI 5 "arm_add_operand" "rIL")])))
7846 (clobber (reg:CC CC_REGNUM))]
7848 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
7851 "TARGET_ARM && reload_completed"
7855 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
7856 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
7858 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
7860 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
7863 [(set_attr "conds" "clob")
7864 (set_attr "length" "16")])
7866 ; If the above pattern is followed by a CMP insn, then the compare is
7867 ; redundant, since we can rework the conditional instruction that follows.
7868 (define_insn_and_split "*ior_scc_scc_cmp"
7869 [(set (match_operand 0 "dominant_cc_register" "")
7870 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
7871 [(match_operand:SI 1 "s_register_operand" "r")
7872 (match_operand:SI 2 "arm_add_operand" "rIL")])
7873 (match_operator:SI 6 "arm_comparison_operator"
7874 [(match_operand:SI 4 "s_register_operand" "r")
7875 (match_operand:SI 5 "arm_add_operand" "rIL")]))
7877 (set (match_operand:SI 7 "s_register_operand" "=r")
7878 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
7879 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
7882 "TARGET_ARM && reload_completed"
7886 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
7887 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
7889 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
7891 [(set_attr "conds" "set")
7892 (set_attr "length" "16")])
7894 (define_insn_and_split "*and_scc_scc"
7895 [(set (match_operand:SI 0 "s_register_operand" "=r")
7896 (and:SI (match_operator:SI 3 "arm_comparison_operator"
7897 [(match_operand:SI 1 "s_register_operand" "r")
7898 (match_operand:SI 2 "arm_add_operand" "rIL")])
7899 (match_operator:SI 6 "arm_comparison_operator"
7900 [(match_operand:SI 4 "s_register_operand" "r")
7901 (match_operand:SI 5 "arm_add_operand" "rIL")])))
7902 (clobber (reg:CC CC_REGNUM))]
7904 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
7907 "TARGET_ARM && reload_completed
7908 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
7913 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
7914 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
7916 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
7918 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
7921 [(set_attr "conds" "clob")
7922 (set_attr "length" "16")])
7924 ; If the above pattern is followed by a CMP insn, then the compare is
7925 ; redundant, since we can rework the conditional instruction that follows.
7926 (define_insn_and_split "*and_scc_scc_cmp"
7927 [(set (match_operand 0 "dominant_cc_register" "")
7928 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
7929 [(match_operand:SI 1 "s_register_operand" "r")
7930 (match_operand:SI 2 "arm_add_operand" "rIL")])
7931 (match_operator:SI 6 "arm_comparison_operator"
7932 [(match_operand:SI 4 "s_register_operand" "r")
7933 (match_operand:SI 5 "arm_add_operand" "rIL")]))
7935 (set (match_operand:SI 7 "s_register_operand" "=r")
7936 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
7937 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
7940 "TARGET_ARM && reload_completed"
7944 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
7945 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
7947 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
7949 [(set_attr "conds" "set")
7950 (set_attr "length" "16")])
7952 ;; If there is no dominance in the comparison, then we can still save an
7953 ;; instruction in the AND case, since we can know that the second compare
7954 ;; need only zero the value if false (if true, then the value is already
7956 (define_insn_and_split "*and_scc_scc_nodom"
7957 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
7958 (and:SI (match_operator:SI 3 "arm_comparison_operator"
7959 [(match_operand:SI 1 "s_register_operand" "r,r,0")
7960 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
7961 (match_operator:SI 6 "arm_comparison_operator"
7962 [(match_operand:SI 4 "s_register_operand" "r,r,r")
7963 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
7964 (clobber (reg:CC CC_REGNUM))]
7966 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
7969 "TARGET_ARM && reload_completed"
7970 [(parallel [(set (match_dup 0)
7971 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
7972 (clobber (reg:CC CC_REGNUM))])
7973 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
7975 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
7978 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
7979 operands[4], operands[5]),
7981 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
7983 [(set_attr "conds" "clob")
7984 (set_attr "length" "20")])
7986 (define_insn "*negscc"
7987 [(set (match_operand:SI 0 "s_register_operand" "=r")
7988 (neg:SI (match_operator 3 "arm_comparison_operator"
7989 [(match_operand:SI 1 "s_register_operand" "r")
7990 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7991 (clobber (reg:CC CC_REGNUM))]
7994 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7995 return \"mov\\t%0, %1, asr #31\";
7997 if (GET_CODE (operands[3]) == NE)
7998 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8000 if (GET_CODE (operands[3]) == GT)
8001 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8003 output_asm_insn (\"cmp\\t%1, %2\", operands);
8004 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8005 return \"mvn%d3\\t%0, #0\";
8007 [(set_attr "conds" "clob")
8008 (set_attr "length" "12")]
8011 (define_insn "movcond"
8012 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8014 (match_operator 5 "arm_comparison_operator"
8015 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8016 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8017 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8018 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8019 (clobber (reg:CC CC_REGNUM))]
8022 if (GET_CODE (operands[5]) == LT
8023 && (operands[4] == const0_rtx))
8025 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8027 if (operands[2] == const0_rtx)
8028 return \"and\\t%0, %1, %3, asr #31\";
8029 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8031 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8033 if (operands[1] == const0_rtx)
8034 return \"bic\\t%0, %2, %3, asr #31\";
8035 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8037 /* The only case that falls through to here is when both ops 1 & 2
8041 if (GET_CODE (operands[5]) == GE
8042 && (operands[4] == const0_rtx))
8044 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8046 if (operands[2] == const0_rtx)
8047 return \"bic\\t%0, %1, %3, asr #31\";
8048 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8050 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8052 if (operands[1] == const0_rtx)
8053 return \"and\\t%0, %2, %3, asr #31\";
8054 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8056 /* The only case that falls through to here is when both ops 1 & 2
8059 if (GET_CODE (operands[4]) == CONST_INT
8060 && !const_ok_for_arm (INTVAL (operands[4])))
8061 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8063 output_asm_insn (\"cmp\\t%3, %4\", operands);
8064 if (which_alternative != 0)
8065 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8066 if (which_alternative != 1)
8067 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8070 [(set_attr "conds" "clob")
8071 (set_attr "length" "8,8,12")]
8074 (define_insn "*ifcompare_plus_move"
8075 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8076 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8077 [(match_operand:SI 4 "s_register_operand" "r,r")
8078 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8080 (match_operand:SI 2 "s_register_operand" "r,r")
8081 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8082 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8083 (clobber (reg:CC CC_REGNUM))]
8086 [(set_attr "conds" "clob")
8087 (set_attr "length" "8,12")]
8090 (define_insn "*if_plus_move"
8091 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8093 (match_operator 4 "arm_comparison_operator"
8094 [(match_operand 5 "cc_register" "") (const_int 0)])
8096 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8097 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8098 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8102 sub%d4\\t%0, %2, #%n3
8103 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8104 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8105 [(set_attr "conds" "use")
8106 (set_attr "length" "4,4,8,8")
8107 (set_attr "type" "*,*,*,*")]
8110 (define_insn "*ifcompare_move_plus"
8111 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8112 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8113 [(match_operand:SI 4 "s_register_operand" "r,r")
8114 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8115 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8117 (match_operand:SI 2 "s_register_operand" "r,r")
8118 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8119 (clobber (reg:CC CC_REGNUM))]
8122 [(set_attr "conds" "clob")
8123 (set_attr "length" "8,12")]
8126 (define_insn "*if_move_plus"
8127 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8129 (match_operator 4 "arm_comparison_operator"
8130 [(match_operand 5 "cc_register" "") (const_int 0)])
8131 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8133 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8134 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8138 sub%D4\\t%0, %2, #%n3
8139 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8140 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8141 [(set_attr "conds" "use")
8142 (set_attr "length" "4,4,8,8")
8143 (set_attr "type" "*,*,*,*")]
8146 (define_insn "*ifcompare_arith_arith"
8147 [(set (match_operand:SI 0 "s_register_operand" "=r")
8148 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8149 [(match_operand:SI 5 "s_register_operand" "r")
8150 (match_operand:SI 6 "arm_add_operand" "rIL")])
8151 (match_operator:SI 8 "shiftable_operator"
8152 [(match_operand:SI 1 "s_register_operand" "r")
8153 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8154 (match_operator:SI 7 "shiftable_operator"
8155 [(match_operand:SI 3 "s_register_operand" "r")
8156 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8157 (clobber (reg:CC CC_REGNUM))]
8160 [(set_attr "conds" "clob")
8161 (set_attr "length" "12")]
8164 (define_insn "*if_arith_arith"
8165 [(set (match_operand:SI 0 "s_register_operand" "=r")
8166 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8167 [(match_operand 8 "cc_register" "") (const_int 0)])
8168 (match_operator:SI 6 "shiftable_operator"
8169 [(match_operand:SI 1 "s_register_operand" "r")
8170 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8171 (match_operator:SI 7 "shiftable_operator"
8172 [(match_operand:SI 3 "s_register_operand" "r")
8173 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8175 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8176 [(set_attr "conds" "use")
8177 (set_attr "length" "8")]
8180 (define_insn "*ifcompare_arith_move"
8181 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8182 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8183 [(match_operand:SI 2 "s_register_operand" "r,r")
8184 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8185 (match_operator:SI 7 "shiftable_operator"
8186 [(match_operand:SI 4 "s_register_operand" "r,r")
8187 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8188 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8189 (clobber (reg:CC CC_REGNUM))]
8192 /* If we have an operation where (op x 0) is the identity operation and
8193 the conditional operator is LT or GE and we are comparing against zero and
8194 everything is in registers then we can do this in two instructions */
8195 if (operands[3] == const0_rtx
8196 && GET_CODE (operands[7]) != AND
8197 && GET_CODE (operands[5]) == REG
8198 && GET_CODE (operands[1]) == REG
8199 && REGNO (operands[1]) == REGNO (operands[4])
8200 && REGNO (operands[4]) != REGNO (operands[0]))
8202 if (GET_CODE (operands[6]) == LT)
8203 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8204 else if (GET_CODE (operands[6]) == GE)
8205 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8207 if (GET_CODE (operands[3]) == CONST_INT
8208 && !const_ok_for_arm (INTVAL (operands[3])))
8209 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8211 output_asm_insn (\"cmp\\t%2, %3\", operands);
8212 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8213 if (which_alternative != 0)
8214 return \"mov%D6\\t%0, %1\";
8217 [(set_attr "conds" "clob")
8218 (set_attr "length" "8,12")]
8221 (define_insn "*if_arith_move"
8222 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8223 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8224 [(match_operand 6 "cc_register" "") (const_int 0)])
8225 (match_operator:SI 5 "shiftable_operator"
8226 [(match_operand:SI 2 "s_register_operand" "r,r")
8227 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8228 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8232 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8233 [(set_attr "conds" "use")
8234 (set_attr "length" "4,8")
8235 (set_attr "type" "*,*")]
8238 (define_insn "*ifcompare_move_arith"
8239 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8240 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8241 [(match_operand:SI 4 "s_register_operand" "r,r")
8242 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8243 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8244 (match_operator:SI 7 "shiftable_operator"
8245 [(match_operand:SI 2 "s_register_operand" "r,r")
8246 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8247 (clobber (reg:CC CC_REGNUM))]
8250 /* If we have an operation where (op x 0) is the identity operation and
8251 the conditional operator is LT or GE and we are comparing against zero and
8252 everything is in registers then we can do this in two instructions */
8253 if (operands[5] == const0_rtx
8254 && GET_CODE (operands[7]) != AND
8255 && GET_CODE (operands[3]) == REG
8256 && GET_CODE (operands[1]) == REG
8257 && REGNO (operands[1]) == REGNO (operands[2])
8258 && REGNO (operands[2]) != REGNO (operands[0]))
8260 if (GET_CODE (operands[6]) == GE)
8261 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8262 else if (GET_CODE (operands[6]) == LT)
8263 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8266 if (GET_CODE (operands[5]) == CONST_INT
8267 && !const_ok_for_arm (INTVAL (operands[5])))
8268 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8270 output_asm_insn (\"cmp\\t%4, %5\", operands);
8272 if (which_alternative != 0)
8273 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8274 return \"%I7%D6\\t%0, %2, %3\";
8276 [(set_attr "conds" "clob")
8277 (set_attr "length" "8,12")]
8280 (define_insn "*if_move_arith"
8281 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8283 (match_operator 4 "arm_comparison_operator"
8284 [(match_operand 6 "cc_register" "") (const_int 0)])
8285 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8286 (match_operator:SI 5 "shiftable_operator"
8287 [(match_operand:SI 2 "s_register_operand" "r,r")
8288 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8292 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8293 [(set_attr "conds" "use")
8294 (set_attr "length" "4,8")
8295 (set_attr "type" "*,*")]
8298 (define_insn "*ifcompare_move_not"
8299 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8301 (match_operator 5 "arm_comparison_operator"
8302 [(match_operand:SI 3 "s_register_operand" "r,r")
8303 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8304 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8306 (match_operand:SI 2 "s_register_operand" "r,r"))))
8307 (clobber (reg:CC CC_REGNUM))]
8310 [(set_attr "conds" "clob")
8311 (set_attr "length" "8,12")]
8314 (define_insn "*if_move_not"
8315 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8317 (match_operator 4 "arm_comparison_operator"
8318 [(match_operand 3 "cc_register" "") (const_int 0)])
8319 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8320 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8324 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8325 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8326 [(set_attr "conds" "use")
8327 (set_attr "length" "4,8,8")]
8330 (define_insn "*ifcompare_not_move"
8331 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8333 (match_operator 5 "arm_comparison_operator"
8334 [(match_operand:SI 3 "s_register_operand" "r,r")
8335 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8337 (match_operand:SI 2 "s_register_operand" "r,r"))
8338 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8339 (clobber (reg:CC CC_REGNUM))]
8342 [(set_attr "conds" "clob")
8343 (set_attr "length" "8,12")]
8346 (define_insn "*if_not_move"
8347 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8349 (match_operator 4 "arm_comparison_operator"
8350 [(match_operand 3 "cc_register" "") (const_int 0)])
8351 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8352 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8356 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
8357 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8358 [(set_attr "conds" "use")
8359 (set_attr "length" "4,8,8")]
8362 (define_insn "*ifcompare_shift_move"
8363 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8365 (match_operator 6 "arm_comparison_operator"
8366 [(match_operand:SI 4 "s_register_operand" "r,r")
8367 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8368 (match_operator:SI 7 "shift_operator"
8369 [(match_operand:SI 2 "s_register_operand" "r,r")
8370 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
8371 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8372 (clobber (reg:CC CC_REGNUM))]
8375 [(set_attr "conds" "clob")
8376 (set_attr "length" "8,12")]
8379 (define_insn "*if_shift_move"
8380 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8382 (match_operator 5 "arm_comparison_operator"
8383 [(match_operand 6 "cc_register" "") (const_int 0)])
8384 (match_operator:SI 4 "shift_operator"
8385 [(match_operand:SI 2 "s_register_operand" "r,r,r")
8386 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
8387 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8391 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
8392 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8393 [(set_attr "conds" "use")
8394 (set_attr "shift" "2")
8395 (set_attr "length" "4,8,8")]
8398 (define_insn "*ifcompare_move_shift"
8399 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8401 (match_operator 6 "arm_comparison_operator"
8402 [(match_operand:SI 4 "s_register_operand" "r,r")
8403 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8404 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8405 (match_operator:SI 7 "shift_operator"
8406 [(match_operand:SI 2 "s_register_operand" "r,r")
8407 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
8408 (clobber (reg:CC CC_REGNUM))]
8411 [(set_attr "conds" "clob")
8412 (set_attr "length" "8,12")]
8415 (define_insn "*if_move_shift"
8416 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8418 (match_operator 5 "arm_comparison_operator"
8419 [(match_operand 6 "cc_register" "") (const_int 0)])
8420 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8421 (match_operator:SI 4 "shift_operator"
8422 [(match_operand:SI 2 "s_register_operand" "r,r,r")
8423 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
8427 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
8428 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8429 [(set_attr "conds" "use")
8430 (set_attr "shift" "2")
8431 (set_attr "length" "4,8,8")]
8434 (define_insn "*ifcompare_shift_shift"
8435 [(set (match_operand:SI 0 "s_register_operand" "=r")
8437 (match_operator 7 "arm_comparison_operator"
8438 [(match_operand:SI 5 "s_register_operand" "r")
8439 (match_operand:SI 6 "arm_add_operand" "rIL")])
8440 (match_operator:SI 8 "shift_operator"
8441 [(match_operand:SI 1 "s_register_operand" "r")
8442 (match_operand:SI 2 "arm_rhs_operand" "rM")])
8443 (match_operator:SI 9 "shift_operator"
8444 [(match_operand:SI 3 "s_register_operand" "r")
8445 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
8446 (clobber (reg:CC CC_REGNUM))]
8449 [(set_attr "conds" "clob")
8450 (set_attr "length" "12")]
8453 (define_insn "*if_shift_shift"
8454 [(set (match_operand:SI 0 "s_register_operand" "=r")
8456 (match_operator 5 "arm_comparison_operator"
8457 [(match_operand 8 "cc_register" "") (const_int 0)])
8458 (match_operator:SI 6 "shift_operator"
8459 [(match_operand:SI 1 "s_register_operand" "r")
8460 (match_operand:SI 2 "arm_rhs_operand" "rM")])
8461 (match_operator:SI 7 "shift_operator"
8462 [(match_operand:SI 3 "s_register_operand" "r")
8463 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
8465 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8466 [(set_attr "conds" "use")
8467 (set_attr "shift" "1")
8468 (set_attr "length" "8")]
8471 (define_insn "*ifcompare_not_arith"
8472 [(set (match_operand:SI 0 "s_register_operand" "=r")
8474 (match_operator 6 "arm_comparison_operator"
8475 [(match_operand:SI 4 "s_register_operand" "r")
8476 (match_operand:SI 5 "arm_add_operand" "rIL")])
8477 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8478 (match_operator:SI 7 "shiftable_operator"
8479 [(match_operand:SI 2 "s_register_operand" "r")
8480 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
8481 (clobber (reg:CC CC_REGNUM))]
8484 [(set_attr "conds" "clob")
8485 (set_attr "length" "12")]
8488 (define_insn "*if_not_arith"
8489 [(set (match_operand:SI 0 "s_register_operand" "=r")
8491 (match_operator 5 "arm_comparison_operator"
8492 [(match_operand 4 "cc_register" "") (const_int 0)])
8493 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8494 (match_operator:SI 6 "shiftable_operator"
8495 [(match_operand:SI 2 "s_register_operand" "r")
8496 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
8498 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8499 [(set_attr "conds" "use")
8500 (set_attr "length" "8")]
8503 (define_insn "*ifcompare_arith_not"
8504 [(set (match_operand:SI 0 "s_register_operand" "=r")
8506 (match_operator 6 "arm_comparison_operator"
8507 [(match_operand:SI 4 "s_register_operand" "r")
8508 (match_operand:SI 5 "arm_add_operand" "rIL")])
8509 (match_operator:SI 7 "shiftable_operator"
8510 [(match_operand:SI 2 "s_register_operand" "r")
8511 (match_operand:SI 3 "arm_rhs_operand" "rI")])
8512 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
8513 (clobber (reg:CC CC_REGNUM))]
8516 [(set_attr "conds" "clob")
8517 (set_attr "length" "12")]
8520 (define_insn "*if_arith_not"
8521 [(set (match_operand:SI 0 "s_register_operand" "=r")
8523 (match_operator 5 "arm_comparison_operator"
8524 [(match_operand 4 "cc_register" "") (const_int 0)])
8525 (match_operator:SI 6 "shiftable_operator"
8526 [(match_operand:SI 2 "s_register_operand" "r")
8527 (match_operand:SI 3 "arm_rhs_operand" "rI")])
8528 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
8530 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8531 [(set_attr "conds" "use")
8532 (set_attr "length" "8")]
8535 (define_insn "*ifcompare_neg_move"
8536 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8538 (match_operator 5 "arm_comparison_operator"
8539 [(match_operand:SI 3 "s_register_operand" "r,r")
8540 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8541 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
8542 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8543 (clobber (reg:CC CC_REGNUM))]
8546 [(set_attr "conds" "clob")
8547 (set_attr "length" "8,12")]
8550 (define_insn "*if_neg_move"
8551 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8553 (match_operator 4 "arm_comparison_operator"
8554 [(match_operand 3 "cc_register" "") (const_int 0)])
8555 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8556 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8560 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
8561 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8562 [(set_attr "conds" "use")
8563 (set_attr "length" "4,8,8")]
8566 (define_insn "*ifcompare_move_neg"
8567 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8569 (match_operator 5 "arm_comparison_operator"
8570 [(match_operand:SI 3 "s_register_operand" "r,r")
8571 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8572 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8573 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
8574 (clobber (reg:CC CC_REGNUM))]
8577 [(set_attr "conds" "clob")
8578 (set_attr "length" "8,12")]
8581 (define_insn "*if_move_neg"
8582 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8584 (match_operator 4 "arm_comparison_operator"
8585 [(match_operand 3 "cc_register" "") (const_int 0)])
8586 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8587 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8591 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
8592 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
8593 [(set_attr "conds" "use")
8594 (set_attr "length" "4,8,8")]
8597 (define_insn "*arith_adjacentmem"
8598 [(set (match_operand:SI 0 "s_register_operand" "=r")
8599 (match_operator:SI 1 "shiftable_operator"
8600 [(match_operand:SI 2 "memory_operand" "m")
8601 (match_operand:SI 3 "memory_operand" "m")]))
8602 (clobber (match_scratch:SI 4 "=r"))]
8603 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
8608 int val1 = 0, val2 = 0;
8610 if (REGNO (operands[0]) > REGNO (operands[4]))
8612 ldm[1] = operands[4];
8613 ldm[2] = operands[0];
8617 ldm[1] = operands[0];
8618 ldm[2] = operands[4];
8620 if (GET_CODE (XEXP (operands[2], 0)) != REG)
8621 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
8622 if (GET_CODE (XEXP (operands[3], 0)) != REG)
8623 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
8624 arith[0] = operands[0];
8625 arith[3] = operands[1];
8639 ldm[0] = ops[0] = operands[4];
8640 ops[1] = XEXP (XEXP (operands[2], 0), 0);
8641 ops[2] = XEXP (XEXP (operands[2], 0), 1);
8642 output_add_immediate (ops);
8644 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8646 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8650 ldm[0] = XEXP (operands[3], 0);
8652 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8654 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8658 ldm[0] = XEXP (operands[2], 0);
8660 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8662 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8664 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
8667 [(set_attr "length" "12")
8668 (set_attr "predicable" "yes")
8669 (set_attr "type" "load")]
8672 ;; the arm can support extended pre-inc instructions
8674 ;; In all these cases, we use operands 0 and 1 for the register being
8675 ;; incremented because those are the operands that local-alloc will
8676 ;; tie and these are the pair most likely to be tieable (and the ones
8677 ;; that will benefit the most).
8679 ;; We reject the frame pointer if it occurs anywhere in these patterns since
8680 ;; elimination will cause too many headaches.
8682 (define_insn "*strqi_preinc"
8683 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8684 (match_operand:SI 2 "index_operand" "rJ")))
8685 (match_operand:QI 3 "s_register_operand" "r"))
8686 (set (match_operand:SI 0 "s_register_operand" "=r")
8687 (plus:SI (match_dup 1) (match_dup 2)))]
8689 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8690 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8691 && (GET_CODE (operands[2]) != REG
8692 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8693 "str%?b\\t%3, [%0, %2]!"
8694 [(set_attr "type" "store1")
8695 (set_attr "predicable" "yes")]
8698 (define_insn "*strqi_predec"
8699 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8700 (match_operand:SI 2 "s_register_operand" "r")))
8701 (match_operand:QI 3 "s_register_operand" "r"))
8702 (set (match_operand:SI 0 "s_register_operand" "=r")
8703 (minus:SI (match_dup 1) (match_dup 2)))]
8705 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8706 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8707 && (GET_CODE (operands[2]) != REG
8708 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8709 "str%?b\\t%3, [%0, -%2]!"
8710 [(set_attr "type" "store1")
8711 (set_attr "predicable" "yes")]
8714 (define_insn "*loadqi_preinc"
8715 [(set (match_operand:QI 3 "s_register_operand" "=r")
8716 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8717 (match_operand:SI 2 "index_operand" "rJ"))))
8718 (set (match_operand:SI 0 "s_register_operand" "=r")
8719 (plus:SI (match_dup 1) (match_dup 2)))]
8721 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8722 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8723 && (GET_CODE (operands[2]) != REG
8724 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8725 "ldr%?b\\t%3, [%0, %2]!"
8726 [(set_attr "type" "load")
8727 (set_attr "predicable" "yes")]
8730 (define_insn "*loadqi_predec"
8731 [(set (match_operand:QI 3 "s_register_operand" "=r")
8732 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8733 (match_operand:SI 2 "s_register_operand" "r"))))
8734 (set (match_operand:SI 0 "s_register_operand" "=r")
8735 (minus:SI (match_dup 1) (match_dup 2)))]
8737 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8738 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8739 && (GET_CODE (operands[2]) != REG
8740 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8741 "ldr%?b\\t%3, [%0, -%2]!"
8742 [(set_attr "type" "load")
8743 (set_attr "predicable" "yes")]
8746 (define_insn "*loadqisi_preinc"
8747 [(set (match_operand:SI 3 "s_register_operand" "=r")
8749 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8750 (match_operand:SI 2 "index_operand" "rJ")))))
8751 (set (match_operand:SI 0 "s_register_operand" "=r")
8752 (plus:SI (match_dup 1) (match_dup 2)))]
8754 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8755 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8756 && (GET_CODE (operands[2]) != REG
8757 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8758 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8759 [(set_attr "type" "load")
8760 (set_attr "predicable" "yes")]
8763 (define_insn "*loadqisi_predec"
8764 [(set (match_operand:SI 3 "s_register_operand" "=r")
8766 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8767 (match_operand:SI 2 "s_register_operand" "r")))))
8768 (set (match_operand:SI 0 "s_register_operand" "=r")
8769 (minus:SI (match_dup 1) (match_dup 2)))]
8771 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8772 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8773 && (GET_CODE (operands[2]) != REG
8774 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8775 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8776 [(set_attr "type" "load")
8777 (set_attr "predicable" "yes")]
8780 (define_insn "*strsi_preinc"
8781 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8782 (match_operand:SI 2 "index_operand" "rJ")))
8783 (match_operand:SI 3 "s_register_operand" "r"))
8784 (set (match_operand:SI 0 "s_register_operand" "=r")
8785 (plus:SI (match_dup 1) (match_dup 2)))]
8787 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8788 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8789 && (GET_CODE (operands[2]) != REG
8790 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8791 "str%?\\t%3, [%0, %2]!"
8792 [(set_attr "type" "store1")
8793 (set_attr "predicable" "yes")]
8796 (define_insn "*strsi_predec"
8797 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8798 (match_operand:SI 2 "s_register_operand" "r")))
8799 (match_operand:SI 3 "s_register_operand" "r"))
8800 (set (match_operand:SI 0 "s_register_operand" "=r")
8801 (minus:SI (match_dup 1) (match_dup 2)))]
8803 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8804 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8805 && (GET_CODE (operands[2]) != REG
8806 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8807 "str%?\\t%3, [%0, -%2]!"
8808 [(set_attr "type" "store1")
8809 (set_attr "predicable" "yes")]
8812 (define_insn "*loadsi_preinc"
8813 [(set (match_operand:SI 3 "s_register_operand" "=r")
8814 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8815 (match_operand:SI 2 "index_operand" "rJ"))))
8816 (set (match_operand:SI 0 "s_register_operand" "=r")
8817 (plus:SI (match_dup 1) (match_dup 2)))]
8819 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8820 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8821 && (GET_CODE (operands[2]) != REG
8822 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8823 "ldr%?\\t%3, [%0, %2]!"
8824 [(set_attr "type" "load")
8825 (set_attr "predicable" "yes")]
8828 (define_insn "*loadsi_predec"
8829 [(set (match_operand:SI 3 "s_register_operand" "=r")
8830 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8831 (match_operand:SI 2 "s_register_operand" "r"))))
8832 (set (match_operand:SI 0 "s_register_operand" "=r")
8833 (minus:SI (match_dup 1) (match_dup 2)))]
8835 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8836 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8837 && (GET_CODE (operands[2]) != REG
8838 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8839 "ldr%?\\t%3, [%0, -%2]!"
8840 [(set_attr "type" "load")
8841 (set_attr "predicable" "yes")]
8844 (define_insn "*loadhi_preinc"
8845 [(set (match_operand:HI 3 "s_register_operand" "=r")
8846 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8847 (match_operand:SI 2 "index_operand" "rJ"))))
8848 (set (match_operand:SI 0 "s_register_operand" "=r")
8849 (plus:SI (match_dup 1) (match_dup 2)))]
8851 && !BYTES_BIG_ENDIAN
8852 && !TARGET_MMU_TRAPS
8854 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8855 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8856 && (GET_CODE (operands[2]) != REG
8857 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8858 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8859 [(set_attr "type" "load")
8860 (set_attr "predicable" "yes")]
8863 (define_insn "*loadhi_predec"
8864 [(set (match_operand:HI 3 "s_register_operand" "=r")
8865 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8866 (match_operand:SI 2 "s_register_operand" "r"))))
8867 (set (match_operand:SI 0 "s_register_operand" "=r")
8868 (minus:SI (match_dup 1) (match_dup 2)))]
8870 && !BYTES_BIG_ENDIAN
8871 && !TARGET_MMU_TRAPS
8873 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8874 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8875 && (GET_CODE (operands[2]) != REG
8876 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8877 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8878 [(set_attr "type" "load")
8879 (set_attr "predicable" "yes")]
8882 (define_insn "*strqi_shiftpreinc"
8883 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8884 [(match_operand:SI 3 "s_register_operand" "r")
8885 (match_operand:SI 4 "const_shift_operand" "n")])
8886 (match_operand:SI 1 "s_register_operand" "0")))
8887 (match_operand:QI 5 "s_register_operand" "r"))
8888 (set (match_operand:SI 0 "s_register_operand" "=r")
8889 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8892 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8893 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8894 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8895 "str%?b\\t%5, [%0, %3%S2]!"
8896 [(set_attr "type" "store1")
8897 (set_attr "predicable" "yes")]
8900 (define_insn "*strqi_shiftpredec"
8901 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8902 (match_operator:SI 2 "shift_operator"
8903 [(match_operand:SI 3 "s_register_operand" "r")
8904 (match_operand:SI 4 "const_shift_operand" "n")])))
8905 (match_operand:QI 5 "s_register_operand" "r"))
8906 (set (match_operand:SI 0 "s_register_operand" "=r")
8907 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8910 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8911 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8912 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8913 "str%?b\\t%5, [%0, -%3%S2]!"
8914 [(set_attr "type" "store1")
8915 (set_attr "predicable" "yes")]
8918 (define_insn "*loadqi_shiftpreinc"
8919 [(set (match_operand:QI 5 "s_register_operand" "=r")
8920 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8921 [(match_operand:SI 3 "s_register_operand" "r")
8922 (match_operand:SI 4 "const_shift_operand" "n")])
8923 (match_operand:SI 1 "s_register_operand" "0"))))
8924 (set (match_operand:SI 0 "s_register_operand" "=r")
8925 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8928 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8929 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8930 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8931 "ldr%?b\\t%5, [%0, %3%S2]!"
8932 [(set_attr "type" "load")
8933 (set_attr "predicable" "yes")]
8936 (define_insn "*loadqi_shiftpredec"
8937 [(set (match_operand:QI 5 "s_register_operand" "=r")
8938 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8939 (match_operator:SI 2 "shift_operator"
8940 [(match_operand:SI 3 "s_register_operand" "r")
8941 (match_operand:SI 4 "const_shift_operand" "n")]))))
8942 (set (match_operand:SI 0 "s_register_operand" "=r")
8943 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8946 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8947 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8948 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8949 "ldr%?b\\t%5, [%0, -%3%S2]!"
8950 [(set_attr "type" "load")
8951 (set_attr "predicable" "yes")]
8954 (define_insn "*strsi_shiftpreinc"
8955 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8956 [(match_operand:SI 3 "s_register_operand" "r")
8957 (match_operand:SI 4 "const_shift_operand" "n")])
8958 (match_operand:SI 1 "s_register_operand" "0")))
8959 (match_operand:SI 5 "s_register_operand" "r"))
8960 (set (match_operand:SI 0 "s_register_operand" "=r")
8961 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8964 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8965 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8966 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8967 "str%?\\t%5, [%0, %3%S2]!"
8968 [(set_attr "type" "store1")
8969 (set_attr "predicable" "yes")]
8972 (define_insn "*strsi_shiftpredec"
8973 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8974 (match_operator:SI 2 "shift_operator"
8975 [(match_operand:SI 3 "s_register_operand" "r")
8976 (match_operand:SI 4 "const_shift_operand" "n")])))
8977 (match_operand:SI 5 "s_register_operand" "r"))
8978 (set (match_operand:SI 0 "s_register_operand" "=r")
8979 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8982 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8983 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8984 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8985 "str%?\\t%5, [%0, -%3%S2]!"
8986 [(set_attr "type" "store1")
8987 (set_attr "predicable" "yes")]
8990 (define_insn "*loadsi_shiftpreinc"
8991 [(set (match_operand:SI 5 "s_register_operand" "=r")
8992 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8993 [(match_operand:SI 3 "s_register_operand" "r")
8994 (match_operand:SI 4 "const_shift_operand" "n")])
8995 (match_operand:SI 1 "s_register_operand" "0"))))
8996 (set (match_operand:SI 0 "s_register_operand" "=r")
8997 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9000 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9001 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9002 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9003 "ldr%?\\t%5, [%0, %3%S2]!"
9004 [(set_attr "type" "load")
9005 (set_attr "predicable" "yes")]
9008 (define_insn "*loadsi_shiftpredec"
9009 [(set (match_operand:SI 5 "s_register_operand" "=r")
9010 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9011 (match_operator:SI 2 "shift_operator"
9012 [(match_operand:SI 3 "s_register_operand" "r")
9013 (match_operand:SI 4 "const_shift_operand" "n")]))))
9014 (set (match_operand:SI 0 "s_register_operand" "=r")
9015 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9018 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9019 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9020 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9021 "ldr%?\\t%5, [%0, -%3%S2]!"
9022 [(set_attr "type" "load")
9023 (set_attr "predicable" "yes")])
9025 (define_insn "*loadhi_shiftpreinc"
9026 [(set (match_operand:HI 5 "s_register_operand" "=r")
9027 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
9028 [(match_operand:SI 3 "s_register_operand" "r")
9029 (match_operand:SI 4 "const_shift_operand" "n")])
9030 (match_operand:SI 1 "s_register_operand" "0"))))
9031 (set (match_operand:SI 0 "s_register_operand" "=r")
9032 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9035 && !BYTES_BIG_ENDIAN
9036 && !TARGET_MMU_TRAPS
9038 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9039 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9040 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9041 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
9042 [(set_attr "type" "load")
9043 (set_attr "predicable" "yes")]
9046 (define_insn "*loadhi_shiftpredec"
9047 [(set (match_operand:HI 5 "s_register_operand" "=r")
9048 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9049 (match_operator:SI 2 "shift_operator"
9050 [(match_operand:SI 3 "s_register_operand" "r")
9051 (match_operand:SI 4 "const_shift_operand" "n")]))))
9052 (set (match_operand:SI 0 "s_register_operand" "=r")
9053 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9056 && !BYTES_BIG_ENDIAN
9057 && !TARGET_MMU_TRAPS
9059 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9060 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9061 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9062 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
9063 [(set_attr "type" "load")
9064 (set_attr "predicable" "yes")]
9067 ; It can also support extended post-inc expressions, but combine doesn't
9069 ; It doesn't seem worth adding peepholes for anything but the most common
9070 ; cases since, unlike combine, the increment must immediately follow the load
9071 ; for this pattern to match.
9072 ; We must watch to see that the source/destination register isn't also the
9073 ; same as the base address register, and that if the index is a register,
9074 ; that it is not the same as the base address register. In such cases the
9075 ; instruction that we would generate would have UNPREDICTABLE behavior so
9079 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9080 (match_operand:QI 2 "s_register_operand" "r"))
9082 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9084 && (REGNO (operands[2]) != REGNO (operands[0]))
9085 && (GET_CODE (operands[1]) != REG
9086 || (REGNO (operands[1]) != REGNO (operands[0])))"
9087 "str%?b\\t%2, [%0], %1"
9091 [(set (match_operand:QI 0 "s_register_operand" "=r")
9092 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9094 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9096 && REGNO (operands[0]) != REGNO(operands[1])
9097 && (GET_CODE (operands[2]) != REG
9098 || REGNO(operands[0]) != REGNO (operands[2]))"
9099 "ldr%?b\\t%0, [%1], %2"
9103 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9104 (match_operand:SI 2 "s_register_operand" "r"))
9106 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9108 && (REGNO (operands[2]) != REGNO (operands[0]))
9109 && (GET_CODE (operands[1]) != REG
9110 || (REGNO (operands[1]) != REGNO (operands[0])))"
9111 "str%?\\t%2, [%0], %1"
9115 [(set (match_operand:HI 0 "s_register_operand" "=r")
9116 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
9118 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9120 && !BYTES_BIG_ENDIAN
9121 && !TARGET_MMU_TRAPS
9123 && REGNO (operands[0]) != REGNO(operands[1])
9124 && (GET_CODE (operands[2]) != REG
9125 || REGNO(operands[0]) != REGNO (operands[2]))"
9126 "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
9130 [(set (match_operand:SI 0 "s_register_operand" "=r")
9131 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9133 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9135 && REGNO (operands[0]) != REGNO(operands[1])
9136 && (GET_CODE (operands[2]) != REG
9137 || REGNO(operands[0]) != REGNO (operands[2]))"
9138 "ldr%?\\t%0, [%1], %2"
9142 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9143 (match_operand:SI 1 "index_operand" "rJ")))
9144 (match_operand:QI 2 "s_register_operand" "r"))
9145 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9147 && (REGNO (operands[2]) != REGNO (operands[0]))
9148 && (GET_CODE (operands[1]) != REG
9149 || (REGNO (operands[1]) != REGNO (operands[0])))"
9150 "str%?b\\t%2, [%0, %1]!"
9154 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9155 [(match_operand:SI 0 "s_register_operand" "r")
9156 (match_operand:SI 1 "const_int_operand" "n")])
9157 (match_operand:SI 2 "s_register_operand" "+r")))
9158 (match_operand:QI 3 "s_register_operand" "r"))
9159 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9162 && (REGNO (operands[3]) != REGNO (operands[2]))
9163 && (REGNO (operands[0]) != REGNO (operands[2]))"
9164 "str%?b\\t%3, [%2, %0%S4]!"
9167 ; This pattern is never tried by combine, so do it as a peephole
9170 [(set (match_operand:SI 0 "s_register_operand" "")
9171 (match_operand:SI 1 "s_register_operand" ""))
9172 (set (reg:CC CC_REGNUM)
9173 (compare:CC (match_dup 1) (const_int 0)))]
9176 || (!cirrus_fp_register (operands[0], SImode)
9177 && !cirrus_fp_register (operands[1], SImode)))
9179 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9180 (set (match_dup 0) (match_dup 1))])]
9184 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9185 ; reversed, check that the memory references aren't volatile.
9188 [(set (match_operand:SI 0 "s_register_operand" "=r")
9189 (match_operand:SI 4 "memory_operand" "m"))
9190 (set (match_operand:SI 1 "s_register_operand" "=r")
9191 (match_operand:SI 5 "memory_operand" "m"))
9192 (set (match_operand:SI 2 "s_register_operand" "=r")
9193 (match_operand:SI 6 "memory_operand" "m"))
9194 (set (match_operand:SI 3 "s_register_operand" "=r")
9195 (match_operand:SI 7 "memory_operand" "m"))]
9196 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9198 return emit_ldm_seq (operands, 4);
9203 [(set (match_operand:SI 0 "s_register_operand" "=r")
9204 (match_operand:SI 3 "memory_operand" "m"))
9205 (set (match_operand:SI 1 "s_register_operand" "=r")
9206 (match_operand:SI 4 "memory_operand" "m"))
9207 (set (match_operand:SI 2 "s_register_operand" "=r")
9208 (match_operand:SI 5 "memory_operand" "m"))]
9209 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9211 return emit_ldm_seq (operands, 3);
9216 [(set (match_operand:SI 0 "s_register_operand" "=r")
9217 (match_operand:SI 2 "memory_operand" "m"))
9218 (set (match_operand:SI 1 "s_register_operand" "=r")
9219 (match_operand:SI 3 "memory_operand" "m"))]
9220 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9222 return emit_ldm_seq (operands, 2);
9227 [(set (match_operand:SI 4 "memory_operand" "=m")
9228 (match_operand:SI 0 "s_register_operand" "r"))
9229 (set (match_operand:SI 5 "memory_operand" "=m")
9230 (match_operand:SI 1 "s_register_operand" "r"))
9231 (set (match_operand:SI 6 "memory_operand" "=m")
9232 (match_operand:SI 2 "s_register_operand" "r"))
9233 (set (match_operand:SI 7 "memory_operand" "=m")
9234 (match_operand:SI 3 "s_register_operand" "r"))]
9235 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9237 return emit_stm_seq (operands, 4);
9242 [(set (match_operand:SI 3 "memory_operand" "=m")
9243 (match_operand:SI 0 "s_register_operand" "r"))
9244 (set (match_operand:SI 4 "memory_operand" "=m")
9245 (match_operand:SI 1 "s_register_operand" "r"))
9246 (set (match_operand:SI 5 "memory_operand" "=m")
9247 (match_operand:SI 2 "s_register_operand" "r"))]
9248 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9250 return emit_stm_seq (operands, 3);
9255 [(set (match_operand:SI 2 "memory_operand" "=m")
9256 (match_operand:SI 0 "s_register_operand" "r"))
9257 (set (match_operand:SI 3 "memory_operand" "=m")
9258 (match_operand:SI 1 "s_register_operand" "r"))]
9259 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9261 return emit_stm_seq (operands, 2);
9266 [(set (match_operand:SI 0 "s_register_operand" "")
9267 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9269 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9270 [(match_operand:SI 3 "s_register_operand" "")
9271 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9272 (clobber (match_operand:SI 5 "s_register_operand" ""))]
9274 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9275 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9280 ;; This split can be used because CC_Z mode implies that the following
9281 ;; branch will be an equality, or an unsigned inequality, so the sign
9282 ;; extension is not needed.
9285 [(set (reg:CC_Z CC_REGNUM)
9287 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9289 (match_operand 1 "const_int_operand" "")))
9290 (clobber (match_scratch:SI 2 ""))]
9292 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9293 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9294 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9295 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9297 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9301 (define_expand "prologue"
9302 [(clobber (const_int 0))]
9305 arm_expand_prologue ();
9307 thumb_expand_prologue ();
9312 (define_expand "epilogue"
9313 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9317 thumb_expand_epilogue ();
9318 else if (USE_RETURN_INSN (FALSE))
9320 emit_jump_insn (gen_return ());
9323 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9325 gen_rtx_RETURN (VOIDmode)),
9331 ;; Note - although unspec_volatile's USE all hard registers,
9332 ;; USEs are ignored after relaod has completed. Thus we need
9333 ;; to add an unspec of the link register to ensure that flow
9334 ;; does not think that it is unused by the sibcall branch that
9335 ;; will replace the standard function epilogue.
9336 (define_insn "sibcall_epilogue"
9337 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9338 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9341 if (USE_RETURN_INSN (FALSE))
9342 return output_return_instruction (const_true_rtx, FALSE, FALSE);
9343 return arm_output_epilogue (FALSE);
9345 ;; Length is absolute worst case
9346 [(set_attr "length" "44")
9347 (set_attr "type" "block")
9348 ;; We don't clobber the conditions, but the potential length of this
9349 ;; operation is sufficient to make conditionalizing the sequence
9350 ;; unlikely to be profitable.
9351 (set_attr "conds" "clob")]
9354 (define_insn "*epilogue_insns"
9355 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9359 return arm_output_epilogue (TRUE);
9360 else /* TARGET_THUMB */
9361 return thumb_unexpanded_epilogue ();
9363 ; Length is absolute worst case
9364 [(set_attr "length" "44")
9365 (set_attr "type" "block")
9366 ;; We don't clobber the conditions, but the potential length of this
9367 ;; operation is sufficient to make conditionalizing the sequence
9368 ;; unlikely to be profitable.
9369 (set_attr "conds" "clob")]
9372 (define_expand "eh_epilogue"
9373 [(use (match_operand:SI 0 "register_operand" ""))
9374 (use (match_operand:SI 1 "register_operand" ""))
9375 (use (match_operand:SI 2 "register_operand" ""))]
9379 cfun->machine->eh_epilogue_sp_ofs = operands[1];
9380 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9382 rtx ra = gen_rtx_REG (Pmode, 2);
9384 emit_move_insn (ra, operands[2]);
9387 /* This is a hack -- we may have crystalized the function type too
9389 cfun->machine->func_type = 0;
9393 ;; This split is only used during output to reduce the number of patterns
9394 ;; that need assembler instructions adding to them. We allowed the setting
9395 ;; of the conditions to be implicit during rtl generation so that
9396 ;; the conditional compare patterns would work. However this conflicts to
9397 ;; some extent with the conditional data operations, so we have to split them
9401 [(set (match_operand:SI 0 "s_register_operand" "")
9402 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9403 [(match_operand 2 "" "") (match_operand 3 "" "")])
9405 (match_operand 4 "" "")))
9406 (clobber (reg:CC CC_REGNUM))]
9407 "TARGET_ARM && reload_completed"
9408 [(set (match_dup 5) (match_dup 6))
9409 (cond_exec (match_dup 7)
9410 (set (match_dup 0) (match_dup 4)))]
9413 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9414 operands[2], operands[3]);
9415 enum rtx_code rc = GET_CODE (operands[1]);
9417 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9418 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9419 if (mode == CCFPmode || mode == CCFPEmode)
9420 rc = reverse_condition_maybe_unordered (rc);
9422 rc = reverse_condition (rc);
9424 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9429 [(set (match_operand:SI 0 "s_register_operand" "")
9430 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9431 [(match_operand 2 "" "") (match_operand 3 "" "")])
9432 (match_operand 4 "" "")
9434 (clobber (reg:CC CC_REGNUM))]
9435 "TARGET_ARM && reload_completed"
9436 [(set (match_dup 5) (match_dup 6))
9437 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9438 (set (match_dup 0) (match_dup 4)))]
9441 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9442 operands[2], operands[3]);
9444 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9445 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9450 [(set (match_operand:SI 0 "s_register_operand" "")
9451 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9452 [(match_operand 2 "" "") (match_operand 3 "" "")])
9453 (match_operand 4 "" "")
9454 (match_operand 5 "" "")))
9455 (clobber (reg:CC CC_REGNUM))]
9456 "TARGET_ARM && reload_completed"
9457 [(set (match_dup 6) (match_dup 7))
9458 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9459 (set (match_dup 0) (match_dup 4)))
9460 (cond_exec (match_dup 8)
9461 (set (match_dup 0) (match_dup 5)))]
9464 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9465 operands[2], operands[3]);
9466 enum rtx_code rc = GET_CODE (operands[1]);
9468 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9469 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9470 if (mode == CCFPmode || mode == CCFPEmode)
9471 rc = reverse_condition_maybe_unordered (rc);
9473 rc = reverse_condition (rc);
9475 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9480 [(set (match_operand:SI 0 "s_register_operand" "")
9481 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9482 [(match_operand:SI 2 "s_register_operand" "")
9483 (match_operand:SI 3 "arm_add_operand" "")])
9484 (match_operand:SI 4 "arm_rhs_operand" "")
9486 (match_operand:SI 5 "s_register_operand" ""))))
9487 (clobber (reg:CC CC_REGNUM))]
9488 "TARGET_ARM && reload_completed"
9489 [(set (match_dup 6) (match_dup 7))
9490 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9491 (set (match_dup 0) (match_dup 4)))
9492 (cond_exec (match_dup 8)
9493 (set (match_dup 0) (not:SI (match_dup 5))))]
9496 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9497 operands[2], operands[3]);
9498 enum rtx_code rc = GET_CODE (operands[1]);
9500 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9501 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
9502 if (mode == CCFPmode || mode == CCFPEmode)
9503 rc = reverse_condition_maybe_unordered (rc);
9505 rc = reverse_condition (rc);
9507 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9511 (define_insn "*cond_move_not"
9512 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9513 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9514 [(match_operand 3 "cc_register" "") (const_int 0)])
9515 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9517 (match_operand:SI 2 "s_register_operand" "r,r"))))]
9521 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9522 [(set_attr "conds" "use")
9523 (set_attr "length" "4,8")]
9526 ;; The next two patterns occur when an AND operation is followed by a
9527 ;; scc insn sequence
9529 (define_insn "*sign_extract_onebit"
9530 [(set (match_operand:SI 0 "s_register_operand" "=r")
9531 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9533 (match_operand:SI 2 "const_int_operand" "n")))
9534 (clobber (reg:CC CC_REGNUM))]
9537 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9538 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9539 return \"mvnne\\t%0, #0\";
9541 [(set_attr "conds" "clob")
9542 (set_attr "length" "8")]
9545 (define_insn "*not_signextract_onebit"
9546 [(set (match_operand:SI 0 "s_register_operand" "=r")
9548 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9550 (match_operand:SI 2 "const_int_operand" "n"))))
9551 (clobber (reg:CC CC_REGNUM))]
9554 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9555 output_asm_insn (\"tst\\t%1, %2\", operands);
9556 output_asm_insn (\"mvneq\\t%0, #0\", operands);
9557 return \"movne\\t%0, #0\";
9559 [(set_attr "conds" "clob")
9560 (set_attr "length" "12")]
9563 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
9564 ;; expressions. For simplicity, the first register is also in the unspec
9566 (define_insn "*push_multi"
9567 [(match_parallel 2 "multi_register_push"
9568 [(set (match_operand:BLK 0 "memory_operand" "=m")
9569 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9570 UNSPEC_PUSH_MULT))])]
9574 int num_saves = XVECLEN (operands[2], 0);
9576 /* For the StrongARM at least it is faster to
9577 use STR to store only a single register. */
9579 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9585 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9587 for (i = 1; i < num_saves; i++)
9589 strcat (pattern, \", %|\");
9591 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9594 strcat (pattern, \"}\");
9595 output_asm_insn (pattern, operands);
9600 [(set_attr "type" "store4")]
9603 (define_insn "stack_tie"
9604 [(set (mem:BLK (scratch))
9605 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9606 (match_operand:SI 1 "s_register_operand" "r")]
9610 [(set_attr "length" "0")]
9613 ;; Similarly for the floating point registers
9614 (define_insn "*push_fp_multi"
9615 [(match_parallel 2 "multi_register_push"
9616 [(set (match_operand:BLK 0 "memory_operand" "=m")
9617 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9618 UNSPEC_PUSH_MULT))])]
9624 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9625 output_asm_insn (pattern, operands);
9628 [(set_attr "type" "f_store")]
9631 ;; Special patterns for dealing with the constant pool
9633 (define_insn "align_4"
9634 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9637 assemble_align (32);
9642 (define_insn "align_8"
9643 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
9644 "TARGET_REALLY_IWMMXT"
9646 assemble_align (64);
9651 (define_insn "consttable_end"
9652 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9655 making_const_table = FALSE;
9660 (define_insn "consttable_1"
9661 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9664 making_const_table = TRUE;
9665 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9669 [(set_attr "length" "4")]
9672 (define_insn "consttable_2"
9673 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9676 making_const_table = TRUE;
9677 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9681 [(set_attr "length" "4")]
9684 (define_insn "consttable_4"
9685 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9689 making_const_table = TRUE;
9690 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9695 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9696 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9700 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9705 [(set_attr "length" "4")]
9708 (define_insn "consttable_8"
9709 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9713 making_const_table = TRUE;
9714 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9719 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9720 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9724 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9729 [(set_attr "length" "8")]
9732 ;; Miscellaneous Thumb patterns
9734 (define_expand "tablejump"
9735 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
9736 (use (label_ref (match_operand 1 "" "")))])]
9741 /* Hopefully, CSE will eliminate this copy. */
9742 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
9743 rtx reg2 = gen_reg_rtx (SImode);
9745 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
9751 (define_insn "*thumb_tablejump"
9752 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9753 (use (label_ref (match_operand 1 "" "")))]
9756 [(set_attr "length" "2")]
9761 (define_insn "clzsi2"
9762 [(set (match_operand:SI 0 "s_register_operand" "=r")
9763 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
9764 "TARGET_ARM && arm_arch5"
9766 [(set_attr "predicable" "yes")])
9768 (define_expand "ffssi2"
9769 [(set (match_operand:SI 0 "s_register_operand" "")
9770 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9771 "TARGET_ARM && arm_arch5"
9776 t1 = gen_reg_rtx (SImode);
9777 t2 = gen_reg_rtx (SImode);
9778 t3 = gen_reg_rtx (SImode);
9780 emit_insn (gen_negsi2 (t1, operands[1]));
9781 emit_insn (gen_andsi3 (t2, operands[1], t1));
9782 emit_insn (gen_clzsi2 (t3, t2));
9783 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
9788 (define_expand "ctzsi2"
9789 [(set (match_operand:SI 0 "s_register_operand" "")
9790 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
9791 "TARGET_ARM && arm_arch5"
9796 t1 = gen_reg_rtx (SImode);
9797 t2 = gen_reg_rtx (SImode);
9798 t3 = gen_reg_rtx (SImode);
9800 emit_insn (gen_negsi2 (t1, operands[1]));
9801 emit_insn (gen_andsi3 (t2, operands[1], t1));
9802 emit_insn (gen_clzsi2 (t3, t2));
9803 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
9808 ;; V5E instructions.
9810 (define_insn "prefetch"
9811 [(prefetch (match_operand:SI 0 "address_operand" "p")
9812 (match_operand:SI 1 "" "")
9813 (match_operand:SI 2 "" ""))]
9814 "TARGET_ARM && arm_arch5e"
9817 ;; General predication pattern
9820 [(match_operator 0 "arm_comparison_operator"
9821 [(match_operand 1 "cc_register" "")
9827 (define_insn "prologue_use"
9828 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
9830 "%@ %0 needed for prologue"
9833 ;; Load the FPA co-processor patterns
9835 ;; Load the Maverick co-processor patterns
9836 (include "cirrus.md")
9837 ;; Load the Intel Wireless Multimedia Extension patterns
9838 (include "iwmmxt.md")