1 ;;- Machine description for ARM for GNU compiler
2 ;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;; 2001, 2002 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 GNU CC.
10 ;; GNU CC is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; GNU CC is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU CC; 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.
27 ;; There are patterns in this file to support XFmode arithmetic.
28 ;; Unfortunately RISC iX doesn't work well with these so they are disabled.
31 ;;---------------------------------------------------------------------------
36 [(IP_REGNUM 12) ; Scratch register
37 (SP_REGNUM 13) ; Stack pointer
38 (LR_REGNUM 14) ; Return address register
39 (PC_REGNUM 15) ; Program counter
40 (CC_REGNUM 24) ; Condition code pseudo register
46 ;; Note: sin and cos are no-longer used.
49 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
50 ; operand 0 is the result,
51 ; operand 1 the parameter.
52 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
53 ; operand 0 is the result,
54 ; operand 1 the parameter.
55 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
56 ; operand 0 is the first register,
57 ; subsequent registers are in parallel (use ...)
59 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
60 ; usage, that is, we will add the pic_register
61 ; value to it before trying to dereference it.
62 (UNSPEC_PRLG_STK 4) ; A special barrier that prevents frame accesses
63 ; being scheduled before the stack adjustment insn.
64 (UNSPEC_CLZ 5) ; `clz' instruction, count leading zeros (SImode):
65 ; operand 0 is the result,
66 ; operand 1 is the parameter.
67 (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
68 ; this unspec is used to prevent the deletion of
69 ; instructions setting registers for EH handling
70 ; and stack frame generation. Operand 0 is the
75 ;; UNSPEC_VOLATILE Usage:
78 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
80 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
81 ; instruction epilogue sequence that isn't expanded
82 ; into normal RTL. Used for both normal and sibcall
84 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
85 ; for inlined constants.
86 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
88 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
90 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
92 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
94 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
99 ;;---------------------------------------------------------------------------
102 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
103 ; generating ARM code. This is used to control the length of some insn
104 ; patterns that share the same RTL in both ARM and Thumb code.
105 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
107 ; PROG_MODE attribute is used to determine whether condition codes are
108 ; clobbered by a call insn: they are if in prog32 mode. This is controlled
109 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
110 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
112 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
113 ; scheduling decisions for the load unit and the multiplier.
114 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
116 ;; Operand number of an input operand that is shifted. Zero if the
117 ;; given instruction does not shift one of its input operands.
118 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_is_xscale")))
119 (define_attr "shift" "" (const_int 0))
121 ; Floating Point Unit. If we only have floating point emulation, then there
122 ; is no point in scheduling the floating point insns. (Well, for best
123 ; performance we should try and group them together).
124 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
126 ; LENGTH of an instruction (in bytes)
127 (define_attr "length" "" (const_int 4))
129 ; POOL_RANGE is how far away from a constant pool entry that this insn
130 ; can be placed. If the distance is zero, then this insn will never
131 ; reference the pool.
132 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
133 ; before its address.
134 (define_attr "pool_range" "" (const_int 0))
135 (define_attr "neg_pool_range" "" (const_int 0))
137 ; An assembler sequence may clobber the condition codes without us knowing.
138 ; If such an insn references the pool, then we have no way of knowing how,
139 ; so use the most conservative value for pool_range.
140 (define_asm_attributes
141 [(set_attr "conds" "clob")
142 (set_attr "length" "4")
143 (set_attr "pool_range" "250")])
145 ; TYPE attribute is used to detect floating point instructions which, if
146 ; running on a co-processor can run in parallel with other, basic instructions
147 ; If write-buffer scheduling is enabled then it can also be used in the
148 ; scheduling of writes.
150 ; Classification of each insn
151 ; normal any data instruction that doesn't hit memory or fp regs
152 ; mult a multiply instruction
153 ; block blockage insn, this blocks all functional units
154 ; float a floating point arithmetic operation (subject to expansion)
155 ; fdivx XFmode floating point division
156 ; fdivd DFmode floating point division
157 ; fdivs SFmode floating point division
158 ; fmul Floating point multiply
159 ; ffmul Fast floating point multiply
160 ; farith Floating point arithmetic (4 cycle)
161 ; ffarith Fast floating point arithmetic (2 cycle)
162 ; float_em a floating point arithmetic operation that is normally emulated
163 ; even on a machine with an fpa.
164 ; f_load a floating point load from memory
165 ; f_store a floating point store to memory
166 ; f_mem_r a transfer of a floating point register to a real reg via mem
167 ; r_mem_f the reverse of f_mem_r
168 ; f_2_r fast transfer float to arm (no memory needed)
169 ; r_2_f fast transfer arm to float
170 ; call a subroutine call
171 ; load any load from memory
172 ; store1 store 1 word to memory from arm registers
173 ; store2 store 2 words
174 ; store3 store 3 words
175 ; store4 store 4 words
178 "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"
179 (const_string "normal"))
181 ; Load scheduling, set from the arm_ld_sched variable
182 ; initialised by arm_override_options()
183 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
185 ; condition codes: this one is used by final_prescan_insn to speed up
186 ; conditionalizing instructions. It saves having to scan the rtl to see if
187 ; it uses or alters the condition codes.
189 ; USE means that the condition codes are used by the insn in the process of
190 ; outputting code, this means (at present) that we can't use the insn in
193 ; SET means that the purpose of the insn is to set the condition codes in a
194 ; well defined manner.
196 ; CLOB means that the condition codes are altered in an undefined manner, if
197 ; they are altered at all
199 ; JUMP_CLOB is used when the condition cannot be represented by a single
200 ; instruction (UNEQ and LTGT). These cannot be predicated.
202 ; NOCOND means that the condition codes are neither altered nor affect the
203 ; output of this insn
205 (define_attr "conds" "use,set,clob,jump_clob,nocond"
206 (if_then_else (eq_attr "type" "call")
207 (if_then_else (eq_attr "prog_mode" "prog32")
208 (const_string "clob") (const_string "nocond"))
209 (const_string "nocond")))
211 ; Predicable means that the insn can be conditionally executed based on
212 ; an automatically added predicate (additional patterns are generated by
213 ; gen...). We default to 'no' because no Thumb patterns match this rule
214 ; and not all ARM patterns do.
215 (define_attr "predicable" "no,yes" (const_string "no"))
217 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
218 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
219 ; suffer blockages enough to warrent modelling this (and it can adversely
220 ; affect the schedule).
221 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
223 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
224 ; to stall the processor. Used with model_wbuf above.
225 (define_attr "write_conflict" "no,yes"
226 (if_then_else (eq_attr "type"
227 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
229 (const_string "no")))
231 ; Classify the insns into those that take one cycle and those that take more
232 ; than one on the main cpu execution unit.
233 (define_attr "core_cycles" "single,multi"
234 (if_then_else (eq_attr "type"
235 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
236 (const_string "single")
237 (const_string "multi")))
239 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
240 ;; distant label. Only applicable to Thumb code.
241 (define_attr "far_jump" "yes,no" (const_string "no"))
243 ;; (define_function_unit {name} {num-units} {n-users} {test}
244 ;; {ready-delay} {issue-delay} [{conflict-list}])
246 ;;--------------------------------------------------------------------
247 ;; Floating point unit (FPA)
248 ;;--------------------------------------------------------------------
249 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
250 (eq_attr "type" "fdivx")) 71 69)
252 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
253 (eq_attr "type" "fdivd")) 59 57)
255 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
256 (eq_attr "type" "fdivs")) 31 29)
258 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
259 (eq_attr "type" "fmul")) 9 7)
261 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
262 (eq_attr "type" "ffmul")) 6 4)
264 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
265 (eq_attr "type" "farith")) 4 2)
267 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
268 (eq_attr "type" "ffarith")) 2 2)
270 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
271 (eq_attr "type" "r_2_f")) 5 3)
273 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
274 (eq_attr "type" "f_2_r")) 1 2)
276 ; The fpa10 doesn't really have a memory read unit, but it can start to
277 ; speculatively execute the instruction in the pipeline, provided the data
278 ; is already loaded, so pretend reads have a delay of 2 (and that the
279 ; pipeline is infinite).
281 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
282 (eq_attr "type" "f_load")) 3 1)
284 ;;--------------------------------------------------------------------
286 ;;--------------------------------------------------------------------
287 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
289 ; The write buffer on some of the arm6 processors is hard to model exactly.
290 ; There is room in the buffer for up to two addresses and up to eight words
291 ; of memory, but the two needn't be split evenly. When writing the two
292 ; addresses are fully pipelined. However, a read from memory that is not
293 ; currently in the cache will block until the writes have completed.
294 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
295 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
296 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
297 ; cycle to add as well.
299 (define_function_unit "write_buf" 1 2
300 (and (eq_attr "model_wbuf" "yes")
301 (eq_attr "type" "store1,r_mem_f")) 5 3)
302 (define_function_unit "write_buf" 1 2
303 (and (eq_attr "model_wbuf" "yes")
304 (eq_attr "type" "store2")) 7 4)
305 (define_function_unit "write_buf" 1 2
306 (and (eq_attr "model_wbuf" "yes")
307 (eq_attr "type" "store3")) 9 5)
308 (define_function_unit "write_buf" 1 2
309 (and (eq_attr "model_wbuf" "yes")
310 (eq_attr "type" "store4")) 11 6)
312 ;;--------------------------------------------------------------------
313 ;; Write blockage unit
314 ;;--------------------------------------------------------------------
315 ; The write_blockage unit models (partially), the fact that reads will stall
316 ; until the write buffer empties.
317 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
318 ; so we don't model them here
319 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
320 (eq_attr "type" "store1")) 5 5
321 [(eq_attr "write_conflict" "yes")])
322 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
323 (eq_attr "type" "store2")) 7 7
324 [(eq_attr "write_conflict" "yes")])
325 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
326 (eq_attr "type" "store3")) 9 9
327 [(eq_attr "write_conflict" "yes")])
328 (define_function_unit "write_blockage" 1 0
329 (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
330 [(eq_attr "write_conflict" "yes")])
331 (define_function_unit "write_blockage" 1 0
332 (and (eq_attr "model_wbuf" "yes")
333 (eq_attr "write_conflict" "yes")) 1 1)
335 ;;--------------------------------------------------------------------
337 ;;--------------------------------------------------------------------
338 ; Everything must spend at least one cycle in the core unit
339 (define_function_unit "core" 1 0 (eq_attr "core_cycles" "single") 1 1)
341 (define_function_unit "core" 1 0
342 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
344 (define_function_unit "core" 1 0
345 (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
347 ;; We do not need to conditionalize the define_function_unit immediately
348 ;; above. This one will be ignored for anything other than xscale
349 ;; compiles and for xscale compiles it provides a larger delay
350 ;; and the scheduler will DTRT.
351 ;; FIXME: this test needs to be revamped to not depend on this feature
354 (define_function_unit "core" 1 0
355 (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
356 (eq_attr "is_xscale" "yes"))
359 (define_function_unit "core" 1 0
360 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
362 (define_function_unit "core" 1 0
363 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
365 (define_function_unit "core" 1 0
366 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
368 (define_function_unit "core" 1 0
369 (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
371 (define_function_unit "core" 1 0
372 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
374 (define_function_unit "core" 1 0
375 (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
377 (define_function_unit "core" 1 0
378 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
379 (eq_attr "type" "mult")) 4 4)
381 (define_function_unit "core" 1 0
382 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
383 (eq_attr "type" "mult")) 3 2)
385 (define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
387 (define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
389 (define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
391 (define_function_unit "core" 1 0
392 (and (eq_attr "core_cycles" "multi")
393 (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
395 ;;---------------------------------------------------------------------------
400 ;; Note: For DImode insns, there is normally no reason why operands should
401 ;; not be in the same register, what we don't want is for something being
402 ;; written to partially overlap something that is an input.
404 (define_expand "adddi3"
406 [(set (match_operand:DI 0 "s_register_operand" "")
407 (plus:DI (match_operand:DI 1 "s_register_operand" "")
408 (match_operand:DI 2 "s_register_operand" "")))
409 (clobber (reg:CC CC_REGNUM))])]
414 if (GET_CODE (operands[1]) != REG)
415 operands[1] = force_reg (SImode, operands[1]);
416 if (GET_CODE (operands[2]) != REG)
417 operands[2] = force_reg (SImode, operands[2]);
422 (define_insn "*thumb_adddi3"
423 [(set (match_operand:DI 0 "register_operand" "=l")
424 (plus:DI (match_operand:DI 1 "register_operand" "%0")
425 (match_operand:DI 2 "register_operand" "l")))
426 (clobber (reg:CC CC_REGNUM))
429 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
430 [(set_attr "length" "4")]
433 (define_insn_and_split "*arm_adddi3"
434 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
435 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
436 (match_operand:DI 2 "s_register_operand" "r, 0")))
437 (clobber (reg:CC CC_REGNUM))]
440 "TARGET_ARM && reload_completed"
441 [(parallel [(set (reg:CC_C CC_REGNUM)
442 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
444 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
445 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
446 (plus:SI (match_dup 4) (match_dup 5))))]
449 operands[3] = gen_highpart (SImode, operands[0]);
450 operands[0] = gen_lowpart (SImode, operands[0]);
451 operands[4] = gen_highpart (SImode, operands[1]);
452 operands[1] = gen_lowpart (SImode, operands[1]);
453 operands[5] = gen_highpart (SImode, operands[2]);
454 operands[2] = gen_lowpart (SImode, operands[2]);
456 [(set_attr "conds" "clob")
457 (set_attr "length" "8")]
460 (define_insn_and_split "*adddi_sesidi_di"
461 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
462 (plus:DI (sign_extend:DI
463 (match_operand:SI 2 "s_register_operand" "r,r"))
464 (match_operand:DI 1 "s_register_operand" "r,0")))
465 (clobber (reg:CC CC_REGNUM))]
468 "TARGET_ARM && reload_completed"
469 [(parallel [(set (reg:CC_C CC_REGNUM)
470 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
472 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
473 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
474 (plus:SI (ashiftrt:SI (match_dup 2)
479 operands[3] = gen_highpart (SImode, operands[0]);
480 operands[0] = gen_lowpart (SImode, operands[0]);
481 operands[4] = gen_highpart (SImode, operands[1]);
482 operands[1] = gen_lowpart (SImode, operands[1]);
483 operands[2] = gen_lowpart (SImode, operands[2]);
485 [(set_attr "conds" "clob")
486 (set_attr "length" "8")]
489 (define_insn_and_split "*adddi_zesidi_di"
490 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
491 (plus:DI (zero_extend:DI
492 (match_operand:SI 2 "s_register_operand" "r,r"))
493 (match_operand:DI 1 "s_register_operand" "r,0")))
494 (clobber (reg:CC CC_REGNUM))]
497 "TARGET_ARM && reload_completed"
498 [(parallel [(set (reg:CC_C CC_REGNUM)
499 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
501 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
502 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
503 (plus:SI (match_dup 4) (const_int 0))))]
506 operands[3] = gen_highpart (SImode, operands[0]);
507 operands[0] = gen_lowpart (SImode, operands[0]);
508 operands[4] = gen_highpart (SImode, operands[1]);
509 operands[1] = gen_lowpart (SImode, operands[1]);
510 operands[2] = gen_lowpart (SImode, operands[2]);
512 [(set_attr "conds" "clob")
513 (set_attr "length" "8")]
516 (define_expand "addsi3"
517 [(set (match_operand:SI 0 "s_register_operand" "")
518 (plus:SI (match_operand:SI 1 "s_register_operand" "")
519 (match_operand:SI 2 "reg_or_int_operand" "")))]
522 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
524 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
526 (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
532 ; If there is a scratch available, this will be faster than synthesising the
535 [(match_scratch:SI 3 "r")
536 (set (match_operand:SI 0 "s_register_operand" "")
537 (plus:SI (match_operand:SI 1 "s_register_operand" "")
538 (match_operand:SI 2 "const_int_operand" "")))]
540 !(const_ok_for_arm (INTVAL (operands[2]))
541 || const_ok_for_arm (-INTVAL (operands[2])))
542 && const_ok_for_arm (~INTVAL (operands[2]))"
543 [(set (match_dup 3) (match_dup 2))
544 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
548 (define_insn_and_split "*arm_addsi3"
549 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
550 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
551 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
558 GET_CODE (operands[2]) == CONST_INT
559 && !(const_ok_for_arm (INTVAL (operands[2]))
560 || const_ok_for_arm (-INTVAL (operands[2])))"
561 [(clobber (const_int 0))]
563 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
567 [(set_attr "length" "4,4,16")
568 (set_attr "predicable" "yes")]
571 ;; Register group 'k' is a single register group containing only the stack
572 ;; register. Trying to reload it will always fail catastrophically,
573 ;; so never allow those alternatives to match if reloading is needed.
575 (define_insn "*thumb_addsi3"
576 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
577 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
578 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
581 static const char * const asms[] =
583 \"add\\t%0, %0, %2\",
584 \"sub\\t%0, %0, #%n2\",
585 \"add\\t%0, %1, %2\",
586 \"add\\t%0, %0, %2\",
587 \"add\\t%0, %0, %2\",
588 \"add\\t%0, %1, %2\",
591 if ((which_alternative == 2 || which_alternative == 6)
592 && GET_CODE (operands[2]) == CONST_INT
593 && INTVAL (operands[2]) < 0)
594 return \"sub\\t%0, %1, #%n2\";
595 return asms[which_alternative];
597 [(set_attr "length" "2")]
600 ;; Reloading and elimination of the frame pointer can
601 ;; sometimes cause this optimization to be missed.
603 [(set (match_operand:SI 0 "register_operand" "")
604 (match_operand:SI 1 "const_int_operand" ""))
606 (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
608 && REGNO (operands[2]) == STACK_POINTER_REGNUM
609 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
610 && (INTVAL (operands[1]) & 3) == 0"
611 [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
615 (define_insn "*addsi3_compare0"
616 [(set (reg:CC_NOOV CC_REGNUM)
618 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
619 (match_operand:SI 2 "arm_add_operand" "rI,L"))
621 (set (match_operand:SI 0 "s_register_operand" "=r,r")
622 (plus:SI (match_dup 1) (match_dup 2)))]
626 sub%?s\\t%0, %1, #%n2"
627 [(set_attr "conds" "set")]
630 (define_insn "*addsi3_compare0_scratch"
631 [(set (reg:CC_NOOV CC_REGNUM)
633 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
634 (match_operand:SI 1 "arm_add_operand" "rI,L"))
640 [(set_attr "conds" "set")]
643 ;; These patterns are the same ones as the two regular addsi3_compare0
644 ;; patterns, except we write them slightly different - the combiner
645 ;; tends to generate them this way.
646 (define_insn "*addsi3_compare0_for_combiner"
647 [(set (reg:CC CC_REGNUM)
649 (match_operand:SI 1 "s_register_operand" "r,r")
650 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
651 (set (match_operand:SI 0 "s_register_operand" "=r,r")
652 (plus:SI (match_dup 1) (match_dup 2)))]
656 sub%?s\\t%0, %1, #%n2"
657 [(set_attr "conds" "set")]
660 (define_insn "*addsi3_compare0_scratch_for_combiner"
661 [(set (reg:CC CC_REGNUM)
663 (match_operand:SI 0 "s_register_operand" "r,r")
664 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
669 [(set_attr "conds" "set")]
672 ;; The next four insns work because they compare the result with one of
673 ;; the operands, and we know that the use of the condition code is
674 ;; either GEU or LTU, so we can use the carry flag from the addition
675 ;; instead of doing the compare a second time.
676 (define_insn "*addsi3_compare_op1"
677 [(set (reg:CC_C CC_REGNUM)
679 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
680 (match_operand:SI 2 "arm_add_operand" "rI,L"))
682 (set (match_operand:SI 0 "s_register_operand" "=r,r")
683 (plus:SI (match_dup 1) (match_dup 2)))]
687 sub%?s\\t%0, %1, #%n2"
688 [(set_attr "conds" "set")]
691 (define_insn "*addsi3_compare_op2"
692 [(set (reg:CC_C CC_REGNUM)
694 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
695 (match_operand:SI 2 "arm_add_operand" "rI,L"))
697 (set (match_operand:SI 0 "s_register_operand" "=r,r")
698 (plus:SI (match_dup 1) (match_dup 2)))]
702 sub%?s\\t%0, %1, #%n2"
703 [(set_attr "conds" "set")]
706 (define_insn "*compare_addsi2_op0"
707 [(set (reg:CC_C CC_REGNUM)
709 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
710 (match_operand:SI 1 "arm_add_operand" "rI,L"))
716 [(set_attr "conds" "set")]
719 (define_insn "*compare_addsi2_op1"
720 [(set (reg:CC_C CC_REGNUM)
722 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
723 (match_operand:SI 1 "arm_add_operand" "rI,L"))
729 [(set_attr "conds" "set")]
732 (define_insn "*addsi3_carryin"
733 [(set (match_operand:SI 0 "s_register_operand" "=r")
734 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
735 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
736 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
739 [(set_attr "conds" "use")]
742 (define_insn "*addsi3_carryin_shift"
743 [(set (match_operand:SI 0 "s_register_operand" "")
744 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
746 (match_operator:SI 2 "shift_operator"
747 [(match_operand:SI 3 "s_register_operand" "")
748 (match_operand:SI 4 "reg_or_int_operand" "")])
749 (match_operand:SI 1 "s_register_operand" ""))))]
751 "adc%?\\t%0, %1, %3%S2"
752 [(set_attr "conds" "use")]
755 (define_insn "*addsi3_carryin_alt1"
756 [(set (match_operand:SI 0 "s_register_operand" "=r")
757 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
758 (match_operand:SI 2 "arm_rhs_operand" "rI"))
759 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
762 [(set_attr "conds" "use")]
765 (define_insn "*addsi3_carryin_alt2"
766 [(set (match_operand:SI 0 "s_register_operand" "=r")
767 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
768 (match_operand:SI 1 "s_register_operand" "r"))
769 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
772 [(set_attr "conds" "use")]
775 (define_insn "*addsi3_carryin_alt3"
776 [(set (match_operand:SI 0 "s_register_operand" "=r")
777 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
778 (match_operand:SI 2 "arm_rhs_operand" "rI"))
779 (match_operand:SI 1 "s_register_operand" "r")))]
782 [(set_attr "conds" "use")]
785 (define_insn "incscc"
786 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
787 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
788 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
789 (match_operand:SI 1 "s_register_operand" "0,?r")))]
793 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
794 [(set_attr "conds" "use")
795 (set_attr "length" "4,8")]
798 (define_insn "addsf3"
799 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
800 (plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
801 (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
802 "TARGET_ARM && TARGET_HARD_FLOAT"
805 suf%?s\\t%0, %1, #%N2"
806 [(set_attr "type" "farith")
807 (set_attr "predicable" "yes")]
810 (define_insn "adddf3"
811 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
812 (plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
813 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
814 "TARGET_ARM && TARGET_HARD_FLOAT"
817 suf%?d\\t%0, %1, #%N2"
818 [(set_attr "type" "farith")
819 (set_attr "predicable" "yes")]
822 (define_insn "*adddf_esfdf_df"
823 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
824 (plus:DF (float_extend:DF
825 (match_operand:SF 1 "s_register_operand" "f,f"))
826 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
827 "TARGET_ARM && TARGET_HARD_FLOAT"
830 suf%?d\\t%0, %1, #%N2"
831 [(set_attr "type" "farith")
832 (set_attr "predicable" "yes")]
835 (define_insn "*adddf_df_esfdf"
836 [(set (match_operand:DF 0 "s_register_operand" "=f")
837 (plus:DF (match_operand:DF 1 "s_register_operand" "f")
839 (match_operand:SF 2 "s_register_operand" "f"))))]
840 "TARGET_ARM && TARGET_HARD_FLOAT"
841 "adf%?d\\t%0, %1, %2"
842 [(set_attr "type" "farith")
843 (set_attr "predicable" "yes")]
846 (define_insn "*adddf_esfdf_esfdf"
847 [(set (match_operand:DF 0 "s_register_operand" "=f")
848 (plus:DF (float_extend:DF
849 (match_operand:SF 1 "s_register_operand" "f"))
851 (match_operand:SF 2 "s_register_operand" "f"))))]
852 "TARGET_ARM && TARGET_HARD_FLOAT"
853 "adf%?d\\t%0, %1, %2"
854 [(set_attr "type" "farith")
855 (set_attr "predicable" "yes")]
858 (define_insn "addxf3"
859 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
860 (plus:XF (match_operand:XF 1 "s_register_operand" "f,f")
861 (match_operand:XF 2 "fpu_add_operand" "fG,H")))]
862 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
865 suf%?e\\t%0, %1, #%N2"
866 [(set_attr "type" "farith")
867 (set_attr "predicable" "yes")]
870 (define_expand "subdi3"
872 [(set (match_operand:DI 0 "s_register_operand" "")
873 (minus:DI (match_operand:DI 1 "s_register_operand" "")
874 (match_operand:DI 2 "s_register_operand" "")))
875 (clobber (reg:CC CC_REGNUM))])]
880 if (GET_CODE (operands[1]) != REG)
881 operands[1] = force_reg (SImode, operands[1]);
882 if (GET_CODE (operands[2]) != REG)
883 operands[2] = force_reg (SImode, operands[2]);
888 (define_insn "*arm_subdi3"
889 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
890 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
891 (match_operand:DI 2 "s_register_operand" "r,0,0")))
892 (clobber (reg:CC CC_REGNUM))]
894 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
895 [(set_attr "conds" "clob")
896 (set_attr "length" "8")]
899 (define_insn "*thumb_subdi3"
900 [(set (match_operand:DI 0 "register_operand" "=l")
901 (minus:DI (match_operand:DI 1 "register_operand" "0")
902 (match_operand:DI 2 "register_operand" "l")))
903 (clobber (reg:CC CC_REGNUM))]
905 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
906 [(set_attr "length" "4")]
909 (define_insn "*subdi_di_zesidi"
910 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
911 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
913 (match_operand:SI 2 "s_register_operand" "r,r"))))
914 (clobber (reg:CC CC_REGNUM))]
916 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
917 [(set_attr "conds" "clob")
918 (set_attr "length" "8")]
921 (define_insn "*subdi_di_sesidi"
922 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
923 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
925 (match_operand:SI 2 "s_register_operand" "r,r"))))
926 (clobber (reg:CC CC_REGNUM))]
928 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
929 [(set_attr "conds" "clob")
930 (set_attr "length" "8")]
933 (define_insn "*subdi_zesidi_di"
934 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
935 (minus:DI (zero_extend:DI
936 (match_operand:SI 2 "s_register_operand" "r,r"))
937 (match_operand:DI 1 "s_register_operand" "?r,0")))
938 (clobber (reg:CC CC_REGNUM))]
940 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
941 [(set_attr "conds" "clob")
942 (set_attr "length" "8")]
945 (define_insn "*subdi_sesidi_di"
946 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
947 (minus:DI (sign_extend:DI
948 (match_operand:SI 2 "s_register_operand" "r,r"))
949 (match_operand:DI 1 "s_register_operand" "?r,0")))
950 (clobber (reg:CC CC_REGNUM))]
952 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
953 [(set_attr "conds" "clob")
954 (set_attr "length" "8")]
957 (define_insn "*subdi_zesidi_zesidi"
958 [(set (match_operand:DI 0 "s_register_operand" "=r")
959 (minus:DI (zero_extend:DI
960 (match_operand:SI 1 "s_register_operand" "r"))
962 (match_operand:SI 2 "s_register_operand" "r"))))
963 (clobber (reg:CC CC_REGNUM))]
965 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
966 [(set_attr "conds" "clob")
967 (set_attr "length" "8")]
970 (define_expand "subsi3"
971 [(set (match_operand:SI 0 "s_register_operand" "")
972 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
973 (match_operand:SI 2 "s_register_operand" "")))]
976 if (GET_CODE (operands[1]) == CONST_INT)
980 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
983 : preserve_subexpressions_p ()));
986 else /* TARGET_THUMB */
987 operands[1] = force_reg (SImode, operands[1]);
992 (define_insn "*thumb_subsi3_insn"
993 [(set (match_operand:SI 0 "register_operand" "=l")
994 (minus:SI (match_operand:SI 1 "register_operand" "l")
995 (match_operand:SI 2 "register_operand" "l")))]
998 [(set_attr "length" "2")]
1001 (define_insn_and_split "*arm_subsi3_insn"
1002 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1003 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
1004 (match_operand:SI 2 "s_register_operand" "r,r")))]
1010 && GET_CODE (operands[1]) == CONST_INT
1011 && !const_ok_for_arm (INTVAL (operands[1]))"
1012 [(clobber (const_int 0))]
1014 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1018 [(set_attr "length" "4,16")
1019 (set_attr "predicable" "yes")]
1023 [(match_scratch:SI 3 "r")
1024 (set (match_operand:SI 0 "s_register_operand" "")
1025 (minus:SI (match_operand:SI 1 "const_int_operand" "")
1026 (match_operand:SI 2 "s_register_operand" "")))]
1028 && !const_ok_for_arm (INTVAL (operands[1]))
1029 && const_ok_for_arm (~INTVAL (operands[1]))"
1030 [(set (match_dup 3) (match_dup 1))
1031 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1035 (define_insn "*subsi3_compare0"
1036 [(set (reg:CC_NOOV CC_REGNUM)
1038 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1039 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1041 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1042 (minus:SI (match_dup 1) (match_dup 2)))]
1046 rsb%?s\\t%0, %2, %1"
1047 [(set_attr "conds" "set")]
1050 (define_insn "decscc"
1051 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1052 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1053 (match_operator:SI 2 "arm_comparison_operator"
1054 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1058 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1059 [(set_attr "conds" "use")
1060 (set_attr "length" "*,8")]
1063 (define_insn "subsf3"
1064 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1065 (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1066 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1067 "TARGET_ARM && TARGET_HARD_FLOAT"
1070 rsf%?s\\t%0, %2, %1"
1071 [(set_attr "type" "farith")]
1074 (define_insn "subdf3"
1075 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1076 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1077 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1078 "TARGET_ARM && TARGET_HARD_FLOAT"
1081 rsf%?d\\t%0, %2, %1"
1082 [(set_attr "type" "farith")
1083 (set_attr "predicable" "yes")]
1086 (define_insn "*subdf_esfdf_df"
1087 [(set (match_operand:DF 0 "s_register_operand" "=f")
1088 (minus:DF (float_extend:DF
1089 (match_operand:SF 1 "s_register_operand" "f"))
1090 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1091 "TARGET_ARM && TARGET_HARD_FLOAT"
1092 "suf%?d\\t%0, %1, %2"
1093 [(set_attr "type" "farith")
1094 (set_attr "predicable" "yes")]
1097 (define_insn "*subdf_df_esfdf"
1098 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1099 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1101 (match_operand:SF 2 "s_register_operand" "f,f"))))]
1102 "TARGET_ARM && TARGET_HARD_FLOAT"
1105 rsf%?d\\t%0, %2, %1"
1106 [(set_attr "type" "farith")
1107 (set_attr "predicable" "yes")]
1110 (define_insn "*subdf_esfdf_esfdf"
1111 [(set (match_operand:DF 0 "s_register_operand" "=f")
1112 (minus:DF (float_extend:DF
1113 (match_operand:SF 1 "s_register_operand" "f"))
1115 (match_operand:SF 2 "s_register_operand" "f"))))]
1116 "TARGET_ARM && TARGET_HARD_FLOAT"
1117 "suf%?d\\t%0, %1, %2"
1118 [(set_attr "type" "farith")
1119 (set_attr "predicable" "yes")]
1122 (define_insn "subxf3"
1123 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1124 (minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1125 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1126 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1129 rsf%?e\\t%0, %2, %1"
1130 [(set_attr "type" "farith")
1131 (set_attr "predicable" "yes")]
1134 ;; Multiplication insns
1136 (define_expand "mulsi3"
1137 [(set (match_operand:SI 0 "s_register_operand" "")
1138 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1139 (match_operand:SI 1 "s_register_operand" "")))]
1144 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1145 (define_insn "*arm_mulsi3"
1146 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1147 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1148 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1150 "mul%?\\t%0, %2, %1"
1151 [(set_attr "type" "mult")
1152 (set_attr "predicable" "yes")]
1155 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1156 ; 1 and 2; are the same, because reload will make operand 0 match
1157 ; operand 1 without realizing that this conflicts with operand 2. We fix
1158 ; this by adding another alternative to match this case, and then `reload'
1159 ; it ourselves. This alternative must come first.
1160 (define_insn "*thumb_mulsi3"
1161 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1162 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1163 (match_operand:SI 2 "register_operand" "l,l,l")))]
1166 if (which_alternative < 2)
1167 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1169 return \"mul\\t%0, %0, %2\";
1171 [(set_attr "length" "4,4,2")
1172 (set_attr "type" "mult")]
1175 (define_insn "*mulsi3_compare0"
1176 [(set (reg:CC_NOOV CC_REGNUM)
1177 (compare:CC_NOOV (mult:SI
1178 (match_operand:SI 2 "s_register_operand" "r,r")
1179 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1181 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1182 (mult:SI (match_dup 2) (match_dup 1)))]
1183 "TARGET_ARM && !arm_is_xscale"
1184 "mul%?s\\t%0, %2, %1"
1185 [(set_attr "conds" "set")
1186 (set_attr "type" "mult")]
1189 (define_insn "*mulsi_compare0_scratch"
1190 [(set (reg:CC_NOOV CC_REGNUM)
1191 (compare:CC_NOOV (mult:SI
1192 (match_operand:SI 2 "s_register_operand" "r,r")
1193 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1195 (clobber (match_scratch:SI 0 "=&r,&r"))]
1196 "TARGET_ARM && !arm_is_xscale"
1197 "mul%?s\\t%0, %2, %1"
1198 [(set_attr "conds" "set")
1199 (set_attr "type" "mult")]
1202 ;; Unnamed templates to match MLA instruction.
1204 (define_insn "*mulsi3addsi"
1205 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1207 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1208 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1209 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1211 "mla%?\\t%0, %2, %1, %3"
1212 [(set_attr "type" "mult")
1213 (set_attr "predicable" "yes")]
1216 (define_insn "*mulsi3addsi_compare0"
1217 [(set (reg:CC_NOOV CC_REGNUM)
1220 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1221 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1222 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1224 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1225 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1227 "TARGET_ARM && !arm_is_xscale"
1228 "mla%?s\\t%0, %2, %1, %3"
1229 [(set_attr "conds" "set")
1230 (set_attr "type" "mult")]
1233 (define_insn "*mulsi3addsi_compare0_scratch"
1234 [(set (reg:CC_NOOV CC_REGNUM)
1237 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1238 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1239 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1241 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1242 "TARGET_ARM && !arm_is_xscale"
1243 "mla%?s\\t%0, %2, %1, %3"
1244 [(set_attr "conds" "set")
1245 (set_attr "type" "mult")]
1248 ;; Unnamed template to match long long multiply-accumlate (smlal)
1250 (define_insn "*mulsidi3adddi"
1251 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1254 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1255 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1256 (match_operand:DI 1 "s_register_operand" "0")))]
1257 "TARGET_ARM && arm_fast_multiply"
1258 "smlal%?\\t%Q0, %R0, %3, %2"
1259 [(set_attr "type" "mult")
1260 (set_attr "predicable" "yes")]
1263 (define_insn "mulsidi3"
1264 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1266 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1267 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1268 "TARGET_ARM && arm_fast_multiply"
1269 "smull%?\\t%Q0, %R0, %1, %2"
1270 [(set_attr "type" "mult")
1271 (set_attr "predicable" "yes")]
1274 (define_insn "umulsidi3"
1275 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1277 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1278 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1279 "TARGET_ARM && arm_fast_multiply"
1280 "umull%?\\t%Q0, %R0, %1, %2"
1281 [(set_attr "type" "mult")
1282 (set_attr "predicable" "yes")]
1285 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1287 (define_insn "*umulsidi3adddi"
1288 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1291 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1292 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1293 (match_operand:DI 1 "s_register_operand" "0")))]
1294 "TARGET_ARM && arm_fast_multiply"
1295 "umlal%?\\t%Q0, %R0, %3, %2"
1296 [(set_attr "type" "mult")
1297 (set_attr "predicable" "yes")]
1300 (define_insn "smulsi3_highpart"
1301 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1305 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1306 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1308 (clobber (match_scratch:SI 3 "=&r,&r"))]
1309 "TARGET_ARM && arm_fast_multiply"
1310 "smull%?\\t%3, %0, %2, %1"
1311 [(set_attr "type" "mult")
1312 (set_attr "predicable" "yes")]
1315 (define_insn "umulsi3_highpart"
1316 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1320 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1321 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1323 (clobber (match_scratch:SI 3 "=&r,&r"))]
1324 "TARGET_ARM && arm_fast_multiply"
1325 "umull%?\\t%3, %0, %2, %1"
1326 [(set_attr "type" "mult")
1327 (set_attr "predicable" "yes")]
1330 (define_insn "mulhisi3"
1331 [(set (match_operand:SI 0 "s_register_operand" "=r")
1332 (mult:SI (sign_extend:SI
1333 (match_operand:HI 1 "s_register_operand" "%r"))
1335 (match_operand:HI 2 "s_register_operand" "r"))))]
1336 "TARGET_ARM && arm_is_xscale"
1337 "smulbb%?\\t%0, %1, %2"
1338 [(set_attr "type" "mult")]
1341 (define_insn "*mulhisi3addsi"
1342 [(set (match_operand:SI 0 "s_register_operand" "=r")
1343 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1344 (mult:SI (sign_extend:SI
1345 (match_operand:HI 2 "s_register_operand" "%r"))
1347 (match_operand:HI 3 "s_register_operand" "r")))))]
1348 "TARGET_ARM && arm_is_xscale"
1349 "smlabb%?\\t%0, %2, %3, %1"
1350 [(set_attr "type" "mult")]
1353 (define_insn "*mulhidi3adddi"
1354 [(set (match_operand:DI 0 "s_register_operand" "=r")
1356 (match_operand:DI 1 "s_register_operand" "0")
1357 (mult:DI (sign_extend:DI
1358 (match_operand:HI 2 "s_register_operand" "%r"))
1360 (match_operand:HI 3 "s_register_operand" "r")))))]
1361 "TARGET_ARM && arm_is_xscale"
1362 "smlalbb%?\\t%Q0, %R0, %2, %3"
1363 [(set_attr "type" "mult")])
1365 (define_insn "mulsf3"
1366 [(set (match_operand:SF 0 "s_register_operand" "=f")
1367 (mult:SF (match_operand:SF 1 "s_register_operand" "f")
1368 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1369 "TARGET_ARM && TARGET_HARD_FLOAT"
1370 "fml%?s\\t%0, %1, %2"
1371 [(set_attr "type" "ffmul")
1372 (set_attr "predicable" "yes")]
1375 (define_insn "muldf3"
1376 [(set (match_operand:DF 0 "s_register_operand" "=f")
1377 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1378 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1379 "TARGET_ARM && TARGET_HARD_FLOAT"
1380 "muf%?d\\t%0, %1, %2"
1381 [(set_attr "type" "fmul")
1382 (set_attr "predicable" "yes")]
1385 (define_insn "*muldf_esfdf_df"
1386 [(set (match_operand:DF 0 "s_register_operand" "=f")
1387 (mult:DF (float_extend:DF
1388 (match_operand:SF 1 "s_register_operand" "f"))
1389 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1390 "TARGET_ARM && TARGET_HARD_FLOAT"
1391 "muf%?d\\t%0, %1, %2"
1392 [(set_attr "type" "fmul")
1393 (set_attr "predicable" "yes")]
1396 (define_insn "*muldf_df_esfdf"
1397 [(set (match_operand:DF 0 "s_register_operand" "=f")
1398 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1400 (match_operand:SF 2 "s_register_operand" "f"))))]
1401 "TARGET_ARM && TARGET_HARD_FLOAT"
1402 "muf%?d\\t%0, %1, %2"
1403 [(set_attr "type" "fmul")
1404 (set_attr "predicable" "yes")]
1407 (define_insn "*muldf_esfdf_esfdf"
1408 [(set (match_operand:DF 0 "s_register_operand" "=f")
1410 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f"))
1411 (float_extend:DF (match_operand:SF 2 "s_register_operand" "f"))))]
1412 "TARGET_ARM && TARGET_HARD_FLOAT"
1413 "muf%?d\\t%0, %1, %2"
1414 [(set_attr "type" "fmul")
1415 (set_attr "predicable" "yes")]
1418 (define_insn "mulxf3"
1419 [(set (match_operand:XF 0 "s_register_operand" "=f")
1420 (mult:XF (match_operand:XF 1 "s_register_operand" "f")
1421 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1422 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1423 "muf%?e\\t%0, %1, %2"
1424 [(set_attr "type" "fmul")
1425 (set_attr "predicable" "yes")]
1430 (define_insn "divsf3"
1431 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1432 (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1433 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1434 "TARGET_ARM && TARGET_HARD_FLOAT"
1437 frd%?s\\t%0, %2, %1"
1438 [(set_attr "type" "fdivs")
1439 (set_attr "predicable" "yes")]
1442 (define_insn "divdf3"
1443 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1444 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1445 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1446 "TARGET_ARM && TARGET_HARD_FLOAT"
1449 rdf%?d\\t%0, %2, %1"
1450 [(set_attr "type" "fdivd")
1451 (set_attr "predicable" "yes")]
1454 (define_insn "*divdf_esfdf_df"
1455 [(set (match_operand:DF 0 "s_register_operand" "=f")
1456 (div:DF (float_extend:DF
1457 (match_operand:SF 1 "s_register_operand" "f"))
1458 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1459 "TARGET_ARM && TARGET_HARD_FLOAT"
1460 "dvf%?d\\t%0, %1, %2"
1461 [(set_attr "type" "fdivd")
1462 (set_attr "predicable" "yes")]
1465 (define_insn "*divdf_df_esfdf"
1466 [(set (match_operand:DF 0 "s_register_operand" "=f")
1467 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1469 (match_operand:SF 2 "s_register_operand" "f"))))]
1470 "TARGET_ARM && TARGET_HARD_FLOAT"
1471 "rdf%?d\\t%0, %2, %1"
1472 [(set_attr "type" "fdivd")
1473 (set_attr "predicable" "yes")]
1476 (define_insn "*divdf_esfdf_esfdf"
1477 [(set (match_operand:DF 0 "s_register_operand" "=f")
1478 (div:DF (float_extend:DF
1479 (match_operand:SF 1 "s_register_operand" "f"))
1481 (match_operand:SF 2 "s_register_operand" "f"))))]
1482 "TARGET_ARM && TARGET_HARD_FLOAT"
1483 "dvf%?d\\t%0, %1, %2"
1484 [(set_attr "type" "fdivd")
1485 (set_attr "predicable" "yes")]
1488 (define_insn "divxf3"
1489 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1490 (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1491 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1492 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1495 rdf%?e\\t%0, %2, %1"
1496 [(set_attr "type" "fdivx")
1497 (set_attr "predicable" "yes")]
1502 (define_insn "modsf3"
1503 [(set (match_operand:SF 0 "s_register_operand" "=f")
1504 (mod:SF (match_operand:SF 1 "s_register_operand" "f")
1505 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1506 "TARGET_ARM && TARGET_HARD_FLOAT"
1507 "rmf%?s\\t%0, %1, %2"
1508 [(set_attr "type" "fdivs")
1509 (set_attr "predicable" "yes")]
1512 (define_insn "moddf3"
1513 [(set (match_operand:DF 0 "s_register_operand" "=f")
1514 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1515 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1516 "TARGET_ARM && TARGET_HARD_FLOAT"
1517 "rmf%?d\\t%0, %1, %2"
1518 [(set_attr "type" "fdivd")
1519 (set_attr "predicable" "yes")]
1522 (define_insn "*moddf_esfdf_df"
1523 [(set (match_operand:DF 0 "s_register_operand" "=f")
1524 (mod:DF (float_extend:DF
1525 (match_operand:SF 1 "s_register_operand" "f"))
1526 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1527 "TARGET_ARM && TARGET_HARD_FLOAT"
1528 "rmf%?d\\t%0, %1, %2"
1529 [(set_attr "type" "fdivd")
1530 (set_attr "predicable" "yes")]
1533 (define_insn "*moddf_df_esfdf"
1534 [(set (match_operand:DF 0 "s_register_operand" "=f")
1535 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1537 (match_operand:SF 2 "s_register_operand" "f"))))]
1538 "TARGET_ARM && TARGET_HARD_FLOAT"
1539 "rmf%?d\\t%0, %1, %2"
1540 [(set_attr "type" "fdivd")
1541 (set_attr "predicable" "yes")]
1544 (define_insn "*moddf_esfdf_esfdf"
1545 [(set (match_operand:DF 0 "s_register_operand" "=f")
1546 (mod:DF (float_extend:DF
1547 (match_operand:SF 1 "s_register_operand" "f"))
1549 (match_operand:SF 2 "s_register_operand" "f"))))]
1550 "TARGET_ARM && TARGET_HARD_FLOAT"
1551 "rmf%?d\\t%0, %1, %2"
1552 [(set_attr "type" "fdivd")
1553 (set_attr "predicable" "yes")]
1556 (define_insn "modxf3"
1557 [(set (match_operand:XF 0 "s_register_operand" "=f")
1558 (mod:XF (match_operand:XF 1 "s_register_operand" "f")
1559 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1560 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1561 "rmf%?e\\t%0, %1, %2"
1562 [(set_attr "type" "fdivx")
1563 (set_attr "predicable" "yes")]
1566 ;; Boolean and,ior,xor insns
1568 ;; Split up double word logical operations
1570 ;; Split up simple DImode logical operations. Simply perform the logical
1571 ;; operation on the upper and lower halves of the registers.
1573 [(set (match_operand:DI 0 "s_register_operand" "")
1574 (match_operator:DI 6 "logical_binary_operator"
1575 [(match_operand:DI 1 "s_register_operand" "")
1576 (match_operand:DI 2 "s_register_operand" "")]))]
1577 "TARGET_ARM && reload_completed"
1578 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1579 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1582 operands[3] = gen_highpart (SImode, operands[0]);
1583 operands[0] = gen_lowpart (SImode, operands[0]);
1584 operands[4] = gen_highpart (SImode, operands[1]);
1585 operands[1] = gen_lowpart (SImode, operands[1]);
1586 operands[5] = gen_highpart (SImode, operands[2]);
1587 operands[2] = gen_lowpart (SImode, operands[2]);
1592 [(set (match_operand:DI 0 "s_register_operand" "")
1593 (match_operator:DI 6 "logical_binary_operator"
1594 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1595 (match_operand:DI 1 "s_register_operand" "")]))]
1596 "TARGET_ARM && reload_completed"
1597 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1598 (set (match_dup 3) (match_op_dup:SI 6
1599 [(ashiftrt:SI (match_dup 2) (const_int 31))
1603 operands[3] = gen_highpart (SImode, operands[0]);
1604 operands[0] = gen_lowpart (SImode, operands[0]);
1605 operands[4] = gen_highpart (SImode, operands[1]);
1606 operands[1] = gen_lowpart (SImode, operands[1]);
1607 operands[5] = gen_highpart (SImode, operands[2]);
1608 operands[2] = gen_lowpart (SImode, operands[2]);
1612 ;; The zero extend of operand 2 means we can just copy the high part of
1613 ;; operand1 into operand0.
1615 [(set (match_operand:DI 0 "s_register_operand" "")
1617 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1618 (match_operand:DI 1 "s_register_operand" "")))]
1619 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1620 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1621 (set (match_dup 3) (match_dup 4))]
1624 operands[4] = gen_highpart (SImode, operands[1]);
1625 operands[3] = gen_highpart (SImode, operands[0]);
1626 operands[0] = gen_lowpart (SImode, operands[0]);
1627 operands[1] = gen_lowpart (SImode, operands[1]);
1631 ;; The zero extend of operand 2 means we can just copy the high part of
1632 ;; operand1 into operand0.
1634 [(set (match_operand:DI 0 "s_register_operand" "")
1636 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1637 (match_operand:DI 1 "s_register_operand" "")))]
1638 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1639 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1640 (set (match_dup 3) (match_dup 4))]
1643 operands[4] = gen_highpart (SImode, operands[1]);
1644 operands[3] = gen_highpart (SImode, operands[0]);
1645 operands[0] = gen_lowpart (SImode, operands[0]);
1646 operands[1] = gen_lowpart (SImode, operands[1]);
1650 (define_insn "anddi3"
1651 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1652 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1653 (match_operand:DI 2 "s_register_operand" "r,r")))]
1656 [(set_attr "length" "8")]
1659 (define_insn_and_split "*anddi_zesidi_di"
1660 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1661 (and:DI (zero_extend:DI
1662 (match_operand:SI 2 "s_register_operand" "r,r"))
1663 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1666 "TARGET_ARM && reload_completed"
1667 ; The zero extend of operand 2 clears the high word of the output
1669 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1670 (set (match_dup 3) (const_int 0))]
1673 operands[3] = gen_highpart (SImode, operands[0]);
1674 operands[0] = gen_lowpart (SImode, operands[0]);
1675 operands[1] = gen_lowpart (SImode, operands[1]);
1677 [(set_attr "length" "8")]
1680 (define_insn "*anddi_sesdi_di"
1681 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1682 (and:DI (sign_extend:DI
1683 (match_operand:SI 2 "s_register_operand" "r,r"))
1684 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1687 [(set_attr "length" "8")]
1690 (define_expand "andsi3"
1691 [(set (match_operand:SI 0 "s_register_operand" "")
1692 (and:SI (match_operand:SI 1 "s_register_operand" "")
1693 (match_operand:SI 2 "reg_or_int_operand" "")))]
1698 if (GET_CODE (operands[2]) == CONST_INT)
1700 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1703 ? 0 : preserve_subexpressions_p ()));
1707 else /* TARGET_THUMB */
1709 if (GET_CODE (operands[2]) != CONST_INT)
1710 operands[2] = force_reg (SImode, operands[2]);
1715 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1717 operands[2] = force_reg (SImode,
1718 GEN_INT (~INTVAL (operands[2])));
1720 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1725 for (i = 9; i <= 31; i++)
1727 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1729 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1733 else if ((((HOST_WIDE_INT) 1) << i) - 1
1734 == ~INTVAL (operands[2]))
1736 rtx shift = GEN_INT (i);
1737 rtx reg = gen_reg_rtx (SImode);
1739 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1740 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1746 operands[2] = force_reg (SImode, operands[2]);
1752 (define_insn_and_split "*arm_andsi3_insn"
1753 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1754 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1755 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1759 bic%?\\t%0, %1, #%B2
1762 && GET_CODE (operands[2]) == CONST_INT
1763 && !(const_ok_for_arm (INTVAL (operands[2]))
1764 || const_ok_for_arm (~INTVAL (operands[2])))"
1765 [(clobber (const_int 0))]
1767 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1771 [(set_attr "length" "4,4,16")
1772 (set_attr "predicable" "yes")]
1775 (define_insn "*thumb_andsi3_insn"
1776 [(set (match_operand:SI 0 "register_operand" "=l")
1777 (and:SI (match_operand:SI 1 "register_operand" "%0")
1778 (match_operand:SI 2 "register_operand" "l")))]
1781 [(set_attr "length" "2")]
1784 (define_insn "*andsi3_compare0"
1785 [(set (reg:CC_NOOV CC_REGNUM)
1787 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1788 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1790 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1791 (and:SI (match_dup 1) (match_dup 2)))]
1795 bic%?s\\t%0, %1, #%B2"
1796 [(set_attr "conds" "set")]
1799 (define_insn "*andsi3_compare0_scratch"
1800 [(set (reg:CC_NOOV CC_REGNUM)
1802 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1803 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1805 (clobber (match_scratch:SI 2 "=X,r"))]
1809 bic%?s\\t%2, %0, #%B1"
1810 [(set_attr "conds" "set")]
1813 (define_insn "*zeroextractsi_compare0_scratch"
1814 [(set (reg:CC_NOOV CC_REGNUM)
1815 (compare:CC_NOOV (zero_extract:SI
1816 (match_operand:SI 0 "s_register_operand" "r")
1817 (match_operand 1 "const_int_operand" "n")
1818 (match_operand 2 "const_int_operand" "n"))
1821 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1822 && INTVAL (operands[1]) > 0
1823 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1824 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1826 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1827 << INTVAL (operands[2]));
1828 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1831 [(set_attr "conds" "set")]
1834 (define_insn "*ne_zeroextractsi"
1835 [(set (match_operand:SI 0 "s_register_operand" "=r")
1836 (ne:SI (zero_extract:SI
1837 (match_operand:SI 1 "s_register_operand" "r")
1838 (match_operand:SI 2 "const_int_operand" "n")
1839 (match_operand:SI 3 "const_int_operand" "n"))
1842 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1843 && INTVAL (operands[2]) > 0
1844 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1845 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1847 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1848 << INTVAL (operands[3]));
1849 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1850 return \"movne\\t%0, #1\";
1852 [(set_attr "conds" "clob")
1853 (set_attr "length" "8")]
1856 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1857 ;;; represented by the bitfield, then this will produce incorrect results.
1858 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1859 ;;; which have a real bitfield insert instruction, the truncation happens
1860 ;;; in the bitfield insert instruction itself. Since arm does not have a
1861 ;;; bitfield insert instruction, we would have to emit code here to truncate
1862 ;;; the value before we insert. This loses some of the advantage of having
1863 ;;; this insv pattern, so this pattern needs to be reevalutated.
1865 (define_expand "insv"
1866 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1867 (match_operand:SI 1 "general_operand" "")
1868 (match_operand:SI 2 "general_operand" ""))
1869 (match_operand:SI 3 "nonmemory_operand" ""))]
1873 int start_bit = INTVAL (operands[2]);
1874 int width = INTVAL (operands[1]);
1875 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1876 rtx target, subtarget;
1878 target = operands[0];
1879 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1880 subreg as the final target. */
1881 if (GET_CODE (target) == SUBREG)
1883 subtarget = gen_reg_rtx (SImode);
1884 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1885 < GET_MODE_SIZE (SImode))
1886 target = SUBREG_REG (target);
1891 if (GET_CODE (operands[3]) == CONST_INT)
1893 /* Since we are inserting a known constant, we may be able to
1894 reduce the number of bits that we have to clear so that
1895 the mask becomes simple. */
1896 /* ??? This code does not check to see if the new mask is actually
1897 simpler. It may not be. */
1898 rtx op1 = gen_reg_rtx (SImode);
1899 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1900 start of this pattern. */
1901 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1902 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1904 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1905 emit_insn (gen_iorsi3 (subtarget, op1,
1906 GEN_INT (op3_value << start_bit)));
1908 else if (start_bit == 0
1909 && !(const_ok_for_arm (mask)
1910 || const_ok_for_arm (~mask)))
1912 /* A Trick, since we are setting the bottom bits in the word,
1913 we can shift operand[3] up, operand[0] down, OR them together
1914 and rotate the result back again. This takes 3 insns, and
1915 the third might be mergable into another op. */
1916 /* The shift up copes with the possibility that operand[3] is
1917 wider than the bitfield. */
1918 rtx op0 = gen_reg_rtx (SImode);
1919 rtx op1 = gen_reg_rtx (SImode);
1921 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1922 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1923 emit_insn (gen_iorsi3 (op1, op1, op0));
1924 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1926 else if ((width + start_bit == 32)
1927 && !(const_ok_for_arm (mask)
1928 || const_ok_for_arm (~mask)))
1930 /* Similar trick, but slightly less efficient. */
1932 rtx op0 = gen_reg_rtx (SImode);
1933 rtx op1 = gen_reg_rtx (SImode);
1935 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1936 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1937 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1938 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1942 rtx op0 = GEN_INT (mask);
1943 rtx op1 = gen_reg_rtx (SImode);
1944 rtx op2 = gen_reg_rtx (SImode);
1946 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1948 rtx tmp = gen_reg_rtx (SImode);
1950 emit_insn (gen_movsi (tmp, op0));
1954 /* Mask out any bits in operand[3] that are not needed. */
1955 emit_insn (gen_andsi3 (op1, operands[3], op0));
1957 if (GET_CODE (op0) == CONST_INT
1958 && (const_ok_for_arm (mask << start_bit)
1959 || const_ok_for_arm (~(mask << start_bit))))
1961 op0 = GEN_INT (~(mask << start_bit));
1962 emit_insn (gen_andsi3 (op2, operands[0], op0));
1966 if (GET_CODE (op0) == CONST_INT)
1968 rtx tmp = gen_reg_rtx (SImode);
1970 emit_insn (gen_movsi (tmp, op0));
1975 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1977 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1981 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1983 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1986 if (subtarget != target)
1988 /* If TARGET is still a SUBREG, then it must be wider than a word,
1989 so we must be careful only to set the subword we were asked to. */
1990 if (GET_CODE (target) == SUBREG)
1991 emit_move_insn (target, subtarget);
1993 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2000 ; constants for op 2 will never be given to these patterns.
2001 (define_insn_and_split "*anddi_notdi_di"
2002 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2003 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2004 (match_operand:DI 2 "s_register_operand" "0,r")))]
2007 "TARGET_ARM && reload_completed"
2008 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2009 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2012 operands[3] = gen_highpart (SImode, operands[0]);
2013 operands[0] = gen_lowpart (SImode, operands[0]);
2014 operands[4] = gen_highpart (SImode, operands[1]);
2015 operands[1] = gen_lowpart (SImode, operands[1]);
2016 operands[5] = gen_highpart (SImode, operands[2]);
2017 operands[2] = gen_lowpart (SImode, operands[2]);
2019 [(set_attr "length" "8")
2020 (set_attr "predicable" "yes")]
2023 (define_insn_and_split "*anddi_notzesidi_di"
2024 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2025 (and:DI (not:DI (zero_extend:DI
2026 (match_operand:SI 2 "s_register_operand" "r,r")))
2027 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2030 bic%?\\t%Q0, %Q1, %2
2032 ; (not (zero_extend ...)) allows us to just copy the high word from
2033 ; operand1 to operand0.
2036 && operands[0] != operands[1]"
2037 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2038 (set (match_dup 3) (match_dup 4))]
2041 operands[3] = gen_highpart (SImode, operands[0]);
2042 operands[0] = gen_lowpart (SImode, operands[0]);
2043 operands[4] = gen_highpart (SImode, operands[1]);
2044 operands[1] = gen_lowpart (SImode, operands[1]);
2046 [(set_attr "length" "4,8")
2047 (set_attr "predicable" "yes")]
2050 (define_insn_and_split "*anddi_notsesidi_di"
2051 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2052 (and:DI (not:DI (sign_extend:DI
2053 (match_operand:SI 2 "s_register_operand" "r,r")))
2054 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2057 "TARGET_ARM && reload_completed"
2058 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2059 (set (match_dup 3) (and:SI (not:SI
2060 (ashiftrt:SI (match_dup 2) (const_int 31)))
2064 operands[3] = gen_highpart (SImode, operands[0]);
2065 operands[0] = gen_lowpart (SImode, operands[0]);
2066 operands[4] = gen_highpart (SImode, operands[1]);
2067 operands[1] = gen_lowpart (SImode, operands[1]);
2069 [(set_attr "length" "8")
2070 (set_attr "predicable" "yes")]
2073 (define_insn "andsi_notsi_si"
2074 [(set (match_operand:SI 0 "s_register_operand" "=r")
2075 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2076 (match_operand:SI 1 "s_register_operand" "r")))]
2078 "bic%?\\t%0, %1, %2"
2079 [(set_attr "predicable" "yes")]
2082 (define_insn "bicsi3"
2083 [(set (match_operand:SI 0 "register_operand" "=l")
2084 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2085 (match_operand:SI 2 "register_operand" "0")))]
2088 [(set_attr "length" "2")]
2091 (define_insn "andsi_not_shiftsi_si"
2092 [(set (match_operand:SI 0 "s_register_operand" "=r")
2093 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2094 [(match_operand:SI 2 "s_register_operand" "r")
2095 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2096 (match_operand:SI 1 "s_register_operand" "r")))]
2098 "bic%?\\t%0, %1, %2%S4"
2099 [(set_attr "predicable" "yes")
2100 (set_attr "shift" "2")
2104 (define_insn "*andsi_notsi_si_compare0"
2105 [(set (reg:CC_NOOV CC_REGNUM)
2107 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2108 (match_operand:SI 1 "s_register_operand" "r"))
2110 (set (match_operand:SI 0 "s_register_operand" "=r")
2111 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2113 "bic%?s\\t%0, %1, %2"
2114 [(set_attr "conds" "set")]
2117 (define_insn "*andsi_notsi_si_compare0_scratch"
2118 [(set (reg:CC_NOOV CC_REGNUM)
2120 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2121 (match_operand:SI 1 "s_register_operand" "r"))
2123 (clobber (match_scratch:SI 0 "=r"))]
2125 "bic%?s\\t%0, %1, %2"
2126 [(set_attr "conds" "set")]
2129 (define_insn "iordi3"
2130 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2131 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2132 (match_operand:DI 2 "s_register_operand" "r,r")))]
2135 [(set_attr "length" "8")
2136 (set_attr "predicable" "yes")]
2139 (define_insn "*iordi_zesidi_di"
2140 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2141 (ior:DI (zero_extend:DI
2142 (match_operand:SI 2 "s_register_operand" "r,r"))
2143 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2146 orr%?\\t%Q0, %Q1, %2
2148 [(set_attr "length" "4,8")
2149 (set_attr "predicable" "yes")]
2152 (define_insn "*iordi_sesidi_di"
2153 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2154 (ior:DI (sign_extend:DI
2155 (match_operand:SI 2 "s_register_operand" "r,r"))
2156 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2159 [(set_attr "length" "8")
2160 (set_attr "predicable" "yes")]
2163 (define_expand "iorsi3"
2164 [(set (match_operand:SI 0 "s_register_operand" "")
2165 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2166 (match_operand:SI 2 "reg_or_int_operand" "")))]
2169 if (GET_CODE (operands[2]) == CONST_INT)
2173 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2176 ? 0 : preserve_subexpressions_p ()));
2179 else /* TARGET_THUMB */
2180 operands [2] = force_reg (SImode, operands [2]);
2185 (define_insn_and_split "*arm_iorsi3"
2186 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2187 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2188 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2194 && GET_CODE (operands[2]) == CONST_INT
2195 && !const_ok_for_arm (INTVAL (operands[2]))"
2196 [(clobber (const_int 0))]
2198 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2202 [(set_attr "length" "4,16")
2203 (set_attr "predicable" "yes")]
2206 (define_insn "*thumb_iorsi3"
2207 [(set (match_operand:SI 0 "register_operand" "=l")
2208 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2209 (match_operand:SI 2 "register_operand" "l")))]
2212 [(set_attr "length" "2")]
2216 [(match_scratch:SI 3 "r")
2217 (set (match_operand:SI 0 "s_register_operand" "")
2218 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2219 (match_operand:SI 2 "const_int_operand" "")))]
2221 && !const_ok_for_arm (INTVAL (operands[2]))
2222 && const_ok_for_arm (~INTVAL (operands[2]))"
2223 [(set (match_dup 3) (match_dup 2))
2224 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2228 (define_insn "*iorsi3_compare0"
2229 [(set (reg:CC_NOOV CC_REGNUM)
2230 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2231 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2233 (set (match_operand:SI 0 "s_register_operand" "=r")
2234 (ior:SI (match_dup 1) (match_dup 2)))]
2236 "orr%?s\\t%0, %1, %2"
2237 [(set_attr "conds" "set")]
2240 (define_insn "*iorsi3_compare0_scratch"
2241 [(set (reg:CC_NOOV CC_REGNUM)
2242 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2243 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2245 (clobber (match_scratch:SI 0 "=r"))]
2247 "orr%?s\\t%0, %1, %2"
2248 [(set_attr "conds" "set")]
2251 (define_insn "xordi3"
2252 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2253 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2254 (match_operand:DI 2 "s_register_operand" "r,r")))]
2257 [(set_attr "length" "8")
2258 (set_attr "predicable" "yes")]
2261 (define_insn "*xordi_zesidi_di"
2262 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2263 (xor:DI (zero_extend:DI
2264 (match_operand:SI 2 "s_register_operand" "r,r"))
2265 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2268 eor%?\\t%Q0, %Q1, %2
2270 [(set_attr "length" "4,8")
2271 (set_attr "predicable" "yes")]
2274 (define_insn "*xordi_sesidi_di"
2275 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2276 (xor:DI (sign_extend:DI
2277 (match_operand:SI 2 "s_register_operand" "r,r"))
2278 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2281 [(set_attr "length" "8")
2282 (set_attr "predicable" "yes")]
2285 (define_expand "xorsi3"
2286 [(set (match_operand:SI 0 "s_register_operand" "")
2287 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2288 (match_operand:SI 2 "arm_rhs_operand" "")))]
2291 if (GET_CODE (operands[2]) == CONST_INT)
2292 operands[2] = force_reg (SImode, operands[2]);
2296 (define_insn "*arm_xorsi3"
2297 [(set (match_operand:SI 0 "s_register_operand" "=r")
2298 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2299 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2301 "eor%?\\t%0, %1, %2"
2302 [(set_attr "predicable" "yes")]
2305 (define_insn "*thumb_xorsi3"
2306 [(set (match_operand:SI 0 "register_operand" "=l")
2307 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2308 (match_operand:SI 2 "register_operand" "l")))]
2311 [(set_attr "length" "2")]
2314 (define_insn "*xorsi3_compare0"
2315 [(set (reg:CC_NOOV CC_REGNUM)
2316 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2317 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2319 (set (match_operand:SI 0 "s_register_operand" "=r")
2320 (xor:SI (match_dup 1) (match_dup 2)))]
2322 "eor%?s\\t%0, %1, %2"
2323 [(set_attr "conds" "set")]
2326 (define_insn "*xorsi3_compare0_scratch"
2327 [(set (reg:CC_NOOV CC_REGNUM)
2328 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2329 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2333 [(set_attr "conds" "set")]
2336 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2337 ; (NOT D) we can sometimes merge the final NOT into one of the following
2341 [(set (match_operand:SI 0 "s_register_operand" "")
2342 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2343 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2344 (match_operand:SI 3 "arm_rhs_operand" "")))
2345 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2347 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2348 (not:SI (match_dup 3))))
2349 (set (match_dup 0) (not:SI (match_dup 4)))]
2353 (define_insn "*andsi_iorsi3_notsi"
2354 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2355 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2356 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2357 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2359 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2360 [(set_attr "length" "8")
2361 (set_attr "predicable" "yes")]
2366 ;; Minimum and maximum insns
2368 (define_insn "smaxsi3"
2369 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2370 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2371 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2372 (clobber (reg:CC CC_REGNUM))]
2375 cmp\\t%1, %2\;movlt\\t%0, %2
2376 cmp\\t%1, %2\;movge\\t%0, %1
2377 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2378 [(set_attr "conds" "clob")
2379 (set_attr "length" "8,8,12")]
2382 (define_insn "sminsi3"
2383 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2384 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2385 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2386 (clobber (reg:CC CC_REGNUM))]
2389 cmp\\t%1, %2\;movge\\t%0, %2
2390 cmp\\t%1, %2\;movlt\\t%0, %1
2391 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2392 [(set_attr "conds" "clob")
2393 (set_attr "length" "8,8,12")]
2396 (define_insn "umaxsi3"
2397 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2398 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2399 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2400 (clobber (reg:CC CC_REGNUM))]
2403 cmp\\t%1, %2\;movcc\\t%0, %2
2404 cmp\\t%1, %2\;movcs\\t%0, %1
2405 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2406 [(set_attr "conds" "clob")
2407 (set_attr "length" "8,8,12")]
2410 (define_insn "uminsi3"
2411 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2412 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2413 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2414 (clobber (reg:CC CC_REGNUM))]
2417 cmp\\t%1, %2\;movcs\\t%0, %2
2418 cmp\\t%1, %2\;movcc\\t%0, %1
2419 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2420 [(set_attr "conds" "clob")
2421 (set_attr "length" "8,8,12")]
2424 (define_insn "*store_minmaxsi"
2425 [(set (match_operand:SI 0 "memory_operand" "=m")
2426 (match_operator:SI 3 "minmax_operator"
2427 [(match_operand:SI 1 "s_register_operand" "r")
2428 (match_operand:SI 2 "s_register_operand" "r")]))
2429 (clobber (reg:CC CC_REGNUM))]
2432 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2434 output_asm_insn (\"cmp\\t%1, %2\", operands);
2435 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2436 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2439 [(set_attr "conds" "clob")
2440 (set_attr "length" "12")
2441 (set_attr "type" "store1")]
2444 ; Reject the frame pointer in operand[1], since reloading this after
2445 ; it has been eliminated can cause carnage.
2446 (define_insn "*minmax_arithsi"
2447 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2448 (match_operator:SI 4 "shiftable_operator"
2449 [(match_operator:SI 5 "minmax_operator"
2450 [(match_operand:SI 2 "s_register_operand" "r,r")
2451 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2452 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2453 (clobber (reg:CC CC_REGNUM))]
2455 && (GET_CODE (operands[1]) != REG
2456 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2457 && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2460 enum rtx_code code = GET_CODE (operands[4]);
2462 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2464 output_asm_insn (\"cmp\\t%2, %3\", operands);
2465 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2466 if (which_alternative != 0 || operands[3] != const0_rtx
2467 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2468 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2471 [(set_attr "conds" "clob")
2472 (set_attr "length" "12")]
2476 ;; Shift and rotation insns
2478 (define_expand "ashlsi3"
2479 [(set (match_operand:SI 0 "s_register_operand" "")
2480 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2481 (match_operand:SI 2 "arm_rhs_operand" "")))]
2484 if (GET_CODE (operands[2]) == CONST_INT
2485 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2487 emit_insn (gen_movsi (operands[0], const0_rtx));
2493 (define_insn "*thumb_ashlsi3"
2494 [(set (match_operand:SI 0 "register_operand" "=l,l")
2495 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2496 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2499 [(set_attr "length" "2")]
2502 (define_expand "ashrsi3"
2503 [(set (match_operand:SI 0 "s_register_operand" "")
2504 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2505 (match_operand:SI 2 "arm_rhs_operand" "")))]
2508 if (GET_CODE (operands[2]) == CONST_INT
2509 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2510 operands[2] = GEN_INT (31);
2514 (define_insn "*thumb_ashrsi3"
2515 [(set (match_operand:SI 0 "register_operand" "=l,l")
2516 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2517 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2520 [(set_attr "length" "2")]
2523 (define_expand "lshrsi3"
2524 [(set (match_operand:SI 0 "s_register_operand" "")
2525 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2526 (match_operand:SI 2 "arm_rhs_operand" "")))]
2529 if (GET_CODE (operands[2]) == CONST_INT
2530 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2532 emit_insn (gen_movsi (operands[0], const0_rtx));
2538 (define_insn "*thumb_lshrsi3"
2539 [(set (match_operand:SI 0 "register_operand" "=l,l")
2540 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2541 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2544 [(set_attr "length" "2")]
2547 (define_expand "rotlsi3"
2548 [(set (match_operand:SI 0 "s_register_operand" "")
2549 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2550 (match_operand:SI 2 "reg_or_int_operand" "")))]
2553 if (GET_CODE (operands[2]) == CONST_INT)
2554 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2557 rtx reg = gen_reg_rtx (SImode);
2558 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2564 (define_expand "rotrsi3"
2565 [(set (match_operand:SI 0 "s_register_operand" "")
2566 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2567 (match_operand:SI 2 "arm_rhs_operand" "")))]
2572 if (GET_CODE (operands[2]) == CONST_INT
2573 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2574 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2576 else /* TARGET_THUMB */
2578 if (GET_CODE (operands [2]) == CONST_INT)
2579 operands [2] = force_reg (SImode, operands[2]);
2584 (define_insn "*thumb_rotrsi3"
2585 [(set (match_operand:SI 0 "register_operand" "=l")
2586 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2587 (match_operand:SI 2 "register_operand" "l")))]
2590 [(set_attr "length" "2")]
2593 (define_insn "*arm_shiftsi3"
2594 [(set (match_operand:SI 0 "s_register_operand" "=r")
2595 (match_operator:SI 3 "shift_operator"
2596 [(match_operand:SI 1 "s_register_operand" "r")
2597 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2600 [(set_attr "predicable" "yes")
2601 (set_attr "shift" "1")
2605 (define_insn "*shiftsi3_compare0"
2606 [(set (reg:CC_NOOV CC_REGNUM)
2607 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2608 [(match_operand:SI 1 "s_register_operand" "r")
2609 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2611 (set (match_operand:SI 0 "s_register_operand" "=r")
2612 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2614 "mov%?s\\t%0, %1%S3"
2615 [(set_attr "conds" "set")
2616 (set_attr "shift" "1")
2620 (define_insn "*shiftsi3_compare0_scratch"
2621 [(set (reg:CC_NOOV CC_REGNUM)
2622 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2623 [(match_operand:SI 1 "s_register_operand" "r")
2624 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2626 (clobber (match_scratch:SI 0 "=r"))]
2628 "mov%?s\\t%0, %1%S3"
2629 [(set_attr "conds" "set")
2630 (set_attr "shift" "1")
2634 (define_insn "*notsi_shiftsi"
2635 [(set (match_operand:SI 0 "s_register_operand" "=r")
2636 (not:SI (match_operator:SI 3 "shift_operator"
2637 [(match_operand:SI 1 "s_register_operand" "r")
2638 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2641 [(set_attr "predicable" "yes")
2642 (set_attr "shift" "1")
2646 (define_insn "*notsi_shiftsi_compare0"
2647 [(set (reg:CC_NOOV CC_REGNUM)
2648 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2649 [(match_operand:SI 1 "s_register_operand" "r")
2650 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2652 (set (match_operand:SI 0 "s_register_operand" "=r")
2653 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2655 "mvn%?s\\t%0, %1%S3"
2656 [(set_attr "conds" "set")
2657 (set_attr "shift" "1")
2661 (define_insn "*not_shiftsi_compare0_scratch"
2662 [(set (reg:CC_NOOV CC_REGNUM)
2663 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2664 [(match_operand:SI 1 "s_register_operand" "r")
2665 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2667 (clobber (match_scratch:SI 0 "=r"))]
2669 "mvn%?s\\t%0, %1%S3"
2670 [(set_attr "conds" "set")
2671 (set_attr "shift" "1")
2675 ;; We don't really have extzv, but defining this using shifts helps
2676 ;; to reduce register pressure later on.
2678 (define_expand "extzv"
2680 (ashift:SI (match_operand:SI 1 "register_operand" "")
2681 (match_operand:SI 2 "const_int_operand" "")))
2682 (set (match_operand:SI 0 "register_operand" "")
2683 (lshiftrt:SI (match_dup 4)
2684 (match_operand:SI 3 "const_int_operand" "")))]
2688 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2689 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2691 operands[3] = GEN_INT (rshift);
2695 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2699 operands[2] = GEN_INT (lshift);
2700 operands[4] = gen_reg_rtx (SImode);
2705 ;; Unary arithmetic insns
2707 (define_expand "negdi2"
2709 [(set (match_operand:DI 0 "s_register_operand" "")
2710 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2711 (clobber (reg:CC CC_REGNUM))])]
2716 if (GET_CODE (operands[1]) != REG)
2717 operands[1] = force_reg (SImode, operands[1]);
2722 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2723 ;; The second alternative is to allow the common case of a *full* overlap.
2724 (define_insn "*arm_negdi2"
2725 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2726 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2727 (clobber (reg:CC CC_REGNUM))]
2729 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2730 [(set_attr "conds" "clob")
2731 (set_attr "length" "8")]
2734 (define_insn "*thumb_negdi2"
2735 [(set (match_operand:DI 0 "register_operand" "=&l")
2736 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2737 (clobber (reg:CC CC_REGNUM))]
2739 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2740 [(set_attr "length" "6")]
2743 (define_expand "negsi2"
2744 [(set (match_operand:SI 0 "s_register_operand" "")
2745 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2750 (define_insn "*arm_negsi2"
2751 [(set (match_operand:SI 0 "s_register_operand" "=r")
2752 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2754 "rsb%?\\t%0, %1, #0"
2755 [(set_attr "predicable" "yes")]
2758 (define_insn "*thumb_negsi2"
2759 [(set (match_operand:SI 0 "register_operand" "=l")
2760 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2763 [(set_attr "length" "2")]
2766 (define_insn "negsf2"
2767 [(set (match_operand:SF 0 "s_register_operand" "=f")
2768 (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
2769 "TARGET_ARM && TARGET_HARD_FLOAT"
2771 [(set_attr "type" "ffarith")
2772 (set_attr "predicable" "yes")]
2775 (define_insn "negdf2"
2776 [(set (match_operand:DF 0 "s_register_operand" "=f")
2777 (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
2778 "TARGET_ARM && TARGET_HARD_FLOAT"
2780 [(set_attr "type" "ffarith")
2781 (set_attr "predicable" "yes")]
2784 (define_insn "*negdf_esfdf"
2785 [(set (match_operand:DF 0 "s_register_operand" "=f")
2786 (neg:DF (float_extend:DF
2787 (match_operand:SF 1 "s_register_operand" "f"))))]
2788 "TARGET_ARM && TARGET_HARD_FLOAT"
2790 [(set_attr "type" "ffarith")
2791 (set_attr "predicable" "yes")]
2794 (define_insn "negxf2"
2795 [(set (match_operand:XF 0 "s_register_operand" "=f")
2796 (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
2797 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2799 [(set_attr "type" "ffarith")
2800 (set_attr "predicable" "yes")]
2803 ;; abssi2 doesn't really clobber the condition codes if a different register
2804 ;; is being set. To keep things simple, assume during rtl manipulations that
2805 ;; it does, but tell the final scan operator the truth. Similarly for
2808 (define_insn "abssi2"
2809 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2810 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2811 (clobber (reg:CC CC_REGNUM))]
2814 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2815 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2816 [(set_attr "conds" "clob,*")
2817 (set_attr "shift" "1")
2818 ;; predicable can't be set based on the variant, so left as no
2819 (set_attr "length" "8")]
2822 (define_insn "*neg_abssi2"
2823 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2824 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2825 (clobber (reg:CC CC_REGNUM))]
2828 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2829 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2830 [(set_attr "conds" "clob,*")
2831 (set_attr "shift" "1")
2832 ;; predicable can't be set based on the variant, so left as no
2833 (set_attr "length" "8")]
2836 (define_insn "abssf2"
2837 [(set (match_operand:SF 0 "s_register_operand" "=f")
2838 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
2839 "TARGET_ARM && TARGET_HARD_FLOAT"
2841 [(set_attr "type" "ffarith")
2842 (set_attr "predicable" "yes")]
2845 (define_insn "absdf2"
2846 [(set (match_operand:DF 0 "s_register_operand" "=f")
2847 (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
2848 "TARGET_ARM && TARGET_HARD_FLOAT"
2850 [(set_attr "type" "ffarith")
2851 (set_attr "predicable" "yes")]
2854 (define_insn "*absdf_esfdf"
2855 [(set (match_operand:DF 0 "s_register_operand" "=f")
2856 (abs:DF (float_extend:DF
2857 (match_operand:SF 1 "s_register_operand" "f"))))]
2858 "TARGET_ARM && TARGET_HARD_FLOAT"
2860 [(set_attr "type" "ffarith")
2861 (set_attr "predicable" "yes")]
2864 (define_insn "absxf2"
2865 [(set (match_operand:XF 0 "s_register_operand" "=f")
2866 (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
2867 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2869 [(set_attr "type" "ffarith")
2870 (set_attr "predicable" "yes")]
2873 (define_insn "sqrtsf2"
2874 [(set (match_operand:SF 0 "s_register_operand" "=f")
2875 (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
2876 "TARGET_ARM && TARGET_HARD_FLOAT"
2878 [(set_attr "type" "float_em")
2879 (set_attr "predicable" "yes")]
2882 (define_insn "sqrtdf2"
2883 [(set (match_operand:DF 0 "s_register_operand" "=f")
2884 (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
2885 "TARGET_ARM && TARGET_HARD_FLOAT"
2887 [(set_attr "type" "float_em")
2888 (set_attr "predicable" "yes")]
2891 (define_insn "*sqrtdf_esfdf"
2892 [(set (match_operand:DF 0 "s_register_operand" "=f")
2893 (sqrt:DF (float_extend:DF
2894 (match_operand:SF 1 "s_register_operand" "f"))))]
2895 "TARGET_ARM && TARGET_HARD_FLOAT"
2897 [(set_attr "type" "float_em")
2898 (set_attr "predicable" "yes")]
2901 (define_insn "sqrtxf2"
2902 [(set (match_operand:XF 0 "s_register_operand" "=f")
2903 (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
2904 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2906 [(set_attr "type" "float_em")
2907 (set_attr "predicable" "yes")]
2910 ;; SIN COS TAN and family are always emulated, so it's probably better
2911 ;; to always call a library function.
2912 ;(define_insn "sinsf2"
2913 ; [(set (match_operand:SF 0 "s_register_operand" "=f")
2914 ; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
2916 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2918 ;[(set_attr "type" "float_em")])
2920 ;(define_insn "sindf2"
2921 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2922 ; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
2924 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2926 ;[(set_attr "type" "float_em")])
2928 ;(define_insn "*sindf_esfdf"
2929 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2930 ; (unspec:DF [(float_extend:DF
2931 ; (match_operand:SF 1 "s_register_operand" "f"))]
2933 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2935 ;[(set_attr "type" "float_em")])
2937 ;(define_insn "sinxf2"
2938 ; [(set (match_operand:XF 0 "s_register_operand" "=f")
2939 ; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
2941 ; "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2943 ;[(set_attr "type" "float_em")])
2945 ;(define_insn "cossf2"
2946 ; [(set (match_operand:SF 0 "s_register_operand" "=f")
2947 ; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
2949 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2951 ;[(set_attr "type" "float_em")])
2953 ;(define_insn "cosdf2"
2954 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2955 ; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
2957 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2959 ;[(set_attr "type" "float_em")])
2961 ;(define_insn "*cosdf_esfdf"
2962 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2963 ; (unspec:DF [(float_extend:DF
2964 ; (match_operand:SF 1 "s_register_operand" "f"))]
2966 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2968 ;[(set_attr "type" "float_em")])
2970 ;(define_insn "cosxf2"
2971 ; [(set (match_operand:XF 0 "s_register_operand" "=f")
2972 ; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
2974 ; "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2976 ;[(set_attr "type" "float_em")])
2978 (define_insn_and_split "one_cmpldi2"
2979 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2980 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2983 "TARGET_ARM && reload_completed"
2984 [(set (match_dup 0) (not:SI (match_dup 1)))
2985 (set (match_dup 2) (not:SI (match_dup 3)))]
2988 operands[2] = gen_highpart (SImode, operands[0]);
2989 operands[0] = gen_lowpart (SImode, operands[0]);
2990 operands[3] = gen_highpart (SImode, operands[1]);
2991 operands[1] = gen_lowpart (SImode, operands[1]);
2993 [(set_attr "length" "8")
2994 (set_attr "predicable" "yes")]
2997 (define_expand "one_cmplsi2"
2998 [(set (match_operand:SI 0 "s_register_operand" "")
2999 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3004 (define_insn "*arm_one_cmplsi2"
3005 [(set (match_operand:SI 0 "s_register_operand" "=r")
3006 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
3009 [(set_attr "predicable" "yes")]
3012 (define_insn "*thumb_one_cmplsi2"
3013 [(set (match_operand:SI 0 "register_operand" "=l")
3014 (not:SI (match_operand:SI 1 "register_operand" "l")))]
3017 [(set_attr "length" "2")]
3020 (define_insn "*notsi_compare0"
3021 [(set (reg:CC_NOOV CC_REGNUM)
3022 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3024 (set (match_operand:SI 0 "s_register_operand" "=r")
3025 (not:SI (match_dup 1)))]
3028 [(set_attr "conds" "set")]
3031 (define_insn "*notsi_compare0_scratch"
3032 [(set (reg:CC_NOOV CC_REGNUM)
3033 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3035 (clobber (match_scratch:SI 0 "=r"))]
3038 [(set_attr "conds" "set")]
3041 ;; Fixed <--> Floating conversion insns
3043 (define_insn "floatsisf2"
3044 [(set (match_operand:SF 0 "s_register_operand" "=f")
3045 (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
3046 "TARGET_ARM && TARGET_HARD_FLOAT"
3048 [(set_attr "type" "r_2_f")
3049 (set_attr "predicable" "yes")]
3052 (define_insn "floatsidf2"
3053 [(set (match_operand:DF 0 "s_register_operand" "=f")
3054 (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
3055 "TARGET_ARM && TARGET_HARD_FLOAT"
3057 [(set_attr "type" "r_2_f")
3058 (set_attr "predicable" "yes")]
3061 (define_insn "floatsixf2"
3062 [(set (match_operand:XF 0 "s_register_operand" "=f")
3063 (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
3064 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3066 [(set_attr "type" "r_2_f")
3067 (set_attr "predicable" "yes")]
3070 (define_insn "fix_truncsfsi2"
3071 [(set (match_operand:SI 0 "s_register_operand" "=r")
3072 (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
3073 "TARGET_ARM && TARGET_HARD_FLOAT"
3075 [(set_attr "type" "f_2_r")
3076 (set_attr "predicable" "yes")]
3079 (define_insn "fix_truncdfsi2"
3080 [(set (match_operand:SI 0 "s_register_operand" "=r")
3081 (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
3082 "TARGET_ARM && TARGET_HARD_FLOAT"
3084 [(set_attr "type" "f_2_r")
3085 (set_attr "predicable" "yes")]
3088 (define_insn "fix_truncxfsi2"
3089 [(set (match_operand:SI 0 "s_register_operand" "=r")
3090 (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
3091 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3093 [(set_attr "type" "f_2_r")
3094 (set_attr "predicable" "yes")]
3099 (define_insn "truncdfsf2"
3100 [(set (match_operand:SF 0 "s_register_operand" "=f")
3102 (match_operand:DF 1 "s_register_operand" "f")))]
3103 "TARGET_ARM && TARGET_HARD_FLOAT"
3105 [(set_attr "type" "ffarith")
3106 (set_attr "predicable" "yes")]
3109 (define_insn "truncxfsf2"
3110 [(set (match_operand:SF 0 "s_register_operand" "=f")
3112 (match_operand:XF 1 "s_register_operand" "f")))]
3113 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3115 [(set_attr "type" "ffarith")
3116 (set_attr "predicable" "yes")]
3119 (define_insn "truncxfdf2"
3120 [(set (match_operand:DF 0 "s_register_operand" "=f")
3122 (match_operand:XF 1 "s_register_operand" "f")))]
3123 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3125 [(set_attr "type" "ffarith")
3126 (set_attr "predicable" "yes")]
3129 ;; Zero and sign extension instructions.
3131 (define_insn "zero_extendsidi2"
3132 [(set (match_operand:DI 0 "s_register_operand" "=r")
3133 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3136 if (REGNO (operands[1])
3137 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3138 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3139 return \"mov%?\\t%R0, #0\";
3141 [(set_attr "length" "8")
3142 (set_attr "predicable" "yes")]
3145 (define_insn "zero_extendqidi2"
3146 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
3147 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3150 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3151 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3152 [(set_attr "length" "8")
3153 (set_attr "predicable" "yes")
3154 (set_attr "type" "*,load")
3155 (set_attr "pool_range" "*,4092")
3156 (set_attr "neg_pool_range" "*,4084")]
3159 (define_insn "extendsidi2"
3160 [(set (match_operand:DI 0 "s_register_operand" "=r")
3161 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3164 if (REGNO (operands[1])
3165 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3166 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3167 return \"mov%?\\t%R0, %Q0, asr #31\";
3169 [(set_attr "length" "8")
3170 (set_attr "shift" "1")
3171 (set_attr "predicable" "yes")]
3174 (define_expand "zero_extendhisi2"
3176 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3178 (set (match_operand:SI 0 "s_register_operand" "")
3179 (lshiftrt:SI (match_dup 2) (const_int 16)))]
3185 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3187 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3188 here because the insn below will generate an LDRH instruction
3189 rather than an LDR instruction, so we cannot get an unaligned
3191 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3192 gen_rtx_ZERO_EXTEND (SImode,
3196 if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3198 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3201 if (!s_register_operand (operands[1], HImode))
3202 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3203 operands[1] = gen_lowpart (SImode, operands[1]);
3204 operands[2] = gen_reg_rtx (SImode);
3206 else /* TARGET_THUMB */
3208 if (GET_CODE (operands[1]) == MEM)
3212 tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3213 tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3220 if (!s_register_operand (operands[1], HImode))
3221 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3222 operands[1] = gen_lowpart (SImode, operands[1]);
3223 operands[2] = gen_reg_rtx (SImode);
3225 ops[0] = operands[2];
3226 ops[1] = operands[1];
3227 ops[2] = GEN_INT (16);
3229 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3230 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3232 ops[0] = operands[0];
3233 ops[1] = operands[2];
3234 ops[2] = GEN_INT (16);
3236 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3237 gen_rtx_LSHIFTRT (SImode, ops[1],
3245 (define_insn "*thumb_zero_extendhisi2"
3246 [(set (match_operand:SI 0 "register_operand" "=l")
3247 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3250 rtx mem = XEXP (operands[1], 0);
3252 if (GET_CODE (mem) == CONST)
3253 mem = XEXP (mem, 0);
3255 if (GET_CODE (mem) == LABEL_REF)
3256 return \"ldr\\t%0, %1\";
3258 if (GET_CODE (mem) == PLUS)
3260 rtx a = XEXP (mem, 0);
3261 rtx b = XEXP (mem, 1);
3263 /* This can happen due to bugs in reload. */
3264 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3267 ops[0] = operands[0];
3270 output_asm_insn (\"mov %0, %1\", ops);
3272 XEXP (mem, 0) = operands[0];
3275 else if ( GET_CODE (a) == LABEL_REF
3276 && GET_CODE (b) == CONST_INT)
3277 return \"ldr\\t%0, %1\";
3280 return \"ldrh\\t%0, %1\";
3282 [(set_attr "length" "4")
3283 (set_attr "type" "load")
3284 (set_attr "pool_range" "60")]
3287 (define_insn "*arm_zero_extendhisi2"
3288 [(set (match_operand:SI 0 "s_register_operand" "=r")
3289 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3290 "TARGET_ARM && arm_arch4"
3292 [(set_attr "type" "load")
3293 (set_attr "predicable" "yes")
3294 (set_attr "pool_range" "256")
3295 (set_attr "neg_pool_range" "244")]
3299 [(set (match_operand:SI 0 "s_register_operand" "")
3300 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3301 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3302 "TARGET_ARM && (!arm_arch4)"
3303 [(set (match_dup 2) (match_dup 1))
3304 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3306 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3312 [(set (match_operand:SI 0 "s_register_operand" "")
3313 (match_operator:SI 3 "shiftable_operator"
3314 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3315 (match_operand:SI 4 "s_register_operand" "")]))
3316 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3317 "TARGET_ARM && (!arm_arch4)"
3318 [(set (match_dup 2) (match_dup 1))
3321 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3323 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3328 (define_expand "zero_extendqisi2"
3329 [(set (match_operand:SI 0 "s_register_operand" "")
3330 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3333 if (GET_CODE (operands[1]) != MEM)
3337 emit_insn (gen_andsi3 (operands[0],
3338 gen_lowpart (SImode, operands[1]),
3341 else /* TARGET_THUMB */
3343 rtx temp = gen_reg_rtx (SImode);
3346 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3347 operands[1] = gen_lowpart (SImode, operands[1]);
3350 ops[1] = operands[1];
3351 ops[2] = GEN_INT (24);
3353 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3354 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3356 ops[0] = operands[0];
3358 ops[2] = GEN_INT (24);
3360 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3361 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3368 (define_insn "*thumb_zero_extendqisi2"
3369 [(set (match_operand:SI 0 "register_operand" "=l")
3370 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3373 [(set_attr "length" "2")
3374 (set_attr "type" "load")
3375 (set_attr "pool_range" "32")]
3378 (define_insn "*arm_zero_extendqisi2"
3379 [(set (match_operand:SI 0 "s_register_operand" "=r")
3380 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3382 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3383 [(set_attr "type" "load")
3384 (set_attr "predicable" "yes")
3385 (set_attr "pool_range" "4096")
3386 (set_attr "neg_pool_range" "4084")]
3390 [(set (match_operand:SI 0 "s_register_operand" "")
3391 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3392 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3393 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3394 [(set (match_dup 2) (match_dup 1))
3395 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3399 (define_insn "*compareqi_eq0"
3400 [(set (reg:CC_Z CC_REGNUM)
3401 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3405 [(set_attr "conds" "set")]
3408 (define_expand "extendhisi2"
3410 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3412 (set (match_operand:SI 0 "s_register_operand" "")
3413 (ashiftrt:SI (match_dup 2)
3418 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3420 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3421 here because the insn below will generate an LDRH instruction
3422 rather than an LDR instruction, so we cannot get an unaligned
3424 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3425 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3429 if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3431 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3434 if (!s_register_operand (operands[1], HImode))
3435 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3436 operands[1] = gen_lowpart (SImode, operands[1]);
3437 operands[2] = gen_reg_rtx (SImode);
3443 ops[0] = operands[2];
3444 ops[1] = operands[1];
3445 ops[2] = GEN_INT (16);
3447 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3448 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3450 ops[0] = operands[0];
3451 ops[1] = operands[2];
3452 ops[2] = GEN_INT (16);
3454 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3455 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3462 (define_insn "*thumb_extendhisi2_insn"
3463 [(set (match_operand:SI 0 "register_operand" "=l")
3464 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3465 (clobber (match_scratch:SI 2 "=&l"))]
3470 rtx mem = XEXP (operands[1], 0);
3472 /* This code used to try to use 'V', and fix the address only if it was
3473 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3474 range of QImode offsets, and offsettable_address_p does a QImode
3477 if (GET_CODE (mem) == CONST)
3478 mem = XEXP (mem, 0);
3480 if (GET_CODE (mem) == LABEL_REF)
3481 return \"ldr\\t%0, %1\";
3483 if (GET_CODE (mem) == PLUS)
3485 rtx a = XEXP (mem, 0);
3486 rtx b = XEXP (mem, 1);
3488 if (GET_CODE (a) == LABEL_REF
3489 && GET_CODE (b) == CONST_INT)
3490 return \"ldr\\t%0, %1\";
3492 if (GET_CODE (b) == REG)
3493 return \"ldrsh\\t%0, %1\";
3501 ops[2] = const0_rtx;
3504 if (GET_CODE (ops[1]) != REG)
3510 ops[0] = operands[0];
3511 ops[3] = operands[2];
3512 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3515 [(set_attr "length" "4")
3516 (set_attr "type" "load")
3517 (set_attr "pool_range" "1020")]
3520 (define_expand "extendhisi2_mem"
3521 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3523 (zero_extend:SI (match_dup 7)))
3524 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3525 (set (match_operand:SI 0 "" "")
3526 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3531 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3533 mem1 = gen_rtx_MEM (QImode, addr);
3534 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3535 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3536 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3537 operands[0] = gen_lowpart (SImode, operands[0]);
3539 operands[2] = gen_reg_rtx (SImode);
3540 operands[3] = gen_reg_rtx (SImode);
3541 operands[6] = gen_reg_rtx (SImode);
3544 if (BYTES_BIG_ENDIAN)
3546 operands[4] = operands[2];
3547 operands[5] = operands[3];
3551 operands[4] = operands[3];
3552 operands[5] = operands[2];
3557 (define_insn "*arm_extendhisi_insn"
3558 [(set (match_operand:SI 0 "s_register_operand" "=r")
3559 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3560 "TARGET_ARM && arm_arch4"
3562 [(set_attr "type" "load")
3563 (set_attr "predicable" "yes")
3564 (set_attr "pool_range" "256")
3565 (set_attr "neg_pool_range" "244")]
3569 [(set (match_operand:SI 0 "s_register_operand" "")
3570 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3571 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3572 "TARGET_ARM && (!arm_arch4)"
3573 [(set (match_dup 2) (match_dup 1))
3574 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3576 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3582 [(set (match_operand:SI 0 "s_register_operand" "")
3583 (match_operator:SI 3 "shiftable_operator"
3584 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3585 (match_operand:SI 4 "s_register_operand" "")]))
3586 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3587 "TARGET_ARM && (!arm_arch4)"
3588 [(set (match_dup 2) (match_dup 1))
3591 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3592 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3597 (define_expand "extendqihi2"
3599 (ashift:SI (match_operand:QI 1 "general_operand" "")
3601 (set (match_operand:HI 0 "s_register_operand" "")
3602 (ashiftrt:SI (match_dup 2)
3607 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3609 emit_insn (gen_rtx_SET (VOIDmode,
3611 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3614 if (!s_register_operand (operands[1], QImode))
3615 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3616 operands[0] = gen_lowpart (SImode, operands[0]);
3617 operands[1] = gen_lowpart (SImode, operands[1]);
3618 operands[2] = gen_reg_rtx (SImode);
3622 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3623 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3624 (define_insn "*extendqihi_insn"
3625 [(set (match_operand:HI 0 "s_register_operand" "=r")
3626 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3627 "TARGET_ARM && arm_arch4"
3629 /* If the address is invalid, this will split the instruction into two. */
3630 if (bad_signed_byte_operand (operands[1], VOIDmode))
3632 return \"ldr%?sb\\t%0, %1\";
3634 [(set_attr "type" "load")
3635 (set_attr "predicable" "yes")
3636 (set_attr "length" "8")
3637 (set_attr "pool_range" "256")
3638 (set_attr "neg_pool_range" "244")]
3642 [(set (match_operand:HI 0 "s_register_operand" "")
3643 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3644 "TARGET_ARM && arm_arch4 && reload_completed"
3645 [(set (match_dup 3) (match_dup 1))
3646 (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3649 HOST_WIDE_INT offset;
3651 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3652 operands[2] = gen_rtx_MEM (QImode, operands[3]);
3653 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3654 operands[1] = XEXP (operands[1], 0);
3655 if (GET_CODE (operands[1]) == PLUS
3656 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3657 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3658 || const_ok_for_arm (-offset)))
3660 HOST_WIDE_INT low = (offset > 0
3661 ? (offset & 0xff) : -((-offset) & 0xff));
3662 XEXP (operands[2], 0) = plus_constant (operands[3], low);
3663 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3665 /* Ensure the sum is in correct canonical form */
3666 else if (GET_CODE (operands[1]) == PLUS
3667 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3668 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3669 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3670 XEXP (operands[1], 1),
3671 XEXP (operands[1], 0));
3675 (define_expand "extendqisi2"
3677 (ashift:SI (match_operand:QI 1 "general_operand" "")
3679 (set (match_operand:SI 0 "s_register_operand" "")
3680 (ashiftrt:SI (match_dup 2)
3685 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3687 emit_insn (gen_rtx_SET (VOIDmode,
3689 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3692 if (!s_register_operand (operands[1], QImode))
3693 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3694 operands[1] = gen_lowpart (SImode, operands[1]);
3695 operands[2] = gen_reg_rtx (SImode);
3701 ops[0] = operands[2];
3702 ops[1] = operands[1];
3703 ops[2] = GEN_INT (24);
3705 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3706 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3708 ops[0] = operands[0];
3709 ops[1] = operands[2];
3710 ops[2] = GEN_INT (24);
3712 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3713 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3720 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3721 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3722 (define_insn "*arm_extendqisi_insn"
3723 [(set (match_operand:SI 0 "s_register_operand" "=r")
3724 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3725 "TARGET_ARM && arm_arch4"
3727 /* If the address is invalid, this will split the instruction into two. */
3728 if (bad_signed_byte_operand (operands[1], VOIDmode))
3730 return \"ldr%?sb\\t%0, %1\";
3732 [(set_attr "type" "load")
3733 (set_attr "predicable" "yes")
3734 (set_attr "length" "8")
3735 (set_attr "pool_range" "256")
3736 (set_attr "neg_pool_range" "244")]
3740 [(set (match_operand:SI 0 "s_register_operand" "")
3741 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3742 "TARGET_ARM && arm_arch4 && reload_completed"
3743 [(set (match_dup 0) (match_dup 1))
3744 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3747 HOST_WIDE_INT offset;
3749 operands[2] = gen_rtx_MEM (QImode, operands[0]);
3750 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3751 operands[1] = XEXP (operands[1], 0);
3752 if (GET_CODE (operands[1]) == PLUS
3753 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3754 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3755 || const_ok_for_arm (-offset)))
3757 HOST_WIDE_INT low = (offset > 0
3758 ? (offset & 0xff) : -((-offset) & 0xff));
3759 XEXP (operands[2], 0) = plus_constant (operands[0], low);
3760 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3762 /* Ensure the sum is in correct canonical form */
3763 else if (GET_CODE (operands[1]) == PLUS
3764 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3765 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3766 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3767 XEXP (operands[1], 1),
3768 XEXP (operands[1], 0));
3772 (define_insn "*thumb_extendqisi2_insn"
3773 [(set (match_operand:SI 0 "register_operand" "=l,l")
3774 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3779 rtx mem = XEXP (operands[1], 0);
3781 if (GET_CODE (mem) == CONST)
3782 mem = XEXP (mem, 0);
3784 if (GET_CODE (mem) == LABEL_REF)
3785 return \"ldr\\t%0, %1\";
3787 if (GET_CODE (mem) == PLUS
3788 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3789 return \"ldr\\t%0, %1\";
3791 if (which_alternative == 0)
3792 return \"ldrsb\\t%0, %1\";
3794 ops[0] = operands[0];
3796 if (GET_CODE (mem) == PLUS)
3798 rtx a = XEXP (mem, 0);
3799 rtx b = XEXP (mem, 1);
3804 if (GET_CODE (a) == REG)
3806 if (GET_CODE (b) == REG)
3807 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3808 else if (REGNO (a) == REGNO (ops[0]))
3810 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3811 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3812 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3815 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3817 else if (GET_CODE (b) != REG)
3821 if (REGNO (b) == REGNO (ops[0]))
3823 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3824 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3825 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3828 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3831 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3833 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3834 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3835 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3840 ops[2] = const0_rtx;
3842 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3846 [(set_attr "length" "2,6")
3847 (set_attr "type" "load,load")
3848 (set_attr "pool_range" "32,32")]
3851 (define_insn "extendsfdf2"
3852 [(set (match_operand:DF 0 "s_register_operand" "=f")
3853 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
3854 "TARGET_ARM && TARGET_HARD_FLOAT"
3856 [(set_attr "type" "ffarith")
3857 (set_attr "predicable" "yes")]
3860 (define_insn "extendsfxf2"
3861 [(set (match_operand:XF 0 "s_register_operand" "=f")
3862 (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
3863 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3865 [(set_attr "type" "ffarith")
3866 (set_attr "predicable" "yes")]
3869 (define_insn "extenddfxf2"
3870 [(set (match_operand:XF 0 "s_register_operand" "=f")
3871 (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
3872 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3874 [(set_attr "type" "ffarith")
3875 (set_attr "predicable" "yes")]
3879 ;; Move insns (including loads and stores)
3881 ;; XXX Just some ideas about movti.
3882 ;; I don't think these are a good idea on the arm, there just aren't enough
3884 ;;(define_expand "loadti"
3885 ;; [(set (match_operand:TI 0 "s_register_operand" "")
3886 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
3889 ;;(define_expand "storeti"
3890 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3891 ;; (match_operand:TI 1 "s_register_operand" ""))]
3894 ;;(define_expand "movti"
3895 ;; [(set (match_operand:TI 0 "general_operand" "")
3896 ;; (match_operand:TI 1 "general_operand" ""))]
3902 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3903 ;; operands[1] = copy_to_reg (operands[1]);
3904 ;; if (GET_CODE (operands[0]) == MEM)
3905 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3906 ;; else if (GET_CODE (operands[1]) == MEM)
3907 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3911 ;; emit_insn (insn);
3915 ;; Recognise garbage generated above.
3918 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3919 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3923 ;; register mem = (which_alternative < 3);
3924 ;; register const char *template;
3926 ;; operands[mem] = XEXP (operands[mem], 0);
3927 ;; switch (which_alternative)
3929 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3930 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
3931 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
3932 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
3933 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
3934 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
3936 ;; output_asm_insn (template, operands);
3940 (define_expand "movdi"
3941 [(set (match_operand:DI 0 "general_operand" "")
3942 (match_operand:DI 1 "general_operand" ""))]
3947 if (!no_new_pseudos)
3949 if (GET_CODE (operands[0]) != REG)
3950 operands[1] = force_reg (DImode, operands[1]);
3956 (define_insn "*arm_movdi"
3957 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3958 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
3961 return (output_move_double (operands));
3963 [(set_attr "length" "8")
3964 (set_attr "type" "*,load,store2")
3965 (set_attr "pool_range" "*,1020,*")
3966 (set_attr "neg_pool_range" "*,1008,*")]
3969 ;;; ??? This should have alternatives for constants.
3970 ;;; ??? This was originally identical to the movdf_insn pattern.
3971 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3972 ;;; thumb_reorg with a memory reference.
3973 (define_insn "*thumb_movdi_insn"
3974 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3975 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
3977 && ( register_operand (operands[0], DImode)
3978 || register_operand (operands[1], DImode))"
3981 switch (which_alternative)
3985 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3986 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
3987 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
3989 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3991 operands[1] = GEN_INT (- INTVAL (operands[1]));
3992 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3994 return \"ldmia\\t%1, {%0, %H0}\";
3996 return \"stmia\\t%0, {%1, %H1}\";
3998 return thumb_load_double_from_address (operands);
4000 operands[2] = gen_rtx (MEM, SImode,
4001 plus_constant (XEXP (operands[0], 0), 4));
4002 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4005 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4006 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4007 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4010 [(set_attr "length" "4,4,6,2,2,6,4,4")
4011 (set_attr "type" "*,*,*,load,store2,load,store2,*")
4012 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4015 (define_expand "movsi"
4016 [(set (match_operand:SI 0 "general_operand" "")
4017 (match_operand:SI 1 "general_operand" ""))]
4022 /* Everything except mem = const or mem = mem can be done easily */
4023 if (GET_CODE (operands[0]) == MEM)
4024 operands[1] = force_reg (SImode, operands[1]);
4025 if (GET_CODE (operands[1]) == CONST_INT
4026 && !(const_ok_for_arm (INTVAL (operands[1]))
4027 || const_ok_for_arm (~INTVAL (operands[1]))))
4029 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4032 : preserve_subexpressions_p ()));
4036 else /* TARGET_THUMB.... */
4038 if (!no_new_pseudos)
4040 if (GET_CODE (operands[0]) != REG)
4041 operands[1] = force_reg (SImode, operands[1]);
4046 && (CONSTANT_P (operands[1])
4047 || symbol_mentioned_p (operands[1])
4048 || label_mentioned_p (operands[1])))
4049 operands[1] = legitimize_pic_address (operands[1], SImode,
4050 (no_new_pseudos ? operands[0] : 0));
4054 (define_insn "*arm_movsi_insn"
4055 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4056 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
4058 && ( register_operand (operands[0], SImode)
4059 || register_operand (operands[1], SImode))"
4065 [(set_attr "type" "*,*,load,store1")
4066 (set_attr "predicable" "yes")
4067 (set_attr "pool_range" "*,*,4096,*")
4068 (set_attr "neg_pool_range" "*,*,4084,*")]
4072 [(set (match_operand:SI 0 "s_register_operand" "")
4073 (match_operand:SI 1 "const_int_operand" ""))]
4075 && (!(const_ok_for_arm (INTVAL (operands[1]))
4076 || const_ok_for_arm (~INTVAL (operands[1]))))"
4077 [(clobber (const_int 0))]
4079 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4085 (define_insn "*thumb_movsi_insn"
4086 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4087 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
4089 && ( register_operand (operands[0], SImode)
4090 || register_operand (operands[1], SImode))"
4101 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4102 (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
4103 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4107 [(set (match_operand:SI 0 "register_operand" "")
4108 (match_operand:SI 1 "const_int_operand" ""))]
4109 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4110 [(set (match_dup 0) (match_dup 1))
4111 (set (match_dup 0) (neg:SI (match_dup 0)))]
4112 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4116 [(set (match_operand:SI 0 "register_operand" "")
4117 (match_operand:SI 1 "const_int_operand" ""))]
4118 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4119 [(set (match_dup 0) (match_dup 1))
4120 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4123 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4124 unsigned HOST_WIDE_INT mask = 0xff;
4127 for (i = 0; i < 25; i++)
4128 if ((val & (mask << i)) == val)
4131 /* Shouldn't happen, but we don't want to split if the shift is zero. */
4135 operands[1] = GEN_INT (val >> i);
4136 operands[2] = GEN_INT (i);
4140 ;; When generating pic, we need to load the symbol offset into a register.
4141 ;; So that the optimizer does not confuse this with a normal symbol load
4142 ;; we use an unspec. The offset will be loaded from a constant pool entry,
4143 ;; since that is the only type of relocation we can use.
4145 ;; The rather odd constraints on the following are to force reload to leave
4146 ;; the insn alone, and to force the minipool generation pass to then move
4147 ;; the GOT symbol to memory.
4149 (define_insn "pic_load_addr_arm"
4150 [(set (match_operand:SI 0 "s_register_operand" "=r")
4151 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4152 "TARGET_ARM && flag_pic"
4154 [(set_attr "type" "load")
4155 (set (attr "pool_range") (const_int 4096))
4156 (set (attr "neg_pool_range") (const_int 4084))]
4159 (define_insn "pic_load_addr_thumb"
4160 [(set (match_operand:SI 0 "s_register_operand" "=l")
4161 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4162 "TARGET_THUMB && flag_pic"
4164 [(set_attr "type" "load")
4165 (set (attr "pool_range") (const_int 1024))]
4168 ;; This variant is used for AOF assembly, since it needs to mention the
4169 ;; pic register in the rtl.
4170 (define_expand "pic_load_addr_based"
4171 [(set (match_operand:SI 0 "s_register_operand" "=r")
4172 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4173 "TARGET_ARM && flag_pic"
4174 "operands[2] = pic_offset_table_rtx;"
4177 (define_insn "*pic_load_addr_based_insn"
4178 [(set (match_operand:SI 0 "s_register_operand" "=r")
4179 (unspec:SI [(match_operand 1 "" "")
4180 (match_operand 2 "s_register_operand" "r")]
4182 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4184 #ifdef AOF_ASSEMBLER
4185 operands[1] = aof_pic_entry (operands[1]);
4187 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4190 [(set_attr "type" "load")
4191 (set (attr "pool_range")
4192 (if_then_else (eq_attr "is_thumb" "yes")
4195 (set (attr "neg_pool_range")
4196 (if_then_else (eq_attr "is_thumb" "yes")
4201 (define_insn "pic_add_dot_plus_four"
4202 [(set (match_operand:SI 0 "register_operand" "+r")
4203 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
4204 (use (label_ref (match_operand 1 "" "")))]
4205 "TARGET_THUMB && flag_pic"
4207 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4208 CODE_LABEL_NUMBER (operands[1]));
4209 return \"add\\t%0, %|pc\";
4211 [(set_attr "length" "2")]
4214 (define_insn "pic_add_dot_plus_eight"
4215 [(set (match_operand:SI 0 "register_operand" "+r")
4216 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
4217 (use (label_ref (match_operand 1 "" "")))]
4218 "TARGET_ARM && flag_pic"
4220 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4221 CODE_LABEL_NUMBER (operands[1]));
4222 return \"add%?\\t%0, %|pc, %0\";
4224 [(set_attr "predicable" "yes")]
4227 (define_expand "builtin_setjmp_receiver"
4228 [(label_ref (match_operand 0 "" ""))]
4232 arm_finalize_pic (0);
4236 ;; If copying one reg to another we can set the condition codes according to
4237 ;; its value. Such a move is common after a return from subroutine and the
4238 ;; result is being tested against zero.
4240 (define_insn "*movsi_compare0"
4241 [(set (reg:CC CC_REGNUM)
4242 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4244 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4249 sub%?s\\t%0, %1, #0"
4250 [(set_attr "conds" "set")]
4253 ;; Subroutine to store a half word from a register into memory.
4254 ;; Operand 0 is the source register (HImode)
4255 ;; Operand 1 is the destination address in a register (SImode)
4257 ;; In both this routine and the next, we must be careful not to spill
4258 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4259 ;; can generate unrecognizable rtl.
4261 (define_expand "storehi"
4262 [;; store the low byte
4263 (set (match_operand 1 "" "") (match_dup 3))
4264 ;; extract the high byte
4266 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4267 ;; store the high byte
4268 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
4272 rtx op1 = operands[1];
4273 rtx addr = XEXP (op1, 0);
4274 enum rtx_code code = GET_CODE (addr);
4276 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4278 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4280 operands[4] = adjust_address (op1, QImode, 1);
4281 operands[1] = adjust_address (operands[1], QImode, 0);
4282 operands[3] = gen_lowpart (QImode, operands[0]);
4283 operands[0] = gen_lowpart (SImode, operands[0]);
4284 operands[2] = gen_reg_rtx (SImode);
4288 (define_expand "storehi_bigend"
4289 [(set (match_dup 4) (match_dup 3))
4291 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4292 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 3))]
4296 rtx op1 = operands[1];
4297 rtx addr = XEXP (op1, 0);
4298 enum rtx_code code = GET_CODE (addr);
4300 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4302 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4304 operands[4] = adjust_address (op1, QImode, 1);
4305 operands[1] = adjust_address (operands[1], QImode, 0);
4306 operands[3] = gen_lowpart (QImode, operands[0]);
4307 operands[0] = gen_lowpart (SImode, operands[0]);
4308 operands[2] = gen_reg_rtx (SImode);
4312 ;; Subroutine to store a half word integer constant into memory.
4313 (define_expand "storeinthi"
4314 [(set (match_operand 0 "" "")
4315 (subreg:QI (match_operand 1 "" "") 0))
4316 (set (match_dup 3) (match_dup 2))]
4320 HOST_WIDE_INT value = INTVAL (operands[1]);
4321 rtx addr = XEXP (operands[0], 0);
4322 rtx op0 = operands[0];
4323 enum rtx_code code = GET_CODE (addr);
4325 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4327 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4329 operands[1] = gen_reg_rtx (SImode);
4330 if (BYTES_BIG_ENDIAN)
4332 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4333 if ((value & 255) == ((value >> 8) & 255))
4334 operands[2] = operands[1];
4337 operands[2] = gen_reg_rtx (SImode);
4338 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4343 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4344 if ((value & 255) == ((value >> 8) & 255))
4345 operands[2] = operands[1];
4348 operands[2] = gen_reg_rtx (SImode);
4349 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4353 operands[3] = adjust_address (op0, QImode, 1);
4354 operands[0] = adjust_address (operands[0], QImode, 0);
4355 operands[2] = gen_lowpart (QImode, operands[2]);
4359 (define_expand "storehi_single_op"
4360 [(set (match_operand:HI 0 "memory_operand" "")
4361 (match_operand:HI 1 "general_operand" ""))]
4362 "TARGET_ARM && arm_arch4"
4364 if (!s_register_operand (operands[1], HImode))
4365 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4369 (define_expand "movhi"
4370 [(set (match_operand:HI 0 "general_operand" "")
4371 (match_operand:HI 1 "general_operand" ""))]
4376 if (!no_new_pseudos)
4378 if (GET_CODE (operands[0]) == MEM)
4382 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4385 if (GET_CODE (operands[1]) == CONST_INT)
4386 emit_insn (gen_storeinthi (operands[0], operands[1]));
4389 if (GET_CODE (operands[1]) == MEM)
4390 operands[1] = force_reg (HImode, operands[1]);
4391 if (BYTES_BIG_ENDIAN)
4392 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4394 emit_insn (gen_storehi (operands[1], operands[0]));
4398 /* Sign extend a constant, and keep it in an SImode reg. */
4399 else if (GET_CODE (operands[1]) == CONST_INT)
4401 rtx reg = gen_reg_rtx (SImode);
4402 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4404 /* If the constant is already valid, leave it alone. */
4405 if (!const_ok_for_arm (val))
4407 /* If setting all the top bits will make the constant
4408 loadable in a single instruction, then set them.
4409 Otherwise, sign extend the number. */
4411 if (const_ok_for_arm (~(val | ~0xffff)))
4413 else if (val & 0x8000)
4417 emit_insn (gen_movsi (reg, GEN_INT (val)));
4418 operands[1] = gen_lowpart (HImode, reg);
4420 else if (arm_arch4 && !no_new_pseudos && optimize > 0
4421 && GET_CODE (operands[1]) == MEM)
4423 rtx reg = gen_reg_rtx (SImode);
4425 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4426 operands[1] = gen_lowpart (HImode, reg);
4428 else if (!arm_arch4)
4430 /* Note: We do not have to worry about TARGET_MMU_TRAPS
4431 for v4 and up architectures because LDRH instructions will
4432 be used to access the HI values, and these cannot generate
4433 unaligned word access faults in the MMU. */
4434 if (GET_CODE (operands[1]) == MEM)
4436 if (TARGET_MMU_TRAPS)
4439 rtx offset = const0_rtx;
4440 rtx reg = gen_reg_rtx (SImode);
4442 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4443 || (GET_CODE (base) == PLUS
4444 && (GET_CODE (offset = XEXP (base, 1))
4446 && ((INTVAL(offset) & 1) != 1)
4447 && GET_CODE (base = XEXP (base, 0)) == REG))
4448 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4450 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4453 new = gen_rtx_MEM (SImode,
4454 plus_constant (base, new_offset));
4455 MEM_COPY_ATTRIBUTES (new, operands[1]);
4456 emit_insn (gen_movsi (reg, new));
4457 if (((INTVAL (offset) & 2) != 0)
4458 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4460 rtx reg2 = gen_reg_rtx (SImode);
4462 emit_insn (gen_lshrsi3 (reg2, reg,
4468 emit_insn (gen_movhi_bytes (reg, operands[1]));
4470 operands[1] = gen_lowpart (HImode, reg);
4472 else if (BYTES_BIG_ENDIAN)
4475 rtx offset = const0_rtx;
4477 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4478 || (GET_CODE (base) == PLUS
4479 && (GET_CODE (offset = XEXP (base, 1))
4481 && GET_CODE (base = XEXP (base, 0)) == REG))
4482 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4484 rtx reg = gen_reg_rtx (SImode);
4487 if ((INTVAL (offset) & 2) == 2)
4489 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4490 new = gen_rtx_MEM (SImode,
4491 plus_constant (base,
4493 MEM_COPY_ATTRIBUTES (new, operands[1]);
4494 emit_insn (gen_movsi (reg, new));
4498 new = gen_rtx_MEM (SImode,
4499 XEXP (operands[1], 0));
4500 MEM_COPY_ATTRIBUTES (new, operands[1]);
4501 emit_insn (gen_rotated_loadsi (reg, new));
4504 operands[1] = gen_lowpart (HImode, reg);
4508 emit_insn (gen_movhi_bigend (operands[0],
4516 /* Handle loading a large integer during reload */
4517 else if (GET_CODE (operands[1]) == CONST_INT
4518 && !const_ok_for_arm (INTVAL (operands[1]))
4519 && !const_ok_for_arm (~INTVAL (operands[1])))
4521 /* Writing a constant to memory needs a scratch, which should
4522 be handled with SECONDARY_RELOADs. */
4523 if (GET_CODE (operands[0]) != REG)
4526 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4527 emit_insn (gen_movsi (operands[0], operands[1]));
4531 else /* TARGET_THUMB */
4533 if (!no_new_pseudos)
4535 if (GET_CODE (operands[0]) != REG)
4536 operands[1] = force_reg (HImode, operands[1]);
4538 /* ??? We shouldn't really get invalid addresses here, but this can
4539 happen if we are passed a SP (never OK for HImode/QImode) or
4540 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4541 HImode/QImode) relative address. */
4542 /* ??? This should perhaps be fixed elsewhere, for instance, in
4543 fixup_stack_1, by checking for other kinds of invalid addresses,
4544 e.g. a bare reference to a virtual register. This may confuse the
4545 alpha though, which must handle this case differently. */
4546 if (GET_CODE (operands[0]) == MEM
4547 && !memory_address_p (GET_MODE (operands[0]),
4548 XEXP (operands[0], 0)))
4550 = replace_equiv_address (operands[0],
4551 copy_to_reg (XEXP (operands[0], 0)));
4553 if (GET_CODE (operands[1]) == MEM
4554 && !memory_address_p (GET_MODE (operands[1]),
4555 XEXP (operands[1], 0)))
4557 = replace_equiv_address (operands[1],
4558 copy_to_reg (XEXP (operands[1], 0)));
4560 /* Handle loading a large integer during reload */
4561 else if (GET_CODE (operands[1]) == CONST_INT
4562 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4564 /* Writing a constant to memory needs a scratch, which should
4565 be handled with SECONDARY_RELOADs. */
4566 if (GET_CODE (operands[0]) != REG)
4569 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4570 emit_insn (gen_movsi (operands[0], operands[1]));
4577 (define_insn "*thumb_movhi_insn"
4578 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4579 (match_operand:HI 1 "general_operand" "l,mn,l,*h,*r,I"))]
4581 && ( register_operand (operands[0], HImode)
4582 || register_operand (operands[1], HImode))"
4584 switch (which_alternative)
4586 case 0: return \"add %0, %1, #0\";
4587 case 2: return \"strh %1, %0\";
4588 case 3: return \"mov %0, %1\";
4589 case 4: return \"mov %0, %1\";
4590 case 5: return \"mov %0, %1\";
4593 /* The stack pointer can end up being taken as an index register.
4594 Catch this case here and deal with it. */
4595 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4596 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4597 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4600 ops[0] = operands[0];
4601 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4603 output_asm_insn (\"mov %0, %1\", ops);
4605 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4608 return \"ldrh %0, %1\";
4610 [(set_attr "length" "2,4,2,2,2,2")
4611 (set_attr "type" "*,load,store1,*,*,*")
4612 (set_attr "pool_range" "*,64,*,*,*,*")]
4616 (define_insn "rotated_loadsi"
4617 [(set (match_operand:SI 0 "s_register_operand" "=r")
4618 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4620 "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4625 ops[0] = operands[0];
4626 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4627 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4630 [(set_attr "type" "load")
4631 (set_attr "predicable" "yes")]
4634 (define_expand "movhi_bytes"
4635 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4637 (zero_extend:SI (match_dup 6)))
4638 (set (match_operand:SI 0 "" "")
4639 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4644 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4646 mem1 = gen_rtx_MEM (QImode, addr);
4647 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4648 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4649 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4650 operands[0] = gen_lowpart (SImode, operands[0]);
4652 operands[2] = gen_reg_rtx (SImode);
4653 operands[3] = gen_reg_rtx (SImode);
4656 if (BYTES_BIG_ENDIAN)
4658 operands[4] = operands[2];
4659 operands[5] = operands[3];
4663 operands[4] = operands[3];
4664 operands[5] = operands[2];
4669 (define_expand "movhi_bigend"
4671 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4674 (ashiftrt:SI (match_dup 2) (const_int 16)))
4675 (set (match_operand:HI 0 "s_register_operand" "")
4676 (subreg:HI (match_dup 3) 0))]
4679 operands[2] = gen_reg_rtx (SImode);
4680 operands[3] = gen_reg_rtx (SImode);
4684 ;; Pattern to recognise insn generated default case above
4685 (define_insn "*movhi_insn_arch4"
4686 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4687 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4690 && (GET_CODE (operands[1]) != CONST_INT
4691 || const_ok_for_arm (INTVAL (operands[1]))
4692 || const_ok_for_arm (~INTVAL (operands[1])))"
4694 mov%?\\t%0, %1\\t%@ movhi
4695 mvn%?\\t%0, #%B1\\t%@ movhi
4696 str%?h\\t%1, %0\\t%@ movhi
4697 ldr%?h\\t%0, %1\\t%@ movhi"
4698 [(set_attr "type" "*,*,store1,load")
4699 (set_attr "predicable" "yes")
4700 (set_attr "pool_range" "*,*,*,256")
4701 (set_attr "neg_pool_range" "*,*,*,244")]
4704 (define_insn "*movhi_insn_littleend"
4705 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4706 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4709 && !BYTES_BIG_ENDIAN
4710 && !TARGET_MMU_TRAPS
4711 && (GET_CODE (operands[1]) != CONST_INT
4712 || const_ok_for_arm (INTVAL (operands[1]))
4713 || const_ok_for_arm (~INTVAL (operands[1])))"
4715 mov%?\\t%0, %1\\t%@ movhi
4716 mvn%?\\t%0, #%B1\\t%@ movhi
4717 ldr%?\\t%0, %1\\t%@ movhi"
4718 [(set_attr "type" "*,*,load")
4719 (set_attr "predicable" "yes")
4720 (set_attr "pool_range" "4096")
4721 (set_attr "neg_pool_range" "4084")]
4724 (define_insn "*movhi_insn_bigend"
4725 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4726 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4730 && !TARGET_MMU_TRAPS
4731 && (GET_CODE (operands[1]) != CONST_INT
4732 || const_ok_for_arm (INTVAL (operands[1]))
4733 || const_ok_for_arm (~INTVAL (operands[1])))"
4735 mov%?\\t%0, %1\\t%@ movhi
4736 mvn%?\\t%0, #%B1\\t%@ movhi
4737 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4738 [(set_attr "type" "*,*,load")
4739 (set_attr "predicable" "yes")
4740 (set_attr "length" "4,4,8")
4741 (set_attr "pool_range" "*,*,4092")
4742 (set_attr "neg_pool_range" "*,*,4084")]
4745 (define_insn "*loadhi_si_bigend"
4746 [(set (match_operand:SI 0 "s_register_operand" "=r")
4747 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
4751 && !TARGET_MMU_TRAPS"
4752 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4753 [(set_attr "type" "load")
4754 (set_attr "predicable" "yes")
4755 (set_attr "pool_range" "4096")
4756 (set_attr "neg_pool_range" "4084")]
4759 (define_insn "*movhi_bytes"
4760 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4761 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4762 "TARGET_ARM && TARGET_MMU_TRAPS"
4764 mov%?\\t%0, %1\\t%@ movhi
4765 mvn%?\\t%0, #%B1\\t%@ movhi"
4766 [(set_attr "predicable" "yes")]
4769 (define_insn "thumb_movhi_clobber"
4770 [(set (match_operand:HI 0 "memory_operand" "=m")
4771 (match_operand:HI 1 "register_operand" "l"))
4772 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4778 ;; We use a DImode scratch because we may occasionally need an additional
4779 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4780 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4781 (define_expand "reload_outhi"
4782 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4783 (match_operand:HI 1 "s_register_operand" "r")
4784 (match_operand:DI 2 "s_register_operand" "=&l")])]
4787 arm_reload_out_hi (operands);
4789 thumb_reload_out_hi (operands);
4794 (define_expand "reload_inhi"
4795 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4796 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4797 (match_operand:DI 2 "s_register_operand" "=&r")])]
4798 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4801 arm_reload_in_hi (operands);
4803 thumb_reload_out_hi (operands);
4807 (define_expand "movqi"
4808 [(set (match_operand:QI 0 "general_operand" "")
4809 (match_operand:QI 1 "general_operand" ""))]
4814 /* Everything except mem = const or mem = mem can be done easily */
4816 if (!no_new_pseudos)
4818 if (GET_CODE (operands[1]) == CONST_INT)
4820 rtx reg = gen_reg_rtx (SImode);
4822 emit_insn (gen_movsi (reg, operands[1]));
4823 operands[1] = gen_lowpart (QImode, reg);
4825 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4827 rtx reg = gen_reg_rtx (SImode);
4829 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4830 operands[1] = gen_lowpart (QImode, reg);
4832 if (GET_CODE (operands[0]) == MEM)
4833 operands[1] = force_reg (QImode, operands[1]);
4836 else /* TARGET_THUMB */
4838 if (!no_new_pseudos)
4840 if (GET_CODE (operands[0]) != REG)
4841 operands[1] = force_reg (QImode, operands[1]);
4843 /* ??? We shouldn't really get invalid addresses here, but this can
4844 happen if we are passed a SP (never OK for HImode/QImode) or
4845 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4846 HImode/QImode) relative address. */
4847 /* ??? This should perhaps be fixed elsewhere, for instance, in
4848 fixup_stack_1, by checking for other kinds of invalid addresses,
4849 e.g. a bare reference to a virtual register. This may confuse the
4850 alpha though, which must handle this case differently. */
4851 if (GET_CODE (operands[0]) == MEM
4852 && !memory_address_p (GET_MODE (operands[0]),
4853 XEXP (operands[0], 0)))
4855 = replace_equiv_address (operands[0],
4856 copy_to_reg (XEXP (operands[0], 0)));
4857 if (GET_CODE (operands[1]) == MEM
4858 && !memory_address_p (GET_MODE (operands[1]),
4859 XEXP (operands[1], 0)))
4861 = replace_equiv_address (operands[1],
4862 copy_to_reg (XEXP (operands[1], 0)));
4864 /* Handle loading a large integer during reload */
4865 else if (GET_CODE (operands[1]) == CONST_INT
4866 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4868 /* Writing a constant to memory needs a scratch, which should
4869 be handled with SECONDARY_RELOADs. */
4870 if (GET_CODE (operands[0]) != REG)
4873 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4874 emit_insn (gen_movsi (operands[0], operands[1]));
4882 (define_insn "*arm_movqi_insn"
4883 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4884 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4886 && ( register_operand (operands[0], QImode)
4887 || register_operand (operands[1], QImode))"
4893 [(set_attr "type" "*,*,load,store1")
4894 (set_attr "predicable" "yes")]
4897 (define_insn "*thumb_movqi_insn"
4898 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4899 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
4901 && ( register_operand (operands[0], QImode)
4902 || register_operand (operands[1], QImode))"
4910 [(set_attr "length" "2")
4911 (set_attr "type" "*,load,store1,*,*,*")
4912 (set_attr "pool_range" "*,32,*,*,*,*")]
4915 (define_expand "movsf"
4916 [(set (match_operand:SF 0 "general_operand" "")
4917 (match_operand:SF 1 "general_operand" ""))]
4922 if (GET_CODE (operands[0]) == MEM)
4923 operands[1] = force_reg (SFmode, operands[1]);
4925 else /* TARGET_THUMB */
4927 if (!no_new_pseudos)
4929 if (GET_CODE (operands[0]) != REG)
4930 operands[1] = force_reg (SFmode, operands[1]);
4937 [(set (match_operand:SF 0 "nonimmediate_operand" "")
4938 (match_operand:SF 1 "immediate_operand" ""))]
4940 && !TARGET_HARD_FLOAT
4942 && GET_CODE (operands[1]) == CONST_DOUBLE"
4943 [(set (match_dup 2) (match_dup 3))]
4945 operands[2] = gen_lowpart (SImode, operands[0]);
4946 operands[3] = gen_lowpart (SImode, operands[1]);
4947 if (operands[2] == 0 || operands[3] == 0)
4952 (define_insn "*arm_movsf_hard_insn"
4953 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
4954 (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
4956 && TARGET_HARD_FLOAT
4957 && (GET_CODE (operands[0]) != MEM
4958 || register_operand (operands[1], SFmode))"
4964 str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
4965 stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
4967 ldr%?\\t%0, %1\\t%@ float
4968 str%?\\t%1, %0\\t%@ float"
4969 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
4970 (set_attr "predicable" "yes")
4972 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
4973 (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
4974 (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
4977 ;; Exactly the same as above, except that all `f' cases are deleted.
4978 ;; This is necessary to prevent reload from ever trying to use a `f' reg
4979 ;; when -msoft-float.
4981 (define_insn "*arm_movsf_soft_insn"
4982 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4983 (match_operand:SF 1 "general_operand" "r,mE,r"))]
4985 && TARGET_SOFT_FLOAT
4986 && (GET_CODE (operands[0]) != MEM
4987 || register_operand (operands[1], SFmode))"
4990 ldr%?\\t%0, %1\\t%@ float
4991 str%?\\t%1, %0\\t%@ float"
4992 [(set_attr "length" "4,4,4")
4993 (set_attr "predicable" "yes")
4994 (set_attr "type" "*,load,store1")
4995 (set_attr "pool_range" "*,4096,*")
4996 (set_attr "neg_pool_range" "*,4084,*")]
4999 ;;; ??? This should have alternatives for constants.
5000 (define_insn "*thumb_movsf_insn"
5001 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5002 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
5004 && ( register_operand (operands[0], SFmode)
5005 || register_operand (operands[1], SFmode))"
5014 [(set_attr "length" "2")
5015 (set_attr "type" "*,load,store1,load,store1,*,*")
5016 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5019 (define_expand "movdf"
5020 [(set (match_operand:DF 0 "general_operand" "")
5021 (match_operand:DF 1 "general_operand" ""))]
5026 if (GET_CODE (operands[0]) == MEM)
5027 operands[1] = force_reg (DFmode, operands[1]);
5029 else /* TARGET_THUMB */
5031 if (!no_new_pseudos)
5033 if (GET_CODE (operands[0]) != REG)
5034 operands[1] = force_reg (DFmode, operands[1]);
5040 ;; Reloading a df mode value stored in integer regs to memory can require a
5042 (define_expand "reload_outdf"
5043 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5044 (match_operand:DF 1 "s_register_operand" "r")
5045 (match_operand:SI 2 "s_register_operand" "=&r")]
5049 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5052 operands[2] = XEXP (operands[0], 0);
5053 else if (code == POST_INC || code == PRE_DEC)
5055 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5056 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5057 emit_insn (gen_movdi (operands[0], operands[1]));
5060 else if (code == PRE_INC)
5062 rtx reg = XEXP (XEXP (operands[0], 0), 0);
5064 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5067 else if (code == POST_DEC)
5068 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5070 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5071 XEXP (XEXP (operands[0], 0), 1)));
5073 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5076 if (code == POST_DEC)
5077 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5083 (define_insn "*movdf_hard_insn"
5084 [(set (match_operand:DF 0 "nonimmediate_operand"
5085 "=r,Q,r,m,r, f, f,f, m,!f,!r")
5086 (match_operand:DF 1 "general_operand"
5087 "Q, r,r,r,mF,fG,H,mF,f,r, f"))]
5089 && TARGET_HARD_FLOAT
5090 && (GET_CODE (operands[0]) != MEM
5091 || register_operand (operands[1], DFmode))"
5094 switch (which_alternative)
5097 case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
5098 case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
5099 case 2: case 3: case 4: return output_move_double (operands);
5100 case 5: return \"mvf%?d\\t%0, %1\";
5101 case 6: return \"mnf%?d\\t%0, #%N1\";
5102 case 7: return \"ldf%?d\\t%0, %1\";
5103 case 8: return \"stf%?d\\t%1, %0\";
5104 case 9: return output_mov_double_fpu_from_arm (operands);
5105 case 10: return output_mov_double_arm_from_fpu (operands);
5109 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
5110 (set_attr "predicable" "yes")
5112 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
5113 (set_attr "pool_range" "*,*,*,*,1020,*,*,1024,*,*,*")
5114 (set_attr "neg_pool_range" "*,*,*,*,1008,*,*,1008,*,*,*")]
5117 ;; Software floating point version. This is essentially the same as movdi.
5118 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
5121 (define_insn "*movdf_soft_insn"
5122 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5123 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5124 "TARGET_ARM && TARGET_SOFT_FLOAT
5126 "* return output_move_double (operands);"
5127 [(set_attr "length" "8,8,8")
5128 (set_attr "type" "*,load,store2")
5129 (set_attr "pool_range" "1020")
5130 (set_attr "neg_pool_range" "1008")]
5133 ;;; ??? This should have alternatives for constants.
5134 ;;; ??? This was originally identical to the movdi_insn pattern.
5135 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5136 ;;; thumb_reorg with a memory reference.
5137 (define_insn "*thumb_movdf_insn"
5138 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5139 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
5141 && ( register_operand (operands[0], DFmode)
5142 || register_operand (operands[1], DFmode))"
5144 switch (which_alternative)
5148 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5149 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5150 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5152 return \"ldmia\\t%1, {%0, %H0}\";
5154 return \"stmia\\t%0, {%1, %H1}\";
5156 return thumb_load_double_from_address (operands);
5158 operands[2] = gen_rtx (MEM, SImode,
5159 plus_constant (XEXP (operands[0], 0), 4));
5160 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5163 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5164 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5165 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5168 [(set_attr "length" "4,2,2,6,4,4")
5169 (set_attr "type" "*,load,store2,load,store2,*")
5170 (set_attr "pool_range" "*,*,*,1020,*,*")]
5174 (define_expand "movxf"
5175 [(set (match_operand:XF 0 "general_operand" "")
5176 (match_operand:XF 1 "general_operand" ""))]
5177 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5180 ;; Even when the XFmode patterns aren't enabled, we enable this after
5181 ;; reloading so that we can push floating point registers in the prologue.
5183 (define_insn "*movxf_hard_insn"
5184 [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
5185 (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
5186 "TARGET_ARM && TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
5188 switch (which_alternative)
5191 case 0: return \"mvf%?e\\t%0, %1\";
5192 case 1: return \"mnf%?e\\t%0, #%N1\";
5193 case 2: return \"ldf%?e\\t%0, %1\";
5194 case 3: return \"stf%?e\\t%1, %0\";
5195 case 4: return output_mov_long_double_fpu_from_arm (operands);
5196 case 5: return output_mov_long_double_arm_from_fpu (operands);
5197 case 6: return output_mov_long_double_arm_from_arm (operands);
5200 [(set_attr "length" "4,4,4,4,8,8,12")
5201 (set_attr "predicable" "yes")
5202 (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
5203 (set_attr "pool_range" "*,*,1024,*,*,*,*")
5204 (set_attr "neg_pool_range" "*,*,1004,*,*,*,*")]
5208 ;; load- and store-multiple insns
5209 ;; The arm can load/store any set of registers, provided that they are in
5210 ;; ascending order; but that is beyond GCC so stick with what it knows.
5212 (define_expand "load_multiple"
5213 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5214 (match_operand:SI 1 "" ""))
5215 (use (match_operand:SI 2 "" ""))])]
5218 /* Support only fixed point registers. */
5219 if (GET_CODE (operands[2]) != CONST_INT
5220 || INTVAL (operands[2]) > 14
5221 || INTVAL (operands[2]) < 2
5222 || GET_CODE (operands[1]) != MEM
5223 || GET_CODE (operands[0]) != REG
5224 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5225 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5229 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5230 force_reg (SImode, XEXP (operands[1], 0)),
5231 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5232 MEM_IN_STRUCT_P(operands[1]),
5233 MEM_SCALAR_P (operands[1]));
5237 ;; Load multiple with write-back
5239 (define_insn "*ldmsi_postinc4"
5240 [(match_parallel 0 "load_multiple_operation"
5241 [(set (match_operand:SI 1 "s_register_operand" "=r")
5242 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5244 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5245 (mem:SI (match_dup 2)))
5246 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5247 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5248 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5249 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5250 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5251 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5252 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5253 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5254 [(set_attr "type" "load")
5255 (set_attr "predicable" "yes")]
5258 (define_insn "*ldmsi_postinc3"
5259 [(match_parallel 0 "load_multiple_operation"
5260 [(set (match_operand:SI 1 "s_register_operand" "=r")
5261 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5263 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5264 (mem:SI (match_dup 2)))
5265 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5266 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5267 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5268 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5269 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5270 "ldm%?ia\\t%1!, {%3, %4, %5}"
5271 [(set_attr "type" "load")
5272 (set_attr "predicable" "yes")]
5275 (define_insn "*ldmsi_postinc2"
5276 [(match_parallel 0 "load_multiple_operation"
5277 [(set (match_operand:SI 1 "s_register_operand" "=r")
5278 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5280 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5281 (mem:SI (match_dup 2)))
5282 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5283 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5284 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5285 "ldm%?ia\\t%1!, {%3, %4}"
5286 [(set_attr "type" "load")
5287 (set_attr "predicable" "yes")]
5290 ;; Ordinary load multiple
5292 (define_insn "*ldmsi4"
5293 [(match_parallel 0 "load_multiple_operation"
5294 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5295 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5296 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5297 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5298 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5299 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5300 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5301 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5302 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5303 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5304 [(set_attr "type" "load")
5305 (set_attr "predicable" "yes")]
5308 (define_insn "*ldmsi3"
5309 [(match_parallel 0 "load_multiple_operation"
5310 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5311 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5312 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5313 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5314 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5315 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5316 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5317 "ldm%?ia\\t%1, {%2, %3, %4}"
5318 [(set_attr "type" "load")
5319 (set_attr "predicable" "yes")]
5322 (define_insn "*ldmsi2"
5323 [(match_parallel 0 "load_multiple_operation"
5324 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5325 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5326 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5327 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5328 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5329 "ldm%?ia\\t%1, {%2, %3}"
5330 [(set_attr "type" "load")
5331 (set_attr "predicable" "yes")]
5334 (define_expand "store_multiple"
5335 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5336 (match_operand:SI 1 "" ""))
5337 (use (match_operand:SI 2 "" ""))])]
5340 /* Support only fixed point registers */
5341 if (GET_CODE (operands[2]) != CONST_INT
5342 || INTVAL (operands[2]) > 14
5343 || INTVAL (operands[2]) < 2
5344 || GET_CODE (operands[1]) != REG
5345 || GET_CODE (operands[0]) != MEM
5346 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5347 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5351 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5352 force_reg (SImode, XEXP (operands[0], 0)),
5353 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5354 MEM_IN_STRUCT_P(operands[0]),
5355 MEM_SCALAR_P (operands[0]));
5359 ;; Store multiple with write-back
5361 (define_insn "*stmsi_postinc4"
5362 [(match_parallel 0 "store_multiple_operation"
5363 [(set (match_operand:SI 1 "s_register_operand" "=r")
5364 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5366 (set (mem:SI (match_dup 2))
5367 (match_operand:SI 3 "arm_hard_register_operand" ""))
5368 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5369 (match_operand:SI 4 "arm_hard_register_operand" ""))
5370 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5371 (match_operand:SI 5 "arm_hard_register_operand" ""))
5372 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5373 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5374 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5375 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5376 [(set_attr "predicable" "yes")
5377 (set_attr "type" "store4")]
5380 (define_insn "*stmsi_postinc3"
5381 [(match_parallel 0 "store_multiple_operation"
5382 [(set (match_operand:SI 1 "s_register_operand" "=r")
5383 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5385 (set (mem:SI (match_dup 2))
5386 (match_operand:SI 3 "arm_hard_register_operand" ""))
5387 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5388 (match_operand:SI 4 "arm_hard_register_operand" ""))
5389 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5390 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5391 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5392 "stm%?ia\\t%1!, {%3, %4, %5}"
5393 [(set_attr "predicable" "yes")
5394 (set_attr "type" "store3")]
5397 (define_insn "*stmsi_postinc2"
5398 [(match_parallel 0 "store_multiple_operation"
5399 [(set (match_operand:SI 1 "s_register_operand" "=r")
5400 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5402 (set (mem:SI (match_dup 2))
5403 (match_operand:SI 3 "arm_hard_register_operand" ""))
5404 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5405 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5406 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5407 "stm%?ia\\t%1!, {%3, %4}"
5408 [(set_attr "predicable" "yes")
5409 (set_attr "type" "store2")]
5412 ;; Ordinary store multiple
5414 (define_insn "*stmsi4"
5415 [(match_parallel 0 "store_multiple_operation"
5416 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5417 (match_operand:SI 2 "arm_hard_register_operand" ""))
5418 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5419 (match_operand:SI 3 "arm_hard_register_operand" ""))
5420 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5421 (match_operand:SI 4 "arm_hard_register_operand" ""))
5422 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5423 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5424 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5425 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5426 [(set_attr "predicable" "yes")
5427 (set_attr "type" "store4")]
5430 (define_insn "*stmsi3"
5431 [(match_parallel 0 "store_multiple_operation"
5432 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5433 (match_operand:SI 2 "arm_hard_register_operand" ""))
5434 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5435 (match_operand:SI 3 "arm_hard_register_operand" ""))
5436 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5437 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5438 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5439 "stm%?ia\\t%1, {%2, %3, %4}"
5440 [(set_attr "predicable" "yes")
5441 (set_attr "type" "store3")]
5444 (define_insn "*stmsi2"
5445 [(match_parallel 0 "store_multiple_operation"
5446 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5447 (match_operand:SI 2 "arm_hard_register_operand" ""))
5448 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5449 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5450 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5451 "stm%?ia\\t%1, {%2, %3}"
5452 [(set_attr "predicable" "yes")
5453 (set_attr "type" "store2")]
5456 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5457 ;; We could let this apply for blocks of less than this, but it clobbers so
5458 ;; many registers that there is then probably a better way.
5460 (define_expand "movstrqi"
5461 [(match_operand:BLK 0 "general_operand" "")
5462 (match_operand:BLK 1 "general_operand" "")
5463 (match_operand:SI 2 "const_int_operand" "")
5464 (match_operand:SI 3 "const_int_operand" "")]
5469 if (arm_gen_movstrqi (operands))
5473 else /* TARGET_THUMB */
5475 if ( INTVAL (operands[3]) != 4
5476 || INTVAL (operands[2]) > 48)
5479 thumb_expand_movstrqi (operands);
5485 ;; Thumb block-move insns
5487 (define_insn "movmem12b"
5488 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5489 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5490 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5491 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5492 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5493 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5494 (set (match_operand:SI 0 "register_operand" "=l")
5495 (plus:SI (match_dup 2) (const_int 12)))
5496 (set (match_operand:SI 1 "register_operand" "=l")
5497 (plus:SI (match_dup 3) (const_int 12)))
5498 (clobber (match_scratch:SI 4 "=&l"))
5499 (clobber (match_scratch:SI 5 "=&l"))
5500 (clobber (match_scratch:SI 6 "=&l"))]
5502 "* return thumb_output_move_mem_multiple (3, operands);"
5503 [(set_attr "length" "4")
5504 ; This isn't entirely accurate... It loads as well, but in terms of
5505 ; scheduling the following insn it is better to consider it as a store
5506 (set_attr "type" "store3")]
5509 (define_insn "movmem8b"
5510 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5511 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5512 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5513 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5514 (set (match_operand:SI 0 "register_operand" "=l")
5515 (plus:SI (match_dup 2) (const_int 8)))
5516 (set (match_operand:SI 1 "register_operand" "=l")
5517 (plus:SI (match_dup 3) (const_int 8)))
5518 (clobber (match_scratch:SI 4 "=&l"))
5519 (clobber (match_scratch:SI 5 "=&l"))]
5521 "* return thumb_output_move_mem_multiple (2, operands);"
5522 [(set_attr "length" "4")
5523 ; This isn't entirely accurate... It loads as well, but in terms of
5524 ; scheduling the following insn it is better to consider it as a store
5525 (set_attr "type" "store2")]
5530 ;; Compare & branch insns
5531 ;; The range calcualations are based as follows:
5532 ;; For forward branches, the address calculation returns the address of
5533 ;; the next instruction. This is 2 beyond the branch instruction.
5534 ;; For backward branches, the address calculation returns the address of
5535 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5536 ;; instruction for the shortest sequence, and 4 before the branch instruction
5537 ;; if we have to jump around an unconditional branch.
5538 ;; To the basic branch range the PC offset must be added (this is +4).
5539 ;; So for forward branches we have
5540 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5541 ;; And for backward branches we have
5542 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5544 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5545 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5547 (define_insn "cbranchsi4"
5550 (match_operator 0 "arm_comparison_operator"
5551 [(match_operand:SI 1 "register_operand" "l,r")
5552 (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5553 (label_ref (match_operand 3 "" ""))
5557 output_asm_insn (\"cmp\\t%1, %2\", operands);
5558 switch (get_attr_length (insn))
5560 case 4: return \"b%d0\\t%l3\";
5561 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5562 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5565 [(set (attr "far_jump")
5567 (eq_attr "length" "8")
5568 (const_string "yes")
5569 (const_string "no")))
5570 (set (attr "length")
5572 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5573 (le (minus (match_dup 3) (pc)) (const_int 256)))
5576 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5577 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5582 (define_insn "*negated_cbranchsi4"
5585 (match_operator 0 "arm_comparison_operator"
5586 [(match_operand:SI 1 "register_operand" "l")
5587 (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5588 (label_ref (match_operand 3 "" ""))
5592 output_asm_insn (\"cmn\\t%1, %2\", operands);
5593 switch (get_attr_length (insn))
5595 case 4: return \"b%d0\\t%l3\";
5596 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5597 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5600 [(set (attr "far_jump")
5602 (eq_attr "length" "8")
5603 (const_string "yes")
5604 (const_string "no")))
5605 (set (attr "length")
5607 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5608 (le (minus (match_dup 3) (pc)) (const_int 256)))
5611 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5612 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5618 ;; Comparison and test insns
5620 (define_expand "cmpsi"
5621 [(match_operand:SI 0 "s_register_operand" "")
5622 (match_operand:SI 1 "arm_add_operand" "")]
5625 arm_compare_op0 = operands[0];
5626 arm_compare_op1 = operands[1];
5631 (define_expand "cmpsf"
5632 [(match_operand:SF 0 "s_register_operand" "")
5633 (match_operand:SF 1 "fpu_rhs_operand" "")]
5634 "TARGET_ARM && TARGET_HARD_FLOAT"
5636 arm_compare_op0 = operands[0];
5637 arm_compare_op1 = operands[1];
5642 (define_expand "cmpdf"
5643 [(match_operand:DF 0 "s_register_operand" "")
5644 (match_operand:DF 1 "fpu_rhs_operand" "")]
5645 "TARGET_ARM && TARGET_HARD_FLOAT"
5647 arm_compare_op0 = operands[0];
5648 arm_compare_op1 = operands[1];
5653 (define_expand "cmpxf"
5654 [(match_operand:XF 0 "s_register_operand" "")
5655 (match_operand:XF 1 "fpu_rhs_operand" "")]
5656 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5658 arm_compare_op0 = operands[0];
5659 arm_compare_op1 = operands[1];
5664 (define_insn "*arm_cmpsi_insn"
5665 [(set (reg:CC CC_REGNUM)
5666 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5667 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
5672 [(set_attr "conds" "set")]
5675 (define_insn "*cmpsi_shiftsi"
5676 [(set (reg:CC CC_REGNUM)
5677 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5678 (match_operator:SI 3 "shift_operator"
5679 [(match_operand:SI 1 "s_register_operand" "r")
5680 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
5683 [(set_attr "conds" "set")
5684 (set_attr "shift" "1")
5688 (define_insn "*cmpsi_shiftsi_swp"
5689 [(set (reg:CC_SWP CC_REGNUM)
5690 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5691 [(match_operand:SI 1 "s_register_operand" "r")
5692 (match_operand:SI 2 "reg_or_int_operand" "rM")])
5693 (match_operand:SI 0 "s_register_operand" "r")))]
5696 [(set_attr "conds" "set")
5697 (set_attr "shift" "1")
5701 (define_insn "*cmpsi_neg_shiftsi"
5702 [(set (reg:CC CC_REGNUM)
5703 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5704 (neg:SI (match_operator:SI 3 "shift_operator"
5705 [(match_operand:SI 1 "s_register_operand" "r")
5706 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5709 [(set_attr "conds" "set")
5710 (set_attr "shift" "1")
5714 (define_insn "*cmpsf_insn"
5715 [(set (reg:CCFP CC_REGNUM)
5716 (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
5717 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5718 "TARGET_ARM && TARGET_HARD_FLOAT"
5722 [(set_attr "conds" "set")
5723 (set_attr "type" "f_2_r")]
5726 (define_insn "*cmpdf_insn"
5727 [(set (reg:CCFP CC_REGNUM)
5728 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
5729 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5730 "TARGET_ARM && TARGET_HARD_FLOAT"
5734 [(set_attr "conds" "set")
5735 (set_attr "type" "f_2_r")]
5738 (define_insn "*cmpesfdf_df"
5739 [(set (reg:CCFP CC_REGNUM)
5740 (compare:CCFP (float_extend:DF
5741 (match_operand:SF 0 "s_register_operand" "f,f"))
5742 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5743 "TARGET_ARM && TARGET_HARD_FLOAT"
5747 [(set_attr "conds" "set")
5748 (set_attr "type" "f_2_r")]
5751 (define_insn "*cmpdf_esfdf"
5752 [(set (reg:CCFP CC_REGNUM)
5753 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5755 (match_operand:SF 1 "s_register_operand" "f"))))]
5756 "TARGET_ARM && TARGET_HARD_FLOAT"
5758 [(set_attr "conds" "set")
5759 (set_attr "type" "f_2_r")]
5762 (define_insn "*cmpxf_insn"
5763 [(set (reg:CCFP CC_REGNUM)
5764 (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
5765 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5766 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5770 [(set_attr "conds" "set")
5771 (set_attr "type" "f_2_r")]
5774 (define_insn "*cmpsf_trap"
5775 [(set (reg:CCFPE CC_REGNUM)
5776 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
5777 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5778 "TARGET_ARM && TARGET_HARD_FLOAT"
5782 [(set_attr "conds" "set")
5783 (set_attr "type" "f_2_r")]
5786 (define_insn "*cmpdf_trap"
5787 [(set (reg:CCFPE CC_REGNUM)
5788 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
5789 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5790 "TARGET_ARM && TARGET_HARD_FLOAT"
5794 [(set_attr "conds" "set")
5795 (set_attr "type" "f_2_r")]
5798 (define_insn "*cmp_esfdf_df_trap"
5799 [(set (reg:CCFPE CC_REGNUM)
5800 (compare:CCFPE (float_extend:DF
5801 (match_operand:SF 0 "s_register_operand" "f,f"))
5802 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5803 "TARGET_ARM && TARGET_HARD_FLOAT"
5807 [(set_attr "conds" "set")
5808 (set_attr "type" "f_2_r")]
5811 (define_insn "*cmp_df_esfdf_trap"
5812 [(set (reg:CCFPE CC_REGNUM)
5813 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
5815 (match_operand:SF 1 "s_register_operand" "f"))))]
5816 "TARGET_ARM && TARGET_HARD_FLOAT"
5818 [(set_attr "conds" "set")
5819 (set_attr "type" "f_2_r")]
5822 (define_insn "*cmpxf_trap"
5823 [(set (reg:CCFPE CC_REGNUM)
5824 (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
5825 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5826 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5830 [(set_attr "conds" "set")
5831 (set_attr "type" "f_2_r")]
5834 ; This insn allows redundant compares to be removed by cse, nothing should
5835 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5836 ; is deleted later on. The match_dup will match the mode here, so that
5837 ; mode changes of the condition codes aren't lost by this even though we don't
5838 ; specify what they are.
5840 (define_insn "*deleted_compare"
5841 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5843 "\\t%@ deleted compare"
5844 [(set_attr "conds" "set")
5845 (set_attr "length" "0")]
5849 ;; Conditional branch insns
5851 (define_expand "beq"
5853 (if_then_else (eq (match_dup 1) (const_int 0))
5854 (label_ref (match_operand 0 "" ""))
5857 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5860 (define_expand "bne"
5862 (if_then_else (ne (match_dup 1) (const_int 0))
5863 (label_ref (match_operand 0 "" ""))
5866 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5869 (define_expand "bgt"
5871 (if_then_else (gt (match_dup 1) (const_int 0))
5872 (label_ref (match_operand 0 "" ""))
5875 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5878 (define_expand "ble"
5880 (if_then_else (le (match_dup 1) (const_int 0))
5881 (label_ref (match_operand 0 "" ""))
5884 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5887 (define_expand "bge"
5889 (if_then_else (ge (match_dup 1) (const_int 0))
5890 (label_ref (match_operand 0 "" ""))
5893 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5896 (define_expand "blt"
5898 (if_then_else (lt (match_dup 1) (const_int 0))
5899 (label_ref (match_operand 0 "" ""))
5902 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5905 (define_expand "bgtu"
5907 (if_then_else (gtu (match_dup 1) (const_int 0))
5908 (label_ref (match_operand 0 "" ""))
5911 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5914 (define_expand "bleu"
5916 (if_then_else (leu (match_dup 1) (const_int 0))
5917 (label_ref (match_operand 0 "" ""))
5920 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5923 (define_expand "bgeu"
5925 (if_then_else (geu (match_dup 1) (const_int 0))
5926 (label_ref (match_operand 0 "" ""))
5929 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5932 (define_expand "bltu"
5934 (if_then_else (ltu (match_dup 1) (const_int 0))
5935 (label_ref (match_operand 0 "" ""))
5938 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5941 (define_expand "bunordered"
5943 (if_then_else (unordered (match_dup 1) (const_int 0))
5944 (label_ref (match_operand 0 "" ""))
5946 "TARGET_ARM && TARGET_HARD_FLOAT"
5947 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5951 (define_expand "bordered"
5953 (if_then_else (ordered (match_dup 1) (const_int 0))
5954 (label_ref (match_operand 0 "" ""))
5956 "TARGET_ARM && TARGET_HARD_FLOAT"
5957 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5961 (define_expand "bungt"
5963 (if_then_else (ungt (match_dup 1) (const_int 0))
5964 (label_ref (match_operand 0 "" ""))
5966 "TARGET_ARM && TARGET_HARD_FLOAT"
5967 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5970 (define_expand "bunlt"
5972 (if_then_else (unlt (match_dup 1) (const_int 0))
5973 (label_ref (match_operand 0 "" ""))
5975 "TARGET_ARM && TARGET_HARD_FLOAT"
5976 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5979 (define_expand "bunge"
5981 (if_then_else (unge (match_dup 1) (const_int 0))
5982 (label_ref (match_operand 0 "" ""))
5984 "TARGET_ARM && TARGET_HARD_FLOAT"
5985 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5988 (define_expand "bunle"
5990 (if_then_else (unle (match_dup 1) (const_int 0))
5991 (label_ref (match_operand 0 "" ""))
5993 "TARGET_ARM && TARGET_HARD_FLOAT"
5994 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5997 ;; The following two patterns need two branch instructions, since there is
5998 ;; no single instruction that will handle all cases.
5999 (define_expand "buneq"
6001 (if_then_else (uneq (match_dup 1) (const_int 0))
6002 (label_ref (match_operand 0 "" ""))
6004 "TARGET_ARM && TARGET_HARD_FLOAT"
6005 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6008 (define_expand "bltgt"
6010 (if_then_else (ltgt (match_dup 1) (const_int 0))
6011 (label_ref (match_operand 0 "" ""))
6013 "TARGET_ARM && TARGET_HARD_FLOAT"
6014 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6018 ;; Patterns to match conditional branch insns.
6021 ; Special pattern to match UNEQ.
6022 (define_insn "*arm_buneq"
6024 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6025 (label_ref (match_operand 0 "" ""))
6027 "TARGET_ARM && TARGET_HARD_FLOAT"
6029 if (arm_ccfsm_state != 0)
6032 return \"bvs\\t%l0\;beq\\t%l0\";
6034 [(set_attr "conds" "jump_clob")
6035 (set_attr "length" "8")]
6038 ; Special pattern to match LTGT.
6039 (define_insn "*arm_bltgt"
6041 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6042 (label_ref (match_operand 0 "" ""))
6044 "TARGET_ARM && TARGET_HARD_FLOAT"
6046 if (arm_ccfsm_state != 0)
6049 return \"bmi\\t%l0\;bgt\\t%l0\";
6051 [(set_attr "conds" "jump_clob")
6052 (set_attr "length" "8")]
6055 (define_insn "*arm_cond_branch"
6057 (if_then_else (match_operator 1 "arm_comparison_operator"
6058 [(match_operand 2 "cc_register" "") (const_int 0)])
6059 (label_ref (match_operand 0 "" ""))
6063 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6065 arm_ccfsm_state += 2;
6068 return \"b%d1\\t%l0\";
6070 [(set_attr "conds" "use")]
6073 ; Special pattern to match reversed UNEQ.
6074 (define_insn "*arm_buneq_reversed"
6076 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6078 (label_ref (match_operand 0 "" ""))))]
6079 "TARGET_ARM && TARGET_HARD_FLOAT"
6081 if (arm_ccfsm_state != 0)
6084 return \"bmi\\t%l0\;bgt\\t%l0\";
6086 [(set_attr "conds" "jump_clob")
6087 (set_attr "length" "8")]
6090 ; Special pattern to match reversed LTGT.
6091 (define_insn "*arm_bltgt_reversed"
6093 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6095 (label_ref (match_operand 0 "" ""))))]
6096 "TARGET_ARM && TARGET_HARD_FLOAT"
6098 if (arm_ccfsm_state != 0)
6101 return \"bvs\\t%l0\;beq\\t%l0\";
6103 [(set_attr "conds" "jump_clob")
6104 (set_attr "length" "8")]
6107 (define_insn "*arm_cond_branch_reversed"
6109 (if_then_else (match_operator 1 "arm_comparison_operator"
6110 [(match_operand 2 "cc_register" "") (const_int 0)])
6112 (label_ref (match_operand 0 "" ""))))]
6115 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6117 arm_ccfsm_state += 2;
6120 return \"b%D1\\t%l0\";
6122 [(set_attr "conds" "use")]
6129 (define_expand "seq"
6130 [(set (match_operand:SI 0 "s_register_operand" "=r")
6131 (eq:SI (match_dup 1) (const_int 0)))]
6133 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6136 (define_expand "sne"
6137 [(set (match_operand:SI 0 "s_register_operand" "=r")
6138 (ne:SI (match_dup 1) (const_int 0)))]
6140 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6143 (define_expand "sgt"
6144 [(set (match_operand:SI 0 "s_register_operand" "=r")
6145 (gt:SI (match_dup 1) (const_int 0)))]
6147 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6150 (define_expand "sle"
6151 [(set (match_operand:SI 0 "s_register_operand" "=r")
6152 (le:SI (match_dup 1) (const_int 0)))]
6154 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6157 (define_expand "sge"
6158 [(set (match_operand:SI 0 "s_register_operand" "=r")
6159 (ge:SI (match_dup 1) (const_int 0)))]
6161 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6164 (define_expand "slt"
6165 [(set (match_operand:SI 0 "s_register_operand" "=r")
6166 (lt:SI (match_dup 1) (const_int 0)))]
6168 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6171 (define_expand "sgtu"
6172 [(set (match_operand:SI 0 "s_register_operand" "=r")
6173 (gtu:SI (match_dup 1) (const_int 0)))]
6175 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6178 (define_expand "sleu"
6179 [(set (match_operand:SI 0 "s_register_operand" "=r")
6180 (leu:SI (match_dup 1) (const_int 0)))]
6182 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6185 (define_expand "sgeu"
6186 [(set (match_operand:SI 0 "s_register_operand" "=r")
6187 (geu:SI (match_dup 1) (const_int 0)))]
6189 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6192 (define_expand "sltu"
6193 [(set (match_operand:SI 0 "s_register_operand" "=r")
6194 (ltu:SI (match_dup 1) (const_int 0)))]
6196 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6199 (define_expand "sunordered"
6200 [(set (match_operand:SI 0 "s_register_operand" "=r")
6201 (unordered:SI (match_dup 1) (const_int 0)))]
6202 "TARGET_ARM && TARGET_HARD_FLOAT"
6203 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6207 (define_expand "sordered"
6208 [(set (match_operand:SI 0 "s_register_operand" "=r")
6209 (ordered:SI (match_dup 1) (const_int 0)))]
6210 "TARGET_ARM && TARGET_HARD_FLOAT"
6211 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6215 (define_expand "sungt"
6216 [(set (match_operand:SI 0 "s_register_operand" "=r")
6217 (ungt:SI (match_dup 1) (const_int 0)))]
6218 "TARGET_ARM && TARGET_HARD_FLOAT"
6219 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6223 (define_expand "sunge"
6224 [(set (match_operand:SI 0 "s_register_operand" "=r")
6225 (unge:SI (match_dup 1) (const_int 0)))]
6226 "TARGET_ARM && TARGET_HARD_FLOAT"
6227 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6231 (define_expand "sunlt"
6232 [(set (match_operand:SI 0 "s_register_operand" "=r")
6233 (unlt:SI (match_dup 1) (const_int 0)))]
6234 "TARGET_ARM && TARGET_HARD_FLOAT"
6235 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6239 (define_expand "sunle"
6240 [(set (match_operand:SI 0 "s_register_operand" "=r")
6241 (unle:SI (match_dup 1) (const_int 0)))]
6242 "TARGET_ARM && TARGET_HARD_FLOAT"
6243 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6247 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6248 ;;; simple ARM instructions.
6250 ; (define_expand "suneq"
6251 ; [(set (match_operand:SI 0 "s_register_operand" "=r")
6252 ; (uneq:SI (match_dup 1) (const_int 0)))]
6253 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6257 ; (define_expand "sltgt"
6258 ; [(set (match_operand:SI 0 "s_register_operand" "=r")
6259 ; (ltgt:SI (match_dup 1) (const_int 0)))]
6260 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6264 (define_insn "*mov_scc"
6265 [(set (match_operand:SI 0 "s_register_operand" "=r")
6266 (match_operator:SI 1 "arm_comparison_operator"
6267 [(match_operand 2 "cc_register" "") (const_int 0)]))]
6269 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6270 [(set_attr "conds" "use")
6271 (set_attr "length" "8")]
6274 (define_insn "*mov_negscc"
6275 [(set (match_operand:SI 0 "s_register_operand" "=r")
6276 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
6277 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6279 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6280 [(set_attr "conds" "use")
6281 (set_attr "length" "8")]
6284 (define_insn "*mov_notscc"
6285 [(set (match_operand:SI 0 "s_register_operand" "=r")
6286 (not:SI (match_operator:SI 1 "arm_comparison_operator"
6287 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6289 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6290 [(set_attr "conds" "use")
6291 (set_attr "length" "8")]
6295 ;; Conditional move insns
6297 (define_expand "movsicc"
6298 [(set (match_operand:SI 0 "s_register_operand" "")
6299 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6300 (match_operand:SI 2 "arm_not_operand" "")
6301 (match_operand:SI 3 "arm_not_operand" "")))]
6305 enum rtx_code code = GET_CODE (operands[1]);
6308 if (code == UNEQ || code == LTGT)
6311 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6312 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6316 (define_expand "movsfcc"
6317 [(set (match_operand:SF 0 "s_register_operand" "")
6318 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6319 (match_operand:SF 2 "s_register_operand" "")
6320 (match_operand:SF 3 "nonmemory_operand" "")))]
6324 enum rtx_code code = GET_CODE (operands[1]);
6327 if (code == UNEQ || code == LTGT)
6330 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
6331 Otherwise, ensure it is a valid FP add operand */
6332 if ((!TARGET_HARD_FLOAT)
6333 || (!fpu_add_operand (operands[3], SFmode)))
6334 operands[3] = force_reg (SFmode, operands[3]);
6336 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6337 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6341 (define_expand "movdfcc"
6342 [(set (match_operand:DF 0 "s_register_operand" "")
6343 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6344 (match_operand:DF 2 "s_register_operand" "")
6345 (match_operand:DF 3 "fpu_add_operand" "")))]
6346 "TARGET_ARM && TARGET_HARD_FLOAT"
6349 enum rtx_code code = GET_CODE (operands[1]);
6352 if (code == UNEQ || code == LTGT)
6355 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6356 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6360 (define_insn "*movsicc_insn"
6361 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6363 (match_operator 3 "arm_comparison_operator"
6364 [(match_operand 4 "cc_register" "") (const_int 0)])
6365 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6366 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6373 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6374 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6375 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6376 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6377 [(set_attr "length" "4,4,4,4,8,8,8,8")
6378 (set_attr "conds" "use")]
6381 (define_insn "*movsfcc_hard_insn"
6382 [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6384 (match_operator 3 "arm_comparison_operator"
6385 [(match_operand 4 "cc_register" "") (const_int 0)])
6386 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6387 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6388 "TARGET_ARM && TARGET_HARD_FLOAT"
6394 mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
6395 mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
6396 mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
6397 mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
6398 [(set_attr "length" "4,4,4,4,8,8,8,8")
6399 (set_attr "type" "ffarith")
6400 (set_attr "conds" "use")]
6403 (define_insn "*movsfcc_soft_insn"
6404 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6405 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
6406 [(match_operand 4 "cc_register" "") (const_int 0)])
6407 (match_operand:SF 1 "s_register_operand" "0,r")
6408 (match_operand:SF 2 "s_register_operand" "r,0")))]
6409 "TARGET_ARM && TARGET_SOFT_FLOAT"
6413 [(set_attr "conds" "use")]
6416 (define_insn "*movdfcc_insn"
6417 [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6419 (match_operator 3 "arm_comparison_operator"
6420 [(match_operand 4 "cc_register" "") (const_int 0)])
6421 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6422 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6423 "TARGET_ARM && TARGET_HARD_FLOAT"
6429 mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
6430 mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
6431 mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
6432 mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
6433 [(set_attr "length" "4,4,4,4,8,8,8,8")
6434 (set_attr "type" "ffarith")
6435 (set_attr "conds" "use")]
6439 ;; Jump and linkage insns
6441 (define_expand "jump"
6443 (label_ref (match_operand 0 "" "")))]
6448 (define_insn "*arm_jump"
6450 (label_ref (match_operand 0 "" "")))]
6454 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6456 arm_ccfsm_state += 2;
6459 return \"b%?\\t%l0\";
6462 [(set_attr "predicable" "yes")]
6465 (define_insn "*thumb_jump"
6467 (label_ref (match_operand 0 "" "")))]
6470 if (get_attr_length (insn) == 2)
6472 return \"bl\\t%l0\\t%@ far jump\";
6474 [(set (attr "far_jump")
6476 (eq_attr "length" "4")
6477 (const_string "yes")
6478 (const_string "no")))
6479 (set (attr "length")
6481 (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6482 (le (minus (match_dup 0) (pc)) (const_int 2044)))
6487 (define_expand "call"
6488 [(parallel [(call (match_operand 0 "memory_operand" "")
6489 (match_operand 1 "general_operand" ""))
6490 (use (match_operand 2 "" ""))
6491 (clobber (reg:SI LR_REGNUM))])]
6497 /* In an untyped call, we can get NULL for operand 2. */
6498 if (operands[2] == NULL_RTX)
6499 operands[2] = const0_rtx;
6501 /* This is to decide if we should generate indirect calls by loading the
6502 32 bit address of the callee into a register before performing the
6503 branch and link. operand[2] encodes the long_call/short_call
6504 attribute of the function being called. This attribute is set whenever
6505 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6506 is used, and the short_call attribute can also be set if function is
6507 declared as static or if it has already been defined in the current
6508 compilation unit. See arm.c and arm.h for info about this. The third
6509 parameter to arm_is_longcall_p is used to tell it which pattern
6511 callee = XEXP (operands[0], 0);
6513 if (GET_CODE (callee) != REG
6514 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6515 XEXP (operands[0], 0) = force_reg (Pmode, callee);
6519 (define_insn "*call_reg"
6520 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
6521 (match_operand 1 "" ""))
6522 (use (match_operand 2 "" ""))
6523 (clobber (reg:SI LR_REGNUM))]
6526 return output_call (operands);
6528 ;; length is worst case, normally it is only two
6529 [(set_attr "length" "12")
6530 (set_attr "type" "call")]
6533 (define_insn "*call_mem"
6534 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
6535 (match_operand 1 "" ""))
6536 (use (match_operand 2 "" ""))
6537 (clobber (reg:SI LR_REGNUM))]
6540 return output_call_mem (operands);
6542 [(set_attr "length" "12")
6543 (set_attr "type" "call")]
6546 (define_insn "*call_indirect"
6547 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6548 (match_operand 1 "" ""))
6549 (use (match_operand 2 "" ""))
6550 (clobber (reg:SI LR_REGNUM))]
6554 if (TARGET_CALLER_INTERWORKING)
6555 return \"bl\\t%__interwork_call_via_%0\";
6557 return \"bl\\t%__call_via_%0\";
6559 [(set_attr "type" "call")]
6562 (define_insn "*call_value_indirect"
6563 [(set (match_operand 0 "" "=l")
6564 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6565 (match_operand 2 "" "")))
6566 (use (match_operand 3 "" ""))
6567 (clobber (reg:SI LR_REGNUM))]
6571 if (TARGET_CALLER_INTERWORKING)
6572 return \"bl\\t%__interwork_call_via_%1\";
6574 return \"bl\\t%__call_via_%1\";
6576 [(set_attr "type" "call")]
6579 (define_expand "call_value"
6580 [(parallel [(set (match_operand 0 "" "")
6581 (call (match_operand 1 "memory_operand" "")
6582 (match_operand 2 "general_operand" "")))
6583 (use (match_operand 3 "" ""))
6584 (clobber (reg:SI LR_REGNUM))])]
6588 rtx callee = XEXP (operands[1], 0);
6590 /* In an untyped call, we can get NULL for operand 2. */
6591 if (operands[3] == 0)
6592 operands[3] = const0_rtx;
6594 /* See the comment in define_expand \"call\". */
6595 if (GET_CODE (callee) != REG
6596 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6597 XEXP (operands[1], 0) = force_reg (Pmode, callee);
6601 (define_insn "*call_value_reg"
6602 [(set (match_operand 0 "" "=r,f")
6603 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r"))
6604 (match_operand 2 "" "")))
6605 (use (match_operand 3 "" ""))
6606 (clobber (reg:SI LR_REGNUM))]
6609 return output_call (&operands[1]);
6611 [(set_attr "length" "12")
6612 (set_attr "type" "call")]
6615 (define_insn "*call_value_mem"
6616 [(set (match_operand 0 "" "=r,f")
6617 (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m"))
6618 (match_operand 2 "" "")))
6619 (use (match_operand 3 "" ""))
6620 (clobber (reg:SI LR_REGNUM))]
6621 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6623 return output_call_mem (&operands[1]);
6625 [(set_attr "length" "12")
6626 (set_attr "type" "call")]
6629 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6630 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6632 (define_insn "*call_symbol"
6633 [(call (mem:SI (match_operand:SI 0 "" "X"))
6634 (match_operand 1 "" ""))
6635 (use (match_operand 2 "" ""))
6636 (clobber (reg:SI LR_REGNUM))]
6638 && (GET_CODE (operands[0]) == SYMBOL_REF)
6639 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6642 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6644 [(set_attr "type" "call")]
6647 (define_insn "*call_value_symbol"
6648 [(set (match_operand 0 "s_register_operand" "=r,f")
6649 (call (mem:SI (match_operand:SI 1 "" "X,X"))
6650 (match_operand:SI 2 "" "")))
6651 (use (match_operand 3 "" ""))
6652 (clobber (reg:SI LR_REGNUM))]
6654 && (GET_CODE (operands[1]) == SYMBOL_REF)
6655 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6658 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6660 [(set_attr "type" "call")]
6663 (define_insn "*call_insn"
6664 [(call (mem:SI (match_operand:SI 0 "" "X"))
6665 (match_operand:SI 1 "" ""))
6666 (use (match_operand 2 "" ""))
6667 (clobber (reg:SI LR_REGNUM))]
6669 && GET_CODE (operands[0]) == SYMBOL_REF
6670 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6672 [(set_attr "length" "4")
6673 (set_attr "type" "call")]
6676 (define_insn "*call_value_insn"
6677 [(set (match_operand 0 "register_operand" "=l")
6678 (call (mem:SI (match_operand 1 "" "X"))
6679 (match_operand 2 "" "")))
6680 (use (match_operand 3 "" ""))
6681 (clobber (reg:SI LR_REGNUM))]
6683 && GET_CODE (operands[1]) == SYMBOL_REF
6684 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6686 [(set_attr "length" "4")
6687 (set_attr "type" "call")]
6690 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6691 (define_expand "sibcall"
6692 [(parallel [(call (match_operand 0 "memory_operand" "")
6693 (match_operand 1 "general_operand" ""))
6694 (use (match_operand 2 "" ""))
6695 (use (reg:SI LR_REGNUM))])]
6699 if (operands[2] == NULL_RTX)
6700 operands[2] = const0_rtx;
6704 (define_expand "sibcall_value"
6705 [(parallel [(set (match_operand 0 "register_operand" "")
6706 (call (match_operand 1 "memory_operand" "")
6707 (match_operand 2 "general_operand" "")))
6708 (use (match_operand 3 "" ""))
6709 (use (reg:SI LR_REGNUM))])]
6713 if (operands[3] == NULL_RTX)
6714 operands[3] = const0_rtx;
6718 (define_insn "*sibcall_insn"
6719 [(call (mem:SI (match_operand:SI 0 "" "X"))
6720 (match_operand 1 "" ""))
6721 (use (match_operand 2 "" ""))
6722 (use (reg:SI LR_REGNUM))]
6723 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6725 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6727 [(set_attr "type" "call")]
6730 (define_insn "*sibcall_value_insn"
6731 [(set (match_operand 0 "s_register_operand" "=r,f")
6732 (call (mem:SI (match_operand:SI 1 "" "X,X"))
6733 (match_operand 2 "" "")))
6734 (use (match_operand 3 "" ""))
6735 (use (reg:SI LR_REGNUM))]
6736 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6738 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6740 [(set_attr "type" "call")]
6743 ;; Often the return insn will be the same as loading from memory, so set attr
6744 (define_insn "return"
6746 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6749 if (arm_ccfsm_state == 2)
6751 arm_ccfsm_state += 2;
6754 return output_return_instruction (const_true_rtx, TRUE, FALSE);
6756 [(set_attr "type" "load")
6757 (set_attr "predicable" "yes")]
6760 (define_insn "*cond_return"
6762 (if_then_else (match_operator 0 "arm_comparison_operator"
6763 [(match_operand 1 "cc_register" "") (const_int 0)])
6766 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6769 if (arm_ccfsm_state == 2)
6771 arm_ccfsm_state += 2;
6774 return output_return_instruction (operands[0], TRUE, FALSE);
6776 [(set_attr "conds" "use")
6777 (set_attr "type" "load")]
6780 (define_insn "*cond_return_inverted"
6782 (if_then_else (match_operator 0 "arm_comparison_operator"
6783 [(match_operand 1 "cc_register" "") (const_int 0)])
6786 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6789 if (arm_ccfsm_state == 2)
6791 arm_ccfsm_state += 2;
6794 return output_return_instruction (operands[0], TRUE, TRUE);
6796 [(set_attr "conds" "use")
6797 (set_attr "type" "load")]
6800 ;; Call subroutine returning any type.
6802 (define_expand "untyped_call"
6803 [(parallel [(call (match_operand 0 "" "")
6805 (match_operand 1 "" "")
6806 (match_operand 2 "" "")])]
6812 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6814 for (i = 0; i < XVECLEN (operands[2], 0); i++)
6816 rtx set = XVECEXP (operands[2], 0, i);
6818 emit_move_insn (SET_DEST (set), SET_SRC (set));
6821 /* The optimizer does not know that the call sets the function value
6822 registers we stored in the result block. We avoid problems by
6823 claiming that all hard registers are used and clobbered at this
6825 emit_insn (gen_blockage ());
6831 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6832 ;; all of memory. This blocks insns from being moved across this point.
6834 (define_insn "blockage"
6835 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6838 [(set_attr "length" "0")
6839 (set_attr "type" "block")]
6842 (define_expand "casesi"
6843 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6844 (match_operand:SI 1 "const_int_operand" "") ; lower bound
6845 (match_operand:SI 2 "const_int_operand" "") ; total range
6846 (match_operand:SI 3 "" "") ; table label
6847 (match_operand:SI 4 "" "")] ; Out of range label
6852 if (operands[1] != const0_rtx)
6854 reg = gen_reg_rtx (SImode);
6856 emit_insn (gen_addsi3 (reg, operands[0],
6857 GEN_INT (-INTVAL (operands[1]))));
6861 if (!const_ok_for_arm (INTVAL (operands[2])))
6862 operands[2] = force_reg (SImode, operands[2]);
6864 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6870 ;; The USE in this pattern is needed to tell flow analysis that this is
6871 ;; a CASESI insn. It has no other purpose.
6872 (define_insn "casesi_internal"
6873 [(parallel [(set (pc)
6875 (leu (match_operand:SI 0 "s_register_operand" "r")
6876 (match_operand:SI 1 "arm_rhs_operand" "rI"))
6877 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6878 (label_ref (match_operand 2 "" ""))))
6879 (label_ref (match_operand 3 "" ""))))
6880 (clobber (reg:CC CC_REGNUM))
6881 (use (label_ref (match_dup 2)))])]
6885 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6886 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6888 [(set_attr "conds" "clob")
6889 (set_attr "length" "12")]
6892 (define_expand "indirect_jump"
6894 (match_operand:SI 0 "s_register_operand" ""))]
6899 (define_insn "*arm_indirect_jump"
6901 (match_operand:SI 0 "s_register_operand" "r"))]
6903 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6904 [(set_attr "predicable" "yes")]
6907 ;; Although not supported by the define_expand above,
6908 ;; cse/combine may generate this form.
6909 (define_insn "*load_indirect_jump"
6911 (match_operand:SI 0 "memory_operand" "m"))]
6913 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6914 [(set_attr "type" "load")
6915 (set_attr "pool_range" "4096")
6916 (set_attr "neg_pool_range" "4084")
6917 (set_attr "predicable" "yes")]
6920 (define_insn "*thumb_indirect_jump"
6922 (match_operand:SI 0 "register_operand" "l*r"))]
6925 [(set_attr "conds" "clob")
6926 (set_attr "length" "2")]
6937 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6938 return \"mov\\tr8, r8\";
6940 [(set (attr "length")
6941 (if_then_else (eq_attr "is_thumb" "yes")
6947 ;; Patterns to allow combination of arithmetic, cond code and shifts
6949 (define_insn "*arith_shiftsi"
6950 [(set (match_operand:SI 0 "s_register_operand" "=r")
6951 (match_operator:SI 1 "shiftable_operator"
6952 [(match_operator:SI 3 "shift_operator"
6953 [(match_operand:SI 4 "s_register_operand" "r")
6954 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6955 (match_operand:SI 2 "s_register_operand" "r")]))]
6957 "%i1%?\\t%0, %2, %4%S3"
6958 [(set_attr "predicable" "yes")
6959 (set_attr "shift" "4")
6963 (define_insn "*arith_shiftsi_compare0"
6964 [(set (reg:CC_NOOV CC_REGNUM)
6965 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6966 [(match_operator:SI 3 "shift_operator"
6967 [(match_operand:SI 4 "s_register_operand" "r")
6968 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6969 (match_operand:SI 2 "s_register_operand" "r")])
6971 (set (match_operand:SI 0 "s_register_operand" "=r")
6972 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6975 "%i1%?s\\t%0, %2, %4%S3"
6976 [(set_attr "conds" "set")
6977 (set_attr "shift" "4")
6981 (define_insn "*arith_shiftsi_compare0_scratch"
6982 [(set (reg:CC_NOOV CC_REGNUM)
6983 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6984 [(match_operator:SI 3 "shift_operator"
6985 [(match_operand:SI 4 "s_register_operand" "r")
6986 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6987 (match_operand:SI 2 "s_register_operand" "r")])
6989 (clobber (match_scratch:SI 0 "=r"))]
6991 "%i1%?s\\t%0, %2, %4%S3"
6992 [(set_attr "conds" "set")
6993 (set_attr "shift" "4")
6997 (define_insn "*sub_shiftsi"
6998 [(set (match_operand:SI 0 "s_register_operand" "=r")
6999 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7000 (match_operator:SI 2 "shift_operator"
7001 [(match_operand:SI 3 "s_register_operand" "r")
7002 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7004 "sub%?\\t%0, %1, %3%S2"
7005 [(set_attr "predicable" "yes")
7006 (set_attr "shift" "3")
7010 (define_insn "*sub_shiftsi_compare0"
7011 [(set (reg:CC_NOOV CC_REGNUM)
7013 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7014 (match_operator:SI 2 "shift_operator"
7015 [(match_operand:SI 3 "s_register_operand" "r")
7016 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7018 (set (match_operand:SI 0 "s_register_operand" "=r")
7019 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7022 "sub%?s\\t%0, %1, %3%S2"
7023 [(set_attr "conds" "set")
7024 (set_attr "shift" "3")
7028 (define_insn "*sub_shiftsi_compare0_scratch"
7029 [(set (reg:CC_NOOV CC_REGNUM)
7031 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7032 (match_operator:SI 2 "shift_operator"
7033 [(match_operand:SI 3 "s_register_operand" "r")
7034 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7036 (clobber (match_scratch:SI 0 "=r"))]
7038 "sub%?s\\t%0, %1, %3%S2"
7039 [(set_attr "conds" "set")
7040 (set_attr "shift" "3")
7046 (define_insn "*and_scc"
7047 [(set (match_operand:SI 0 "s_register_operand" "=r")
7048 (and:SI (match_operator:SI 1 "arm_comparison_operator"
7049 [(match_operand 3 "cc_register" "") (const_int 0)])
7050 (match_operand:SI 2 "s_register_operand" "r")))]
7052 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7053 [(set_attr "conds" "use")
7054 (set_attr "length" "8")]
7057 (define_insn "*ior_scc"
7058 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7059 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
7060 [(match_operand 3 "cc_register" "") (const_int 0)])
7061 (match_operand:SI 1 "s_register_operand" "0,?r")))]
7065 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7066 [(set_attr "conds" "use")
7067 (set_attr "length" "4,8")]
7070 (define_insn "*compare_scc"
7071 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7072 (match_operator:SI 1 "arm_comparison_operator"
7073 [(match_operand:SI 2 "s_register_operand" "r,r")
7074 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7075 (clobber (reg:CC CC_REGNUM))]
7078 if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
7079 return \"mov\\t%0, %2, lsr #31\";
7081 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
7082 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7084 if (GET_CODE (operands[1]) == NE)
7086 if (which_alternative == 1)
7087 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7088 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7090 if (which_alternative == 1)
7091 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7093 output_asm_insn (\"cmp\\t%2, %3\", operands);
7094 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7096 [(set_attr "conds" "clob")
7097 (set_attr "length" "12")]
7100 (define_insn "*cond_move"
7101 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7102 (if_then_else:SI (match_operator 3 "equality_operator"
7103 [(match_operator 4 "arm_comparison_operator"
7104 [(match_operand 5 "cc_register" "") (const_int 0)])
7106 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7107 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7110 if (GET_CODE (operands[3]) == NE)
7112 if (which_alternative != 1)
7113 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7114 if (which_alternative != 0)
7115 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7118 if (which_alternative != 0)
7119 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7120 if (which_alternative != 1)
7121 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7124 [(set_attr "conds" "use")
7125 (set_attr "length" "4,4,8")]
7128 (define_insn "*cond_arith"
7129 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7130 (match_operator:SI 5 "shiftable_operator"
7131 [(match_operator:SI 4 "arm_comparison_operator"
7132 [(match_operand:SI 2 "s_register_operand" "r,r")
7133 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7134 (match_operand:SI 1 "s_register_operand" "0,?r")]))
7135 (clobber (reg:CC CC_REGNUM))]
7138 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7139 return \"%i5\\t%0, %1, %2, lsr #31\";
7141 output_asm_insn (\"cmp\\t%2, %3\", operands);
7142 if (GET_CODE (operands[5]) == AND)
7143 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7144 else if (GET_CODE (operands[5]) == MINUS)
7145 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7146 else if (which_alternative != 0)
7147 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7148 return \"%i5%d4\\t%0, %1, #1\";
7150 [(set_attr "conds" "clob")
7151 (set_attr "length" "12")]
7154 (define_insn "*cond_sub"
7155 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7156 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7157 (match_operator:SI 4 "arm_comparison_operator"
7158 [(match_operand:SI 2 "s_register_operand" "r,r")
7159 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7160 (clobber (reg:CC CC_REGNUM))]
7163 output_asm_insn (\"cmp\\t%2, %3\", operands);
7164 if (which_alternative != 0)
7165 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7166 return \"sub%d4\\t%0, %1, #1\";
7168 [(set_attr "conds" "clob")
7169 (set_attr "length" "8,12")]
7172 (define_insn "*cmp_ite0"
7173 [(set (match_operand 6 "dominant_cc_register" "")
7176 (match_operator 4 "arm_comparison_operator"
7177 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7178 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7179 (match_operator:SI 5 "arm_comparison_operator"
7180 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7181 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7187 static const char * const opcodes[4][2] =
7189 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7190 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7191 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7192 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7193 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7194 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7195 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7196 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7199 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7201 return opcodes[which_alternative][swap];
7203 [(set_attr "conds" "set")
7204 (set_attr "length" "8")]
7207 (define_insn "*cmp_ite1"
7208 [(set (match_operand 6 "dominant_cc_register" "")
7211 (match_operator 4 "arm_comparison_operator"
7212 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7213 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7214 (match_operator:SI 5 "arm_comparison_operator"
7215 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7216 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7222 static const char * const opcodes[4][2] =
7224 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7225 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7226 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7227 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7228 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7229 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7230 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7231 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7234 comparison_dominates_p (GET_CODE (operands[5]),
7235 reverse_condition (GET_CODE (operands[4])));
7237 return opcodes[which_alternative][swap];
7239 [(set_attr "conds" "set")
7240 (set_attr "length" "8")]
7243 (define_insn "*cmp_and"
7244 [(set (match_operand 6 "dominant_cc_register" "")
7247 (match_operator 4 "arm_comparison_operator"
7248 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7249 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7250 (match_operator:SI 5 "arm_comparison_operator"
7251 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7252 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7257 static const char *const opcodes[4][2] =
7259 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7260 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7261 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7262 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7263 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7264 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7265 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7266 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7269 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7271 return opcodes[which_alternative][swap];
7273 [(set_attr "conds" "set")
7274 (set_attr "predicable" "no")
7275 (set_attr "length" "8")]
7278 (define_insn "*cmp_ior"
7279 [(set (match_operand 6 "dominant_cc_register" "")
7282 (match_operator 4 "arm_comparison_operator"
7283 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7284 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7285 (match_operator:SI 5 "arm_comparison_operator"
7286 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7287 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7292 static const char *const opcodes[4][2] =
7294 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7295 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7296 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7297 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7298 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7299 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7300 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7301 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7304 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7306 return opcodes[which_alternative][swap];
7309 [(set_attr "conds" "set")
7310 (set_attr "length" "8")]
7313 (define_insn "*negscc"
7314 [(set (match_operand:SI 0 "s_register_operand" "=r")
7315 (neg:SI (match_operator 3 "arm_comparison_operator"
7316 [(match_operand:SI 1 "s_register_operand" "r")
7317 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7318 (clobber (reg:CC CC_REGNUM))]
7321 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7322 return \"mov\\t%0, %1, asr #31\";
7324 if (GET_CODE (operands[3]) == NE)
7325 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7327 if (GET_CODE (operands[3]) == GT)
7328 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7330 output_asm_insn (\"cmp\\t%1, %2\", operands);
7331 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7332 return \"mvn%d3\\t%0, #0\";
7334 [(set_attr "conds" "clob")
7335 (set_attr "length" "12")]
7338 (define_insn "movcond"
7339 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7341 (match_operator 5 "arm_comparison_operator"
7342 [(match_operand:SI 3 "s_register_operand" "r,r,r")
7343 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7344 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7345 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
7346 (clobber (reg:CC CC_REGNUM))]
7349 if (GET_CODE (operands[5]) == LT
7350 && (operands[4] == const0_rtx))
7352 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7354 if (operands[2] == const0_rtx)
7355 return \"and\\t%0, %1, %3, asr #31\";
7356 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
7358 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7360 if (operands[1] == const0_rtx)
7361 return \"bic\\t%0, %2, %3, asr #31\";
7362 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
7364 /* The only case that falls through to here is when both ops 1 & 2
7368 if (GET_CODE (operands[5]) == GE
7369 && (operands[4] == const0_rtx))
7371 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7373 if (operands[2] == const0_rtx)
7374 return \"bic\\t%0, %1, %3, asr #31\";
7375 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7377 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7379 if (operands[1] == const0_rtx)
7380 return \"and\\t%0, %2, %3, asr #31\";
7381 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7383 /* The only case that falls through to here is when both ops 1 & 2
7386 if (GET_CODE (operands[4]) == CONST_INT
7387 && !const_ok_for_arm (INTVAL (operands[4])))
7388 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7390 output_asm_insn (\"cmp\\t%3, %4\", operands);
7391 if (which_alternative != 0)
7392 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7393 if (which_alternative != 1)
7394 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7397 [(set_attr "conds" "clob")
7398 (set_attr "length" "8,8,12")]
7401 (define_insn "*ifcompare_plus_move"
7402 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7403 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7404 [(match_operand:SI 4 "s_register_operand" "r,r")
7405 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7407 (match_operand:SI 2 "s_register_operand" "r,r")
7408 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7409 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7410 (clobber (reg:CC CC_REGNUM))]
7413 [(set_attr "conds" "clob")
7414 (set_attr "length" "8,12")]
7417 (define_insn "*if_plus_move"
7418 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7420 (match_operator 4 "arm_comparison_operator"
7421 [(match_operand 5 "cc_register" "") (const_int 0)])
7423 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7424 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7425 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7429 sub%d4\\t%0, %2, #%n3
7430 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7431 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7432 [(set_attr "conds" "use")
7433 (set_attr "length" "4,4,8,8")
7434 (set_attr "type" "*,*,*,*")]
7437 (define_insn "*ifcompare_move_plus"
7438 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7439 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7440 [(match_operand:SI 4 "s_register_operand" "r,r")
7441 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7442 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7444 (match_operand:SI 2 "s_register_operand" "r,r")
7445 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7446 (clobber (reg:CC CC_REGNUM))]
7449 [(set_attr "conds" "clob")
7450 (set_attr "length" "8,12")]
7453 (define_insn "*if_move_plus"
7454 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7456 (match_operator 4 "arm_comparison_operator"
7457 [(match_operand 5 "cc_register" "") (const_int 0)])
7458 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7460 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7461 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7465 sub%D4\\t%0, %2, #%n3
7466 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7467 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7468 [(set_attr "conds" "use")
7469 (set_attr "length" "4,4,8,8")
7470 (set_attr "type" "*,*,*,*")]
7473 (define_insn "*ifcompare_arith_arith"
7474 [(set (match_operand:SI 0 "s_register_operand" "=r")
7475 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7476 [(match_operand:SI 5 "s_register_operand" "r")
7477 (match_operand:SI 6 "arm_add_operand" "rIL")])
7478 (match_operator:SI 8 "shiftable_operator"
7479 [(match_operand:SI 1 "s_register_operand" "r")
7480 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7481 (match_operator:SI 7 "shiftable_operator"
7482 [(match_operand:SI 3 "s_register_operand" "r")
7483 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7484 (clobber (reg:CC CC_REGNUM))]
7487 [(set_attr "conds" "clob")
7488 (set_attr "length" "12")]
7491 (define_insn "*if_arith_arith"
7492 [(set (match_operand:SI 0 "s_register_operand" "=r")
7493 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7494 [(match_operand 8 "cc_register" "") (const_int 0)])
7495 (match_operator:SI 6 "shiftable_operator"
7496 [(match_operand:SI 1 "s_register_operand" "r")
7497 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7498 (match_operator:SI 7 "shiftable_operator"
7499 [(match_operand:SI 3 "s_register_operand" "r")
7500 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7502 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7503 [(set_attr "conds" "use")
7504 (set_attr "length" "8")]
7507 (define_insn "*ifcompare_arith_move"
7508 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7509 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7510 [(match_operand:SI 2 "s_register_operand" "r,r")
7511 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7512 (match_operator:SI 7 "shiftable_operator"
7513 [(match_operand:SI 4 "s_register_operand" "r,r")
7514 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7515 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7516 (clobber (reg:CC CC_REGNUM))]
7519 /* If we have an operation where (op x 0) is the identity operation and
7520 the conditional operator is LT or GE and we are comparing against zero and
7521 everything is in registers then we can do this in two instructions */
7522 if (operands[3] == const0_rtx
7523 && GET_CODE (operands[7]) != AND
7524 && GET_CODE (operands[5]) == REG
7525 && GET_CODE (operands[1]) == REG
7526 && REGNO (operands[1]) == REGNO (operands[4])
7527 && REGNO (operands[4]) != REGNO (operands[0]))
7529 if (GET_CODE (operands[6]) == LT)
7530 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7531 else if (GET_CODE (operands[6]) == GE)
7532 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7534 if (GET_CODE (operands[3]) == CONST_INT
7535 && !const_ok_for_arm (INTVAL (operands[3])))
7536 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7538 output_asm_insn (\"cmp\\t%2, %3\", operands);
7539 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7540 if (which_alternative != 0)
7541 return \"mov%D6\\t%0, %1\";
7544 [(set_attr "conds" "clob")
7545 (set_attr "length" "8,12")]
7548 (define_insn "*if_arith_move"
7549 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7550 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7551 [(match_operand 6 "cc_register" "") (const_int 0)])
7552 (match_operator:SI 5 "shiftable_operator"
7553 [(match_operand:SI 2 "s_register_operand" "r,r")
7554 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7555 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7559 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7560 [(set_attr "conds" "use")
7561 (set_attr "length" "4,8")
7562 (set_attr "type" "*,*")]
7565 (define_insn "*ifcompare_move_arith"
7566 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7567 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7568 [(match_operand:SI 4 "s_register_operand" "r,r")
7569 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7570 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7571 (match_operator:SI 7 "shiftable_operator"
7572 [(match_operand:SI 2 "s_register_operand" "r,r")
7573 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7574 (clobber (reg:CC CC_REGNUM))]
7577 /* If we have an operation where (op x 0) is the identity operation and
7578 the conditional operator is LT or GE and we are comparing against zero and
7579 everything is in registers then we can do this in two instructions */
7580 if (operands[5] == const0_rtx
7581 && GET_CODE (operands[7]) != AND
7582 && GET_CODE (operands[3]) == REG
7583 && GET_CODE (operands[1]) == REG
7584 && REGNO (operands[1]) == REGNO (operands[2])
7585 && REGNO (operands[2]) != REGNO (operands[0]))
7587 if (GET_CODE (operands[6]) == GE)
7588 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7589 else if (GET_CODE (operands[6]) == LT)
7590 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7593 if (GET_CODE (operands[5]) == CONST_INT
7594 && !const_ok_for_arm (INTVAL (operands[5])))
7595 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7597 output_asm_insn (\"cmp\\t%4, %5\", operands);
7599 if (which_alternative != 0)
7600 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7601 return \"%I7%D6\\t%0, %2, %3\";
7603 [(set_attr "conds" "clob")
7604 (set_attr "length" "8,12")]
7607 (define_insn "*if_move_arith"
7608 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7610 (match_operator 4 "arm_comparison_operator"
7611 [(match_operand 6 "cc_register" "") (const_int 0)])
7612 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7613 (match_operator:SI 5 "shiftable_operator"
7614 [(match_operand:SI 2 "s_register_operand" "r,r")
7615 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7619 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7620 [(set_attr "conds" "use")
7621 (set_attr "length" "4,8")
7622 (set_attr "type" "*,*")]
7625 (define_insn "*ifcompare_move_not"
7626 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7628 (match_operator 5 "arm_comparison_operator"
7629 [(match_operand:SI 3 "s_register_operand" "r,r")
7630 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7631 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7633 (match_operand:SI 2 "s_register_operand" "r,r"))))
7634 (clobber (reg:CC CC_REGNUM))]
7637 [(set_attr "conds" "clob")
7638 (set_attr "length" "8,12")]
7641 (define_insn "*if_move_not"
7642 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7644 (match_operator 4 "arm_comparison_operator"
7645 [(match_operand 3 "cc_register" "") (const_int 0)])
7646 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7647 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7651 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7652 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7653 [(set_attr "conds" "use")
7654 (set_attr "length" "4,8,8")]
7657 (define_insn "*ifcompare_not_move"
7658 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7660 (match_operator 5 "arm_comparison_operator"
7661 [(match_operand:SI 3 "s_register_operand" "r,r")
7662 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7664 (match_operand:SI 2 "s_register_operand" "r,r"))
7665 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7666 (clobber (reg:CC CC_REGNUM))]
7669 [(set_attr "conds" "clob")
7670 (set_attr "length" "8,12")]
7673 (define_insn "*if_not_move"
7674 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7676 (match_operator 4 "arm_comparison_operator"
7677 [(match_operand 3 "cc_register" "") (const_int 0)])
7678 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7679 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7683 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7684 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7685 [(set_attr "conds" "use")
7686 (set_attr "length" "4,8,8")]
7689 (define_insn "*ifcompare_shift_move"
7690 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7692 (match_operator 6 "arm_comparison_operator"
7693 [(match_operand:SI 4 "s_register_operand" "r,r")
7694 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7695 (match_operator:SI 7 "shift_operator"
7696 [(match_operand:SI 2 "s_register_operand" "r,r")
7697 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7698 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7699 (clobber (reg:CC CC_REGNUM))]
7702 [(set_attr "conds" "clob")
7703 (set_attr "length" "8,12")]
7706 (define_insn "*if_shift_move"
7707 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7709 (match_operator 5 "arm_comparison_operator"
7710 [(match_operand 6 "cc_register" "") (const_int 0)])
7711 (match_operator:SI 4 "shift_operator"
7712 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7713 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7714 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7718 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7719 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7720 [(set_attr "conds" "use")
7721 (set_attr "shift" "2")
7722 (set_attr "length" "4,8,8")]
7725 (define_insn "*ifcompare_move_shift"
7726 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7728 (match_operator 6 "arm_comparison_operator"
7729 [(match_operand:SI 4 "s_register_operand" "r,r")
7730 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7731 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7732 (match_operator:SI 7 "shift_operator"
7733 [(match_operand:SI 2 "s_register_operand" "r,r")
7734 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7735 (clobber (reg:CC CC_REGNUM))]
7738 [(set_attr "conds" "clob")
7739 (set_attr "length" "8,12")]
7742 (define_insn "*if_move_shift"
7743 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7745 (match_operator 5 "arm_comparison_operator"
7746 [(match_operand 6 "cc_register" "") (const_int 0)])
7747 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7748 (match_operator:SI 4 "shift_operator"
7749 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7750 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7754 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7755 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7756 [(set_attr "conds" "use")
7757 (set_attr "shift" "2")
7758 (set_attr "length" "4,8,8")]
7761 (define_insn "*ifcompare_shift_shift"
7762 [(set (match_operand:SI 0 "s_register_operand" "=r")
7764 (match_operator 7 "arm_comparison_operator"
7765 [(match_operand:SI 5 "s_register_operand" "r")
7766 (match_operand:SI 6 "arm_add_operand" "rIL")])
7767 (match_operator:SI 8 "shift_operator"
7768 [(match_operand:SI 1 "s_register_operand" "r")
7769 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7770 (match_operator:SI 9 "shift_operator"
7771 [(match_operand:SI 3 "s_register_operand" "r")
7772 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7773 (clobber (reg:CC CC_REGNUM))]
7776 [(set_attr "conds" "clob")
7777 (set_attr "length" "12")]
7780 (define_insn "*if_shift_shift"
7781 [(set (match_operand:SI 0 "s_register_operand" "=r")
7783 (match_operator 5 "arm_comparison_operator"
7784 [(match_operand 8 "cc_register" "") (const_int 0)])
7785 (match_operator:SI 6 "shift_operator"
7786 [(match_operand:SI 1 "s_register_operand" "r")
7787 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7788 (match_operator:SI 7 "shift_operator"
7789 [(match_operand:SI 3 "s_register_operand" "r")
7790 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7792 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7793 [(set_attr "conds" "use")
7794 (set_attr "shift" "1")
7795 (set_attr "length" "8")]
7798 (define_insn "*ifcompare_not_arith"
7799 [(set (match_operand:SI 0 "s_register_operand" "=r")
7801 (match_operator 6 "arm_comparison_operator"
7802 [(match_operand:SI 4 "s_register_operand" "r")
7803 (match_operand:SI 5 "arm_add_operand" "rIL")])
7804 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7805 (match_operator:SI 7 "shiftable_operator"
7806 [(match_operand:SI 2 "s_register_operand" "r")
7807 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7808 (clobber (reg:CC CC_REGNUM))]
7811 [(set_attr "conds" "clob")
7812 (set_attr "length" "12")]
7815 (define_insn "*if_not_arith"
7816 [(set (match_operand:SI 0 "s_register_operand" "=r")
7818 (match_operator 5 "arm_comparison_operator"
7819 [(match_operand 4 "cc_register" "") (const_int 0)])
7820 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7821 (match_operator:SI 6 "shiftable_operator"
7822 [(match_operand:SI 2 "s_register_operand" "r")
7823 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7825 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7826 [(set_attr "conds" "use")
7827 (set_attr "length" "8")]
7830 (define_insn "*ifcompare_arith_not"
7831 [(set (match_operand:SI 0 "s_register_operand" "=r")
7833 (match_operator 6 "arm_comparison_operator"
7834 [(match_operand:SI 4 "s_register_operand" "r")
7835 (match_operand:SI 5 "arm_add_operand" "rIL")])
7836 (match_operator:SI 7 "shiftable_operator"
7837 [(match_operand:SI 2 "s_register_operand" "r")
7838 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7839 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7840 (clobber (reg:CC CC_REGNUM))]
7843 [(set_attr "conds" "clob")
7844 (set_attr "length" "12")]
7847 (define_insn "*if_arith_not"
7848 [(set (match_operand:SI 0 "s_register_operand" "=r")
7850 (match_operator 5 "arm_comparison_operator"
7851 [(match_operand 4 "cc_register" "") (const_int 0)])
7852 (match_operator:SI 6 "shiftable_operator"
7853 [(match_operand:SI 2 "s_register_operand" "r")
7854 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7855 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7857 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7858 [(set_attr "conds" "use")
7859 (set_attr "length" "8")]
7862 (define_insn "*ifcompare_neg_move"
7863 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7865 (match_operator 5 "arm_comparison_operator"
7866 [(match_operand:SI 3 "s_register_operand" "r,r")
7867 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7868 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7869 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7870 (clobber (reg:CC CC_REGNUM))]
7873 [(set_attr "conds" "clob")
7874 (set_attr "length" "8,12")]
7877 (define_insn "*if_neg_move"
7878 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7880 (match_operator 4 "arm_comparison_operator"
7881 [(match_operand 3 "cc_register" "") (const_int 0)])
7882 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7883 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7887 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7888 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
7889 [(set_attr "conds" "use")
7890 (set_attr "length" "4,8,8")]
7893 (define_insn "*ifcompare_move_neg"
7894 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7896 (match_operator 5 "arm_comparison_operator"
7897 [(match_operand:SI 3 "s_register_operand" "r,r")
7898 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7899 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7900 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
7901 (clobber (reg:CC CC_REGNUM))]
7904 [(set_attr "conds" "clob")
7905 (set_attr "length" "8,12")]
7908 (define_insn "*if_move_neg"
7909 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7911 (match_operator 4 "arm_comparison_operator"
7912 [(match_operand 3 "cc_register" "") (const_int 0)])
7913 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7914 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7918 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
7919 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
7920 [(set_attr "conds" "use")
7921 (set_attr "length" "4,8,8")]
7924 (define_insn "*arith_adjacentmem"
7925 [(set (match_operand:SI 0 "s_register_operand" "=r")
7926 (match_operator:SI 1 "shiftable_operator"
7927 [(match_operand:SI 2 "memory_operand" "m")
7928 (match_operand:SI 3 "memory_operand" "m")]))
7929 (clobber (match_scratch:SI 4 "=r"))]
7930 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
7935 int val1 = 0, val2 = 0;
7937 if (REGNO (operands[0]) > REGNO (operands[4]))
7939 ldm[1] = operands[4];
7940 ldm[2] = operands[0];
7944 ldm[1] = operands[0];
7945 ldm[2] = operands[4];
7947 if (GET_CODE (XEXP (operands[2], 0)) != REG)
7948 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
7949 if (GET_CODE (XEXP (operands[3], 0)) != REG)
7950 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
7951 arith[0] = operands[0];
7952 arith[3] = operands[1];
7966 ldm[0] = ops[0] = operands[4];
7967 ops[1] = XEXP (XEXP (operands[2], 0), 0);
7968 ops[2] = XEXP (XEXP (operands[2], 0), 1);
7969 output_add_immediate (ops);
7971 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7973 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7977 ldm[0] = XEXP (operands[3], 0);
7979 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7981 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7985 ldm[0] = XEXP (operands[2], 0);
7987 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7989 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7991 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
7994 [(set_attr "length" "12")
7995 (set_attr "predicable" "yes")
7996 (set_attr "type" "load")]
7999 ;; the arm can support extended pre-inc instructions
8001 ;; In all these cases, we use operands 0 and 1 for the register being
8002 ;; incremented because those are the operands that local-alloc will
8003 ;; tie and these are the pair most likely to be tieable (and the ones
8004 ;; that will benefit the most).
8006 ;; We reject the frame pointer if it occurs anywhere in these patterns since
8007 ;; elimination will cause too many headaches.
8009 (define_insn "*strqi_preinc"
8010 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8011 (match_operand:SI 2 "index_operand" "rJ")))
8012 (match_operand:QI 3 "s_register_operand" "r"))
8013 (set (match_operand:SI 0 "s_register_operand" "=r")
8014 (plus:SI (match_dup 1) (match_dup 2)))]
8016 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8017 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8018 && (GET_CODE (operands[2]) != REG
8019 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8020 "str%?b\\t%3, [%0, %2]!"
8021 [(set_attr "type" "store1")
8022 (set_attr "predicable" "yes")]
8025 (define_insn "*strqi_predec"
8026 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8027 (match_operand:SI 2 "s_register_operand" "r")))
8028 (match_operand:QI 3 "s_register_operand" "r"))
8029 (set (match_operand:SI 0 "s_register_operand" "=r")
8030 (minus:SI (match_dup 1) (match_dup 2)))]
8032 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8033 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8034 && (GET_CODE (operands[2]) != REG
8035 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8036 "str%?b\\t%3, [%0, -%2]!"
8037 [(set_attr "type" "store1")
8038 (set_attr "predicable" "yes")]
8041 (define_insn "*loadqi_preinc"
8042 [(set (match_operand:QI 3 "s_register_operand" "=r")
8043 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8044 (match_operand:SI 2 "index_operand" "rJ"))))
8045 (set (match_operand:SI 0 "s_register_operand" "=r")
8046 (plus:SI (match_dup 1) (match_dup 2)))]
8048 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8049 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8050 && (GET_CODE (operands[2]) != REG
8051 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8052 "ldr%?b\\t%3, [%0, %2]!"
8053 [(set_attr "type" "load")
8054 (set_attr "predicable" "yes")]
8057 (define_insn "*loadqi_predec"
8058 [(set (match_operand:QI 3 "s_register_operand" "=r")
8059 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8060 (match_operand:SI 2 "s_register_operand" "r"))))
8061 (set (match_operand:SI 0 "s_register_operand" "=r")
8062 (minus:SI (match_dup 1) (match_dup 2)))]
8064 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8065 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8066 && (GET_CODE (operands[2]) != REG
8067 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8068 "ldr%?b\\t%3, [%0, -%2]!"
8069 [(set_attr "type" "load")
8070 (set_attr "predicable" "yes")]
8073 (define_insn "*loadqisi_preinc"
8074 [(set (match_operand:SI 3 "s_register_operand" "=r")
8076 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8077 (match_operand:SI 2 "index_operand" "rJ")))))
8078 (set (match_operand:SI 0 "s_register_operand" "=r")
8079 (plus:SI (match_dup 1) (match_dup 2)))]
8081 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8082 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8083 && (GET_CODE (operands[2]) != REG
8084 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8085 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8086 [(set_attr "type" "load")
8087 (set_attr "predicable" "yes")]
8090 (define_insn "*loadqisi_predec"
8091 [(set (match_operand:SI 3 "s_register_operand" "=r")
8093 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8094 (match_operand:SI 2 "s_register_operand" "r")))))
8095 (set (match_operand:SI 0 "s_register_operand" "=r")
8096 (minus:SI (match_dup 1) (match_dup 2)))]
8098 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8099 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8100 && (GET_CODE (operands[2]) != REG
8101 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8102 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8103 [(set_attr "type" "load")
8104 (set_attr "predicable" "yes")]
8107 (define_insn "*strsi_preinc"
8108 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8109 (match_operand:SI 2 "index_operand" "rJ")))
8110 (match_operand:SI 3 "s_register_operand" "r"))
8111 (set (match_operand:SI 0 "s_register_operand" "=r")
8112 (plus:SI (match_dup 1) (match_dup 2)))]
8114 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8115 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8116 && (GET_CODE (operands[2]) != REG
8117 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8118 "str%?\\t%3, [%0, %2]!"
8119 [(set_attr "type" "store1")
8120 (set_attr "predicable" "yes")]
8123 (define_insn "*strsi_predec"
8124 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8125 (match_operand:SI 2 "s_register_operand" "r")))
8126 (match_operand:SI 3 "s_register_operand" "r"))
8127 (set (match_operand:SI 0 "s_register_operand" "=r")
8128 (minus:SI (match_dup 1) (match_dup 2)))]
8130 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8131 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8132 && (GET_CODE (operands[2]) != REG
8133 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8134 "str%?\\t%3, [%0, -%2]!"
8135 [(set_attr "type" "store1")
8136 (set_attr "predicable" "yes")]
8139 (define_insn "*loadsi_preinc"
8140 [(set (match_operand:SI 3 "s_register_operand" "=r")
8141 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8142 (match_operand:SI 2 "index_operand" "rJ"))))
8143 (set (match_operand:SI 0 "s_register_operand" "=r")
8144 (plus:SI (match_dup 1) (match_dup 2)))]
8146 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8147 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8148 && (GET_CODE (operands[2]) != REG
8149 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8150 "ldr%?\\t%3, [%0, %2]!"
8151 [(set_attr "type" "load")
8152 (set_attr "predicable" "yes")]
8155 (define_insn "*loadsi_predec"
8156 [(set (match_operand:SI 3 "s_register_operand" "=r")
8157 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8158 (match_operand:SI 2 "s_register_operand" "r"))))
8159 (set (match_operand:SI 0 "s_register_operand" "=r")
8160 (minus:SI (match_dup 1) (match_dup 2)))]
8162 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8163 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8164 && (GET_CODE (operands[2]) != REG
8165 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8166 "ldr%?\\t%3, [%0, -%2]!"
8167 [(set_attr "type" "load")
8168 (set_attr "predicable" "yes")]
8171 (define_insn "*loadhi_preinc"
8172 [(set (match_operand:HI 3 "s_register_operand" "=r")
8173 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8174 (match_operand:SI 2 "index_operand" "rJ"))))
8175 (set (match_operand:SI 0 "s_register_operand" "=r")
8176 (plus:SI (match_dup 1) (match_dup 2)))]
8178 && !BYTES_BIG_ENDIAN
8179 && !TARGET_MMU_TRAPS
8181 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8182 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8183 && (GET_CODE (operands[2]) != REG
8184 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8185 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8186 [(set_attr "type" "load")
8187 (set_attr "predicable" "yes")]
8190 (define_insn "*loadhi_predec"
8191 [(set (match_operand:HI 3 "s_register_operand" "=r")
8192 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8193 (match_operand:SI 2 "s_register_operand" "r"))))
8194 (set (match_operand:SI 0 "s_register_operand" "=r")
8195 (minus:SI (match_dup 1) (match_dup 2)))]
8197 && !BYTES_BIG_ENDIAN
8198 && !TARGET_MMU_TRAPS
8200 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8201 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8202 && (GET_CODE (operands[2]) != REG
8203 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8204 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8205 [(set_attr "type" "load")
8206 (set_attr "predicable" "yes")]
8209 (define_insn "*strqi_shiftpreinc"
8210 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8211 [(match_operand:SI 3 "s_register_operand" "r")
8212 (match_operand:SI 4 "const_shift_operand" "n")])
8213 (match_operand:SI 1 "s_register_operand" "0")))
8214 (match_operand:QI 5 "s_register_operand" "r"))
8215 (set (match_operand:SI 0 "s_register_operand" "=r")
8216 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8219 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8220 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8221 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8222 "str%?b\\t%5, [%0, %3%S2]!"
8223 [(set_attr "type" "store1")
8224 (set_attr "predicable" "yes")]
8227 (define_insn "*strqi_shiftpredec"
8228 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8229 (match_operator:SI 2 "shift_operator"
8230 [(match_operand:SI 3 "s_register_operand" "r")
8231 (match_operand:SI 4 "const_shift_operand" "n")])))
8232 (match_operand:QI 5 "s_register_operand" "r"))
8233 (set (match_operand:SI 0 "s_register_operand" "=r")
8234 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8237 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8238 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8239 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8240 "str%?b\\t%5, [%0, -%3%S2]!"
8241 [(set_attr "type" "store1")
8242 (set_attr "predicable" "yes")]
8245 (define_insn "*loadqi_shiftpreinc"
8246 [(set (match_operand:QI 5 "s_register_operand" "=r")
8247 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8248 [(match_operand:SI 3 "s_register_operand" "r")
8249 (match_operand:SI 4 "const_shift_operand" "n")])
8250 (match_operand:SI 1 "s_register_operand" "0"))))
8251 (set (match_operand:SI 0 "s_register_operand" "=r")
8252 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8255 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8256 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8257 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8258 "ldr%?b\\t%5, [%0, %3%S2]!"
8259 [(set_attr "type" "load")
8260 (set_attr "predicable" "yes")]
8263 (define_insn "*loadqi_shiftpredec"
8264 [(set (match_operand:QI 5 "s_register_operand" "=r")
8265 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8266 (match_operator:SI 2 "shift_operator"
8267 [(match_operand:SI 3 "s_register_operand" "r")
8268 (match_operand:SI 4 "const_shift_operand" "n")]))))
8269 (set (match_operand:SI 0 "s_register_operand" "=r")
8270 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8273 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8274 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8275 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8276 "ldr%?b\\t%5, [%0, -%3%S2]!"
8277 [(set_attr "type" "load")
8278 (set_attr "predicable" "yes")]
8281 (define_insn "*strsi_shiftpreinc"
8282 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8283 [(match_operand:SI 3 "s_register_operand" "r")
8284 (match_operand:SI 4 "const_shift_operand" "n")])
8285 (match_operand:SI 1 "s_register_operand" "0")))
8286 (match_operand:SI 5 "s_register_operand" "r"))
8287 (set (match_operand:SI 0 "s_register_operand" "=r")
8288 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8291 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8292 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8293 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8294 "str%?\\t%5, [%0, %3%S2]!"
8295 [(set_attr "type" "store1")
8296 (set_attr "predicable" "yes")]
8299 (define_insn "*strsi_shiftpredec"
8300 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8301 (match_operator:SI 2 "shift_operator"
8302 [(match_operand:SI 3 "s_register_operand" "r")
8303 (match_operand:SI 4 "const_shift_operand" "n")])))
8304 (match_operand:SI 5 "s_register_operand" "r"))
8305 (set (match_operand:SI 0 "s_register_operand" "=r")
8306 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8309 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8310 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8311 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8312 "str%?\\t%5, [%0, -%3%S2]!"
8313 [(set_attr "type" "store1")
8314 (set_attr "predicable" "yes")]
8317 (define_insn "*loadsi_shiftpreinc"
8318 [(set (match_operand:SI 5 "s_register_operand" "=r")
8319 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8320 [(match_operand:SI 3 "s_register_operand" "r")
8321 (match_operand:SI 4 "const_shift_operand" "n")])
8322 (match_operand:SI 1 "s_register_operand" "0"))))
8323 (set (match_operand:SI 0 "s_register_operand" "=r")
8324 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8327 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8328 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8329 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8330 "ldr%?\\t%5, [%0, %3%S2]!"
8331 [(set_attr "type" "load")
8332 (set_attr "predicable" "yes")]
8335 (define_insn "*loadsi_shiftpredec"
8336 [(set (match_operand:SI 5 "s_register_operand" "=r")
8337 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8338 (match_operator:SI 2 "shift_operator"
8339 [(match_operand:SI 3 "s_register_operand" "r")
8340 (match_operand:SI 4 "const_shift_operand" "n")]))))
8341 (set (match_operand:SI 0 "s_register_operand" "=r")
8342 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8345 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8346 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8347 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8348 "ldr%?\\t%5, [%0, -%3%S2]!"
8349 [(set_attr "type" "load")
8350 (set_attr "predicable" "yes")])
8352 (define_insn "*loadhi_shiftpreinc"
8353 [(set (match_operand:HI 5 "s_register_operand" "=r")
8354 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8355 [(match_operand:SI 3 "s_register_operand" "r")
8356 (match_operand:SI 4 "const_shift_operand" "n")])
8357 (match_operand:SI 1 "s_register_operand" "0"))))
8358 (set (match_operand:SI 0 "s_register_operand" "=r")
8359 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8362 && !BYTES_BIG_ENDIAN
8363 && !TARGET_MMU_TRAPS
8365 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8366 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8367 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8368 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8369 [(set_attr "type" "load")
8370 (set_attr "predicable" "yes")]
8373 (define_insn "*loadhi_shiftpredec"
8374 [(set (match_operand:HI 5 "s_register_operand" "=r")
8375 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8376 (match_operator:SI 2 "shift_operator"
8377 [(match_operand:SI 3 "s_register_operand" "r")
8378 (match_operand:SI 4 "const_shift_operand" "n")]))))
8379 (set (match_operand:SI 0 "s_register_operand" "=r")
8380 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8383 && !BYTES_BIG_ENDIAN
8384 && !TARGET_MMU_TRAPS
8386 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8387 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8388 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8389 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8390 [(set_attr "type" "load")
8391 (set_attr "predicable" "yes")]
8394 ; It can also support extended post-inc expressions, but combine doesn't
8396 ; It doesn't seem worth adding peepholes for anything but the most common
8397 ; cases since, unlike combine, the increment must immediately follow the load
8398 ; for this pattern to match.
8399 ; We must watch to see that the source/destination register isn't also the
8400 ; same as the base address register, and that if the index is a register,
8401 ; that it is not the same as the base address register. In such cases the
8402 ; instruction that we would generate would have UNPREDICTABLE behaviour so
8406 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8407 (match_operand:QI 2 "s_register_operand" "r"))
8409 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8411 && (REGNO (operands[2]) != REGNO (operands[0]))
8412 && (GET_CODE (operands[1]) != REG
8413 || (REGNO (operands[1]) != REGNO (operands[0])))"
8414 "str%?b\\t%2, [%0], %1"
8418 [(set (match_operand:QI 0 "s_register_operand" "=r")
8419 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8421 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8423 && REGNO (operands[0]) != REGNO(operands[1])
8424 && (GET_CODE (operands[2]) != REG
8425 || REGNO(operands[0]) != REGNO (operands[2]))"
8426 "ldr%?b\\t%0, [%1], %2"
8430 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8431 (match_operand:SI 2 "s_register_operand" "r"))
8433 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8435 && (REGNO (operands[2]) != REGNO (operands[0]))
8436 && (GET_CODE (operands[1]) != REG
8437 || (REGNO (operands[1]) != REGNO (operands[0])))"
8438 "str%?\\t%2, [%0], %1"
8442 [(set (match_operand:HI 0 "s_register_operand" "=r")
8443 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8445 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8447 && !BYTES_BIG_ENDIAN
8448 && !TARGET_MMU_TRAPS
8450 && REGNO (operands[0]) != REGNO(operands[1])
8451 && (GET_CODE (operands[2]) != REG
8452 || REGNO(operands[0]) != REGNO (operands[2]))"
8453 "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8457 [(set (match_operand:SI 0 "s_register_operand" "=r")
8458 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8460 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8462 && REGNO (operands[0]) != REGNO(operands[1])
8463 && (GET_CODE (operands[2]) != REG
8464 || REGNO(operands[0]) != REGNO (operands[2]))"
8465 "ldr%?\\t%0, [%1], %2"
8469 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8470 (match_operand:SI 1 "index_operand" "rJ")))
8471 (match_operand:QI 2 "s_register_operand" "r"))
8472 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8474 && (REGNO (operands[2]) != REGNO (operands[0]))
8475 && (GET_CODE (operands[1]) != REG
8476 || (REGNO (operands[1]) != REGNO (operands[0])))"
8477 "str%?b\\t%2, [%0, %1]!"
8481 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8482 [(match_operand:SI 0 "s_register_operand" "r")
8483 (match_operand:SI 1 "const_int_operand" "n")])
8484 (match_operand:SI 2 "s_register_operand" "+r")))
8485 (match_operand:QI 3 "s_register_operand" "r"))
8486 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8489 && (REGNO (operands[3]) != REGNO (operands[2]))
8490 && (REGNO (operands[0]) != REGNO (operands[2]))"
8491 "str%?b\\t%3, [%2, %0%S4]!"
8494 ; This pattern is never tried by combine, so do it as a peephole
8497 [(set (match_operand:SI 0 "s_register_operand" "")
8498 (match_operand:SI 1 "s_register_operand" ""))
8499 (set (reg:CC CC_REGNUM)
8500 (compare:CC (match_dup 1) (const_int 0)))]
8503 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8504 (set (match_dup 0) (match_dup 1))])]
8508 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8509 ; reversed, check that the memory references aren't volatile.
8512 [(set (match_operand:SI 0 "s_register_operand" "=r")
8513 (match_operand:SI 4 "memory_operand" "m"))
8514 (set (match_operand:SI 1 "s_register_operand" "=r")
8515 (match_operand:SI 5 "memory_operand" "m"))
8516 (set (match_operand:SI 2 "s_register_operand" "=r")
8517 (match_operand:SI 6 "memory_operand" "m"))
8518 (set (match_operand:SI 3 "s_register_operand" "=r")
8519 (match_operand:SI 7 "memory_operand" "m"))]
8520 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8522 return emit_ldm_seq (operands, 4);
8527 [(set (match_operand:SI 0 "s_register_operand" "=r")
8528 (match_operand:SI 3 "memory_operand" "m"))
8529 (set (match_operand:SI 1 "s_register_operand" "=r")
8530 (match_operand:SI 4 "memory_operand" "m"))
8531 (set (match_operand:SI 2 "s_register_operand" "=r")
8532 (match_operand:SI 5 "memory_operand" "m"))]
8533 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8535 return emit_ldm_seq (operands, 3);
8540 [(set (match_operand:SI 0 "s_register_operand" "=r")
8541 (match_operand:SI 2 "memory_operand" "m"))
8542 (set (match_operand:SI 1 "s_register_operand" "=r")
8543 (match_operand:SI 3 "memory_operand" "m"))]
8544 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8546 return emit_ldm_seq (operands, 2);
8551 [(set (match_operand:SI 4 "memory_operand" "=m")
8552 (match_operand:SI 0 "s_register_operand" "r"))
8553 (set (match_operand:SI 5 "memory_operand" "=m")
8554 (match_operand:SI 1 "s_register_operand" "r"))
8555 (set (match_operand:SI 6 "memory_operand" "=m")
8556 (match_operand:SI 2 "s_register_operand" "r"))
8557 (set (match_operand:SI 7 "memory_operand" "=m")
8558 (match_operand:SI 3 "s_register_operand" "r"))]
8559 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8561 return emit_stm_seq (operands, 4);
8566 [(set (match_operand:SI 3 "memory_operand" "=m")
8567 (match_operand:SI 0 "s_register_operand" "r"))
8568 (set (match_operand:SI 4 "memory_operand" "=m")
8569 (match_operand:SI 1 "s_register_operand" "r"))
8570 (set (match_operand:SI 5 "memory_operand" "=m")
8571 (match_operand:SI 2 "s_register_operand" "r"))]
8572 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8574 return emit_stm_seq (operands, 3);
8579 [(set (match_operand:SI 2 "memory_operand" "=m")
8580 (match_operand:SI 0 "s_register_operand" "r"))
8581 (set (match_operand:SI 3 "memory_operand" "=m")
8582 (match_operand:SI 1 "s_register_operand" "r"))]
8583 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8585 return emit_stm_seq (operands, 2);
8590 [(set (match_operand:SI 0 "s_register_operand" "")
8591 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8593 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8594 [(match_operand:SI 3 "s_register_operand" "")
8595 (match_operand:SI 4 "arm_rhs_operand" "")]))))
8596 (clobber (match_operand:SI 5 "s_register_operand" ""))]
8598 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8599 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8604 ;; This split can be used because CC_Z mode implies that the following
8605 ;; branch will be an equality, or an unsigned inequality, so the sign
8606 ;; extension is not needed.
8609 [(set (reg:CC_Z CC_REGNUM)
8611 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8613 (match_operand 1 "const_int_operand" "")))
8614 (clobber (match_scratch:SI 2 ""))]
8616 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8617 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8618 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8619 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8621 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8625 (define_expand "prologue"
8626 [(clobber (const_int 0))]
8629 arm_expand_prologue ();
8631 thumb_expand_prologue ();
8636 (define_expand "epilogue"
8637 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8641 thumb_expand_epilogue ();
8642 else if (USE_RETURN_INSN (FALSE))
8644 emit_jump_insn (gen_return ());
8647 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8649 gen_rtx_RETURN (VOIDmode)),
8655 (define_insn "sibcall_epilogue"
8656 [(unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)]
8659 output_asm_insn (\"%@ Sibcall epilogue\", operands);
8660 if (USE_RETURN_INSN (FALSE))
8661 return output_return_instruction (const_true_rtx, FALSE, FALSE);
8662 return arm_output_epilogue (FALSE);
8664 ;; Length is absolute worst case
8665 [(set_attr "length" "44")
8666 (set_attr "type" "block")]
8669 (define_insn "*epilogue_insns"
8670 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8674 return arm_output_epilogue (TRUE);
8675 else /* TARGET_THUMB */
8676 return thumb_unexpanded_epilogue ();
8678 ; Length is absolute worst case
8679 [(set_attr "length" "44")
8680 (set_attr "type" "block")]
8683 (define_expand "eh_epilogue"
8684 [(use (match_operand:SI 0 "register_operand" "r"))
8685 (use (match_operand:SI 1 "register_operand" "r"))
8686 (use (match_operand:SI 2 "register_operand" "r"))]
8690 cfun->machine->eh_epilogue_sp_ofs = operands[1];
8691 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8693 rtx ra = gen_rtx_REG (Pmode, 2);
8695 emit_move_insn (ra, operands[2]);
8698 /* This is a hack -- we may have crystalized the function type too
8700 cfun->machine->func_type = 0;
8704 ;; This split is only used during output to reduce the number of patterns
8705 ;; that need assembler instructions adding to them. We allowed the setting
8706 ;; of the conditions to be implicit during rtl generation so that
8707 ;; the conditional compare patterns would work. However this conflicts to
8708 ;; some extent with the conditional data operations, so we have to split them
8712 [(set (match_operand:SI 0 "s_register_operand" "")
8713 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8714 [(match_operand 2 "" "") (match_operand 3 "" "")])
8716 (match_operand 4 "" "")))
8717 (clobber (reg:CC CC_REGNUM))]
8718 "TARGET_ARM && reload_completed"
8719 [(set (match_dup 5) (match_dup 6))
8720 (cond_exec (match_dup 7)
8721 (set (match_dup 0) (match_dup 4)))]
8724 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8725 operands[2], operands[3]);
8726 enum rtx_code rc = GET_CODE (operands[1]);
8728 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8729 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8730 if (mode == CCFPmode || mode == CCFPEmode)
8731 rc = reverse_condition_maybe_unordered (rc);
8733 rc = reverse_condition (rc);
8735 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8740 [(set (match_operand:SI 0 "s_register_operand" "")
8741 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8742 [(match_operand 2 "" "") (match_operand 3 "" "")])
8743 (match_operand 4 "" "")
8745 (clobber (reg:CC CC_REGNUM))]
8746 "TARGET_ARM && reload_completed"
8747 [(set (match_dup 5) (match_dup 6))
8748 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8749 (set (match_dup 0) (match_dup 4)))]
8752 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8753 operands[2], operands[3]);
8755 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8756 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8761 [(set (match_operand:SI 0 "s_register_operand" "")
8762 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8763 [(match_operand 2 "" "") (match_operand 3 "" "")])
8764 (match_operand 4 "" "")
8765 (match_operand 5 "" "")))
8766 (clobber (reg:CC CC_REGNUM))]
8767 "TARGET_ARM && reload_completed"
8768 [(set (match_dup 6) (match_dup 7))
8769 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8770 (set (match_dup 0) (match_dup 4)))
8771 (cond_exec (match_dup 8)
8772 (set (match_dup 0) (match_dup 5)))]
8775 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8776 operands[2], operands[3]);
8777 enum rtx_code rc = GET_CODE (operands[1]);
8779 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8780 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8781 if (mode == CCFPmode || mode == CCFPEmode)
8782 rc = reverse_condition_maybe_unordered (rc);
8784 rc = reverse_condition (rc);
8786 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8791 [(set (match_operand:SI 0 "s_register_operand" "")
8792 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8793 [(match_operand:SI 2 "s_register_operand" "")
8794 (match_operand:SI 3 "arm_add_operand" "")])
8795 (match_operand:SI 4 "arm_rhs_operand" "")
8797 (match_operand:SI 5 "s_register_operand" ""))))
8798 (clobber (reg:CC CC_REGNUM))]
8799 "TARGET_ARM && reload_completed"
8800 [(set (match_dup 6) (match_dup 7))
8801 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8802 (set (match_dup 0) (match_dup 4)))
8803 (cond_exec (match_dup 8)
8804 (set (match_dup 0) (not:SI (match_dup 5))))]
8807 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8808 operands[2], operands[3]);
8809 enum rtx_code rc = GET_CODE (operands[1]);
8811 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8812 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8813 if (mode == CCFPmode || mode == CCFPEmode)
8814 rc = reverse_condition_maybe_unordered (rc);
8816 rc = reverse_condition (rc);
8818 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8822 (define_insn "*cond_move_not"
8823 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8824 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8825 [(match_operand 3 "cc_register" "") (const_int 0)])
8826 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8828 (match_operand:SI 2 "s_register_operand" "r,r"))))]
8832 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8833 [(set_attr "conds" "use")
8834 (set_attr "length" "4,8")]
8837 ;; The next two patterns occur when an AND operation is followed by a
8838 ;; scc insn sequence
8840 (define_insn "*sign_extract_onebit"
8841 [(set (match_operand:SI 0 "s_register_operand" "=r")
8842 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8844 (match_operand:SI 2 "const_int_operand" "n")))]
8847 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8848 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8849 return \"mvnne\\t%0, #0\";
8851 [(set_attr "conds" "clob")
8852 (set_attr "length" "8")]
8855 (define_insn "*not_signextract_onebit"
8856 [(set (match_operand:SI 0 "s_register_operand" "=r")
8858 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8860 (match_operand:SI 2 "const_int_operand" "n"))))]
8863 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8864 output_asm_insn (\"tst\\t%1, %2\", operands);
8865 output_asm_insn (\"mvneq\\t%0, #0\", operands);
8866 return \"movne\\t%0, #0\";
8868 [(set_attr "conds" "clob")
8869 (set_attr "length" "12")]
8872 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
8873 ;; expressions. For simplicity, the first register is also in the unspec
8875 (define_insn "*push_multi"
8876 [(match_parallel 2 "multi_register_push"
8877 [(set (match_operand:BLK 0 "memory_operand" "=m")
8878 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8879 UNSPEC_PUSH_MULT))])]
8883 int num_saves = XVECLEN (operands[2], 0);
8885 /* For the StrongARM at least it is faster to
8886 use STR to store only a single register. */
8888 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8894 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
8896 for (i = 1; i < num_saves; i++)
8898 strcat (pattern, \", %|\");
8900 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
8903 strcat (pattern, \"}\");
8904 output_asm_insn (pattern, operands);
8909 [(set_attr "type" "store4")]
8912 (define_insn "stack_tie"
8913 [(set (mem:BLK (scratch))
8914 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
8915 (match_operand:SI 1 "s_register_operand" "r")]
8919 [(set_attr "length" "0")]
8922 ;; Similarly for the floating point registers
8923 (define_insn "*push_fp_multi"
8924 [(match_parallel 2 "multi_register_push"
8925 [(set (match_operand:BLK 0 "memory_operand" "=m")
8926 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
8927 UNSPEC_PUSH_MULT))])]
8933 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
8934 output_asm_insn (pattern, operands);
8937 [(set_attr "type" "f_store")]
8940 ;; Special patterns for dealing with the constant pool
8942 (define_insn "align_4"
8943 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
8946 assemble_align (32);
8951 (define_insn "consttable_end"
8952 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
8955 making_const_table = FALSE;
8960 (define_insn "consttable_1"
8961 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
8964 making_const_table = TRUE;
8965 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
8969 [(set_attr "length" "4")]
8972 (define_insn "consttable_2"
8973 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
8976 making_const_table = TRUE;
8977 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
8981 [(set_attr "length" "4")]
8984 (define_insn "consttable_4"
8985 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
8989 making_const_table = TRUE;
8990 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8995 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8996 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9000 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9005 [(set_attr "length" "4")]
9008 (define_insn "consttable_8"
9009 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9013 making_const_table = TRUE;
9014 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9019 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9020 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9024 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9029 [(set_attr "length" "8")]
9032 ;; Miscellaneous Thumb patterns
9034 (define_expand "tablejump"
9035 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9036 (use (label_ref (match_operand 1 "" "")))])]
9041 /* Hopefully, CSE will eliminate this copy. */
9042 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
9043 rtx reg2 = gen_reg_rtx (SImode);
9045 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
9051 (define_insn "*thumb_tablejump"
9052 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9053 (use (label_ref (match_operand 1 "" "")))]
9056 [(set_attr "length" "2")]
9062 [(set (match_operand:SI 0 "s_register_operand" "=r")
9063 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")]
9065 "TARGET_ARM && arm_arch5"
9068 (define_expand "ffssi2"
9069 [(set (match_operand:SI 0 "s_register_operand" "")
9070 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9071 "TARGET_ARM && arm_arch5"
9076 t1 = gen_reg_rtx (SImode);
9077 t2 = gen_reg_rtx (SImode);
9078 t3 = gen_reg_rtx (SImode);
9080 emit_insn (gen_negsi2 (t1, operands[1]));
9081 emit_insn (gen_andsi3 (t2, operands[1], t1));
9082 emit_insn (gen_clz (t3, t2));
9083 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
9088 ;; V5E instructions.
9090 (define_insn "prefetch"
9091 [(prefetch (match_operand:SI 0 "address_operand" "p")
9092 (match_operand:SI 1 "" "")
9093 (match_operand:SI 2 "" ""))]
9094 "TARGET_ARM && arm_arch5e"
9097 ;; General predication pattern
9100 [(match_operator 0 "arm_comparison_operator"
9101 [(match_operand 1 "cc_register" "")
9107 (define_insn "prologue_use"
9108 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
9110 "%@ %0 needed for prologue"