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
72 (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
76 ;; UNSPEC_VOLATILE Usage:
79 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
81 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
82 ; instruction epilogue sequence that isn't expanded
83 ; into normal RTL. Used for both normal and sibcall
85 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
86 ; for inlined constants.
87 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
89 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
91 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
93 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
95 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
100 ;;---------------------------------------------------------------------------
103 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
104 ; generating ARM code. This is used to control the length of some insn
105 ; patterns that share the same RTL in both ARM and Thumb code.
106 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
108 ; PROG_MODE attribute is used to determine whether condition codes are
109 ; clobbered by a call insn: they are if in prog32 mode. This is controlled
110 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
111 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
113 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
114 ; scheduling decisions for the load unit and the multiplier.
115 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
117 ;; Operand number of an input operand that is shifted. Zero if the
118 ;; given instruction does not shift one of its input operands.
119 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_is_xscale")))
120 (define_attr "shift" "" (const_int 0))
122 ; Floating Point Unit. If we only have floating point emulation, then there
123 ; is no point in scheduling the floating point insns. (Well, for best
124 ; performance we should try and group them together).
125 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
127 ; LENGTH of an instruction (in bytes)
128 (define_attr "length" "" (const_int 4))
130 ; POOL_RANGE is how far away from a constant pool entry that this insn
131 ; can be placed. If the distance is zero, then this insn will never
132 ; reference the pool.
133 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
134 ; before its address.
135 (define_attr "pool_range" "" (const_int 0))
136 (define_attr "neg_pool_range" "" (const_int 0))
138 ; An assembler sequence may clobber the condition codes without us knowing.
139 ; If such an insn references the pool, then we have no way of knowing how,
140 ; so use the most conservative value for pool_range.
141 (define_asm_attributes
142 [(set_attr "conds" "clob")
143 (set_attr "length" "4")
144 (set_attr "pool_range" "250")])
146 ; TYPE attribute is used to detect floating point instructions which, if
147 ; running on a co-processor can run in parallel with other, basic instructions
148 ; If write-buffer scheduling is enabled then it can also be used in the
149 ; scheduling of writes.
151 ; Classification of each insn
152 ; normal any data instruction that doesn't hit memory or fp regs
153 ; mult a multiply instruction
154 ; block blockage insn, this blocks all functional units
155 ; float a floating point arithmetic operation (subject to expansion)
156 ; fdivx XFmode floating point division
157 ; fdivd DFmode floating point division
158 ; fdivs SFmode floating point division
159 ; fmul Floating point multiply
160 ; ffmul Fast floating point multiply
161 ; farith Floating point arithmetic (4 cycle)
162 ; ffarith Fast floating point arithmetic (2 cycle)
163 ; float_em a floating point arithmetic operation that is normally emulated
164 ; even on a machine with an fpa.
165 ; f_load a floating point load from memory
166 ; f_store a floating point store to memory
167 ; f_mem_r a transfer of a floating point register to a real reg via mem
168 ; r_mem_f the reverse of f_mem_r
169 ; f_2_r fast transfer float to arm (no memory needed)
170 ; r_2_f fast transfer arm to float
171 ; call a subroutine call
172 ; load any load from memory
173 ; store1 store 1 word to memory from arm registers
174 ; store2 store 2 words
175 ; store3 store 3 words
176 ; store4 store 4 words
179 "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"
180 (const_string "normal"))
182 ; Load scheduling, set from the arm_ld_sched variable
183 ; initialized by arm_override_options()
184 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
186 ; condition codes: this one is used by final_prescan_insn to speed up
187 ; conditionalizing instructions. It saves having to scan the rtl to see if
188 ; it uses or alters the condition codes.
190 ; USE means that the condition codes are used by the insn in the process of
191 ; outputting code, this means (at present) that we can't use the insn in
194 ; SET means that the purpose of the insn is to set the condition codes in a
195 ; well defined manner.
197 ; CLOB means that the condition codes are altered in an undefined manner, if
198 ; they are altered at all
200 ; JUMP_CLOB is used when the condition cannot be represented by a single
201 ; instruction (UNEQ and LTGT). These cannot be predicated.
203 ; NOCOND means that the condition codes are neither altered nor affect the
204 ; output of this insn
206 (define_attr "conds" "use,set,clob,jump_clob,nocond"
207 (if_then_else (eq_attr "type" "call")
208 (if_then_else (eq_attr "prog_mode" "prog32")
209 (const_string "clob") (const_string "nocond"))
210 (const_string "nocond")))
212 ; Predicable means that the insn can be conditionally executed based on
213 ; an automatically added predicate (additional patterns are generated by
214 ; gen...). We default to 'no' because no Thumb patterns match this rule
215 ; and not all ARM patterns do.
216 (define_attr "predicable" "no,yes" (const_string "no"))
218 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
219 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
220 ; suffer blockages enough to warrent modelling this (and it can adversely
221 ; affect the schedule).
222 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
224 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
225 ; to stall the processor. Used with model_wbuf above.
226 (define_attr "write_conflict" "no,yes"
227 (if_then_else (eq_attr "type"
228 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
230 (const_string "no")))
232 ; Classify the insns into those that take one cycle and those that take more
233 ; than one on the main cpu execution unit.
234 (define_attr "core_cycles" "single,multi"
235 (if_then_else (eq_attr "type"
236 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
237 (const_string "single")
238 (const_string "multi")))
240 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
241 ;; distant label. Only applicable to Thumb code.
242 (define_attr "far_jump" "yes,no" (const_string "no"))
244 ;; (define_function_unit {name} {num-units} {n-users} {test}
245 ;; {ready-delay} {issue-delay} [{conflict-list}])
247 ;;--------------------------------------------------------------------
248 ;; Floating point unit (FPA)
249 ;;--------------------------------------------------------------------
250 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
251 (eq_attr "type" "fdivx")) 71 69)
253 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
254 (eq_attr "type" "fdivd")) 59 57)
256 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
257 (eq_attr "type" "fdivs")) 31 29)
259 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
260 (eq_attr "type" "fmul")) 9 7)
262 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
263 (eq_attr "type" "ffmul")) 6 4)
265 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
266 (eq_attr "type" "farith")) 4 2)
268 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
269 (eq_attr "type" "ffarith")) 2 2)
271 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
272 (eq_attr "type" "r_2_f")) 5 3)
274 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
275 (eq_attr "type" "f_2_r")) 1 2)
277 ; The fpa10 doesn't really have a memory read unit, but it can start to
278 ; speculatively execute the instruction in the pipeline, provided the data
279 ; is already loaded, so pretend reads have a delay of 2 (and that the
280 ; pipeline is infinite).
282 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
283 (eq_attr "type" "f_load")) 3 1)
285 ;;--------------------------------------------------------------------
287 ;;--------------------------------------------------------------------
288 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
290 ; The write buffer on some of the arm6 processors is hard to model exactly.
291 ; There is room in the buffer for up to two addresses and up to eight words
292 ; of memory, but the two needn't be split evenly. When writing the two
293 ; addresses are fully pipelined. However, a read from memory that is not
294 ; currently in the cache will block until the writes have completed.
295 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
296 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
297 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
298 ; cycle to add as well.
300 (define_function_unit "write_buf" 1 2
301 (and (eq_attr "model_wbuf" "yes")
302 (eq_attr "type" "store1,r_mem_f")) 5 3)
303 (define_function_unit "write_buf" 1 2
304 (and (eq_attr "model_wbuf" "yes")
305 (eq_attr "type" "store2")) 7 4)
306 (define_function_unit "write_buf" 1 2
307 (and (eq_attr "model_wbuf" "yes")
308 (eq_attr "type" "store3")) 9 5)
309 (define_function_unit "write_buf" 1 2
310 (and (eq_attr "model_wbuf" "yes")
311 (eq_attr "type" "store4")) 11 6)
313 ;;--------------------------------------------------------------------
314 ;; Write blockage unit
315 ;;--------------------------------------------------------------------
316 ; The write_blockage unit models (partially), the fact that reads will stall
317 ; until the write buffer empties.
318 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
319 ; so we don't model them here
320 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
321 (eq_attr "type" "store1")) 5 5
322 [(eq_attr "write_conflict" "yes")])
323 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
324 (eq_attr "type" "store2")) 7 7
325 [(eq_attr "write_conflict" "yes")])
326 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
327 (eq_attr "type" "store3")) 9 9
328 [(eq_attr "write_conflict" "yes")])
329 (define_function_unit "write_blockage" 1 0
330 (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
331 [(eq_attr "write_conflict" "yes")])
332 (define_function_unit "write_blockage" 1 0
333 (and (eq_attr "model_wbuf" "yes")
334 (eq_attr "write_conflict" "yes")) 1 1)
336 ;;--------------------------------------------------------------------
338 ;;--------------------------------------------------------------------
339 ; Everything must spend at least one cycle in the core unit
340 (define_function_unit "core" 1 0 (eq_attr "core_cycles" "single") 1 1)
342 (define_function_unit "core" 1 0
343 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
345 (define_function_unit "core" 1 0
346 (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
348 ;; We do not need to conditionalize the define_function_unit immediately
349 ;; above. This one will be ignored for anything other than xscale
350 ;; compiles and for xscale compiles it provides a larger delay
351 ;; and the scheduler will DTRT.
352 ;; FIXME: this test needs to be revamped to not depend on this feature
355 (define_function_unit "core" 1 0
356 (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
357 (eq_attr "is_xscale" "yes"))
360 (define_function_unit "core" 1 0
361 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
363 (define_function_unit "core" 1 0
364 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
366 (define_function_unit "core" 1 0
367 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
369 (define_function_unit "core" 1 0
370 (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
372 (define_function_unit "core" 1 0
373 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
375 (define_function_unit "core" 1 0
376 (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
378 (define_function_unit "core" 1 0
379 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
380 (eq_attr "type" "mult")) 4 4)
382 (define_function_unit "core" 1 0
383 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
384 (eq_attr "type" "mult")) 3 2)
386 (define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
388 (define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
390 (define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
392 (define_function_unit "core" 1 0
393 (and (eq_attr "core_cycles" "multi")
394 (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
396 ;;---------------------------------------------------------------------------
401 ;; Note: For DImode insns, there is normally no reason why operands should
402 ;; not be in the same register, what we don't want is for something being
403 ;; written to partially overlap something that is an input.
405 (define_expand "adddi3"
407 [(set (match_operand:DI 0 "s_register_operand" "")
408 (plus:DI (match_operand:DI 1 "s_register_operand" "")
409 (match_operand:DI 2 "s_register_operand" "")))
410 (clobber (reg:CC CC_REGNUM))])]
415 if (GET_CODE (operands[1]) != REG)
416 operands[1] = force_reg (SImode, operands[1]);
417 if (GET_CODE (operands[2]) != REG)
418 operands[2] = force_reg (SImode, operands[2]);
423 (define_insn "*thumb_adddi3"
424 [(set (match_operand:DI 0 "register_operand" "=l")
425 (plus:DI (match_operand:DI 1 "register_operand" "%0")
426 (match_operand:DI 2 "register_operand" "l")))
427 (clobber (reg:CC CC_REGNUM))
430 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
431 [(set_attr "length" "4")]
434 (define_insn_and_split "*arm_adddi3"
435 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
436 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
437 (match_operand:DI 2 "s_register_operand" "r, 0")))
438 (clobber (reg:CC CC_REGNUM))]
441 "TARGET_ARM && reload_completed"
442 [(parallel [(set (reg:CC_C CC_REGNUM)
443 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
445 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
446 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
447 (plus:SI (match_dup 4) (match_dup 5))))]
450 operands[3] = gen_highpart (SImode, operands[0]);
451 operands[0] = gen_lowpart (SImode, operands[0]);
452 operands[4] = gen_highpart (SImode, operands[1]);
453 operands[1] = gen_lowpart (SImode, operands[1]);
454 operands[5] = gen_highpart (SImode, operands[2]);
455 operands[2] = gen_lowpart (SImode, operands[2]);
457 [(set_attr "conds" "clob")
458 (set_attr "length" "8")]
461 (define_insn_and_split "*adddi_sesidi_di"
462 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
463 (plus:DI (sign_extend:DI
464 (match_operand:SI 2 "s_register_operand" "r,r"))
465 (match_operand:DI 1 "s_register_operand" "r,0")))
466 (clobber (reg:CC CC_REGNUM))]
469 "TARGET_ARM && reload_completed"
470 [(parallel [(set (reg:CC_C CC_REGNUM)
471 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
473 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
474 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
475 (plus:SI (ashiftrt:SI (match_dup 2)
480 operands[3] = gen_highpart (SImode, operands[0]);
481 operands[0] = gen_lowpart (SImode, operands[0]);
482 operands[4] = gen_highpart (SImode, operands[1]);
483 operands[1] = gen_lowpart (SImode, operands[1]);
484 operands[2] = gen_lowpart (SImode, operands[2]);
486 [(set_attr "conds" "clob")
487 (set_attr "length" "8")]
490 (define_insn_and_split "*adddi_zesidi_di"
491 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
492 (plus:DI (zero_extend:DI
493 (match_operand:SI 2 "s_register_operand" "r,r"))
494 (match_operand:DI 1 "s_register_operand" "r,0")))
495 (clobber (reg:CC CC_REGNUM))]
498 "TARGET_ARM && reload_completed"
499 [(parallel [(set (reg:CC_C CC_REGNUM)
500 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
502 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
503 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
504 (plus:SI (match_dup 4) (const_int 0))))]
507 operands[3] = gen_highpart (SImode, operands[0]);
508 operands[0] = gen_lowpart (SImode, operands[0]);
509 operands[4] = gen_highpart (SImode, operands[1]);
510 operands[1] = gen_lowpart (SImode, operands[1]);
511 operands[2] = gen_lowpart (SImode, operands[2]);
513 [(set_attr "conds" "clob")
514 (set_attr "length" "8")]
517 (define_expand "addsi3"
518 [(set (match_operand:SI 0 "s_register_operand" "")
519 (plus:SI (match_operand:SI 1 "s_register_operand" "")
520 (match_operand:SI 2 "reg_or_int_operand" "")))]
523 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
525 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
527 (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
533 ; If there is a scratch available, this will be faster than synthesising the
536 [(match_scratch:SI 3 "r")
537 (set (match_operand:SI 0 "s_register_operand" "")
538 (plus:SI (match_operand:SI 1 "s_register_operand" "")
539 (match_operand:SI 2 "const_int_operand" "")))]
541 !(const_ok_for_arm (INTVAL (operands[2]))
542 || const_ok_for_arm (-INTVAL (operands[2])))
543 && const_ok_for_arm (~INTVAL (operands[2]))"
544 [(set (match_dup 3) (match_dup 2))
545 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
549 (define_insn_and_split "*arm_addsi3"
550 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
551 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
552 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
559 GET_CODE (operands[2]) == CONST_INT
560 && !(const_ok_for_arm (INTVAL (operands[2]))
561 || const_ok_for_arm (-INTVAL (operands[2])))"
562 [(clobber (const_int 0))]
564 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
568 [(set_attr "length" "4,4,16")
569 (set_attr "predicable" "yes")]
572 ;; Register group 'k' is a single register group containing only the stack
573 ;; register. Trying to reload it will always fail catastrophically,
574 ;; so never allow those alternatives to match if reloading is needed.
576 (define_insn "*thumb_addsi3"
577 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
578 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
579 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
582 static const char * const asms[] =
584 \"add\\t%0, %0, %2\",
585 \"sub\\t%0, %0, #%n2\",
586 \"add\\t%0, %1, %2\",
587 \"add\\t%0, %0, %2\",
588 \"add\\t%0, %0, %2\",
589 \"add\\t%0, %1, %2\",
592 if ((which_alternative == 2 || which_alternative == 6)
593 && GET_CODE (operands[2]) == CONST_INT
594 && INTVAL (operands[2]) < 0)
595 return \"sub\\t%0, %1, #%n2\";
596 return asms[which_alternative];
598 [(set_attr "length" "2")]
601 ;; Reloading and elimination of the frame pointer can
602 ;; sometimes cause this optimization to be missed.
604 [(set (match_operand:SI 0 "register_operand" "")
605 (match_operand:SI 1 "const_int_operand" ""))
607 (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
609 && REGNO (operands[2]) == STACK_POINTER_REGNUM
610 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
611 && (INTVAL (operands[1]) & 3) == 0"
612 [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
616 (define_insn "*addsi3_compare0"
617 [(set (reg:CC_NOOV CC_REGNUM)
619 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
620 (match_operand:SI 2 "arm_add_operand" "rI,L"))
622 (set (match_operand:SI 0 "s_register_operand" "=r,r")
623 (plus:SI (match_dup 1) (match_dup 2)))]
627 sub%?s\\t%0, %1, #%n2"
628 [(set_attr "conds" "set")]
631 (define_insn "*addsi3_compare0_scratch"
632 [(set (reg:CC_NOOV CC_REGNUM)
634 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
635 (match_operand:SI 1 "arm_add_operand" "rI,L"))
641 [(set_attr "conds" "set")]
644 ;; These patterns are the same ones as the two regular addsi3_compare0
645 ;; patterns, except we write them slightly different - the combiner
646 ;; tends to generate them this way.
647 (define_insn "*addsi3_compare0_for_combiner"
648 [(set (reg:CC CC_REGNUM)
650 (match_operand:SI 1 "s_register_operand" "r,r")
651 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
652 (set (match_operand:SI 0 "s_register_operand" "=r,r")
653 (plus:SI (match_dup 1) (match_dup 2)))]
657 sub%?s\\t%0, %1, #%n2"
658 [(set_attr "conds" "set")]
661 (define_insn "*addsi3_compare0_scratch_for_combiner"
662 [(set (reg:CC CC_REGNUM)
664 (match_operand:SI 0 "s_register_operand" "r,r")
665 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
670 [(set_attr "conds" "set")]
673 ;; The next four insns work because they compare the result with one of
674 ;; the operands, and we know that the use of the condition code is
675 ;; either GEU or LTU, so we can use the carry flag from the addition
676 ;; instead of doing the compare a second time.
677 (define_insn "*addsi3_compare_op1"
678 [(set (reg:CC_C CC_REGNUM)
680 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
681 (match_operand:SI 2 "arm_add_operand" "rI,L"))
683 (set (match_operand:SI 0 "s_register_operand" "=r,r")
684 (plus:SI (match_dup 1) (match_dup 2)))]
688 sub%?s\\t%0, %1, #%n2"
689 [(set_attr "conds" "set")]
692 (define_insn "*addsi3_compare_op2"
693 [(set (reg:CC_C CC_REGNUM)
695 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
696 (match_operand:SI 2 "arm_add_operand" "rI,L"))
698 (set (match_operand:SI 0 "s_register_operand" "=r,r")
699 (plus:SI (match_dup 1) (match_dup 2)))]
703 sub%?s\\t%0, %1, #%n2"
704 [(set_attr "conds" "set")]
707 (define_insn "*compare_addsi2_op0"
708 [(set (reg:CC_C CC_REGNUM)
710 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
711 (match_operand:SI 1 "arm_add_operand" "rI,L"))
717 [(set_attr "conds" "set")]
720 (define_insn "*compare_addsi2_op1"
721 [(set (reg:CC_C CC_REGNUM)
723 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
724 (match_operand:SI 1 "arm_add_operand" "rI,L"))
730 [(set_attr "conds" "set")]
733 (define_insn "*addsi3_carryin"
734 [(set (match_operand:SI 0 "s_register_operand" "=r")
735 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
736 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
737 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
740 [(set_attr "conds" "use")]
743 (define_insn "*addsi3_carryin_shift"
744 [(set (match_operand:SI 0 "s_register_operand" "")
745 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
747 (match_operator:SI 2 "shift_operator"
748 [(match_operand:SI 3 "s_register_operand" "")
749 (match_operand:SI 4 "reg_or_int_operand" "")])
750 (match_operand:SI 1 "s_register_operand" ""))))]
752 "adc%?\\t%0, %1, %3%S2"
753 [(set_attr "conds" "use")]
756 (define_insn "*addsi3_carryin_alt1"
757 [(set (match_operand:SI 0 "s_register_operand" "=r")
758 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
759 (match_operand:SI 2 "arm_rhs_operand" "rI"))
760 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
763 [(set_attr "conds" "use")]
766 (define_insn "*addsi3_carryin_alt2"
767 [(set (match_operand:SI 0 "s_register_operand" "=r")
768 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
769 (match_operand:SI 1 "s_register_operand" "r"))
770 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
773 [(set_attr "conds" "use")]
776 (define_insn "*addsi3_carryin_alt3"
777 [(set (match_operand:SI 0 "s_register_operand" "=r")
778 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
779 (match_operand:SI 2 "arm_rhs_operand" "rI"))
780 (match_operand:SI 1 "s_register_operand" "r")))]
783 [(set_attr "conds" "use")]
786 (define_insn "incscc"
787 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
788 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
789 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
790 (match_operand:SI 1 "s_register_operand" "0,?r")))]
794 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
795 [(set_attr "conds" "use")
796 (set_attr "length" "4,8")]
799 (define_insn "addsf3"
800 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
801 (plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
802 (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
803 "TARGET_ARM && TARGET_HARD_FLOAT"
806 suf%?s\\t%0, %1, #%N2"
807 [(set_attr "type" "farith")
808 (set_attr "predicable" "yes")]
811 (define_insn "adddf3"
812 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
813 (plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
814 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
815 "TARGET_ARM && TARGET_HARD_FLOAT"
818 suf%?d\\t%0, %1, #%N2"
819 [(set_attr "type" "farith")
820 (set_attr "predicable" "yes")]
823 (define_insn "*adddf_esfdf_df"
824 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
825 (plus:DF (float_extend:DF
826 (match_operand:SF 1 "s_register_operand" "f,f"))
827 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
828 "TARGET_ARM && TARGET_HARD_FLOAT"
831 suf%?d\\t%0, %1, #%N2"
832 [(set_attr "type" "farith")
833 (set_attr "predicable" "yes")]
836 (define_insn "*adddf_df_esfdf"
837 [(set (match_operand:DF 0 "s_register_operand" "=f")
838 (plus:DF (match_operand:DF 1 "s_register_operand" "f")
840 (match_operand:SF 2 "s_register_operand" "f"))))]
841 "TARGET_ARM && TARGET_HARD_FLOAT"
842 "adf%?d\\t%0, %1, %2"
843 [(set_attr "type" "farith")
844 (set_attr "predicable" "yes")]
847 (define_insn "*adddf_esfdf_esfdf"
848 [(set (match_operand:DF 0 "s_register_operand" "=f")
849 (plus:DF (float_extend:DF
850 (match_operand:SF 1 "s_register_operand" "f"))
852 (match_operand:SF 2 "s_register_operand" "f"))))]
853 "TARGET_ARM && TARGET_HARD_FLOAT"
854 "adf%?d\\t%0, %1, %2"
855 [(set_attr "type" "farith")
856 (set_attr "predicable" "yes")]
859 (define_insn "addxf3"
860 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
861 (plus:XF (match_operand:XF 1 "s_register_operand" "f,f")
862 (match_operand:XF 2 "fpu_add_operand" "fG,H")))]
863 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
866 suf%?e\\t%0, %1, #%N2"
867 [(set_attr "type" "farith")
868 (set_attr "predicable" "yes")]
871 (define_expand "subdi3"
873 [(set (match_operand:DI 0 "s_register_operand" "")
874 (minus:DI (match_operand:DI 1 "s_register_operand" "")
875 (match_operand:DI 2 "s_register_operand" "")))
876 (clobber (reg:CC CC_REGNUM))])]
881 if (GET_CODE (operands[1]) != REG)
882 operands[1] = force_reg (SImode, operands[1]);
883 if (GET_CODE (operands[2]) != REG)
884 operands[2] = force_reg (SImode, operands[2]);
889 (define_insn "*arm_subdi3"
890 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
891 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
892 (match_operand:DI 2 "s_register_operand" "r,0,0")))
893 (clobber (reg:CC CC_REGNUM))]
895 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
896 [(set_attr "conds" "clob")
897 (set_attr "length" "8")]
900 (define_insn "*thumb_subdi3"
901 [(set (match_operand:DI 0 "register_operand" "=l")
902 (minus:DI (match_operand:DI 1 "register_operand" "0")
903 (match_operand:DI 2 "register_operand" "l")))
904 (clobber (reg:CC CC_REGNUM))]
906 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
907 [(set_attr "length" "4")]
910 (define_insn "*subdi_di_zesidi"
911 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
912 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
914 (match_operand:SI 2 "s_register_operand" "r,r"))))
915 (clobber (reg:CC CC_REGNUM))]
917 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
918 [(set_attr "conds" "clob")
919 (set_attr "length" "8")]
922 (define_insn "*subdi_di_sesidi"
923 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
924 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
926 (match_operand:SI 2 "s_register_operand" "r,r"))))
927 (clobber (reg:CC CC_REGNUM))]
929 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
930 [(set_attr "conds" "clob")
931 (set_attr "length" "8")]
934 (define_insn "*subdi_zesidi_di"
935 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
936 (minus:DI (zero_extend:DI
937 (match_operand:SI 2 "s_register_operand" "r,r"))
938 (match_operand:DI 1 "s_register_operand" "?r,0")))
939 (clobber (reg:CC CC_REGNUM))]
941 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
942 [(set_attr "conds" "clob")
943 (set_attr "length" "8")]
946 (define_insn "*subdi_sesidi_di"
947 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
948 (minus:DI (sign_extend:DI
949 (match_operand:SI 2 "s_register_operand" "r,r"))
950 (match_operand:DI 1 "s_register_operand" "?r,0")))
951 (clobber (reg:CC CC_REGNUM))]
953 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
954 [(set_attr "conds" "clob")
955 (set_attr "length" "8")]
958 (define_insn "*subdi_zesidi_zesidi"
959 [(set (match_operand:DI 0 "s_register_operand" "=r")
960 (minus:DI (zero_extend:DI
961 (match_operand:SI 1 "s_register_operand" "r"))
963 (match_operand:SI 2 "s_register_operand" "r"))))
964 (clobber (reg:CC CC_REGNUM))]
966 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
967 [(set_attr "conds" "clob")
968 (set_attr "length" "8")]
971 (define_expand "subsi3"
972 [(set (match_operand:SI 0 "s_register_operand" "")
973 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
974 (match_operand:SI 2 "s_register_operand" "")))]
977 if (GET_CODE (operands[1]) == CONST_INT)
981 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
984 : preserve_subexpressions_p ()));
987 else /* TARGET_THUMB */
988 operands[1] = force_reg (SImode, operands[1]);
993 (define_insn "*thumb_subsi3_insn"
994 [(set (match_operand:SI 0 "register_operand" "=l")
995 (minus:SI (match_operand:SI 1 "register_operand" "l")
996 (match_operand:SI 2 "register_operand" "l")))]
999 [(set_attr "length" "2")]
1002 (define_insn_and_split "*arm_subsi3_insn"
1003 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1004 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
1005 (match_operand:SI 2 "s_register_operand" "r,r")))]
1011 && GET_CODE (operands[1]) == CONST_INT
1012 && !const_ok_for_arm (INTVAL (operands[1]))"
1013 [(clobber (const_int 0))]
1015 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1019 [(set_attr "length" "4,16")
1020 (set_attr "predicable" "yes")]
1024 [(match_scratch:SI 3 "r")
1025 (set (match_operand:SI 0 "s_register_operand" "")
1026 (minus:SI (match_operand:SI 1 "const_int_operand" "")
1027 (match_operand:SI 2 "s_register_operand" "")))]
1029 && !const_ok_for_arm (INTVAL (operands[1]))
1030 && const_ok_for_arm (~INTVAL (operands[1]))"
1031 [(set (match_dup 3) (match_dup 1))
1032 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1036 (define_insn "*subsi3_compare0"
1037 [(set (reg:CC_NOOV CC_REGNUM)
1039 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1040 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1042 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1043 (minus:SI (match_dup 1) (match_dup 2)))]
1047 rsb%?s\\t%0, %2, %1"
1048 [(set_attr "conds" "set")]
1051 (define_insn "decscc"
1052 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1053 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1054 (match_operator:SI 2 "arm_comparison_operator"
1055 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1059 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1060 [(set_attr "conds" "use")
1061 (set_attr "length" "*,8")]
1064 (define_insn "subsf3"
1065 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1066 (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1067 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1068 "TARGET_ARM && TARGET_HARD_FLOAT"
1071 rsf%?s\\t%0, %2, %1"
1072 [(set_attr "type" "farith")]
1075 (define_insn "subdf3"
1076 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1077 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1078 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1079 "TARGET_ARM && TARGET_HARD_FLOAT"
1082 rsf%?d\\t%0, %2, %1"
1083 [(set_attr "type" "farith")
1084 (set_attr "predicable" "yes")]
1087 (define_insn "*subdf_esfdf_df"
1088 [(set (match_operand:DF 0 "s_register_operand" "=f")
1089 (minus:DF (float_extend:DF
1090 (match_operand:SF 1 "s_register_operand" "f"))
1091 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1092 "TARGET_ARM && TARGET_HARD_FLOAT"
1093 "suf%?d\\t%0, %1, %2"
1094 [(set_attr "type" "farith")
1095 (set_attr "predicable" "yes")]
1098 (define_insn "*subdf_df_esfdf"
1099 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1100 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1102 (match_operand:SF 2 "s_register_operand" "f,f"))))]
1103 "TARGET_ARM && TARGET_HARD_FLOAT"
1106 rsf%?d\\t%0, %2, %1"
1107 [(set_attr "type" "farith")
1108 (set_attr "predicable" "yes")]
1111 (define_insn "*subdf_esfdf_esfdf"
1112 [(set (match_operand:DF 0 "s_register_operand" "=f")
1113 (minus:DF (float_extend:DF
1114 (match_operand:SF 1 "s_register_operand" "f"))
1116 (match_operand:SF 2 "s_register_operand" "f"))))]
1117 "TARGET_ARM && TARGET_HARD_FLOAT"
1118 "suf%?d\\t%0, %1, %2"
1119 [(set_attr "type" "farith")
1120 (set_attr "predicable" "yes")]
1123 (define_insn "subxf3"
1124 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1125 (minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1126 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1127 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1130 rsf%?e\\t%0, %2, %1"
1131 [(set_attr "type" "farith")
1132 (set_attr "predicable" "yes")]
1135 ;; Multiplication insns
1137 (define_expand "mulsi3"
1138 [(set (match_operand:SI 0 "s_register_operand" "")
1139 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1140 (match_operand:SI 1 "s_register_operand" "")))]
1145 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1146 (define_insn "*arm_mulsi3"
1147 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1148 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1149 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1151 "mul%?\\t%0, %2, %1"
1152 [(set_attr "type" "mult")
1153 (set_attr "predicable" "yes")]
1156 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1157 ; 1 and 2; are the same, because reload will make operand 0 match
1158 ; operand 1 without realizing that this conflicts with operand 2. We fix
1159 ; this by adding another alternative to match this case, and then `reload'
1160 ; it ourselves. This alternative must come first.
1161 (define_insn "*thumb_mulsi3"
1162 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1163 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1164 (match_operand:SI 2 "register_operand" "l,l,l")))]
1167 if (which_alternative < 2)
1168 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1170 return \"mul\\t%0, %0, %2\";
1172 [(set_attr "length" "4,4,2")
1173 (set_attr "type" "mult")]
1176 (define_insn "*mulsi3_compare0"
1177 [(set (reg:CC_NOOV CC_REGNUM)
1178 (compare:CC_NOOV (mult:SI
1179 (match_operand:SI 2 "s_register_operand" "r,r")
1180 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1182 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1183 (mult:SI (match_dup 2) (match_dup 1)))]
1184 "TARGET_ARM && !arm_is_xscale"
1185 "mul%?s\\t%0, %2, %1"
1186 [(set_attr "conds" "set")
1187 (set_attr "type" "mult")]
1190 (define_insn "*mulsi_compare0_scratch"
1191 [(set (reg:CC_NOOV CC_REGNUM)
1192 (compare:CC_NOOV (mult:SI
1193 (match_operand:SI 2 "s_register_operand" "r,r")
1194 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1196 (clobber (match_scratch:SI 0 "=&r,&r"))]
1197 "TARGET_ARM && !arm_is_xscale"
1198 "mul%?s\\t%0, %2, %1"
1199 [(set_attr "conds" "set")
1200 (set_attr "type" "mult")]
1203 ;; Unnamed templates to match MLA instruction.
1205 (define_insn "*mulsi3addsi"
1206 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1208 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1209 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1210 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1212 "mla%?\\t%0, %2, %1, %3"
1213 [(set_attr "type" "mult")
1214 (set_attr "predicable" "yes")]
1217 (define_insn "*mulsi3addsi_compare0"
1218 [(set (reg:CC_NOOV CC_REGNUM)
1221 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1222 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1223 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1225 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1226 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1228 "TARGET_ARM && !arm_is_xscale"
1229 "mla%?s\\t%0, %2, %1, %3"
1230 [(set_attr "conds" "set")
1231 (set_attr "type" "mult")]
1234 (define_insn "*mulsi3addsi_compare0_scratch"
1235 [(set (reg:CC_NOOV CC_REGNUM)
1238 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1239 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1240 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1242 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1243 "TARGET_ARM && !arm_is_xscale"
1244 "mla%?s\\t%0, %2, %1, %3"
1245 [(set_attr "conds" "set")
1246 (set_attr "type" "mult")]
1249 ;; Unnamed template to match long long multiply-accumlate (smlal)
1251 (define_insn "*mulsidi3adddi"
1252 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1255 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1256 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1257 (match_operand:DI 1 "s_register_operand" "0")))]
1258 "TARGET_ARM && arm_fast_multiply"
1259 "smlal%?\\t%Q0, %R0, %3, %2"
1260 [(set_attr "type" "mult")
1261 (set_attr "predicable" "yes")]
1264 (define_insn "mulsidi3"
1265 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1267 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1268 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1269 "TARGET_ARM && arm_fast_multiply"
1270 "smull%?\\t%Q0, %R0, %1, %2"
1271 [(set_attr "type" "mult")
1272 (set_attr "predicable" "yes")]
1275 (define_insn "umulsidi3"
1276 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1278 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1279 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1280 "TARGET_ARM && arm_fast_multiply"
1281 "umull%?\\t%Q0, %R0, %1, %2"
1282 [(set_attr "type" "mult")
1283 (set_attr "predicable" "yes")]
1286 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1288 (define_insn "*umulsidi3adddi"
1289 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1292 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1293 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1294 (match_operand:DI 1 "s_register_operand" "0")))]
1295 "TARGET_ARM && arm_fast_multiply"
1296 "umlal%?\\t%Q0, %R0, %3, %2"
1297 [(set_attr "type" "mult")
1298 (set_attr "predicable" "yes")]
1301 (define_insn "smulsi3_highpart"
1302 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1306 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1307 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1309 (clobber (match_scratch:SI 3 "=&r,&r"))]
1310 "TARGET_ARM && arm_fast_multiply"
1311 "smull%?\\t%3, %0, %2, %1"
1312 [(set_attr "type" "mult")
1313 (set_attr "predicable" "yes")]
1316 (define_insn "umulsi3_highpart"
1317 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1321 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1322 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1324 (clobber (match_scratch:SI 3 "=&r,&r"))]
1325 "TARGET_ARM && arm_fast_multiply"
1326 "umull%?\\t%3, %0, %2, %1"
1327 [(set_attr "type" "mult")
1328 (set_attr "predicable" "yes")]
1331 (define_insn "mulhisi3"
1332 [(set (match_operand:SI 0 "s_register_operand" "=r")
1333 (mult:SI (sign_extend:SI
1334 (match_operand:HI 1 "s_register_operand" "%r"))
1336 (match_operand:HI 2 "s_register_operand" "r"))))]
1337 "TARGET_ARM && arm_is_xscale"
1338 "smulbb%?\\t%0, %1, %2"
1339 [(set_attr "type" "mult")]
1342 (define_insn "*mulhisi3addsi"
1343 [(set (match_operand:SI 0 "s_register_operand" "=r")
1344 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1345 (mult:SI (sign_extend:SI
1346 (match_operand:HI 2 "s_register_operand" "%r"))
1348 (match_operand:HI 3 "s_register_operand" "r")))))]
1349 "TARGET_ARM && arm_is_xscale"
1350 "smlabb%?\\t%0, %2, %3, %1"
1351 [(set_attr "type" "mult")]
1354 (define_insn "*mulhidi3adddi"
1355 [(set (match_operand:DI 0 "s_register_operand" "=r")
1357 (match_operand:DI 1 "s_register_operand" "0")
1358 (mult:DI (sign_extend:DI
1359 (match_operand:HI 2 "s_register_operand" "%r"))
1361 (match_operand:HI 3 "s_register_operand" "r")))))]
1362 "TARGET_ARM && arm_is_xscale"
1363 "smlalbb%?\\t%Q0, %R0, %2, %3"
1364 [(set_attr "type" "mult")])
1366 (define_insn "mulsf3"
1367 [(set (match_operand:SF 0 "s_register_operand" "=f")
1368 (mult:SF (match_operand:SF 1 "s_register_operand" "f")
1369 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1370 "TARGET_ARM && TARGET_HARD_FLOAT"
1371 "fml%?s\\t%0, %1, %2"
1372 [(set_attr "type" "ffmul")
1373 (set_attr "predicable" "yes")]
1376 (define_insn "muldf3"
1377 [(set (match_operand:DF 0 "s_register_operand" "=f")
1378 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1379 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1380 "TARGET_ARM && TARGET_HARD_FLOAT"
1381 "muf%?d\\t%0, %1, %2"
1382 [(set_attr "type" "fmul")
1383 (set_attr "predicable" "yes")]
1386 (define_insn "*muldf_esfdf_df"
1387 [(set (match_operand:DF 0 "s_register_operand" "=f")
1388 (mult:DF (float_extend:DF
1389 (match_operand:SF 1 "s_register_operand" "f"))
1390 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1391 "TARGET_ARM && TARGET_HARD_FLOAT"
1392 "muf%?d\\t%0, %1, %2"
1393 [(set_attr "type" "fmul")
1394 (set_attr "predicable" "yes")]
1397 (define_insn "*muldf_df_esfdf"
1398 [(set (match_operand:DF 0 "s_register_operand" "=f")
1399 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1401 (match_operand:SF 2 "s_register_operand" "f"))))]
1402 "TARGET_ARM && TARGET_HARD_FLOAT"
1403 "muf%?d\\t%0, %1, %2"
1404 [(set_attr "type" "fmul")
1405 (set_attr "predicable" "yes")]
1408 (define_insn "*muldf_esfdf_esfdf"
1409 [(set (match_operand:DF 0 "s_register_operand" "=f")
1411 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f"))
1412 (float_extend:DF (match_operand:SF 2 "s_register_operand" "f"))))]
1413 "TARGET_ARM && TARGET_HARD_FLOAT"
1414 "muf%?d\\t%0, %1, %2"
1415 [(set_attr "type" "fmul")
1416 (set_attr "predicable" "yes")]
1419 (define_insn "mulxf3"
1420 [(set (match_operand:XF 0 "s_register_operand" "=f")
1421 (mult:XF (match_operand:XF 1 "s_register_operand" "f")
1422 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1423 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1424 "muf%?e\\t%0, %1, %2"
1425 [(set_attr "type" "fmul")
1426 (set_attr "predicable" "yes")]
1431 (define_insn "divsf3"
1432 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1433 (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1434 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1435 "TARGET_ARM && TARGET_HARD_FLOAT"
1438 frd%?s\\t%0, %2, %1"
1439 [(set_attr "type" "fdivs")
1440 (set_attr "predicable" "yes")]
1443 (define_insn "divdf3"
1444 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1445 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1446 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1447 "TARGET_ARM && TARGET_HARD_FLOAT"
1450 rdf%?d\\t%0, %2, %1"
1451 [(set_attr "type" "fdivd")
1452 (set_attr "predicable" "yes")]
1455 (define_insn "*divdf_esfdf_df"
1456 [(set (match_operand:DF 0 "s_register_operand" "=f")
1457 (div:DF (float_extend:DF
1458 (match_operand:SF 1 "s_register_operand" "f"))
1459 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1460 "TARGET_ARM && TARGET_HARD_FLOAT"
1461 "dvf%?d\\t%0, %1, %2"
1462 [(set_attr "type" "fdivd")
1463 (set_attr "predicable" "yes")]
1466 (define_insn "*divdf_df_esfdf"
1467 [(set (match_operand:DF 0 "s_register_operand" "=f")
1468 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1470 (match_operand:SF 2 "s_register_operand" "f"))))]
1471 "TARGET_ARM && TARGET_HARD_FLOAT"
1472 "rdf%?d\\t%0, %2, %1"
1473 [(set_attr "type" "fdivd")
1474 (set_attr "predicable" "yes")]
1477 (define_insn "*divdf_esfdf_esfdf"
1478 [(set (match_operand:DF 0 "s_register_operand" "=f")
1479 (div:DF (float_extend:DF
1480 (match_operand:SF 1 "s_register_operand" "f"))
1482 (match_operand:SF 2 "s_register_operand" "f"))))]
1483 "TARGET_ARM && TARGET_HARD_FLOAT"
1484 "dvf%?d\\t%0, %1, %2"
1485 [(set_attr "type" "fdivd")
1486 (set_attr "predicable" "yes")]
1489 (define_insn "divxf3"
1490 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1491 (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1492 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1493 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1496 rdf%?e\\t%0, %2, %1"
1497 [(set_attr "type" "fdivx")
1498 (set_attr "predicable" "yes")]
1503 (define_insn "modsf3"
1504 [(set (match_operand:SF 0 "s_register_operand" "=f")
1505 (mod:SF (match_operand:SF 1 "s_register_operand" "f")
1506 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1507 "TARGET_ARM && TARGET_HARD_FLOAT"
1508 "rmf%?s\\t%0, %1, %2"
1509 [(set_attr "type" "fdivs")
1510 (set_attr "predicable" "yes")]
1513 (define_insn "moddf3"
1514 [(set (match_operand:DF 0 "s_register_operand" "=f")
1515 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1516 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1517 "TARGET_ARM && TARGET_HARD_FLOAT"
1518 "rmf%?d\\t%0, %1, %2"
1519 [(set_attr "type" "fdivd")
1520 (set_attr "predicable" "yes")]
1523 (define_insn "*moddf_esfdf_df"
1524 [(set (match_operand:DF 0 "s_register_operand" "=f")
1525 (mod:DF (float_extend:DF
1526 (match_operand:SF 1 "s_register_operand" "f"))
1527 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1528 "TARGET_ARM && TARGET_HARD_FLOAT"
1529 "rmf%?d\\t%0, %1, %2"
1530 [(set_attr "type" "fdivd")
1531 (set_attr "predicable" "yes")]
1534 (define_insn "*moddf_df_esfdf"
1535 [(set (match_operand:DF 0 "s_register_operand" "=f")
1536 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1538 (match_operand:SF 2 "s_register_operand" "f"))))]
1539 "TARGET_ARM && TARGET_HARD_FLOAT"
1540 "rmf%?d\\t%0, %1, %2"
1541 [(set_attr "type" "fdivd")
1542 (set_attr "predicable" "yes")]
1545 (define_insn "*moddf_esfdf_esfdf"
1546 [(set (match_operand:DF 0 "s_register_operand" "=f")
1547 (mod:DF (float_extend:DF
1548 (match_operand:SF 1 "s_register_operand" "f"))
1550 (match_operand:SF 2 "s_register_operand" "f"))))]
1551 "TARGET_ARM && TARGET_HARD_FLOAT"
1552 "rmf%?d\\t%0, %1, %2"
1553 [(set_attr "type" "fdivd")
1554 (set_attr "predicable" "yes")]
1557 (define_insn "modxf3"
1558 [(set (match_operand:XF 0 "s_register_operand" "=f")
1559 (mod:XF (match_operand:XF 1 "s_register_operand" "f")
1560 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1561 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1562 "rmf%?e\\t%0, %1, %2"
1563 [(set_attr "type" "fdivx")
1564 (set_attr "predicable" "yes")]
1567 ;; Boolean and,ior,xor insns
1569 ;; Split up double word logical operations
1571 ;; Split up simple DImode logical operations. Simply perform the logical
1572 ;; operation on the upper and lower halves of the registers.
1574 [(set (match_operand:DI 0 "s_register_operand" "")
1575 (match_operator:DI 6 "logical_binary_operator"
1576 [(match_operand:DI 1 "s_register_operand" "")
1577 (match_operand:DI 2 "s_register_operand" "")]))]
1578 "TARGET_ARM && reload_completed"
1579 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1580 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1583 operands[3] = gen_highpart (SImode, operands[0]);
1584 operands[0] = gen_lowpart (SImode, operands[0]);
1585 operands[4] = gen_highpart (SImode, operands[1]);
1586 operands[1] = gen_lowpart (SImode, operands[1]);
1587 operands[5] = gen_highpart (SImode, operands[2]);
1588 operands[2] = gen_lowpart (SImode, operands[2]);
1593 [(set (match_operand:DI 0 "s_register_operand" "")
1594 (match_operator:DI 6 "logical_binary_operator"
1595 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1596 (match_operand:DI 1 "s_register_operand" "")]))]
1597 "TARGET_ARM && reload_completed"
1598 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1599 (set (match_dup 3) (match_op_dup:SI 6
1600 [(ashiftrt:SI (match_dup 2) (const_int 31))
1604 operands[3] = gen_highpart (SImode, operands[0]);
1605 operands[0] = gen_lowpart (SImode, operands[0]);
1606 operands[4] = gen_highpart (SImode, operands[1]);
1607 operands[1] = gen_lowpart (SImode, operands[1]);
1608 operands[5] = gen_highpart (SImode, operands[2]);
1609 operands[2] = gen_lowpart (SImode, operands[2]);
1613 ;; The zero extend of operand 2 means we can just copy the high part of
1614 ;; operand1 into operand0.
1616 [(set (match_operand:DI 0 "s_register_operand" "")
1618 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1619 (match_operand:DI 1 "s_register_operand" "")))]
1620 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1621 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1622 (set (match_dup 3) (match_dup 4))]
1625 operands[4] = gen_highpart (SImode, operands[1]);
1626 operands[3] = gen_highpart (SImode, operands[0]);
1627 operands[0] = gen_lowpart (SImode, operands[0]);
1628 operands[1] = gen_lowpart (SImode, operands[1]);
1632 ;; The zero extend of operand 2 means we can just copy the high part of
1633 ;; operand1 into operand0.
1635 [(set (match_operand:DI 0 "s_register_operand" "")
1637 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1638 (match_operand:DI 1 "s_register_operand" "")))]
1639 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1640 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1641 (set (match_dup 3) (match_dup 4))]
1644 operands[4] = gen_highpart (SImode, operands[1]);
1645 operands[3] = gen_highpart (SImode, operands[0]);
1646 operands[0] = gen_lowpart (SImode, operands[0]);
1647 operands[1] = gen_lowpart (SImode, operands[1]);
1651 (define_insn "anddi3"
1652 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1653 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1654 (match_operand:DI 2 "s_register_operand" "r,r")))]
1657 [(set_attr "length" "8")]
1660 (define_insn_and_split "*anddi_zesidi_di"
1661 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1662 (and:DI (zero_extend:DI
1663 (match_operand:SI 2 "s_register_operand" "r,r"))
1664 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1667 "TARGET_ARM && reload_completed"
1668 ; The zero extend of operand 2 clears the high word of the output
1670 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1671 (set (match_dup 3) (const_int 0))]
1674 operands[3] = gen_highpart (SImode, operands[0]);
1675 operands[0] = gen_lowpart (SImode, operands[0]);
1676 operands[1] = gen_lowpart (SImode, operands[1]);
1678 [(set_attr "length" "8")]
1681 (define_insn "*anddi_sesdi_di"
1682 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1683 (and:DI (sign_extend:DI
1684 (match_operand:SI 2 "s_register_operand" "r,r"))
1685 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1688 [(set_attr "length" "8")]
1691 (define_expand "andsi3"
1692 [(set (match_operand:SI 0 "s_register_operand" "")
1693 (and:SI (match_operand:SI 1 "s_register_operand" "")
1694 (match_operand:SI 2 "reg_or_int_operand" "")))]
1699 if (GET_CODE (operands[2]) == CONST_INT)
1701 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1704 ? 0 : preserve_subexpressions_p ()));
1708 else /* TARGET_THUMB */
1710 if (GET_CODE (operands[2]) != CONST_INT)
1711 operands[2] = force_reg (SImode, operands[2]);
1716 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1718 operands[2] = force_reg (SImode,
1719 GEN_INT (~INTVAL (operands[2])));
1721 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1726 for (i = 9; i <= 31; i++)
1728 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1730 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1734 else if ((((HOST_WIDE_INT) 1) << i) - 1
1735 == ~INTVAL (operands[2]))
1737 rtx shift = GEN_INT (i);
1738 rtx reg = gen_reg_rtx (SImode);
1740 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1741 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1747 operands[2] = force_reg (SImode, operands[2]);
1753 (define_insn_and_split "*arm_andsi3_insn"
1754 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1755 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1756 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1760 bic%?\\t%0, %1, #%B2
1763 && GET_CODE (operands[2]) == CONST_INT
1764 && !(const_ok_for_arm (INTVAL (operands[2]))
1765 || const_ok_for_arm (~INTVAL (operands[2])))"
1766 [(clobber (const_int 0))]
1768 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1772 [(set_attr "length" "4,4,16")
1773 (set_attr "predicable" "yes")]
1776 (define_insn "*thumb_andsi3_insn"
1777 [(set (match_operand:SI 0 "register_operand" "=l")
1778 (and:SI (match_operand:SI 1 "register_operand" "%0")
1779 (match_operand:SI 2 "register_operand" "l")))]
1782 [(set_attr "length" "2")]
1785 (define_insn "*andsi3_compare0"
1786 [(set (reg:CC_NOOV CC_REGNUM)
1788 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1789 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1791 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1792 (and:SI (match_dup 1) (match_dup 2)))]
1796 bic%?s\\t%0, %1, #%B2"
1797 [(set_attr "conds" "set")]
1800 (define_insn "*andsi3_compare0_scratch"
1801 [(set (reg:CC_NOOV CC_REGNUM)
1803 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1804 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1806 (clobber (match_scratch:SI 2 "=X,r"))]
1810 bic%?s\\t%2, %0, #%B1"
1811 [(set_attr "conds" "set")]
1814 (define_insn "*zeroextractsi_compare0_scratch"
1815 [(set (reg:CC_NOOV CC_REGNUM)
1816 (compare:CC_NOOV (zero_extract:SI
1817 (match_operand:SI 0 "s_register_operand" "r")
1818 (match_operand 1 "const_int_operand" "n")
1819 (match_operand 2 "const_int_operand" "n"))
1822 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1823 && INTVAL (operands[1]) > 0
1824 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1825 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1827 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1828 << INTVAL (operands[2]));
1829 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1832 [(set_attr "conds" "set")]
1835 (define_insn "*ne_zeroextractsi"
1836 [(set (match_operand:SI 0 "s_register_operand" "=r")
1837 (ne:SI (zero_extract:SI
1838 (match_operand:SI 1 "s_register_operand" "r")
1839 (match_operand:SI 2 "const_int_operand" "n")
1840 (match_operand:SI 3 "const_int_operand" "n"))
1842 (clobber (reg:CC CC_REGNUM))]
1844 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1845 && INTVAL (operands[2]) > 0
1846 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1847 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1849 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1850 << INTVAL (operands[3]));
1851 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1852 return \"movne\\t%0, #1\";
1854 [(set_attr "conds" "clob")
1855 (set_attr "length" "8")]
1858 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1859 ;;; represented by the bitfield, then this will produce incorrect results.
1860 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1861 ;;; which have a real bit-field insert instruction, the truncation happens
1862 ;;; in the bit-field insert instruction itself. Since arm does not have a
1863 ;;; bit-field insert instruction, we would have to emit code here to truncate
1864 ;;; the value before we insert. This loses some of the advantage of having
1865 ;;; this insv pattern, so this pattern needs to be reevalutated.
1867 (define_expand "insv"
1868 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1869 (match_operand:SI 1 "general_operand" "")
1870 (match_operand:SI 2 "general_operand" ""))
1871 (match_operand:SI 3 "reg_or_int_operand" ""))]
1875 int start_bit = INTVAL (operands[2]);
1876 int width = INTVAL (operands[1]);
1877 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1878 rtx target, subtarget;
1880 target = operands[0];
1881 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1882 subreg as the final target. */
1883 if (GET_CODE (target) == SUBREG)
1885 subtarget = gen_reg_rtx (SImode);
1886 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1887 < GET_MODE_SIZE (SImode))
1888 target = SUBREG_REG (target);
1893 if (GET_CODE (operands[3]) == CONST_INT)
1895 /* Since we are inserting a known constant, we may be able to
1896 reduce the number of bits that we have to clear so that
1897 the mask becomes simple. */
1898 /* ??? This code does not check to see if the new mask is actually
1899 simpler. It may not be. */
1900 rtx op1 = gen_reg_rtx (SImode);
1901 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1902 start of this pattern. */
1903 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1904 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1906 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1907 emit_insn (gen_iorsi3 (subtarget, op1,
1908 GEN_INT (op3_value << start_bit)));
1910 else if (start_bit == 0
1911 && !(const_ok_for_arm (mask)
1912 || const_ok_for_arm (~mask)))
1914 /* A Trick, since we are setting the bottom bits in the word,
1915 we can shift operand[3] up, operand[0] down, OR them together
1916 and rotate the result back again. This takes 3 insns, and
1917 the third might be mergable into another op. */
1918 /* The shift up copes with the possibility that operand[3] is
1919 wider than the bitfield. */
1920 rtx op0 = gen_reg_rtx (SImode);
1921 rtx op1 = gen_reg_rtx (SImode);
1923 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1924 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1925 emit_insn (gen_iorsi3 (op1, op1, op0));
1926 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1928 else if ((width + start_bit == 32)
1929 && !(const_ok_for_arm (mask)
1930 || const_ok_for_arm (~mask)))
1932 /* Similar trick, but slightly less efficient. */
1934 rtx op0 = gen_reg_rtx (SImode);
1935 rtx op1 = gen_reg_rtx (SImode);
1937 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1938 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1939 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1940 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1944 rtx op0 = GEN_INT (mask);
1945 rtx op1 = gen_reg_rtx (SImode);
1946 rtx op2 = gen_reg_rtx (SImode);
1948 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1950 rtx tmp = gen_reg_rtx (SImode);
1952 emit_insn (gen_movsi (tmp, op0));
1956 /* Mask out any bits in operand[3] that are not needed. */
1957 emit_insn (gen_andsi3 (op1, operands[3], op0));
1959 if (GET_CODE (op0) == CONST_INT
1960 && (const_ok_for_arm (mask << start_bit)
1961 || const_ok_for_arm (~(mask << start_bit))))
1963 op0 = GEN_INT (~(mask << start_bit));
1964 emit_insn (gen_andsi3 (op2, operands[0], op0));
1968 if (GET_CODE (op0) == CONST_INT)
1970 rtx tmp = gen_reg_rtx (SImode);
1972 emit_insn (gen_movsi (tmp, op0));
1977 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1979 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1983 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1985 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1988 if (subtarget != target)
1990 /* If TARGET is still a SUBREG, then it must be wider than a word,
1991 so we must be careful only to set the subword we were asked to. */
1992 if (GET_CODE (target) == SUBREG)
1993 emit_move_insn (target, subtarget);
1995 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2002 ; constants for op 2 will never be given to these patterns.
2003 (define_insn_and_split "*anddi_notdi_di"
2004 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2005 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2006 (match_operand:DI 2 "s_register_operand" "0,r")))]
2009 "TARGET_ARM && reload_completed"
2010 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2011 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2014 operands[3] = gen_highpart (SImode, operands[0]);
2015 operands[0] = gen_lowpart (SImode, operands[0]);
2016 operands[4] = gen_highpart (SImode, operands[1]);
2017 operands[1] = gen_lowpart (SImode, operands[1]);
2018 operands[5] = gen_highpart (SImode, operands[2]);
2019 operands[2] = gen_lowpart (SImode, operands[2]);
2021 [(set_attr "length" "8")
2022 (set_attr "predicable" "yes")]
2025 (define_insn_and_split "*anddi_notzesidi_di"
2026 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2027 (and:DI (not:DI (zero_extend:DI
2028 (match_operand:SI 2 "s_register_operand" "r,r")))
2029 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2032 bic%?\\t%Q0, %Q1, %2
2034 ; (not (zero_extend ...)) allows us to just copy the high word from
2035 ; operand1 to operand0.
2038 && operands[0] != operands[1]"
2039 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2040 (set (match_dup 3) (match_dup 4))]
2043 operands[3] = gen_highpart (SImode, operands[0]);
2044 operands[0] = gen_lowpart (SImode, operands[0]);
2045 operands[4] = gen_highpart (SImode, operands[1]);
2046 operands[1] = gen_lowpart (SImode, operands[1]);
2048 [(set_attr "length" "4,8")
2049 (set_attr "predicable" "yes")]
2052 (define_insn_and_split "*anddi_notsesidi_di"
2053 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2054 (and:DI (not:DI (sign_extend:DI
2055 (match_operand:SI 2 "s_register_operand" "r,r")))
2056 (match_operand:DI 1 "s_register_operand" "0,r")))]
2059 "TARGET_ARM && reload_completed"
2060 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2061 (set (match_dup 3) (and:SI (not:SI
2062 (ashiftrt:SI (match_dup 2) (const_int 31)))
2066 operands[3] = gen_highpart (SImode, operands[0]);
2067 operands[0] = gen_lowpart (SImode, operands[0]);
2068 operands[4] = gen_highpart (SImode, operands[1]);
2069 operands[1] = gen_lowpart (SImode, operands[1]);
2071 [(set_attr "length" "8")
2072 (set_attr "predicable" "yes")]
2075 (define_insn "andsi_notsi_si"
2076 [(set (match_operand:SI 0 "s_register_operand" "=r")
2077 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2078 (match_operand:SI 1 "s_register_operand" "r")))]
2080 "bic%?\\t%0, %1, %2"
2081 [(set_attr "predicable" "yes")]
2084 (define_insn "bicsi3"
2085 [(set (match_operand:SI 0 "register_operand" "=l")
2086 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2087 (match_operand:SI 2 "register_operand" "0")))]
2090 [(set_attr "length" "2")]
2093 (define_insn "andsi_not_shiftsi_si"
2094 [(set (match_operand:SI 0 "s_register_operand" "=r")
2095 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2096 [(match_operand:SI 2 "s_register_operand" "r")
2097 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2098 (match_operand:SI 1 "s_register_operand" "r")))]
2100 "bic%?\\t%0, %1, %2%S4"
2101 [(set_attr "predicable" "yes")
2102 (set_attr "shift" "2")
2106 (define_insn "*andsi_notsi_si_compare0"
2107 [(set (reg:CC_NOOV CC_REGNUM)
2109 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2110 (match_operand:SI 1 "s_register_operand" "r"))
2112 (set (match_operand:SI 0 "s_register_operand" "=r")
2113 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2115 "bic%?s\\t%0, %1, %2"
2116 [(set_attr "conds" "set")]
2119 (define_insn "*andsi_notsi_si_compare0_scratch"
2120 [(set (reg:CC_NOOV CC_REGNUM)
2122 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2123 (match_operand:SI 1 "s_register_operand" "r"))
2125 (clobber (match_scratch:SI 0 "=r"))]
2127 "bic%?s\\t%0, %1, %2"
2128 [(set_attr "conds" "set")]
2131 (define_insn "iordi3"
2132 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2133 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2134 (match_operand:DI 2 "s_register_operand" "r,r")))]
2137 [(set_attr "length" "8")
2138 (set_attr "predicable" "yes")]
2141 (define_insn "*iordi_zesidi_di"
2142 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2143 (ior:DI (zero_extend:DI
2144 (match_operand:SI 2 "s_register_operand" "r,r"))
2145 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2148 orr%?\\t%Q0, %Q1, %2
2150 [(set_attr "length" "4,8")
2151 (set_attr "predicable" "yes")]
2154 (define_insn "*iordi_sesidi_di"
2155 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2156 (ior:DI (sign_extend:DI
2157 (match_operand:SI 2 "s_register_operand" "r,r"))
2158 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2161 [(set_attr "length" "8")
2162 (set_attr "predicable" "yes")]
2165 (define_expand "iorsi3"
2166 [(set (match_operand:SI 0 "s_register_operand" "")
2167 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2168 (match_operand:SI 2 "reg_or_int_operand" "")))]
2171 if (GET_CODE (operands[2]) == CONST_INT)
2175 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2178 ? 0 : preserve_subexpressions_p ()));
2181 else /* TARGET_THUMB */
2182 operands [2] = force_reg (SImode, operands [2]);
2187 (define_insn_and_split "*arm_iorsi3"
2188 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2189 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2190 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2196 && GET_CODE (operands[2]) == CONST_INT
2197 && !const_ok_for_arm (INTVAL (operands[2]))"
2198 [(clobber (const_int 0))]
2200 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2204 [(set_attr "length" "4,16")
2205 (set_attr "predicable" "yes")]
2208 (define_insn "*thumb_iorsi3"
2209 [(set (match_operand:SI 0 "register_operand" "=l")
2210 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2211 (match_operand:SI 2 "register_operand" "l")))]
2214 [(set_attr "length" "2")]
2218 [(match_scratch:SI 3 "r")
2219 (set (match_operand:SI 0 "s_register_operand" "")
2220 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2221 (match_operand:SI 2 "const_int_operand" "")))]
2223 && !const_ok_for_arm (INTVAL (operands[2]))
2224 && const_ok_for_arm (~INTVAL (operands[2]))"
2225 [(set (match_dup 3) (match_dup 2))
2226 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2230 (define_insn "*iorsi3_compare0"
2231 [(set (reg:CC_NOOV CC_REGNUM)
2232 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2233 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2235 (set (match_operand:SI 0 "s_register_operand" "=r")
2236 (ior:SI (match_dup 1) (match_dup 2)))]
2238 "orr%?s\\t%0, %1, %2"
2239 [(set_attr "conds" "set")]
2242 (define_insn "*iorsi3_compare0_scratch"
2243 [(set (reg:CC_NOOV CC_REGNUM)
2244 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2245 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2247 (clobber (match_scratch:SI 0 "=r"))]
2249 "orr%?s\\t%0, %1, %2"
2250 [(set_attr "conds" "set")]
2253 (define_insn "xordi3"
2254 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2255 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2256 (match_operand:DI 2 "s_register_operand" "r,r")))]
2259 [(set_attr "length" "8")
2260 (set_attr "predicable" "yes")]
2263 (define_insn "*xordi_zesidi_di"
2264 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2265 (xor:DI (zero_extend:DI
2266 (match_operand:SI 2 "s_register_operand" "r,r"))
2267 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2270 eor%?\\t%Q0, %Q1, %2
2272 [(set_attr "length" "4,8")
2273 (set_attr "predicable" "yes")]
2276 (define_insn "*xordi_sesidi_di"
2277 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2278 (xor:DI (sign_extend:DI
2279 (match_operand:SI 2 "s_register_operand" "r,r"))
2280 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2283 [(set_attr "length" "8")
2284 (set_attr "predicable" "yes")]
2287 (define_expand "xorsi3"
2288 [(set (match_operand:SI 0 "s_register_operand" "")
2289 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2290 (match_operand:SI 2 "arm_rhs_operand" "")))]
2293 if (GET_CODE (operands[2]) == CONST_INT)
2294 operands[2] = force_reg (SImode, operands[2]);
2298 (define_insn "*arm_xorsi3"
2299 [(set (match_operand:SI 0 "s_register_operand" "=r")
2300 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2301 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2303 "eor%?\\t%0, %1, %2"
2304 [(set_attr "predicable" "yes")]
2307 (define_insn "*thumb_xorsi3"
2308 [(set (match_operand:SI 0 "register_operand" "=l")
2309 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2310 (match_operand:SI 2 "register_operand" "l")))]
2313 [(set_attr "length" "2")]
2316 (define_insn "*xorsi3_compare0"
2317 [(set (reg:CC_NOOV CC_REGNUM)
2318 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2319 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2321 (set (match_operand:SI 0 "s_register_operand" "=r")
2322 (xor:SI (match_dup 1) (match_dup 2)))]
2324 "eor%?s\\t%0, %1, %2"
2325 [(set_attr "conds" "set")]
2328 (define_insn "*xorsi3_compare0_scratch"
2329 [(set (reg:CC_NOOV CC_REGNUM)
2330 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2331 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2335 [(set_attr "conds" "set")]
2338 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2339 ; (NOT D) we can sometimes merge the final NOT into one of the following
2343 [(set (match_operand:SI 0 "s_register_operand" "")
2344 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2345 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2346 (match_operand:SI 3 "arm_rhs_operand" "")))
2347 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2349 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2350 (not:SI (match_dup 3))))
2351 (set (match_dup 0) (not:SI (match_dup 4)))]
2355 (define_insn "*andsi_iorsi3_notsi"
2356 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2357 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2358 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2359 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2361 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2362 [(set_attr "length" "8")
2363 (set_attr "predicable" "yes")]
2368 ;; Minimum and maximum insns
2370 (define_insn "smaxsi3"
2371 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2372 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2373 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2374 (clobber (reg:CC CC_REGNUM))]
2377 cmp\\t%1, %2\;movlt\\t%0, %2
2378 cmp\\t%1, %2\;movge\\t%0, %1
2379 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2380 [(set_attr "conds" "clob")
2381 (set_attr "length" "8,8,12")]
2384 (define_insn "sminsi3"
2385 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2386 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2387 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2388 (clobber (reg:CC CC_REGNUM))]
2391 cmp\\t%1, %2\;movge\\t%0, %2
2392 cmp\\t%1, %2\;movlt\\t%0, %1
2393 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2394 [(set_attr "conds" "clob")
2395 (set_attr "length" "8,8,12")]
2398 (define_insn "umaxsi3"
2399 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2400 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2401 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2402 (clobber (reg:CC CC_REGNUM))]
2405 cmp\\t%1, %2\;movcc\\t%0, %2
2406 cmp\\t%1, %2\;movcs\\t%0, %1
2407 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2408 [(set_attr "conds" "clob")
2409 (set_attr "length" "8,8,12")]
2412 (define_insn "uminsi3"
2413 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2414 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2415 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2416 (clobber (reg:CC CC_REGNUM))]
2419 cmp\\t%1, %2\;movcs\\t%0, %2
2420 cmp\\t%1, %2\;movcc\\t%0, %1
2421 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2422 [(set_attr "conds" "clob")
2423 (set_attr "length" "8,8,12")]
2426 (define_insn "*store_minmaxsi"
2427 [(set (match_operand:SI 0 "memory_operand" "=m")
2428 (match_operator:SI 3 "minmax_operator"
2429 [(match_operand:SI 1 "s_register_operand" "r")
2430 (match_operand:SI 2 "s_register_operand" "r")]))
2431 (clobber (reg:CC CC_REGNUM))]
2434 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2436 output_asm_insn (\"cmp\\t%1, %2\", operands);
2437 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2438 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2441 [(set_attr "conds" "clob")
2442 (set_attr "length" "12")
2443 (set_attr "type" "store1")]
2446 ; Reject the frame pointer in operand[1], since reloading this after
2447 ; it has been eliminated can cause carnage.
2448 (define_insn "*minmax_arithsi"
2449 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2450 (match_operator:SI 4 "shiftable_operator"
2451 [(match_operator:SI 5 "minmax_operator"
2452 [(match_operand:SI 2 "s_register_operand" "r,r")
2453 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2454 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2455 (clobber (reg:CC CC_REGNUM))]
2457 && (GET_CODE (operands[1]) != REG
2458 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2459 && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2462 enum rtx_code code = GET_CODE (operands[4]);
2464 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2466 output_asm_insn (\"cmp\\t%2, %3\", operands);
2467 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2468 if (which_alternative != 0 || operands[3] != const0_rtx
2469 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2470 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2473 [(set_attr "conds" "clob")
2474 (set_attr "length" "12")]
2478 ;; Shift and rotation insns
2480 (define_expand "ashlsi3"
2481 [(set (match_operand:SI 0 "s_register_operand" "")
2482 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2483 (match_operand:SI 2 "arm_rhs_operand" "")))]
2486 if (GET_CODE (operands[2]) == CONST_INT
2487 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2489 emit_insn (gen_movsi (operands[0], const0_rtx));
2495 (define_insn "*thumb_ashlsi3"
2496 [(set (match_operand:SI 0 "register_operand" "=l,l")
2497 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2498 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2501 [(set_attr "length" "2")]
2504 (define_expand "ashrsi3"
2505 [(set (match_operand:SI 0 "s_register_operand" "")
2506 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2507 (match_operand:SI 2 "arm_rhs_operand" "")))]
2510 if (GET_CODE (operands[2]) == CONST_INT
2511 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2512 operands[2] = GEN_INT (31);
2516 (define_insn "*thumb_ashrsi3"
2517 [(set (match_operand:SI 0 "register_operand" "=l,l")
2518 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2519 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2522 [(set_attr "length" "2")]
2525 (define_expand "lshrsi3"
2526 [(set (match_operand:SI 0 "s_register_operand" "")
2527 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2528 (match_operand:SI 2 "arm_rhs_operand" "")))]
2531 if (GET_CODE (operands[2]) == CONST_INT
2532 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2534 emit_insn (gen_movsi (operands[0], const0_rtx));
2540 (define_insn "*thumb_lshrsi3"
2541 [(set (match_operand:SI 0 "register_operand" "=l,l")
2542 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2543 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2546 [(set_attr "length" "2")]
2549 (define_expand "rotlsi3"
2550 [(set (match_operand:SI 0 "s_register_operand" "")
2551 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2552 (match_operand:SI 2 "reg_or_int_operand" "")))]
2555 if (GET_CODE (operands[2]) == CONST_INT)
2556 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2559 rtx reg = gen_reg_rtx (SImode);
2560 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2566 (define_expand "rotrsi3"
2567 [(set (match_operand:SI 0 "s_register_operand" "")
2568 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2569 (match_operand:SI 2 "arm_rhs_operand" "")))]
2574 if (GET_CODE (operands[2]) == CONST_INT
2575 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2576 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2578 else /* TARGET_THUMB */
2580 if (GET_CODE (operands [2]) == CONST_INT)
2581 operands [2] = force_reg (SImode, operands[2]);
2586 (define_insn "*thumb_rotrsi3"
2587 [(set (match_operand:SI 0 "register_operand" "=l")
2588 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2589 (match_operand:SI 2 "register_operand" "l")))]
2592 [(set_attr "length" "2")]
2595 (define_insn "*arm_shiftsi3"
2596 [(set (match_operand:SI 0 "s_register_operand" "=r")
2597 (match_operator:SI 3 "shift_operator"
2598 [(match_operand:SI 1 "s_register_operand" "r")
2599 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2602 [(set_attr "predicable" "yes")
2603 (set_attr "shift" "1")
2607 (define_insn "*shiftsi3_compare0"
2608 [(set (reg:CC_NOOV CC_REGNUM)
2609 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2610 [(match_operand:SI 1 "s_register_operand" "r")
2611 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2613 (set (match_operand:SI 0 "s_register_operand" "=r")
2614 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2616 "mov%?s\\t%0, %1%S3"
2617 [(set_attr "conds" "set")
2618 (set_attr "shift" "1")
2622 (define_insn "*shiftsi3_compare0_scratch"
2623 [(set (reg:CC_NOOV CC_REGNUM)
2624 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2625 [(match_operand:SI 1 "s_register_operand" "r")
2626 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2628 (clobber (match_scratch:SI 0 "=r"))]
2630 "mov%?s\\t%0, %1%S3"
2631 [(set_attr "conds" "set")
2632 (set_attr "shift" "1")
2636 (define_insn "*notsi_shiftsi"
2637 [(set (match_operand:SI 0 "s_register_operand" "=r")
2638 (not:SI (match_operator:SI 3 "shift_operator"
2639 [(match_operand:SI 1 "s_register_operand" "r")
2640 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2643 [(set_attr "predicable" "yes")
2644 (set_attr "shift" "1")
2648 (define_insn "*notsi_shiftsi_compare0"
2649 [(set (reg:CC_NOOV CC_REGNUM)
2650 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2651 [(match_operand:SI 1 "s_register_operand" "r")
2652 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2654 (set (match_operand:SI 0 "s_register_operand" "=r")
2655 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2657 "mvn%?s\\t%0, %1%S3"
2658 [(set_attr "conds" "set")
2659 (set_attr "shift" "1")
2663 (define_insn "*not_shiftsi_compare0_scratch"
2664 [(set (reg:CC_NOOV CC_REGNUM)
2665 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2666 [(match_operand:SI 1 "s_register_operand" "r")
2667 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2669 (clobber (match_scratch:SI 0 "=r"))]
2671 "mvn%?s\\t%0, %1%S3"
2672 [(set_attr "conds" "set")
2673 (set_attr "shift" "1")
2677 ;; We don't really have extzv, but defining this using shifts helps
2678 ;; to reduce register pressure later on.
2680 (define_expand "extzv"
2682 (ashift:SI (match_operand:SI 1 "register_operand" "")
2683 (match_operand:SI 2 "const_int_operand" "")))
2684 (set (match_operand:SI 0 "register_operand" "")
2685 (lshiftrt:SI (match_dup 4)
2686 (match_operand:SI 3 "const_int_operand" "")))]
2690 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2691 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2693 operands[3] = GEN_INT (rshift);
2697 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2701 operands[2] = GEN_INT (lshift);
2702 operands[4] = gen_reg_rtx (SImode);
2707 ;; Unary arithmetic insns
2709 (define_expand "negdi2"
2711 [(set (match_operand:DI 0 "s_register_operand" "")
2712 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2713 (clobber (reg:CC CC_REGNUM))])]
2718 if (GET_CODE (operands[1]) != REG)
2719 operands[1] = force_reg (SImode, operands[1]);
2724 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2725 ;; The second alternative is to allow the common case of a *full* overlap.
2726 (define_insn "*arm_negdi2"
2727 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2728 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2729 (clobber (reg:CC CC_REGNUM))]
2731 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2732 [(set_attr "conds" "clob")
2733 (set_attr "length" "8")]
2736 (define_insn "*thumb_negdi2"
2737 [(set (match_operand:DI 0 "register_operand" "=&l")
2738 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2739 (clobber (reg:CC CC_REGNUM))]
2741 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2742 [(set_attr "length" "6")]
2745 (define_expand "negsi2"
2746 [(set (match_operand:SI 0 "s_register_operand" "")
2747 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2752 (define_insn "*arm_negsi2"
2753 [(set (match_operand:SI 0 "s_register_operand" "=r")
2754 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2756 "rsb%?\\t%0, %1, #0"
2757 [(set_attr "predicable" "yes")]
2760 (define_insn "*thumb_negsi2"
2761 [(set (match_operand:SI 0 "register_operand" "=l")
2762 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2765 [(set_attr "length" "2")]
2768 (define_insn "negsf2"
2769 [(set (match_operand:SF 0 "s_register_operand" "=f")
2770 (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
2771 "TARGET_ARM && TARGET_HARD_FLOAT"
2773 [(set_attr "type" "ffarith")
2774 (set_attr "predicable" "yes")]
2777 (define_insn "negdf2"
2778 [(set (match_operand:DF 0 "s_register_operand" "=f")
2779 (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
2780 "TARGET_ARM && TARGET_HARD_FLOAT"
2782 [(set_attr "type" "ffarith")
2783 (set_attr "predicable" "yes")]
2786 (define_insn "*negdf_esfdf"
2787 [(set (match_operand:DF 0 "s_register_operand" "=f")
2788 (neg:DF (float_extend:DF
2789 (match_operand:SF 1 "s_register_operand" "f"))))]
2790 "TARGET_ARM && TARGET_HARD_FLOAT"
2792 [(set_attr "type" "ffarith")
2793 (set_attr "predicable" "yes")]
2796 (define_insn "negxf2"
2797 [(set (match_operand:XF 0 "s_register_operand" "=f")
2798 (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
2799 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2801 [(set_attr "type" "ffarith")
2802 (set_attr "predicable" "yes")]
2805 ;; abssi2 doesn't really clobber the condition codes if a different register
2806 ;; is being set. To keep things simple, assume during rtl manipulations that
2807 ;; it does, but tell the final scan operator the truth. Similarly for
2810 (define_insn "abssi2"
2811 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2812 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2813 (clobber (reg:CC CC_REGNUM))]
2816 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2817 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2818 [(set_attr "conds" "clob,*")
2819 (set_attr "shift" "1")
2820 ;; predicable can't be set based on the variant, so left as no
2821 (set_attr "length" "8")]
2824 (define_insn "*neg_abssi2"
2825 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2826 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2827 (clobber (reg:CC CC_REGNUM))]
2830 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2831 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2832 [(set_attr "conds" "clob,*")
2833 (set_attr "shift" "1")
2834 ;; predicable can't be set based on the variant, so left as no
2835 (set_attr "length" "8")]
2838 (define_insn "abssf2"
2839 [(set (match_operand:SF 0 "s_register_operand" "=f")
2840 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
2841 "TARGET_ARM && TARGET_HARD_FLOAT"
2843 [(set_attr "type" "ffarith")
2844 (set_attr "predicable" "yes")]
2847 (define_insn "absdf2"
2848 [(set (match_operand:DF 0 "s_register_operand" "=f")
2849 (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
2850 "TARGET_ARM && TARGET_HARD_FLOAT"
2852 [(set_attr "type" "ffarith")
2853 (set_attr "predicable" "yes")]
2856 (define_insn "*absdf_esfdf"
2857 [(set (match_operand:DF 0 "s_register_operand" "=f")
2858 (abs:DF (float_extend:DF
2859 (match_operand:SF 1 "s_register_operand" "f"))))]
2860 "TARGET_ARM && TARGET_HARD_FLOAT"
2862 [(set_attr "type" "ffarith")
2863 (set_attr "predicable" "yes")]
2866 (define_insn "absxf2"
2867 [(set (match_operand:XF 0 "s_register_operand" "=f")
2868 (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
2869 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2871 [(set_attr "type" "ffarith")
2872 (set_attr "predicable" "yes")]
2875 (define_insn "sqrtsf2"
2876 [(set (match_operand:SF 0 "s_register_operand" "=f")
2877 (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
2878 "TARGET_ARM && TARGET_HARD_FLOAT"
2880 [(set_attr "type" "float_em")
2881 (set_attr "predicable" "yes")]
2884 (define_insn "sqrtdf2"
2885 [(set (match_operand:DF 0 "s_register_operand" "=f")
2886 (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
2887 "TARGET_ARM && TARGET_HARD_FLOAT"
2889 [(set_attr "type" "float_em")
2890 (set_attr "predicable" "yes")]
2893 (define_insn "*sqrtdf_esfdf"
2894 [(set (match_operand:DF 0 "s_register_operand" "=f")
2895 (sqrt:DF (float_extend:DF
2896 (match_operand:SF 1 "s_register_operand" "f"))))]
2897 "TARGET_ARM && TARGET_HARD_FLOAT"
2899 [(set_attr "type" "float_em")
2900 (set_attr "predicable" "yes")]
2903 (define_insn "sqrtxf2"
2904 [(set (match_operand:XF 0 "s_register_operand" "=f")
2905 (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
2906 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2908 [(set_attr "type" "float_em")
2909 (set_attr "predicable" "yes")]
2912 ;; SIN COS TAN and family are always emulated, so it's probably better
2913 ;; to always call a library function.
2914 ;(define_insn "sinsf2"
2915 ; [(set (match_operand:SF 0 "s_register_operand" "=f")
2916 ; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
2918 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2920 ;[(set_attr "type" "float_em")])
2922 ;(define_insn "sindf2"
2923 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2924 ; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
2926 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2928 ;[(set_attr "type" "float_em")])
2930 ;(define_insn "*sindf_esfdf"
2931 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2932 ; (unspec:DF [(float_extend:DF
2933 ; (match_operand:SF 1 "s_register_operand" "f"))]
2935 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2937 ;[(set_attr "type" "float_em")])
2939 ;(define_insn "sinxf2"
2940 ; [(set (match_operand:XF 0 "s_register_operand" "=f")
2941 ; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
2943 ; "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2945 ;[(set_attr "type" "float_em")])
2947 ;(define_insn "cossf2"
2948 ; [(set (match_operand:SF 0 "s_register_operand" "=f")
2949 ; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
2951 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2953 ;[(set_attr "type" "float_em")])
2955 ;(define_insn "cosdf2"
2956 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2957 ; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
2959 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2961 ;[(set_attr "type" "float_em")])
2963 ;(define_insn "*cosdf_esfdf"
2964 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2965 ; (unspec:DF [(float_extend:DF
2966 ; (match_operand:SF 1 "s_register_operand" "f"))]
2968 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2970 ;[(set_attr "type" "float_em")])
2972 ;(define_insn "cosxf2"
2973 ; [(set (match_operand:XF 0 "s_register_operand" "=f")
2974 ; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
2976 ; "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2978 ;[(set_attr "type" "float_em")])
2980 (define_insn_and_split "one_cmpldi2"
2981 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2982 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2985 "TARGET_ARM && reload_completed"
2986 [(set (match_dup 0) (not:SI (match_dup 1)))
2987 (set (match_dup 2) (not:SI (match_dup 3)))]
2990 operands[2] = gen_highpart (SImode, operands[0]);
2991 operands[0] = gen_lowpart (SImode, operands[0]);
2992 operands[3] = gen_highpart (SImode, operands[1]);
2993 operands[1] = gen_lowpart (SImode, operands[1]);
2995 [(set_attr "length" "8")
2996 (set_attr "predicable" "yes")]
2999 (define_expand "one_cmplsi2"
3000 [(set (match_operand:SI 0 "s_register_operand" "")
3001 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3006 (define_insn "*arm_one_cmplsi2"
3007 [(set (match_operand:SI 0 "s_register_operand" "=r")
3008 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
3011 [(set_attr "predicable" "yes")]
3014 (define_insn "*thumb_one_cmplsi2"
3015 [(set (match_operand:SI 0 "register_operand" "=l")
3016 (not:SI (match_operand:SI 1 "register_operand" "l")))]
3019 [(set_attr "length" "2")]
3022 (define_insn "*notsi_compare0"
3023 [(set (reg:CC_NOOV CC_REGNUM)
3024 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3026 (set (match_operand:SI 0 "s_register_operand" "=r")
3027 (not:SI (match_dup 1)))]
3030 [(set_attr "conds" "set")]
3033 (define_insn "*notsi_compare0_scratch"
3034 [(set (reg:CC_NOOV CC_REGNUM)
3035 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3037 (clobber (match_scratch:SI 0 "=r"))]
3040 [(set_attr "conds" "set")]
3043 ;; Fixed <--> Floating conversion insns
3045 (define_insn "floatsisf2"
3046 [(set (match_operand:SF 0 "s_register_operand" "=f")
3047 (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
3048 "TARGET_ARM && TARGET_HARD_FLOAT"
3050 [(set_attr "type" "r_2_f")
3051 (set_attr "predicable" "yes")]
3054 (define_insn "floatsidf2"
3055 [(set (match_operand:DF 0 "s_register_operand" "=f")
3056 (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
3057 "TARGET_ARM && TARGET_HARD_FLOAT"
3059 [(set_attr "type" "r_2_f")
3060 (set_attr "predicable" "yes")]
3063 (define_insn "floatsixf2"
3064 [(set (match_operand:XF 0 "s_register_operand" "=f")
3065 (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
3066 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3068 [(set_attr "type" "r_2_f")
3069 (set_attr "predicable" "yes")]
3072 (define_insn "fix_truncsfsi2"
3073 [(set (match_operand:SI 0 "s_register_operand" "=r")
3074 (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
3075 "TARGET_ARM && TARGET_HARD_FLOAT"
3077 [(set_attr "type" "f_2_r")
3078 (set_attr "predicable" "yes")]
3081 (define_insn "fix_truncdfsi2"
3082 [(set (match_operand:SI 0 "s_register_operand" "=r")
3083 (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
3084 "TARGET_ARM && TARGET_HARD_FLOAT"
3086 [(set_attr "type" "f_2_r")
3087 (set_attr "predicable" "yes")]
3090 (define_insn "fix_truncxfsi2"
3091 [(set (match_operand:SI 0 "s_register_operand" "=r")
3092 (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
3093 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3095 [(set_attr "type" "f_2_r")
3096 (set_attr "predicable" "yes")]
3101 (define_insn "truncdfsf2"
3102 [(set (match_operand:SF 0 "s_register_operand" "=f")
3104 (match_operand:DF 1 "s_register_operand" "f")))]
3105 "TARGET_ARM && TARGET_HARD_FLOAT"
3107 [(set_attr "type" "ffarith")
3108 (set_attr "predicable" "yes")]
3111 (define_insn "truncxfsf2"
3112 [(set (match_operand:SF 0 "s_register_operand" "=f")
3114 (match_operand:XF 1 "s_register_operand" "f")))]
3115 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3117 [(set_attr "type" "ffarith")
3118 (set_attr "predicable" "yes")]
3121 (define_insn "truncxfdf2"
3122 [(set (match_operand:DF 0 "s_register_operand" "=f")
3124 (match_operand:XF 1 "s_register_operand" "f")))]
3125 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3127 [(set_attr "type" "ffarith")
3128 (set_attr "predicable" "yes")]
3131 ;; Zero and sign extension instructions.
3133 (define_insn "zero_extendsidi2"
3134 [(set (match_operand:DI 0 "s_register_operand" "=r")
3135 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3138 if (REGNO (operands[1])
3139 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3140 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3141 return \"mov%?\\t%R0, #0\";
3143 [(set_attr "length" "8")
3144 (set_attr "predicable" "yes")]
3147 (define_insn "zero_extendqidi2"
3148 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
3149 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3152 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3153 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3154 [(set_attr "length" "8")
3155 (set_attr "predicable" "yes")
3156 (set_attr "type" "*,load")
3157 (set_attr "pool_range" "*,4092")
3158 (set_attr "neg_pool_range" "*,4084")]
3161 (define_insn "extendsidi2"
3162 [(set (match_operand:DI 0 "s_register_operand" "=r")
3163 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3166 if (REGNO (operands[1])
3167 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3168 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3169 return \"mov%?\\t%R0, %Q0, asr #31\";
3171 [(set_attr "length" "8")
3172 (set_attr "shift" "1")
3173 (set_attr "predicable" "yes")]
3176 (define_expand "zero_extendhisi2"
3178 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3180 (set (match_operand:SI 0 "s_register_operand" "")
3181 (lshiftrt:SI (match_dup 2) (const_int 16)))]
3187 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3189 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3190 here because the insn below will generate an LDRH instruction
3191 rather than an LDR instruction, so we cannot get an unaligned
3193 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3194 gen_rtx_ZERO_EXTEND (SImode,
3198 if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3200 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3203 if (!s_register_operand (operands[1], HImode))
3204 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3205 operands[1] = gen_lowpart (SImode, operands[1]);
3206 operands[2] = gen_reg_rtx (SImode);
3208 else /* TARGET_THUMB */
3210 if (GET_CODE (operands[1]) == MEM)
3214 tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3215 tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3222 if (!s_register_operand (operands[1], HImode))
3223 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3224 operands[1] = gen_lowpart (SImode, operands[1]);
3225 operands[2] = gen_reg_rtx (SImode);
3227 ops[0] = operands[2];
3228 ops[1] = operands[1];
3229 ops[2] = GEN_INT (16);
3231 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3232 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3234 ops[0] = operands[0];
3235 ops[1] = operands[2];
3236 ops[2] = GEN_INT (16);
3238 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3239 gen_rtx_LSHIFTRT (SImode, ops[1],
3247 (define_insn "*thumb_zero_extendhisi2"
3248 [(set (match_operand:SI 0 "register_operand" "=l")
3249 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3252 rtx mem = XEXP (operands[1], 0);
3254 if (GET_CODE (mem) == CONST)
3255 mem = XEXP (mem, 0);
3257 if (GET_CODE (mem) == LABEL_REF)
3258 return \"ldr\\t%0, %1\";
3260 if (GET_CODE (mem) == PLUS)
3262 rtx a = XEXP (mem, 0);
3263 rtx b = XEXP (mem, 1);
3265 /* This can happen due to bugs in reload. */
3266 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3269 ops[0] = operands[0];
3272 output_asm_insn (\"mov %0, %1\", ops);
3274 XEXP (mem, 0) = operands[0];
3277 else if ( GET_CODE (a) == LABEL_REF
3278 && GET_CODE (b) == CONST_INT)
3279 return \"ldr\\t%0, %1\";
3282 return \"ldrh\\t%0, %1\";
3284 [(set_attr "length" "4")
3285 (set_attr "type" "load")
3286 (set_attr "pool_range" "60")]
3289 (define_insn "*arm_zero_extendhisi2"
3290 [(set (match_operand:SI 0 "s_register_operand" "=r")
3291 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3292 "TARGET_ARM && arm_arch4"
3294 [(set_attr "type" "load")
3295 (set_attr "predicable" "yes")
3296 (set_attr "pool_range" "256")
3297 (set_attr "neg_pool_range" "244")]
3301 [(set (match_operand:SI 0 "s_register_operand" "")
3302 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3303 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3304 "TARGET_ARM && (!arm_arch4)"
3305 [(set (match_dup 2) (match_dup 1))
3306 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3308 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3314 [(set (match_operand:SI 0 "s_register_operand" "")
3315 (match_operator:SI 3 "shiftable_operator"
3316 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3317 (match_operand:SI 4 "s_register_operand" "")]))
3318 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3319 "TARGET_ARM && (!arm_arch4)"
3320 [(set (match_dup 2) (match_dup 1))
3323 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3325 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3330 (define_expand "zero_extendqisi2"
3331 [(set (match_operand:SI 0 "s_register_operand" "")
3332 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3335 if (GET_CODE (operands[1]) != MEM)
3339 emit_insn (gen_andsi3 (operands[0],
3340 gen_lowpart (SImode, operands[1]),
3343 else /* TARGET_THUMB */
3345 rtx temp = gen_reg_rtx (SImode);
3348 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3349 operands[1] = gen_lowpart (SImode, operands[1]);
3352 ops[1] = operands[1];
3353 ops[2] = GEN_INT (24);
3355 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3356 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3358 ops[0] = operands[0];
3360 ops[2] = GEN_INT (24);
3362 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3363 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3370 (define_insn "*thumb_zero_extendqisi2"
3371 [(set (match_operand:SI 0 "register_operand" "=l")
3372 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3375 [(set_attr "length" "2")
3376 (set_attr "type" "load")
3377 (set_attr "pool_range" "32")]
3380 (define_insn "*arm_zero_extendqisi2"
3381 [(set (match_operand:SI 0 "s_register_operand" "=r")
3382 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3384 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3385 [(set_attr "type" "load")
3386 (set_attr "predicable" "yes")
3387 (set_attr "pool_range" "4096")
3388 (set_attr "neg_pool_range" "4084")]
3392 [(set (match_operand:SI 0 "s_register_operand" "")
3393 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3394 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3395 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3396 [(set (match_dup 2) (match_dup 1))
3397 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3401 (define_insn "*compareqi_eq0"
3402 [(set (reg:CC_Z CC_REGNUM)
3403 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3407 [(set_attr "conds" "set")]
3410 (define_expand "extendhisi2"
3412 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3414 (set (match_operand:SI 0 "s_register_operand" "")
3415 (ashiftrt:SI (match_dup 2)
3420 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3422 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3423 here because the insn below will generate an LDRH instruction
3424 rather than an LDR instruction, so we cannot get an unaligned
3426 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3427 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3431 if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3433 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3436 if (!s_register_operand (operands[1], HImode))
3437 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3438 operands[1] = gen_lowpart (SImode, operands[1]);
3439 operands[2] = gen_reg_rtx (SImode);
3445 ops[0] = operands[2];
3446 ops[1] = operands[1];
3447 ops[2] = GEN_INT (16);
3449 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3450 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3452 ops[0] = operands[0];
3453 ops[1] = operands[2];
3454 ops[2] = GEN_INT (16);
3456 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3457 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3464 (define_insn "*thumb_extendhisi2_insn"
3465 [(set (match_operand:SI 0 "register_operand" "=l")
3466 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3467 (clobber (match_scratch:SI 2 "=&l"))]
3472 rtx mem = XEXP (operands[1], 0);
3474 /* This code used to try to use 'V', and fix the address only if it was
3475 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3476 range of QImode offsets, and offsettable_address_p does a QImode
3479 if (GET_CODE (mem) == CONST)
3480 mem = XEXP (mem, 0);
3482 if (GET_CODE (mem) == LABEL_REF)
3483 return \"ldr\\t%0, %1\";
3485 if (GET_CODE (mem) == PLUS)
3487 rtx a = XEXP (mem, 0);
3488 rtx b = XEXP (mem, 1);
3490 if (GET_CODE (a) == LABEL_REF
3491 && GET_CODE (b) == CONST_INT)
3492 return \"ldr\\t%0, %1\";
3494 if (GET_CODE (b) == REG)
3495 return \"ldrsh\\t%0, %1\";
3503 ops[2] = const0_rtx;
3506 if (GET_CODE (ops[1]) != REG)
3512 ops[0] = operands[0];
3513 ops[3] = operands[2];
3514 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3517 [(set_attr "length" "4")
3518 (set_attr "type" "load")
3519 (set_attr "pool_range" "1020")]
3522 (define_expand "extendhisi2_mem"
3523 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3525 (zero_extend:SI (match_dup 7)))
3526 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3527 (set (match_operand:SI 0 "" "")
3528 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3533 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3535 mem1 = gen_rtx_MEM (QImode, addr);
3536 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3537 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3538 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3539 operands[0] = gen_lowpart (SImode, operands[0]);
3541 operands[2] = gen_reg_rtx (SImode);
3542 operands[3] = gen_reg_rtx (SImode);
3543 operands[6] = gen_reg_rtx (SImode);
3546 if (BYTES_BIG_ENDIAN)
3548 operands[4] = operands[2];
3549 operands[5] = operands[3];
3553 operands[4] = operands[3];
3554 operands[5] = operands[2];
3559 (define_insn "*arm_extendhisi_insn"
3560 [(set (match_operand:SI 0 "s_register_operand" "=r")
3561 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3562 "TARGET_ARM && arm_arch4"
3564 [(set_attr "type" "load")
3565 (set_attr "predicable" "yes")
3566 (set_attr "pool_range" "256")
3567 (set_attr "neg_pool_range" "244")]
3571 [(set (match_operand:SI 0 "s_register_operand" "")
3572 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3573 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3574 "TARGET_ARM && (!arm_arch4)"
3575 [(set (match_dup 2) (match_dup 1))
3576 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3578 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3584 [(set (match_operand:SI 0 "s_register_operand" "")
3585 (match_operator:SI 3 "shiftable_operator"
3586 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3587 (match_operand:SI 4 "s_register_operand" "")]))
3588 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3589 "TARGET_ARM && (!arm_arch4)"
3590 [(set (match_dup 2) (match_dup 1))
3593 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3594 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3599 (define_expand "extendqihi2"
3601 (ashift:SI (match_operand:QI 1 "general_operand" "")
3603 (set (match_operand:HI 0 "s_register_operand" "")
3604 (ashiftrt:SI (match_dup 2)
3609 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3611 emit_insn (gen_rtx_SET (VOIDmode,
3613 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3616 if (!s_register_operand (operands[1], QImode))
3617 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3618 operands[0] = gen_lowpart (SImode, operands[0]);
3619 operands[1] = gen_lowpart (SImode, operands[1]);
3620 operands[2] = gen_reg_rtx (SImode);
3624 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3625 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3626 (define_insn "*extendqihi_insn"
3627 [(set (match_operand:HI 0 "s_register_operand" "=r")
3628 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3629 "TARGET_ARM && arm_arch4"
3631 /* If the address is invalid, this will split the instruction into two. */
3632 if (bad_signed_byte_operand (operands[1], VOIDmode))
3634 return \"ldr%?sb\\t%0, %1\";
3636 [(set_attr "type" "load")
3637 (set_attr "predicable" "yes")
3638 (set_attr "length" "8")
3639 (set_attr "pool_range" "256")
3640 (set_attr "neg_pool_range" "244")]
3644 [(set (match_operand:HI 0 "s_register_operand" "")
3645 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3646 "TARGET_ARM && arm_arch4 && reload_completed"
3647 [(set (match_dup 3) (match_dup 1))
3648 (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3651 HOST_WIDE_INT offset;
3653 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3654 operands[2] = gen_rtx_MEM (QImode, operands[3]);
3655 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3656 operands[1] = XEXP (operands[1], 0);
3657 if (GET_CODE (operands[1]) == PLUS
3658 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3659 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3660 || const_ok_for_arm (-offset)))
3662 HOST_WIDE_INT low = (offset > 0
3663 ? (offset & 0xff) : -((-offset) & 0xff));
3664 XEXP (operands[2], 0) = plus_constant (operands[3], low);
3665 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3667 /* Ensure the sum is in correct canonical form */
3668 else if (GET_CODE (operands[1]) == PLUS
3669 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3670 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3671 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3672 XEXP (operands[1], 1),
3673 XEXP (operands[1], 0));
3677 (define_expand "extendqisi2"
3679 (ashift:SI (match_operand:QI 1 "general_operand" "")
3681 (set (match_operand:SI 0 "s_register_operand" "")
3682 (ashiftrt:SI (match_dup 2)
3687 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3689 emit_insn (gen_rtx_SET (VOIDmode,
3691 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3694 if (!s_register_operand (operands[1], QImode))
3695 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3696 operands[1] = gen_lowpart (SImode, operands[1]);
3697 operands[2] = gen_reg_rtx (SImode);
3703 ops[0] = operands[2];
3704 ops[1] = operands[1];
3705 ops[2] = GEN_INT (24);
3707 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3708 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3710 ops[0] = operands[0];
3711 ops[1] = operands[2];
3712 ops[2] = GEN_INT (24);
3714 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3715 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3722 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3723 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3724 (define_insn "*arm_extendqisi_insn"
3725 [(set (match_operand:SI 0 "s_register_operand" "=r")
3726 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3727 "TARGET_ARM && arm_arch4"
3729 /* If the address is invalid, this will split the instruction into two. */
3730 if (bad_signed_byte_operand (operands[1], VOIDmode))
3732 return \"ldr%?sb\\t%0, %1\";
3734 [(set_attr "type" "load")
3735 (set_attr "predicable" "yes")
3736 (set_attr "length" "8")
3737 (set_attr "pool_range" "256")
3738 (set_attr "neg_pool_range" "244")]
3742 [(set (match_operand:SI 0 "s_register_operand" "")
3743 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3744 "TARGET_ARM && arm_arch4 && reload_completed"
3745 [(set (match_dup 0) (match_dup 1))
3746 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3749 HOST_WIDE_INT offset;
3751 operands[2] = gen_rtx_MEM (QImode, operands[0]);
3752 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3753 operands[1] = XEXP (operands[1], 0);
3754 if (GET_CODE (operands[1]) == PLUS
3755 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3756 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3757 || const_ok_for_arm (-offset)))
3759 HOST_WIDE_INT low = (offset > 0
3760 ? (offset & 0xff) : -((-offset) & 0xff));
3761 XEXP (operands[2], 0) = plus_constant (operands[0], low);
3762 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3764 /* Ensure the sum is in correct canonical form */
3765 else if (GET_CODE (operands[1]) == PLUS
3766 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3767 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3768 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3769 XEXP (operands[1], 1),
3770 XEXP (operands[1], 0));
3774 (define_insn "*thumb_extendqisi2_insn"
3775 [(set (match_operand:SI 0 "register_operand" "=l,l")
3776 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3781 rtx mem = XEXP (operands[1], 0);
3783 if (GET_CODE (mem) == CONST)
3784 mem = XEXP (mem, 0);
3786 if (GET_CODE (mem) == LABEL_REF)
3787 return \"ldr\\t%0, %1\";
3789 if (GET_CODE (mem) == PLUS
3790 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3791 return \"ldr\\t%0, %1\";
3793 if (which_alternative == 0)
3794 return \"ldrsb\\t%0, %1\";
3796 ops[0] = operands[0];
3798 if (GET_CODE (mem) == PLUS)
3800 rtx a = XEXP (mem, 0);
3801 rtx b = XEXP (mem, 1);
3806 if (GET_CODE (a) == REG)
3808 if (GET_CODE (b) == REG)
3809 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3810 else if (REGNO (a) == REGNO (ops[0]))
3812 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3813 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3814 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3817 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3819 else if (GET_CODE (b) != REG)
3823 if (REGNO (b) == REGNO (ops[0]))
3825 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3826 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3827 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3830 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3833 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3835 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3836 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3837 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3842 ops[2] = const0_rtx;
3844 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3848 [(set_attr "length" "2,6")
3849 (set_attr "type" "load,load")
3850 (set_attr "pool_range" "32,32")]
3853 (define_insn "extendsfdf2"
3854 [(set (match_operand:DF 0 "s_register_operand" "=f")
3855 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
3856 "TARGET_ARM && TARGET_HARD_FLOAT"
3858 [(set_attr "type" "ffarith")
3859 (set_attr "predicable" "yes")]
3862 (define_insn "extendsfxf2"
3863 [(set (match_operand:XF 0 "s_register_operand" "=f")
3864 (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
3865 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3867 [(set_attr "type" "ffarith")
3868 (set_attr "predicable" "yes")]
3871 (define_insn "extenddfxf2"
3872 [(set (match_operand:XF 0 "s_register_operand" "=f")
3873 (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
3874 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3876 [(set_attr "type" "ffarith")
3877 (set_attr "predicable" "yes")]
3881 ;; Move insns (including loads and stores)
3883 ;; XXX Just some ideas about movti.
3884 ;; I don't think these are a good idea on the arm, there just aren't enough
3886 ;;(define_expand "loadti"
3887 ;; [(set (match_operand:TI 0 "s_register_operand" "")
3888 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
3891 ;;(define_expand "storeti"
3892 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3893 ;; (match_operand:TI 1 "s_register_operand" ""))]
3896 ;;(define_expand "movti"
3897 ;; [(set (match_operand:TI 0 "general_operand" "")
3898 ;; (match_operand:TI 1 "general_operand" ""))]
3904 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3905 ;; operands[1] = copy_to_reg (operands[1]);
3906 ;; if (GET_CODE (operands[0]) == MEM)
3907 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3908 ;; else if (GET_CODE (operands[1]) == MEM)
3909 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3913 ;; emit_insn (insn);
3917 ;; Recognize garbage generated above.
3920 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3921 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3925 ;; register mem = (which_alternative < 3);
3926 ;; register const char *template;
3928 ;; operands[mem] = XEXP (operands[mem], 0);
3929 ;; switch (which_alternative)
3931 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3932 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
3933 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
3934 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
3935 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
3936 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
3938 ;; output_asm_insn (template, operands);
3942 (define_expand "movdi"
3943 [(set (match_operand:DI 0 "general_operand" "")
3944 (match_operand:DI 1 "general_operand" ""))]
3949 if (!no_new_pseudos)
3951 if (GET_CODE (operands[0]) != REG)
3952 operands[1] = force_reg (DImode, operands[1]);
3958 (define_insn "*arm_movdi"
3959 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3960 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
3963 return (output_move_double (operands));
3965 [(set_attr "length" "8")
3966 (set_attr "type" "*,load,store2")
3967 (set_attr "pool_range" "*,1020,*")
3968 (set_attr "neg_pool_range" "*,1008,*")]
3971 ;;; ??? This should have alternatives for constants.
3972 ;;; ??? This was originally identical to the movdf_insn pattern.
3973 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3974 ;;; thumb_reorg with a memory reference.
3975 (define_insn "*thumb_movdi_insn"
3976 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3977 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
3979 && ( register_operand (operands[0], DImode)
3980 || register_operand (operands[1], DImode))"
3983 switch (which_alternative)
3987 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3988 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
3989 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
3991 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3993 operands[1] = GEN_INT (- INTVAL (operands[1]));
3994 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3996 return \"ldmia\\t%1, {%0, %H0}\";
3998 return \"stmia\\t%0, {%1, %H1}\";
4000 return thumb_load_double_from_address (operands);
4002 operands[2] = gen_rtx (MEM, SImode,
4003 plus_constant (XEXP (operands[0], 0), 4));
4004 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4007 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4008 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4009 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4012 [(set_attr "length" "4,4,6,2,2,6,4,4")
4013 (set_attr "type" "*,*,*,load,store2,load,store2,*")
4014 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4017 (define_expand "movsi"
4018 [(set (match_operand:SI 0 "general_operand" "")
4019 (match_operand:SI 1 "general_operand" ""))]
4024 /* Everything except mem = const or mem = mem can be done easily */
4025 if (GET_CODE (operands[0]) == MEM)
4026 operands[1] = force_reg (SImode, operands[1]);
4027 if (GET_CODE (operands[1]) == CONST_INT
4028 && !(const_ok_for_arm (INTVAL (operands[1]))
4029 || const_ok_for_arm (~INTVAL (operands[1]))))
4031 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4034 : preserve_subexpressions_p ()));
4038 else /* TARGET_THUMB.... */
4040 if (!no_new_pseudos)
4042 if (GET_CODE (operands[0]) != REG)
4043 operands[1] = force_reg (SImode, operands[1]);
4048 && (CONSTANT_P (operands[1])
4049 || symbol_mentioned_p (operands[1])
4050 || label_mentioned_p (operands[1])))
4051 operands[1] = legitimize_pic_address (operands[1], SImode,
4052 (no_new_pseudos ? operands[0] : 0));
4056 (define_insn "*arm_movsi_insn"
4057 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4058 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
4060 && ( register_operand (operands[0], SImode)
4061 || register_operand (operands[1], SImode))"
4067 [(set_attr "type" "*,*,load,store1")
4068 (set_attr "predicable" "yes")
4069 (set_attr "pool_range" "*,*,4096,*")
4070 (set_attr "neg_pool_range" "*,*,4084,*")]
4074 [(set (match_operand:SI 0 "s_register_operand" "")
4075 (match_operand:SI 1 "const_int_operand" ""))]
4077 && (!(const_ok_for_arm (INTVAL (operands[1]))
4078 || const_ok_for_arm (~INTVAL (operands[1]))))"
4079 [(clobber (const_int 0))]
4081 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4087 (define_insn "*thumb_movsi_insn"
4088 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4089 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
4091 && ( register_operand (operands[0], SImode)
4092 || register_operand (operands[1], SImode))"
4103 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4104 (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
4105 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4109 [(set (match_operand:SI 0 "register_operand" "")
4110 (match_operand:SI 1 "const_int_operand" ""))]
4111 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4112 [(set (match_dup 0) (match_dup 1))
4113 (set (match_dup 0) (neg:SI (match_dup 0)))]
4114 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4118 [(set (match_operand:SI 0 "register_operand" "")
4119 (match_operand:SI 1 "const_int_operand" ""))]
4120 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4121 [(set (match_dup 0) (match_dup 1))
4122 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4125 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4126 unsigned HOST_WIDE_INT mask = 0xff;
4129 for (i = 0; i < 25; i++)
4130 if ((val & (mask << i)) == val)
4133 /* Shouldn't happen, but we don't want to split if the shift is zero. */
4137 operands[1] = GEN_INT (val >> i);
4138 operands[2] = GEN_INT (i);
4142 ;; When generating pic, we need to load the symbol offset into a register.
4143 ;; So that the optimizer does not confuse this with a normal symbol load
4144 ;; we use an unspec. The offset will be loaded from a constant pool entry,
4145 ;; since that is the only type of relocation we can use.
4147 ;; The rather odd constraints on the following are to force reload to leave
4148 ;; the insn alone, and to force the minipool generation pass to then move
4149 ;; the GOT symbol to memory.
4151 (define_insn "pic_load_addr_arm"
4152 [(set (match_operand:SI 0 "s_register_operand" "=r")
4153 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4154 "TARGET_ARM && flag_pic"
4156 [(set_attr "type" "load")
4157 (set (attr "pool_range") (const_int 4096))
4158 (set (attr "neg_pool_range") (const_int 4084))]
4161 (define_insn "pic_load_addr_thumb"
4162 [(set (match_operand:SI 0 "s_register_operand" "=l")
4163 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4164 "TARGET_THUMB && flag_pic"
4166 [(set_attr "type" "load")
4167 (set (attr "pool_range") (const_int 1024))]
4170 ;; This variant is used for AOF assembly, since it needs to mention the
4171 ;; pic register in the rtl.
4172 (define_expand "pic_load_addr_based"
4173 [(set (match_operand:SI 0 "s_register_operand" "=r")
4174 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4175 "TARGET_ARM && flag_pic"
4176 "operands[2] = pic_offset_table_rtx;"
4179 (define_insn "*pic_load_addr_based_insn"
4180 [(set (match_operand:SI 0 "s_register_operand" "=r")
4181 (unspec:SI [(match_operand 1 "" "")
4182 (match_operand 2 "s_register_operand" "r")]
4184 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4186 #ifdef AOF_ASSEMBLER
4187 operands[1] = aof_pic_entry (operands[1]);
4189 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4192 [(set_attr "type" "load")
4193 (set (attr "pool_range")
4194 (if_then_else (eq_attr "is_thumb" "yes")
4197 (set (attr "neg_pool_range")
4198 (if_then_else (eq_attr "is_thumb" "yes")
4203 (define_insn "pic_add_dot_plus_four"
4204 [(set (match_operand:SI 0 "register_operand" "+r")
4205 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
4206 (use (label_ref (match_operand 1 "" "")))]
4207 "TARGET_THUMB && flag_pic"
4209 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4210 CODE_LABEL_NUMBER (operands[1]));
4211 return \"add\\t%0, %|pc\";
4213 [(set_attr "length" "2")]
4216 (define_insn "pic_add_dot_plus_eight"
4217 [(set (match_operand:SI 0 "register_operand" "+r")
4218 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
4219 (use (label_ref (match_operand 1 "" "")))]
4220 "TARGET_ARM && flag_pic"
4222 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4223 CODE_LABEL_NUMBER (operands[1]));
4224 return \"add%?\\t%0, %|pc, %0\";
4226 [(set_attr "predicable" "yes")]
4229 (define_expand "builtin_setjmp_receiver"
4230 [(label_ref (match_operand 0 "" ""))]
4234 arm_finalize_pic (0);
4238 ;; If copying one reg to another we can set the condition codes according to
4239 ;; its value. Such a move is common after a return from subroutine and the
4240 ;; result is being tested against zero.
4242 (define_insn "*movsi_compare0"
4243 [(set (reg:CC CC_REGNUM)
4244 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4246 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4251 sub%?s\\t%0, %1, #0"
4252 [(set_attr "conds" "set")]
4255 ;; Subroutine to store a half word from a register into memory.
4256 ;; Operand 0 is the source register (HImode)
4257 ;; Operand 1 is the destination address in a register (SImode)
4259 ;; In both this routine and the next, we must be careful not to spill
4260 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4261 ;; can generate unrecognizable rtl.
4263 (define_expand "storehi"
4264 [;; store the low byte
4265 (set (match_operand 1 "" "") (match_dup 3))
4266 ;; extract the high byte
4268 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4269 ;; store the high byte
4270 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
4274 rtx op1 = operands[1];
4275 rtx addr = XEXP (op1, 0);
4276 enum rtx_code code = GET_CODE (addr);
4278 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4280 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4282 operands[4] = adjust_address (op1, QImode, 1);
4283 operands[1] = adjust_address (operands[1], QImode, 0);
4284 operands[3] = gen_lowpart (QImode, operands[0]);
4285 operands[0] = gen_lowpart (SImode, operands[0]);
4286 operands[2] = gen_reg_rtx (SImode);
4290 (define_expand "storehi_bigend"
4291 [(set (match_dup 4) (match_dup 3))
4293 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4294 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 3))]
4298 rtx op1 = operands[1];
4299 rtx addr = XEXP (op1, 0);
4300 enum rtx_code code = GET_CODE (addr);
4302 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4304 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4306 operands[4] = adjust_address (op1, QImode, 1);
4307 operands[1] = adjust_address (operands[1], QImode, 0);
4308 operands[3] = gen_lowpart (QImode, operands[0]);
4309 operands[0] = gen_lowpart (SImode, operands[0]);
4310 operands[2] = gen_reg_rtx (SImode);
4314 ;; Subroutine to store a half word integer constant into memory.
4315 (define_expand "storeinthi"
4316 [(set (match_operand 0 "" "")
4317 (subreg:QI (match_operand 1 "" "") 0))
4318 (set (match_dup 3) (match_dup 2))]
4322 HOST_WIDE_INT value = INTVAL (operands[1]);
4323 rtx addr = XEXP (operands[0], 0);
4324 rtx op0 = operands[0];
4325 enum rtx_code code = GET_CODE (addr);
4327 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4329 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4331 operands[1] = gen_reg_rtx (SImode);
4332 if (BYTES_BIG_ENDIAN)
4334 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4335 if ((value & 255) == ((value >> 8) & 255))
4336 operands[2] = operands[1];
4339 operands[2] = gen_reg_rtx (SImode);
4340 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4345 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4346 if ((value & 255) == ((value >> 8) & 255))
4347 operands[2] = operands[1];
4350 operands[2] = gen_reg_rtx (SImode);
4351 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4355 operands[3] = adjust_address (op0, QImode, 1);
4356 operands[0] = adjust_address (operands[0], QImode, 0);
4357 operands[2] = gen_lowpart (QImode, operands[2]);
4361 (define_expand "storehi_single_op"
4362 [(set (match_operand:HI 0 "memory_operand" "")
4363 (match_operand:HI 1 "general_operand" ""))]
4364 "TARGET_ARM && arm_arch4"
4366 if (!s_register_operand (operands[1], HImode))
4367 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4371 (define_expand "movhi"
4372 [(set (match_operand:HI 0 "general_operand" "")
4373 (match_operand:HI 1 "general_operand" ""))]
4378 if (!no_new_pseudos)
4380 if (GET_CODE (operands[0]) == MEM)
4384 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4387 if (GET_CODE (operands[1]) == CONST_INT)
4388 emit_insn (gen_storeinthi (operands[0], operands[1]));
4391 if (GET_CODE (operands[1]) == MEM)
4392 operands[1] = force_reg (HImode, operands[1]);
4393 if (BYTES_BIG_ENDIAN)
4394 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4396 emit_insn (gen_storehi (operands[1], operands[0]));
4400 /* Sign extend a constant, and keep it in an SImode reg. */
4401 else if (GET_CODE (operands[1]) == CONST_INT)
4403 rtx reg = gen_reg_rtx (SImode);
4404 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4406 /* If the constant is already valid, leave it alone. */
4407 if (!const_ok_for_arm (val))
4409 /* If setting all the top bits will make the constant
4410 loadable in a single instruction, then set them.
4411 Otherwise, sign extend the number. */
4413 if (const_ok_for_arm (~(val | ~0xffff)))
4415 else if (val & 0x8000)
4419 emit_insn (gen_movsi (reg, GEN_INT (val)));
4420 operands[1] = gen_lowpart (HImode, reg);
4422 else if (arm_arch4 && !no_new_pseudos && optimize > 0
4423 && GET_CODE (operands[1]) == MEM)
4425 rtx reg = gen_reg_rtx (SImode);
4427 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4428 operands[1] = gen_lowpart (HImode, reg);
4430 else if (!arm_arch4)
4432 /* Note: We do not have to worry about TARGET_MMU_TRAPS
4433 for v4 and up architectures because LDRH instructions will
4434 be used to access the HI values, and these cannot generate
4435 unaligned word access faults in the MMU. */
4436 if (GET_CODE (operands[1]) == MEM)
4438 if (TARGET_MMU_TRAPS)
4441 rtx offset = const0_rtx;
4442 rtx reg = gen_reg_rtx (SImode);
4444 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4445 || (GET_CODE (base) == PLUS
4446 && (GET_CODE (offset = XEXP (base, 1))
4448 && ((INTVAL(offset) & 1) != 1)
4449 && GET_CODE (base = XEXP (base, 0)) == REG))
4450 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4452 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4455 new = gen_rtx_MEM (SImode,
4456 plus_constant (base, new_offset));
4457 MEM_COPY_ATTRIBUTES (new, operands[1]);
4458 emit_insn (gen_movsi (reg, new));
4459 if (((INTVAL (offset) & 2) != 0)
4460 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4462 rtx reg2 = gen_reg_rtx (SImode);
4464 emit_insn (gen_lshrsi3 (reg2, reg,
4470 emit_insn (gen_movhi_bytes (reg, operands[1]));
4472 operands[1] = gen_lowpart (HImode, reg);
4474 else if (BYTES_BIG_ENDIAN)
4477 rtx offset = const0_rtx;
4479 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4480 || (GET_CODE (base) == PLUS
4481 && (GET_CODE (offset = XEXP (base, 1))
4483 && GET_CODE (base = XEXP (base, 0)) == REG))
4484 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4486 rtx reg = gen_reg_rtx (SImode);
4489 if ((INTVAL (offset) & 2) == 2)
4491 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4492 new = gen_rtx_MEM (SImode,
4493 plus_constant (base,
4495 MEM_COPY_ATTRIBUTES (new, operands[1]);
4496 emit_insn (gen_movsi (reg, new));
4500 new = gen_rtx_MEM (SImode,
4501 XEXP (operands[1], 0));
4502 MEM_COPY_ATTRIBUTES (new, operands[1]);
4503 emit_insn (gen_rotated_loadsi (reg, new));
4506 operands[1] = gen_lowpart (HImode, reg);
4510 emit_insn (gen_movhi_bigend (operands[0],
4518 /* Handle loading a large integer during reload */
4519 else if (GET_CODE (operands[1]) == CONST_INT
4520 && !const_ok_for_arm (INTVAL (operands[1]))
4521 && !const_ok_for_arm (~INTVAL (operands[1])))
4523 /* Writing a constant to memory needs a scratch, which should
4524 be handled with SECONDARY_RELOADs. */
4525 if (GET_CODE (operands[0]) != REG)
4528 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4529 emit_insn (gen_movsi (operands[0], operands[1]));
4533 else /* TARGET_THUMB */
4535 if (!no_new_pseudos)
4537 if (GET_CODE (operands[0]) != REG)
4538 operands[1] = force_reg (HImode, operands[1]);
4540 /* ??? We shouldn't really get invalid addresses here, but this can
4541 happen if we are passed a SP (never OK for HImode/QImode) or
4542 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4543 HImode/QImode) relative address. */
4544 /* ??? This should perhaps be fixed elsewhere, for instance, in
4545 fixup_stack_1, by checking for other kinds of invalid addresses,
4546 e.g. a bare reference to a virtual register. This may confuse the
4547 alpha though, which must handle this case differently. */
4548 if (GET_CODE (operands[0]) == MEM
4549 && !memory_address_p (GET_MODE (operands[0]),
4550 XEXP (operands[0], 0)))
4552 = replace_equiv_address (operands[0],
4553 copy_to_reg (XEXP (operands[0], 0)));
4555 if (GET_CODE (operands[1]) == MEM
4556 && !memory_address_p (GET_MODE (operands[1]),
4557 XEXP (operands[1], 0)))
4559 = replace_equiv_address (operands[1],
4560 copy_to_reg (XEXP (operands[1], 0)));
4562 /* Handle loading a large integer during reload */
4563 else if (GET_CODE (operands[1]) == CONST_INT
4564 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4566 /* Writing a constant to memory needs a scratch, which should
4567 be handled with SECONDARY_RELOADs. */
4568 if (GET_CODE (operands[0]) != REG)
4571 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4572 emit_insn (gen_movsi (operands[0], operands[1]));
4579 (define_insn "*thumb_movhi_insn"
4580 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4581 (match_operand:HI 1 "general_operand" "l,mn,l,*h,*r,I"))]
4583 && ( register_operand (operands[0], HImode)
4584 || register_operand (operands[1], HImode))"
4586 switch (which_alternative)
4588 case 0: return \"add %0, %1, #0\";
4589 case 2: return \"strh %1, %0\";
4590 case 3: return \"mov %0, %1\";
4591 case 4: return \"mov %0, %1\";
4592 case 5: return \"mov %0, %1\";
4595 /* The stack pointer can end up being taken as an index register.
4596 Catch this case here and deal with it. */
4597 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4598 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4599 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4602 ops[0] = operands[0];
4603 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4605 output_asm_insn (\"mov %0, %1\", ops);
4607 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4610 return \"ldrh %0, %1\";
4612 [(set_attr "length" "2,4,2,2,2,2")
4613 (set_attr "type" "*,load,store1,*,*,*")
4614 (set_attr "pool_range" "*,64,*,*,*,*")]
4618 (define_insn "rotated_loadsi"
4619 [(set (match_operand:SI 0 "s_register_operand" "=r")
4620 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4622 "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4627 ops[0] = operands[0];
4628 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4629 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4632 [(set_attr "type" "load")
4633 (set_attr "predicable" "yes")]
4636 (define_expand "movhi_bytes"
4637 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4639 (zero_extend:SI (match_dup 6)))
4640 (set (match_operand:SI 0 "" "")
4641 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4646 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4648 mem1 = gen_rtx_MEM (QImode, addr);
4649 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4650 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4651 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4652 operands[0] = gen_lowpart (SImode, operands[0]);
4654 operands[2] = gen_reg_rtx (SImode);
4655 operands[3] = gen_reg_rtx (SImode);
4658 if (BYTES_BIG_ENDIAN)
4660 operands[4] = operands[2];
4661 operands[5] = operands[3];
4665 operands[4] = operands[3];
4666 operands[5] = operands[2];
4671 (define_expand "movhi_bigend"
4673 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4676 (ashiftrt:SI (match_dup 2) (const_int 16)))
4677 (set (match_operand:HI 0 "s_register_operand" "")
4678 (subreg:HI (match_dup 3) 0))]
4681 operands[2] = gen_reg_rtx (SImode);
4682 operands[3] = gen_reg_rtx (SImode);
4686 ;; Pattern to recognize insn generated default case above
4687 (define_insn "*movhi_insn_arch4"
4688 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4689 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4692 && (GET_CODE (operands[1]) != CONST_INT
4693 || const_ok_for_arm (INTVAL (operands[1]))
4694 || const_ok_for_arm (~INTVAL (operands[1])))"
4696 mov%?\\t%0, %1\\t%@ movhi
4697 mvn%?\\t%0, #%B1\\t%@ movhi
4698 str%?h\\t%1, %0\\t%@ movhi
4699 ldr%?h\\t%0, %1\\t%@ movhi"
4700 [(set_attr "type" "*,*,store1,load")
4701 (set_attr "predicable" "yes")
4702 (set_attr "pool_range" "*,*,*,256")
4703 (set_attr "neg_pool_range" "*,*,*,244")]
4706 (define_insn "*movhi_insn_littleend"
4707 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4708 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4711 && !BYTES_BIG_ENDIAN
4712 && !TARGET_MMU_TRAPS
4713 && (GET_CODE (operands[1]) != CONST_INT
4714 || const_ok_for_arm (INTVAL (operands[1]))
4715 || const_ok_for_arm (~INTVAL (operands[1])))"
4717 mov%?\\t%0, %1\\t%@ movhi
4718 mvn%?\\t%0, #%B1\\t%@ movhi
4719 ldr%?\\t%0, %1\\t%@ movhi"
4720 [(set_attr "type" "*,*,load")
4721 (set_attr "predicable" "yes")
4722 (set_attr "pool_range" "4096")
4723 (set_attr "neg_pool_range" "4084")]
4726 (define_insn "*movhi_insn_bigend"
4727 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4728 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4732 && !TARGET_MMU_TRAPS
4733 && (GET_CODE (operands[1]) != CONST_INT
4734 || const_ok_for_arm (INTVAL (operands[1]))
4735 || const_ok_for_arm (~INTVAL (operands[1])))"
4737 mov%?\\t%0, %1\\t%@ movhi
4738 mvn%?\\t%0, #%B1\\t%@ movhi
4739 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4740 [(set_attr "type" "*,*,load")
4741 (set_attr "predicable" "yes")
4742 (set_attr "length" "4,4,8")
4743 (set_attr "pool_range" "*,*,4092")
4744 (set_attr "neg_pool_range" "*,*,4084")]
4747 (define_insn "*loadhi_si_bigend"
4748 [(set (match_operand:SI 0 "s_register_operand" "=r")
4749 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
4753 && !TARGET_MMU_TRAPS"
4754 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4755 [(set_attr "type" "load")
4756 (set_attr "predicable" "yes")
4757 (set_attr "pool_range" "4096")
4758 (set_attr "neg_pool_range" "4084")]
4761 (define_insn "*movhi_bytes"
4762 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4763 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4764 "TARGET_ARM && TARGET_MMU_TRAPS"
4766 mov%?\\t%0, %1\\t%@ movhi
4767 mvn%?\\t%0, #%B1\\t%@ movhi"
4768 [(set_attr "predicable" "yes")]
4771 (define_insn "thumb_movhi_clobber"
4772 [(set (match_operand:HI 0 "memory_operand" "=m")
4773 (match_operand:HI 1 "register_operand" "l"))
4774 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4780 ;; We use a DImode scratch because we may occasionally need an additional
4781 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4782 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4783 (define_expand "reload_outhi"
4784 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4785 (match_operand:HI 1 "s_register_operand" "r")
4786 (match_operand:DI 2 "s_register_operand" "=&l")])]
4789 arm_reload_out_hi (operands);
4791 thumb_reload_out_hi (operands);
4796 (define_expand "reload_inhi"
4797 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4798 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4799 (match_operand:DI 2 "s_register_operand" "=&r")])]
4800 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4803 arm_reload_in_hi (operands);
4805 thumb_reload_out_hi (operands);
4809 (define_expand "movqi"
4810 [(set (match_operand:QI 0 "general_operand" "")
4811 (match_operand:QI 1 "general_operand" ""))]
4816 /* Everything except mem = const or mem = mem can be done easily */
4818 if (!no_new_pseudos)
4820 if (GET_CODE (operands[1]) == CONST_INT)
4822 rtx reg = gen_reg_rtx (SImode);
4824 emit_insn (gen_movsi (reg, operands[1]));
4825 operands[1] = gen_lowpart (QImode, reg);
4827 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4829 rtx reg = gen_reg_rtx (SImode);
4831 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4832 operands[1] = gen_lowpart (QImode, reg);
4834 if (GET_CODE (operands[0]) == MEM)
4835 operands[1] = force_reg (QImode, operands[1]);
4838 else /* TARGET_THUMB */
4840 if (!no_new_pseudos)
4842 if (GET_CODE (operands[0]) != REG)
4843 operands[1] = force_reg (QImode, operands[1]);
4845 /* ??? We shouldn't really get invalid addresses here, but this can
4846 happen if we are passed a SP (never OK for HImode/QImode) or
4847 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4848 HImode/QImode) relative address. */
4849 /* ??? This should perhaps be fixed elsewhere, for instance, in
4850 fixup_stack_1, by checking for other kinds of invalid addresses,
4851 e.g. a bare reference to a virtual register. This may confuse the
4852 alpha though, which must handle this case differently. */
4853 if (GET_CODE (operands[0]) == MEM
4854 && !memory_address_p (GET_MODE (operands[0]),
4855 XEXP (operands[0], 0)))
4857 = replace_equiv_address (operands[0],
4858 copy_to_reg (XEXP (operands[0], 0)));
4859 if (GET_CODE (operands[1]) == MEM
4860 && !memory_address_p (GET_MODE (operands[1]),
4861 XEXP (operands[1], 0)))
4863 = replace_equiv_address (operands[1],
4864 copy_to_reg (XEXP (operands[1], 0)));
4866 /* Handle loading a large integer during reload */
4867 else if (GET_CODE (operands[1]) == CONST_INT
4868 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4870 /* Writing a constant to memory needs a scratch, which should
4871 be handled with SECONDARY_RELOADs. */
4872 if (GET_CODE (operands[0]) != REG)
4875 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4876 emit_insn (gen_movsi (operands[0], operands[1]));
4884 (define_insn "*arm_movqi_insn"
4885 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4886 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4888 && ( register_operand (operands[0], QImode)
4889 || register_operand (operands[1], QImode))"
4895 [(set_attr "type" "*,*,load,store1")
4896 (set_attr "predicable" "yes")]
4899 (define_insn "*thumb_movqi_insn"
4900 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4901 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
4903 && ( register_operand (operands[0], QImode)
4904 || register_operand (operands[1], QImode))"
4912 [(set_attr "length" "2")
4913 (set_attr "type" "*,load,store1,*,*,*")
4914 (set_attr "pool_range" "*,32,*,*,*,*")]
4917 (define_expand "movsf"
4918 [(set (match_operand:SF 0 "general_operand" "")
4919 (match_operand:SF 1 "general_operand" ""))]
4924 if (GET_CODE (operands[0]) == MEM)
4925 operands[1] = force_reg (SFmode, operands[1]);
4927 else /* TARGET_THUMB */
4929 if (!no_new_pseudos)
4931 if (GET_CODE (operands[0]) != REG)
4932 operands[1] = force_reg (SFmode, operands[1]);
4939 [(set (match_operand:SF 0 "nonimmediate_operand" "")
4940 (match_operand:SF 1 "immediate_operand" ""))]
4942 && !TARGET_HARD_FLOAT
4944 && GET_CODE (operands[1]) == CONST_DOUBLE"
4945 [(set (match_dup 2) (match_dup 3))]
4947 operands[2] = gen_lowpart (SImode, operands[0]);
4948 operands[3] = gen_lowpart (SImode, operands[1]);
4949 if (operands[2] == 0 || operands[3] == 0)
4954 (define_insn "*arm_movsf_hard_insn"
4955 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
4956 (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
4958 && TARGET_HARD_FLOAT
4959 && (GET_CODE (operands[0]) != MEM
4960 || register_operand (operands[1], SFmode))"
4966 str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
4967 stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
4969 ldr%?\\t%0, %1\\t%@ float
4970 str%?\\t%1, %0\\t%@ float"
4971 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
4972 (set_attr "predicable" "yes")
4974 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
4975 (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
4976 (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
4979 ;; Exactly the same as above, except that all `f' cases are deleted.
4980 ;; This is necessary to prevent reload from ever trying to use a `f' reg
4981 ;; when -msoft-float.
4983 (define_insn "*arm_movsf_soft_insn"
4984 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4985 (match_operand:SF 1 "general_operand" "r,mE,r"))]
4987 && TARGET_SOFT_FLOAT
4988 && (GET_CODE (operands[0]) != MEM
4989 || register_operand (operands[1], SFmode))"
4992 ldr%?\\t%0, %1\\t%@ float
4993 str%?\\t%1, %0\\t%@ float"
4994 [(set_attr "length" "4,4,4")
4995 (set_attr "predicable" "yes")
4996 (set_attr "type" "*,load,store1")
4997 (set_attr "pool_range" "*,4096,*")
4998 (set_attr "neg_pool_range" "*,4084,*")]
5001 ;;; ??? This should have alternatives for constants.
5002 (define_insn "*thumb_movsf_insn"
5003 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5004 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
5006 && ( register_operand (operands[0], SFmode)
5007 || register_operand (operands[1], SFmode))"
5016 [(set_attr "length" "2")
5017 (set_attr "type" "*,load,store1,load,store1,*,*")
5018 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5021 (define_expand "movdf"
5022 [(set (match_operand:DF 0 "general_operand" "")
5023 (match_operand:DF 1 "general_operand" ""))]
5028 if (GET_CODE (operands[0]) == MEM)
5029 operands[1] = force_reg (DFmode, operands[1]);
5031 else /* TARGET_THUMB */
5033 if (!no_new_pseudos)
5035 if (GET_CODE (operands[0]) != REG)
5036 operands[1] = force_reg (DFmode, operands[1]);
5042 ;; Reloading a df mode value stored in integer regs to memory can require a
5044 (define_expand "reload_outdf"
5045 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5046 (match_operand:DF 1 "s_register_operand" "r")
5047 (match_operand:SI 2 "s_register_operand" "=&r")]
5051 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5054 operands[2] = XEXP (operands[0], 0);
5055 else if (code == POST_INC || code == PRE_DEC)
5057 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5058 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5059 emit_insn (gen_movdi (operands[0], operands[1]));
5062 else if (code == PRE_INC)
5064 rtx reg = XEXP (XEXP (operands[0], 0), 0);
5066 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5069 else if (code == POST_DEC)
5070 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5072 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5073 XEXP (XEXP (operands[0], 0), 1)));
5075 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5078 if (code == POST_DEC)
5079 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5085 (define_insn "*movdf_hard_insn"
5086 [(set (match_operand:DF 0 "nonimmediate_operand"
5087 "=r,Q,r,m,r, f, f,f, m,!f,!r")
5088 (match_operand:DF 1 "general_operand"
5089 "Q, r,r,r,mF,fG,H,mF,f,r, f"))]
5091 && TARGET_HARD_FLOAT
5092 && (GET_CODE (operands[0]) != MEM
5093 || register_operand (operands[1], DFmode))"
5096 switch (which_alternative)
5099 case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
5100 case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
5101 case 2: case 3: case 4: return output_move_double (operands);
5102 case 5: return \"mvf%?d\\t%0, %1\";
5103 case 6: return \"mnf%?d\\t%0, #%N1\";
5104 case 7: return \"ldf%?d\\t%0, %1\";
5105 case 8: return \"stf%?d\\t%1, %0\";
5106 case 9: return output_mov_double_fpu_from_arm (operands);
5107 case 10: return output_mov_double_arm_from_fpu (operands);
5111 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
5112 (set_attr "predicable" "yes")
5114 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
5115 (set_attr "pool_range" "*,*,*,*,1020,*,*,1024,*,*,*")
5116 (set_attr "neg_pool_range" "*,*,*,*,1008,*,*,1008,*,*,*")]
5119 ;; Software floating point version. This is essentially the same as movdi.
5120 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
5123 (define_insn "*movdf_soft_insn"
5124 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5125 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5126 "TARGET_ARM && TARGET_SOFT_FLOAT
5128 "* return output_move_double (operands);"
5129 [(set_attr "length" "8,8,8")
5130 (set_attr "type" "*,load,store2")
5131 (set_attr "pool_range" "1020")
5132 (set_attr "neg_pool_range" "1008")]
5135 ;;; ??? This should have alternatives for constants.
5136 ;;; ??? This was originally identical to the movdi_insn pattern.
5137 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5138 ;;; thumb_reorg with a memory reference.
5139 (define_insn "*thumb_movdf_insn"
5140 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5141 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
5143 && ( register_operand (operands[0], DFmode)
5144 || register_operand (operands[1], DFmode))"
5146 switch (which_alternative)
5150 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5151 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5152 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5154 return \"ldmia\\t%1, {%0, %H0}\";
5156 return \"stmia\\t%0, {%1, %H1}\";
5158 return thumb_load_double_from_address (operands);
5160 operands[2] = gen_rtx (MEM, SImode,
5161 plus_constant (XEXP (operands[0], 0), 4));
5162 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5165 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5166 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5167 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5170 [(set_attr "length" "4,2,2,6,4,4")
5171 (set_attr "type" "*,load,store2,load,store2,*")
5172 (set_attr "pool_range" "*,*,*,1020,*,*")]
5176 (define_expand "movxf"
5177 [(set (match_operand:XF 0 "general_operand" "")
5178 (match_operand:XF 1 "general_operand" ""))]
5179 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5182 ;; Even when the XFmode patterns aren't enabled, we enable this after
5183 ;; reloading so that we can push floating point registers in the prologue.
5185 (define_insn "*movxf_hard_insn"
5186 [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
5187 (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
5188 "TARGET_ARM && TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
5190 switch (which_alternative)
5193 case 0: return \"mvf%?e\\t%0, %1\";
5194 case 1: return \"mnf%?e\\t%0, #%N1\";
5195 case 2: return \"ldf%?e\\t%0, %1\";
5196 case 3: return \"stf%?e\\t%1, %0\";
5197 case 4: return output_mov_long_double_fpu_from_arm (operands);
5198 case 5: return output_mov_long_double_arm_from_fpu (operands);
5199 case 6: return output_mov_long_double_arm_from_arm (operands);
5202 [(set_attr "length" "4,4,4,4,8,8,12")
5203 (set_attr "predicable" "yes")
5204 (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
5205 (set_attr "pool_range" "*,*,1024,*,*,*,*")
5206 (set_attr "neg_pool_range" "*,*,1004,*,*,*,*")]
5210 ;; load- and store-multiple insns
5211 ;; The arm can load/store any set of registers, provided that they are in
5212 ;; ascending order; but that is beyond GCC so stick with what it knows.
5214 (define_expand "load_multiple"
5215 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5216 (match_operand:SI 1 "" ""))
5217 (use (match_operand:SI 2 "" ""))])]
5220 /* Support only fixed point registers. */
5221 if (GET_CODE (operands[2]) != CONST_INT
5222 || INTVAL (operands[2]) > 14
5223 || INTVAL (operands[2]) < 2
5224 || GET_CODE (operands[1]) != MEM
5225 || GET_CODE (operands[0]) != REG
5226 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5227 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5231 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5232 force_reg (SImode, XEXP (operands[1], 0)),
5233 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5234 MEM_IN_STRUCT_P(operands[1]),
5235 MEM_SCALAR_P (operands[1]));
5239 ;; Load multiple with write-back
5241 (define_insn "*ldmsi_postinc4"
5242 [(match_parallel 0 "load_multiple_operation"
5243 [(set (match_operand:SI 1 "s_register_operand" "=r")
5244 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5246 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5247 (mem:SI (match_dup 2)))
5248 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5249 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5250 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5251 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5252 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5253 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5254 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5255 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5256 [(set_attr "type" "load")
5257 (set_attr "predicable" "yes")]
5260 (define_insn "*ldmsi_postinc3"
5261 [(match_parallel 0 "load_multiple_operation"
5262 [(set (match_operand:SI 1 "s_register_operand" "=r")
5263 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5265 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5266 (mem:SI (match_dup 2)))
5267 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5268 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5269 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5270 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5271 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5272 "ldm%?ia\\t%1!, {%3, %4, %5}"
5273 [(set_attr "type" "load")
5274 (set_attr "predicable" "yes")]
5277 (define_insn "*ldmsi_postinc2"
5278 [(match_parallel 0 "load_multiple_operation"
5279 [(set (match_operand:SI 1 "s_register_operand" "=r")
5280 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5282 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5283 (mem:SI (match_dup 2)))
5284 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5285 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5286 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5287 "ldm%?ia\\t%1!, {%3, %4}"
5288 [(set_attr "type" "load")
5289 (set_attr "predicable" "yes")]
5292 ;; Ordinary load multiple
5294 (define_insn "*ldmsi4"
5295 [(match_parallel 0 "load_multiple_operation"
5296 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5297 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5298 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5299 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5300 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5301 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5302 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5303 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5304 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5305 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5306 [(set_attr "type" "load")
5307 (set_attr "predicable" "yes")]
5310 (define_insn "*ldmsi3"
5311 [(match_parallel 0 "load_multiple_operation"
5312 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5313 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5314 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5315 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5316 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5317 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5318 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5319 "ldm%?ia\\t%1, {%2, %3, %4}"
5320 [(set_attr "type" "load")
5321 (set_attr "predicable" "yes")]
5324 (define_insn "*ldmsi2"
5325 [(match_parallel 0 "load_multiple_operation"
5326 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5327 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5328 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5329 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5330 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5331 "ldm%?ia\\t%1, {%2, %3}"
5332 [(set_attr "type" "load")
5333 (set_attr "predicable" "yes")]
5336 (define_expand "store_multiple"
5337 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5338 (match_operand:SI 1 "" ""))
5339 (use (match_operand:SI 2 "" ""))])]
5342 /* Support only fixed point registers */
5343 if (GET_CODE (operands[2]) != CONST_INT
5344 || INTVAL (operands[2]) > 14
5345 || INTVAL (operands[2]) < 2
5346 || GET_CODE (operands[1]) != REG
5347 || GET_CODE (operands[0]) != MEM
5348 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5349 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5353 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5354 force_reg (SImode, XEXP (operands[0], 0)),
5355 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5356 MEM_IN_STRUCT_P(operands[0]),
5357 MEM_SCALAR_P (operands[0]));
5361 ;; Store multiple with write-back
5363 (define_insn "*stmsi_postinc4"
5364 [(match_parallel 0 "store_multiple_operation"
5365 [(set (match_operand:SI 1 "s_register_operand" "=r")
5366 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5368 (set (mem:SI (match_dup 2))
5369 (match_operand:SI 3 "arm_hard_register_operand" ""))
5370 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5371 (match_operand:SI 4 "arm_hard_register_operand" ""))
5372 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5373 (match_operand:SI 5 "arm_hard_register_operand" ""))
5374 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5375 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5376 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5377 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5378 [(set_attr "predicable" "yes")
5379 (set_attr "type" "store4")]
5382 (define_insn "*stmsi_postinc3"
5383 [(match_parallel 0 "store_multiple_operation"
5384 [(set (match_operand:SI 1 "s_register_operand" "=r")
5385 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5387 (set (mem:SI (match_dup 2))
5388 (match_operand:SI 3 "arm_hard_register_operand" ""))
5389 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5390 (match_operand:SI 4 "arm_hard_register_operand" ""))
5391 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5392 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5393 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5394 "stm%?ia\\t%1!, {%3, %4, %5}"
5395 [(set_attr "predicable" "yes")
5396 (set_attr "type" "store3")]
5399 (define_insn "*stmsi_postinc2"
5400 [(match_parallel 0 "store_multiple_operation"
5401 [(set (match_operand:SI 1 "s_register_operand" "=r")
5402 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5404 (set (mem:SI (match_dup 2))
5405 (match_operand:SI 3 "arm_hard_register_operand" ""))
5406 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5407 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5408 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5409 "stm%?ia\\t%1!, {%3, %4}"
5410 [(set_attr "predicable" "yes")
5411 (set_attr "type" "store2")]
5414 ;; Ordinary store multiple
5416 (define_insn "*stmsi4"
5417 [(match_parallel 0 "store_multiple_operation"
5418 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5419 (match_operand:SI 2 "arm_hard_register_operand" ""))
5420 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5421 (match_operand:SI 3 "arm_hard_register_operand" ""))
5422 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5423 (match_operand:SI 4 "arm_hard_register_operand" ""))
5424 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5425 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5426 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5427 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5428 [(set_attr "predicable" "yes")
5429 (set_attr "type" "store4")]
5432 (define_insn "*stmsi3"
5433 [(match_parallel 0 "store_multiple_operation"
5434 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5435 (match_operand:SI 2 "arm_hard_register_operand" ""))
5436 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5437 (match_operand:SI 3 "arm_hard_register_operand" ""))
5438 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5439 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5440 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5441 "stm%?ia\\t%1, {%2, %3, %4}"
5442 [(set_attr "predicable" "yes")
5443 (set_attr "type" "store3")]
5446 (define_insn "*stmsi2"
5447 [(match_parallel 0 "store_multiple_operation"
5448 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5449 (match_operand:SI 2 "arm_hard_register_operand" ""))
5450 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5451 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5452 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5453 "stm%?ia\\t%1, {%2, %3}"
5454 [(set_attr "predicable" "yes")
5455 (set_attr "type" "store2")]
5458 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5459 ;; We could let this apply for blocks of less than this, but it clobbers so
5460 ;; many registers that there is then probably a better way.
5462 (define_expand "movstrqi"
5463 [(match_operand:BLK 0 "general_operand" "")
5464 (match_operand:BLK 1 "general_operand" "")
5465 (match_operand:SI 2 "const_int_operand" "")
5466 (match_operand:SI 3 "const_int_operand" "")]
5471 if (arm_gen_movstrqi (operands))
5475 else /* TARGET_THUMB */
5477 if ( INTVAL (operands[3]) != 4
5478 || INTVAL (operands[2]) > 48)
5481 thumb_expand_movstrqi (operands);
5487 ;; Thumb block-move insns
5489 (define_insn "movmem12b"
5490 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5491 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5492 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5493 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5494 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5495 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5496 (set (match_operand:SI 0 "register_operand" "=l")
5497 (plus:SI (match_dup 2) (const_int 12)))
5498 (set (match_operand:SI 1 "register_operand" "=l")
5499 (plus:SI (match_dup 3) (const_int 12)))
5500 (clobber (match_scratch:SI 4 "=&l"))
5501 (clobber (match_scratch:SI 5 "=&l"))
5502 (clobber (match_scratch:SI 6 "=&l"))]
5504 "* return thumb_output_move_mem_multiple (3, operands);"
5505 [(set_attr "length" "4")
5506 ; This isn't entirely accurate... It loads as well, but in terms of
5507 ; scheduling the following insn it is better to consider it as a store
5508 (set_attr "type" "store3")]
5511 (define_insn "movmem8b"
5512 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5513 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5514 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5515 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5516 (set (match_operand:SI 0 "register_operand" "=l")
5517 (plus:SI (match_dup 2) (const_int 8)))
5518 (set (match_operand:SI 1 "register_operand" "=l")
5519 (plus:SI (match_dup 3) (const_int 8)))
5520 (clobber (match_scratch:SI 4 "=&l"))
5521 (clobber (match_scratch:SI 5 "=&l"))]
5523 "* return thumb_output_move_mem_multiple (2, operands);"
5524 [(set_attr "length" "4")
5525 ; This isn't entirely accurate... It loads as well, but in terms of
5526 ; scheduling the following insn it is better to consider it as a store
5527 (set_attr "type" "store2")]
5532 ;; Compare & branch insns
5533 ;; The range calcualations are based as follows:
5534 ;; For forward branches, the address calculation returns the address of
5535 ;; the next instruction. This is 2 beyond the branch instruction.
5536 ;; For backward branches, the address calculation returns the address of
5537 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5538 ;; instruction for the shortest sequence, and 4 before the branch instruction
5539 ;; if we have to jump around an unconditional branch.
5540 ;; To the basic branch range the PC offset must be added (this is +4).
5541 ;; So for forward branches we have
5542 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5543 ;; And for backward branches we have
5544 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5546 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5547 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5549 (define_insn "cbranchsi4"
5552 (match_operator 0 "arm_comparison_operator"
5553 [(match_operand:SI 1 "register_operand" "l,r")
5554 (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5555 (label_ref (match_operand 3 "" ""))
5559 output_asm_insn (\"cmp\\t%1, %2\", operands);
5560 switch (get_attr_length (insn))
5562 case 4: return \"b%d0\\t%l3\";
5563 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5564 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5567 [(set (attr "far_jump")
5569 (eq_attr "length" "8")
5570 (const_string "yes")
5571 (const_string "no")))
5572 (set (attr "length")
5574 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5575 (le (minus (match_dup 3) (pc)) (const_int 256)))
5578 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5579 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5584 (define_insn "*negated_cbranchsi4"
5587 (match_operator 0 "arm_comparison_operator"
5588 [(match_operand:SI 1 "register_operand" "l")
5589 (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5590 (label_ref (match_operand 3 "" ""))
5594 output_asm_insn (\"cmn\\t%1, %2\", operands);
5595 switch (get_attr_length (insn))
5597 case 4: return \"b%d0\\t%l3\";
5598 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5599 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5602 [(set (attr "far_jump")
5604 (eq_attr "length" "8")
5605 (const_string "yes")
5606 (const_string "no")))
5607 (set (attr "length")
5609 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5610 (le (minus (match_dup 3) (pc)) (const_int 256)))
5613 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5614 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5620 ;; Comparison and test insns
5622 (define_expand "cmpsi"
5623 [(match_operand:SI 0 "s_register_operand" "")
5624 (match_operand:SI 1 "arm_add_operand" "")]
5627 arm_compare_op0 = operands[0];
5628 arm_compare_op1 = operands[1];
5633 (define_expand "cmpsf"
5634 [(match_operand:SF 0 "s_register_operand" "")
5635 (match_operand:SF 1 "fpu_rhs_operand" "")]
5636 "TARGET_ARM && TARGET_HARD_FLOAT"
5638 arm_compare_op0 = operands[0];
5639 arm_compare_op1 = operands[1];
5644 (define_expand "cmpdf"
5645 [(match_operand:DF 0 "s_register_operand" "")
5646 (match_operand:DF 1 "fpu_rhs_operand" "")]
5647 "TARGET_ARM && TARGET_HARD_FLOAT"
5649 arm_compare_op0 = operands[0];
5650 arm_compare_op1 = operands[1];
5655 (define_expand "cmpxf"
5656 [(match_operand:XF 0 "s_register_operand" "")
5657 (match_operand:XF 1 "fpu_rhs_operand" "")]
5658 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5660 arm_compare_op0 = operands[0];
5661 arm_compare_op1 = operands[1];
5666 (define_insn "*arm_cmpsi_insn"
5667 [(set (reg:CC CC_REGNUM)
5668 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5669 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
5674 [(set_attr "conds" "set")]
5677 (define_insn "*cmpsi_shiftsi"
5678 [(set (reg:CC CC_REGNUM)
5679 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5680 (match_operator:SI 3 "shift_operator"
5681 [(match_operand:SI 1 "s_register_operand" "r")
5682 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
5685 [(set_attr "conds" "set")
5686 (set_attr "shift" "1")
5690 (define_insn "*cmpsi_shiftsi_swp"
5691 [(set (reg:CC_SWP CC_REGNUM)
5692 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5693 [(match_operand:SI 1 "s_register_operand" "r")
5694 (match_operand:SI 2 "reg_or_int_operand" "rM")])
5695 (match_operand:SI 0 "s_register_operand" "r")))]
5698 [(set_attr "conds" "set")
5699 (set_attr "shift" "1")
5703 (define_insn "*cmpsi_neg_shiftsi"
5704 [(set (reg:CC CC_REGNUM)
5705 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5706 (neg:SI (match_operator:SI 3 "shift_operator"
5707 [(match_operand:SI 1 "s_register_operand" "r")
5708 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5711 [(set_attr "conds" "set")
5712 (set_attr "shift" "1")
5716 (define_insn "*cmpsf_insn"
5717 [(set (reg:CCFP CC_REGNUM)
5718 (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
5719 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5720 "TARGET_ARM && TARGET_HARD_FLOAT"
5724 [(set_attr "conds" "set")
5725 (set_attr "type" "f_2_r")]
5728 (define_insn "*cmpdf_insn"
5729 [(set (reg:CCFP CC_REGNUM)
5730 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
5731 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5732 "TARGET_ARM && TARGET_HARD_FLOAT"
5736 [(set_attr "conds" "set")
5737 (set_attr "type" "f_2_r")]
5740 (define_insn "*cmpesfdf_df"
5741 [(set (reg:CCFP CC_REGNUM)
5742 (compare:CCFP (float_extend:DF
5743 (match_operand:SF 0 "s_register_operand" "f,f"))
5744 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5745 "TARGET_ARM && TARGET_HARD_FLOAT"
5749 [(set_attr "conds" "set")
5750 (set_attr "type" "f_2_r")]
5753 (define_insn "*cmpdf_esfdf"
5754 [(set (reg:CCFP CC_REGNUM)
5755 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5757 (match_operand:SF 1 "s_register_operand" "f"))))]
5758 "TARGET_ARM && TARGET_HARD_FLOAT"
5760 [(set_attr "conds" "set")
5761 (set_attr "type" "f_2_r")]
5764 (define_insn "*cmpxf_insn"
5765 [(set (reg:CCFP CC_REGNUM)
5766 (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
5767 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5768 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5772 [(set_attr "conds" "set")
5773 (set_attr "type" "f_2_r")]
5776 (define_insn "*cmpsf_trap"
5777 [(set (reg:CCFPE CC_REGNUM)
5778 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
5779 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5780 "TARGET_ARM && TARGET_HARD_FLOAT"
5784 [(set_attr "conds" "set")
5785 (set_attr "type" "f_2_r")]
5788 (define_insn "*cmpdf_trap"
5789 [(set (reg:CCFPE CC_REGNUM)
5790 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
5791 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5792 "TARGET_ARM && TARGET_HARD_FLOAT"
5796 [(set_attr "conds" "set")
5797 (set_attr "type" "f_2_r")]
5800 (define_insn "*cmp_esfdf_df_trap"
5801 [(set (reg:CCFPE CC_REGNUM)
5802 (compare:CCFPE (float_extend:DF
5803 (match_operand:SF 0 "s_register_operand" "f,f"))
5804 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5805 "TARGET_ARM && TARGET_HARD_FLOAT"
5809 [(set_attr "conds" "set")
5810 (set_attr "type" "f_2_r")]
5813 (define_insn "*cmp_df_esfdf_trap"
5814 [(set (reg:CCFPE CC_REGNUM)
5815 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
5817 (match_operand:SF 1 "s_register_operand" "f"))))]
5818 "TARGET_ARM && TARGET_HARD_FLOAT"
5820 [(set_attr "conds" "set")
5821 (set_attr "type" "f_2_r")]
5824 (define_insn "*cmpxf_trap"
5825 [(set (reg:CCFPE CC_REGNUM)
5826 (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
5827 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5828 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5832 [(set_attr "conds" "set")
5833 (set_attr "type" "f_2_r")]
5836 ; This insn allows redundant compares to be removed by cse, nothing should
5837 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5838 ; is deleted later on. The match_dup will match the mode here, so that
5839 ; mode changes of the condition codes aren't lost by this even though we don't
5840 ; specify what they are.
5842 (define_insn "*deleted_compare"
5843 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5845 "\\t%@ deleted compare"
5846 [(set_attr "conds" "set")
5847 (set_attr "length" "0")]
5851 ;; Conditional branch insns
5853 (define_expand "beq"
5855 (if_then_else (eq (match_dup 1) (const_int 0))
5856 (label_ref (match_operand 0 "" ""))
5859 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5862 (define_expand "bne"
5864 (if_then_else (ne (match_dup 1) (const_int 0))
5865 (label_ref (match_operand 0 "" ""))
5868 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5871 (define_expand "bgt"
5873 (if_then_else (gt (match_dup 1) (const_int 0))
5874 (label_ref (match_operand 0 "" ""))
5877 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5880 (define_expand "ble"
5882 (if_then_else (le (match_dup 1) (const_int 0))
5883 (label_ref (match_operand 0 "" ""))
5886 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5889 (define_expand "bge"
5891 (if_then_else (ge (match_dup 1) (const_int 0))
5892 (label_ref (match_operand 0 "" ""))
5895 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5898 (define_expand "blt"
5900 (if_then_else (lt (match_dup 1) (const_int 0))
5901 (label_ref (match_operand 0 "" ""))
5904 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5907 (define_expand "bgtu"
5909 (if_then_else (gtu (match_dup 1) (const_int 0))
5910 (label_ref (match_operand 0 "" ""))
5913 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5916 (define_expand "bleu"
5918 (if_then_else (leu (match_dup 1) (const_int 0))
5919 (label_ref (match_operand 0 "" ""))
5922 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5925 (define_expand "bgeu"
5927 (if_then_else (geu (match_dup 1) (const_int 0))
5928 (label_ref (match_operand 0 "" ""))
5931 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5934 (define_expand "bltu"
5936 (if_then_else (ltu (match_dup 1) (const_int 0))
5937 (label_ref (match_operand 0 "" ""))
5940 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5943 (define_expand "bunordered"
5945 (if_then_else (unordered (match_dup 1) (const_int 0))
5946 (label_ref (match_operand 0 "" ""))
5948 "TARGET_ARM && TARGET_HARD_FLOAT"
5949 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5953 (define_expand "bordered"
5955 (if_then_else (ordered (match_dup 1) (const_int 0))
5956 (label_ref (match_operand 0 "" ""))
5958 "TARGET_ARM && TARGET_HARD_FLOAT"
5959 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5963 (define_expand "bungt"
5965 (if_then_else (ungt (match_dup 1) (const_int 0))
5966 (label_ref (match_operand 0 "" ""))
5968 "TARGET_ARM && TARGET_HARD_FLOAT"
5969 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5972 (define_expand "bunlt"
5974 (if_then_else (unlt (match_dup 1) (const_int 0))
5975 (label_ref (match_operand 0 "" ""))
5977 "TARGET_ARM && TARGET_HARD_FLOAT"
5978 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5981 (define_expand "bunge"
5983 (if_then_else (unge (match_dup 1) (const_int 0))
5984 (label_ref (match_operand 0 "" ""))
5986 "TARGET_ARM && TARGET_HARD_FLOAT"
5987 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5990 (define_expand "bunle"
5992 (if_then_else (unle (match_dup 1) (const_int 0))
5993 (label_ref (match_operand 0 "" ""))
5995 "TARGET_ARM && TARGET_HARD_FLOAT"
5996 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5999 ;; The following two patterns need two branch instructions, since there is
6000 ;; no single instruction that will handle all cases.
6001 (define_expand "buneq"
6003 (if_then_else (uneq (match_dup 1) (const_int 0))
6004 (label_ref (match_operand 0 "" ""))
6006 "TARGET_ARM && TARGET_HARD_FLOAT"
6007 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6010 (define_expand "bltgt"
6012 (if_then_else (ltgt (match_dup 1) (const_int 0))
6013 (label_ref (match_operand 0 "" ""))
6015 "TARGET_ARM && TARGET_HARD_FLOAT"
6016 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6020 ;; Patterns to match conditional branch insns.
6023 ; Special pattern to match UNEQ.
6024 (define_insn "*arm_buneq"
6026 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6027 (label_ref (match_operand 0 "" ""))
6029 "TARGET_ARM && TARGET_HARD_FLOAT"
6031 if (arm_ccfsm_state != 0)
6034 return \"bvs\\t%l0\;beq\\t%l0\";
6036 [(set_attr "conds" "jump_clob")
6037 (set_attr "length" "8")]
6040 ; Special pattern to match LTGT.
6041 (define_insn "*arm_bltgt"
6043 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6044 (label_ref (match_operand 0 "" ""))
6046 "TARGET_ARM && TARGET_HARD_FLOAT"
6048 if (arm_ccfsm_state != 0)
6051 return \"bmi\\t%l0\;bgt\\t%l0\";
6053 [(set_attr "conds" "jump_clob")
6054 (set_attr "length" "8")]
6057 (define_insn "*arm_cond_branch"
6059 (if_then_else (match_operator 1 "arm_comparison_operator"
6060 [(match_operand 2 "cc_register" "") (const_int 0)])
6061 (label_ref (match_operand 0 "" ""))
6065 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6067 arm_ccfsm_state += 2;
6070 return \"b%d1\\t%l0\";
6072 [(set_attr "conds" "use")]
6075 ; Special pattern to match reversed UNEQ.
6076 (define_insn "*arm_buneq_reversed"
6078 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6080 (label_ref (match_operand 0 "" ""))))]
6081 "TARGET_ARM && TARGET_HARD_FLOAT"
6083 if (arm_ccfsm_state != 0)
6086 return \"bmi\\t%l0\;bgt\\t%l0\";
6088 [(set_attr "conds" "jump_clob")
6089 (set_attr "length" "8")]
6092 ; Special pattern to match reversed LTGT.
6093 (define_insn "*arm_bltgt_reversed"
6095 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6097 (label_ref (match_operand 0 "" ""))))]
6098 "TARGET_ARM && TARGET_HARD_FLOAT"
6100 if (arm_ccfsm_state != 0)
6103 return \"bvs\\t%l0\;beq\\t%l0\";
6105 [(set_attr "conds" "jump_clob")
6106 (set_attr "length" "8")]
6109 (define_insn "*arm_cond_branch_reversed"
6111 (if_then_else (match_operator 1 "arm_comparison_operator"
6112 [(match_operand 2 "cc_register" "") (const_int 0)])
6114 (label_ref (match_operand 0 "" ""))))]
6117 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6119 arm_ccfsm_state += 2;
6122 return \"b%D1\\t%l0\";
6124 [(set_attr "conds" "use")]
6131 (define_expand "seq"
6132 [(set (match_operand:SI 0 "s_register_operand" "=r")
6133 (eq:SI (match_dup 1) (const_int 0)))]
6135 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6138 (define_expand "sne"
6139 [(set (match_operand:SI 0 "s_register_operand" "=r")
6140 (ne:SI (match_dup 1) (const_int 0)))]
6142 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6145 (define_expand "sgt"
6146 [(set (match_operand:SI 0 "s_register_operand" "=r")
6147 (gt:SI (match_dup 1) (const_int 0)))]
6149 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6152 (define_expand "sle"
6153 [(set (match_operand:SI 0 "s_register_operand" "=r")
6154 (le:SI (match_dup 1) (const_int 0)))]
6156 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6159 (define_expand "sge"
6160 [(set (match_operand:SI 0 "s_register_operand" "=r")
6161 (ge:SI (match_dup 1) (const_int 0)))]
6163 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6166 (define_expand "slt"
6167 [(set (match_operand:SI 0 "s_register_operand" "=r")
6168 (lt:SI (match_dup 1) (const_int 0)))]
6170 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6173 (define_expand "sgtu"
6174 [(set (match_operand:SI 0 "s_register_operand" "=r")
6175 (gtu:SI (match_dup 1) (const_int 0)))]
6177 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6180 (define_expand "sleu"
6181 [(set (match_operand:SI 0 "s_register_operand" "=r")
6182 (leu:SI (match_dup 1) (const_int 0)))]
6184 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6187 (define_expand "sgeu"
6188 [(set (match_operand:SI 0 "s_register_operand" "=r")
6189 (geu:SI (match_dup 1) (const_int 0)))]
6191 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6194 (define_expand "sltu"
6195 [(set (match_operand:SI 0 "s_register_operand" "=r")
6196 (ltu:SI (match_dup 1) (const_int 0)))]
6198 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6201 (define_expand "sunordered"
6202 [(set (match_operand:SI 0 "s_register_operand" "=r")
6203 (unordered:SI (match_dup 1) (const_int 0)))]
6204 "TARGET_ARM && TARGET_HARD_FLOAT"
6205 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6209 (define_expand "sordered"
6210 [(set (match_operand:SI 0 "s_register_operand" "=r")
6211 (ordered:SI (match_dup 1) (const_int 0)))]
6212 "TARGET_ARM && TARGET_HARD_FLOAT"
6213 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6217 (define_expand "sungt"
6218 [(set (match_operand:SI 0 "s_register_operand" "=r")
6219 (ungt:SI (match_dup 1) (const_int 0)))]
6220 "TARGET_ARM && TARGET_HARD_FLOAT"
6221 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6225 (define_expand "sunge"
6226 [(set (match_operand:SI 0 "s_register_operand" "=r")
6227 (unge:SI (match_dup 1) (const_int 0)))]
6228 "TARGET_ARM && TARGET_HARD_FLOAT"
6229 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6233 (define_expand "sunlt"
6234 [(set (match_operand:SI 0 "s_register_operand" "=r")
6235 (unlt:SI (match_dup 1) (const_int 0)))]
6236 "TARGET_ARM && TARGET_HARD_FLOAT"
6237 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6241 (define_expand "sunle"
6242 [(set (match_operand:SI 0 "s_register_operand" "=r")
6243 (unle:SI (match_dup 1) (const_int 0)))]
6244 "TARGET_ARM && TARGET_HARD_FLOAT"
6245 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6249 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6250 ;;; simple ARM instructions.
6252 ; (define_expand "suneq"
6253 ; [(set (match_operand:SI 0 "s_register_operand" "=r")
6254 ; (uneq:SI (match_dup 1) (const_int 0)))]
6255 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6259 ; (define_expand "sltgt"
6260 ; [(set (match_operand:SI 0 "s_register_operand" "=r")
6261 ; (ltgt:SI (match_dup 1) (const_int 0)))]
6262 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6266 (define_insn "*mov_scc"
6267 [(set (match_operand:SI 0 "s_register_operand" "=r")
6268 (match_operator:SI 1 "arm_comparison_operator"
6269 [(match_operand 2 "cc_register" "") (const_int 0)]))]
6271 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6272 [(set_attr "conds" "use")
6273 (set_attr "length" "8")]
6276 (define_insn "*mov_negscc"
6277 [(set (match_operand:SI 0 "s_register_operand" "=r")
6278 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
6279 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6281 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6282 [(set_attr "conds" "use")
6283 (set_attr "length" "8")]
6286 (define_insn "*mov_notscc"
6287 [(set (match_operand:SI 0 "s_register_operand" "=r")
6288 (not:SI (match_operator:SI 1 "arm_comparison_operator"
6289 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6291 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6292 [(set_attr "conds" "use")
6293 (set_attr "length" "8")]
6297 ;; Conditional move insns
6299 (define_expand "movsicc"
6300 [(set (match_operand:SI 0 "s_register_operand" "")
6301 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6302 (match_operand:SI 2 "arm_not_operand" "")
6303 (match_operand:SI 3 "arm_not_operand" "")))]
6307 enum rtx_code code = GET_CODE (operands[1]);
6310 if (code == UNEQ || code == LTGT)
6313 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6314 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6318 (define_expand "movsfcc"
6319 [(set (match_operand:SF 0 "s_register_operand" "")
6320 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6321 (match_operand:SF 2 "s_register_operand" "")
6322 (match_operand:SF 3 "nonmemory_operand" "")))]
6326 enum rtx_code code = GET_CODE (operands[1]);
6329 if (code == UNEQ || code == LTGT)
6332 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
6333 Otherwise, ensure it is a valid FP add operand */
6334 if ((!TARGET_HARD_FLOAT)
6335 || (!fpu_add_operand (operands[3], SFmode)))
6336 operands[3] = force_reg (SFmode, operands[3]);
6338 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6339 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6343 (define_expand "movdfcc"
6344 [(set (match_operand:DF 0 "s_register_operand" "")
6345 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6346 (match_operand:DF 2 "s_register_operand" "")
6347 (match_operand:DF 3 "fpu_add_operand" "")))]
6348 "TARGET_ARM && TARGET_HARD_FLOAT"
6351 enum rtx_code code = GET_CODE (operands[1]);
6354 if (code == UNEQ || code == LTGT)
6357 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6358 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6362 (define_insn "*movsicc_insn"
6363 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6365 (match_operator 3 "arm_comparison_operator"
6366 [(match_operand 4 "cc_register" "") (const_int 0)])
6367 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6368 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6375 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6376 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6377 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6378 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6379 [(set_attr "length" "4,4,4,4,8,8,8,8")
6380 (set_attr "conds" "use")]
6383 (define_insn "*movsfcc_hard_insn"
6384 [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6386 (match_operator 3 "arm_comparison_operator"
6387 [(match_operand 4 "cc_register" "") (const_int 0)])
6388 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6389 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6390 "TARGET_ARM && TARGET_HARD_FLOAT"
6396 mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
6397 mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
6398 mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
6399 mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
6400 [(set_attr "length" "4,4,4,4,8,8,8,8")
6401 (set_attr "type" "ffarith")
6402 (set_attr "conds" "use")]
6405 (define_insn "*movsfcc_soft_insn"
6406 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6407 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
6408 [(match_operand 4 "cc_register" "") (const_int 0)])
6409 (match_operand:SF 1 "s_register_operand" "0,r")
6410 (match_operand:SF 2 "s_register_operand" "r,0")))]
6411 "TARGET_ARM && TARGET_SOFT_FLOAT"
6415 [(set_attr "conds" "use")]
6418 (define_insn "*movdfcc_insn"
6419 [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6421 (match_operator 3 "arm_comparison_operator"
6422 [(match_operand 4 "cc_register" "") (const_int 0)])
6423 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6424 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6425 "TARGET_ARM && TARGET_HARD_FLOAT"
6431 mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
6432 mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
6433 mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
6434 mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
6435 [(set_attr "length" "4,4,4,4,8,8,8,8")
6436 (set_attr "type" "ffarith")
6437 (set_attr "conds" "use")]
6441 ;; Jump and linkage insns
6443 (define_expand "jump"
6445 (label_ref (match_operand 0 "" "")))]
6450 (define_insn "*arm_jump"
6452 (label_ref (match_operand 0 "" "")))]
6456 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6458 arm_ccfsm_state += 2;
6461 return \"b%?\\t%l0\";
6464 [(set_attr "predicable" "yes")]
6467 (define_insn "*thumb_jump"
6469 (label_ref (match_operand 0 "" "")))]
6472 if (get_attr_length (insn) == 2)
6474 return \"bl\\t%l0\\t%@ far jump\";
6476 [(set (attr "far_jump")
6478 (eq_attr "length" "4")
6479 (const_string "yes")
6480 (const_string "no")))
6481 (set (attr "length")
6483 (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6484 (le (minus (match_dup 0) (pc)) (const_int 2044)))
6489 (define_expand "call"
6490 [(parallel [(call (match_operand 0 "memory_operand" "")
6491 (match_operand 1 "general_operand" ""))
6492 (use (match_operand 2 "" ""))
6493 (clobber (reg:SI LR_REGNUM))])]
6499 /* In an untyped call, we can get NULL for operand 2. */
6500 if (operands[2] == NULL_RTX)
6501 operands[2] = const0_rtx;
6503 /* This is to decide if we should generate indirect calls by loading the
6504 32 bit address of the callee into a register before performing the
6505 branch and link. operand[2] encodes the long_call/short_call
6506 attribute of the function being called. This attribute is set whenever
6507 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6508 is used, and the short_call attribute can also be set if function is
6509 declared as static or if it has already been defined in the current
6510 compilation unit. See arm.c and arm.h for info about this. The third
6511 parameter to arm_is_longcall_p is used to tell it which pattern
6513 callee = XEXP (operands[0], 0);
6515 if (GET_CODE (callee) != REG
6516 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6517 XEXP (operands[0], 0) = force_reg (Pmode, callee);
6521 (define_insn "*call_reg"
6522 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
6523 (match_operand 1 "" ""))
6524 (use (match_operand 2 "" ""))
6525 (clobber (reg:SI LR_REGNUM))]
6528 return output_call (operands);
6530 ;; length is worst case, normally it is only two
6531 [(set_attr "length" "12")
6532 (set_attr "type" "call")]
6535 (define_insn "*call_mem"
6536 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
6537 (match_operand 1 "" ""))
6538 (use (match_operand 2 "" ""))
6539 (clobber (reg:SI LR_REGNUM))]
6542 return output_call_mem (operands);
6544 [(set_attr "length" "12")
6545 (set_attr "type" "call")]
6548 (define_insn "*call_indirect"
6549 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6550 (match_operand 1 "" ""))
6551 (use (match_operand 2 "" ""))
6552 (clobber (reg:SI LR_REGNUM))]
6556 if (TARGET_CALLER_INTERWORKING)
6557 return \"bl\\t%__interwork_call_via_%0\";
6559 return \"bl\\t%__call_via_%0\";
6561 [(set_attr "type" "call")]
6564 (define_insn "*call_value_indirect"
6565 [(set (match_operand 0 "" "=l")
6566 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6567 (match_operand 2 "" "")))
6568 (use (match_operand 3 "" ""))
6569 (clobber (reg:SI LR_REGNUM))]
6573 if (TARGET_CALLER_INTERWORKING)
6574 return \"bl\\t%__interwork_call_via_%1\";
6576 return \"bl\\t%__call_via_%1\";
6578 [(set_attr "type" "call")]
6581 (define_expand "call_value"
6582 [(parallel [(set (match_operand 0 "" "")
6583 (call (match_operand 1 "memory_operand" "")
6584 (match_operand 2 "general_operand" "")))
6585 (use (match_operand 3 "" ""))
6586 (clobber (reg:SI LR_REGNUM))])]
6590 rtx callee = XEXP (operands[1], 0);
6592 /* In an untyped call, we can get NULL for operand 2. */
6593 if (operands[3] == 0)
6594 operands[3] = const0_rtx;
6596 /* See the comment in define_expand \"call\". */
6597 if (GET_CODE (callee) != REG
6598 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6599 XEXP (operands[1], 0) = force_reg (Pmode, callee);
6603 (define_insn "*call_value_reg"
6604 [(set (match_operand 0 "" "=r,f")
6605 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r"))
6606 (match_operand 2 "" "")))
6607 (use (match_operand 3 "" ""))
6608 (clobber (reg:SI LR_REGNUM))]
6611 return output_call (&operands[1]);
6613 [(set_attr "length" "12")
6614 (set_attr "type" "call")]
6617 (define_insn "*call_value_mem"
6618 [(set (match_operand 0 "" "=r,f")
6619 (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m"))
6620 (match_operand 2 "" "")))
6621 (use (match_operand 3 "" ""))
6622 (clobber (reg:SI LR_REGNUM))]
6623 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6625 return output_call_mem (&operands[1]);
6627 [(set_attr "length" "12")
6628 (set_attr "type" "call")]
6631 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6632 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6634 (define_insn "*call_symbol"
6635 [(call (mem:SI (match_operand:SI 0 "" "X"))
6636 (match_operand 1 "" ""))
6637 (use (match_operand 2 "" ""))
6638 (clobber (reg:SI LR_REGNUM))]
6640 && (GET_CODE (operands[0]) == SYMBOL_REF)
6641 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6644 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6646 [(set_attr "type" "call")]
6649 (define_insn "*call_value_symbol"
6650 [(set (match_operand 0 "s_register_operand" "=r,f")
6651 (call (mem:SI (match_operand:SI 1 "" "X,X"))
6652 (match_operand:SI 2 "" "")))
6653 (use (match_operand 3 "" ""))
6654 (clobber (reg:SI LR_REGNUM))]
6656 && (GET_CODE (operands[1]) == SYMBOL_REF)
6657 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6660 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6662 [(set_attr "type" "call")]
6665 (define_insn "*call_insn"
6666 [(call (mem:SI (match_operand:SI 0 "" "X"))
6667 (match_operand:SI 1 "" ""))
6668 (use (match_operand 2 "" ""))
6669 (clobber (reg:SI LR_REGNUM))]
6671 && GET_CODE (operands[0]) == SYMBOL_REF
6672 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6674 [(set_attr "length" "4")
6675 (set_attr "type" "call")]
6678 (define_insn "*call_value_insn"
6679 [(set (match_operand 0 "register_operand" "=l")
6680 (call (mem:SI (match_operand 1 "" "X"))
6681 (match_operand 2 "" "")))
6682 (use (match_operand 3 "" ""))
6683 (clobber (reg:SI LR_REGNUM))]
6685 && GET_CODE (operands[1]) == SYMBOL_REF
6686 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6688 [(set_attr "length" "4")
6689 (set_attr "type" "call")]
6692 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6693 (define_expand "sibcall"
6694 [(parallel [(call (match_operand 0 "memory_operand" "")
6695 (match_operand 1 "general_operand" ""))
6697 (use (match_operand 2 "" ""))])]
6701 if (operands[2] == NULL_RTX)
6702 operands[2] = const0_rtx;
6706 (define_expand "sibcall_value"
6707 [(parallel [(set (match_operand 0 "register_operand" "")
6708 (call (match_operand 1 "memory_operand" "")
6709 (match_operand 2 "general_operand" "")))
6711 (use (match_operand 3 "" ""))])]
6715 if (operands[3] == NULL_RTX)
6716 operands[3] = const0_rtx;
6720 (define_insn "*sibcall_insn"
6721 [(call (mem:SI (match_operand:SI 0 "" "X"))
6722 (match_operand 1 "" ""))
6724 (use (match_operand 2 "" ""))]
6725 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6727 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6729 [(set_attr "type" "call")]
6732 (define_insn "*sibcall_value_insn"
6733 [(set (match_operand 0 "s_register_operand" "=r,f")
6734 (call (mem:SI (match_operand:SI 1 "" "X,X"))
6735 (match_operand 2 "" "")))
6737 (use (match_operand 3 "" ""))]
6738 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6740 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6742 [(set_attr "type" "call")]
6745 ;; Often the return insn will be the same as loading from memory, so set attr
6746 (define_insn "return"
6748 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6751 if (arm_ccfsm_state == 2)
6753 arm_ccfsm_state += 2;
6756 return output_return_instruction (const_true_rtx, TRUE, FALSE);
6758 [(set_attr "type" "load")
6759 (set_attr "predicable" "yes")]
6762 (define_insn "*cond_return"
6764 (if_then_else (match_operator 0 "arm_comparison_operator"
6765 [(match_operand 1 "cc_register" "") (const_int 0)])
6768 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6771 if (arm_ccfsm_state == 2)
6773 arm_ccfsm_state += 2;
6776 return output_return_instruction (operands[0], TRUE, FALSE);
6778 [(set_attr "conds" "use")
6779 (set_attr "type" "load")]
6782 (define_insn "*cond_return_inverted"
6784 (if_then_else (match_operator 0 "arm_comparison_operator"
6785 [(match_operand 1 "cc_register" "") (const_int 0)])
6788 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6791 if (arm_ccfsm_state == 2)
6793 arm_ccfsm_state += 2;
6796 return output_return_instruction (operands[0], TRUE, TRUE);
6798 [(set_attr "conds" "use")
6799 (set_attr "type" "load")]
6802 ;; Generate a sequence of instructions to determine if the processor is
6803 ;; in 26-bit or 32-bit mode, and return the appropriate return address
6806 (define_expand "return_addr_mask"
6808 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6810 (set (match_operand:SI 0 "s_register_operand" "")
6811 (if_then_else:SI (eq (match_dup 1) (const_int 0))
6813 (const_int 67108860)))] ; 0x03fffffc
6816 operands[1] = gen_rtx_REG (CC_NOOVmode, 24);
6819 (define_insn "*check_arch2"
6820 [(set (match_operand:CC_NOOV 0 "cc_register" "")
6821 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6824 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
6825 [(set_attr "length" "8")
6826 (set_attr "conds" "set")]
6829 ;; Call subroutine returning any type.
6831 (define_expand "untyped_call"
6832 [(parallel [(call (match_operand 0 "" "")
6834 (match_operand 1 "" "")
6835 (match_operand 2 "" "")])]
6841 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6843 for (i = 0; i < XVECLEN (operands[2], 0); i++)
6845 rtx set = XVECEXP (operands[2], 0, i);
6847 emit_move_insn (SET_DEST (set), SET_SRC (set));
6850 /* The optimizer does not know that the call sets the function value
6851 registers we stored in the result block. We avoid problems by
6852 claiming that all hard registers are used and clobbered at this
6854 emit_insn (gen_blockage ());
6860 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6861 ;; all of memory. This blocks insns from being moved across this point.
6863 (define_insn "blockage"
6864 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6867 [(set_attr "length" "0")
6868 (set_attr "type" "block")]
6871 (define_expand "casesi"
6872 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6873 (match_operand:SI 1 "const_int_operand" "") ; lower bound
6874 (match_operand:SI 2 "const_int_operand" "") ; total range
6875 (match_operand:SI 3 "" "") ; table label
6876 (match_operand:SI 4 "" "")] ; Out of range label
6881 if (operands[1] != const0_rtx)
6883 reg = gen_reg_rtx (SImode);
6885 emit_insn (gen_addsi3 (reg, operands[0],
6886 GEN_INT (-INTVAL (operands[1]))));
6890 if (!const_ok_for_arm (INTVAL (operands[2])))
6891 operands[2] = force_reg (SImode, operands[2]);
6893 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6899 ;; The USE in this pattern is needed to tell flow analysis that this is
6900 ;; a CASESI insn. It has no other purpose.
6901 (define_insn "casesi_internal"
6902 [(parallel [(set (pc)
6904 (leu (match_operand:SI 0 "s_register_operand" "r")
6905 (match_operand:SI 1 "arm_rhs_operand" "rI"))
6906 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6907 (label_ref (match_operand 2 "" ""))))
6908 (label_ref (match_operand 3 "" ""))))
6909 (clobber (reg:CC CC_REGNUM))
6910 (use (label_ref (match_dup 2)))])]
6914 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6915 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6917 [(set_attr "conds" "clob")
6918 (set_attr "length" "12")]
6921 (define_expand "indirect_jump"
6923 (match_operand:SI 0 "s_register_operand" ""))]
6928 (define_insn "*arm_indirect_jump"
6930 (match_operand:SI 0 "s_register_operand" "r"))]
6932 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6933 [(set_attr "predicable" "yes")]
6936 ;; Although not supported by the define_expand above,
6937 ;; cse/combine may generate this form.
6938 (define_insn "*load_indirect_jump"
6940 (match_operand:SI 0 "memory_operand" "m"))]
6942 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6943 [(set_attr "type" "load")
6944 (set_attr "pool_range" "4096")
6945 (set_attr "neg_pool_range" "4084")
6946 (set_attr "predicable" "yes")]
6949 (define_insn "*thumb_indirect_jump"
6951 (match_operand:SI 0 "register_operand" "l*r"))]
6954 [(set_attr "conds" "clob")
6955 (set_attr "length" "2")]
6966 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6967 return \"mov\\tr8, r8\";
6969 [(set (attr "length")
6970 (if_then_else (eq_attr "is_thumb" "yes")
6976 ;; Patterns to allow combination of arithmetic, cond code and shifts
6978 (define_insn "*arith_shiftsi"
6979 [(set (match_operand:SI 0 "s_register_operand" "=r")
6980 (match_operator:SI 1 "shiftable_operator"
6981 [(match_operator:SI 3 "shift_operator"
6982 [(match_operand:SI 4 "s_register_operand" "r")
6983 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6984 (match_operand:SI 2 "s_register_operand" "r")]))]
6986 "%i1%?\\t%0, %2, %4%S3"
6987 [(set_attr "predicable" "yes")
6988 (set_attr "shift" "4")
6992 (define_insn "*arith_shiftsi_compare0"
6993 [(set (reg:CC_NOOV CC_REGNUM)
6994 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6995 [(match_operator:SI 3 "shift_operator"
6996 [(match_operand:SI 4 "s_register_operand" "r")
6997 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6998 (match_operand:SI 2 "s_register_operand" "r")])
7000 (set (match_operand:SI 0 "s_register_operand" "=r")
7001 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7004 "%i1%?s\\t%0, %2, %4%S3"
7005 [(set_attr "conds" "set")
7006 (set_attr "shift" "4")
7010 (define_insn "*arith_shiftsi_compare0_scratch"
7011 [(set (reg:CC_NOOV CC_REGNUM)
7012 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7013 [(match_operator:SI 3 "shift_operator"
7014 [(match_operand:SI 4 "s_register_operand" "r")
7015 (match_operand:SI 5 "reg_or_int_operand" "rI")])
7016 (match_operand:SI 2 "s_register_operand" "r")])
7018 (clobber (match_scratch:SI 0 "=r"))]
7020 "%i1%?s\\t%0, %2, %4%S3"
7021 [(set_attr "conds" "set")
7022 (set_attr "shift" "4")
7026 (define_insn "*sub_shiftsi"
7027 [(set (match_operand:SI 0 "s_register_operand" "=r")
7028 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7029 (match_operator:SI 2 "shift_operator"
7030 [(match_operand:SI 3 "s_register_operand" "r")
7031 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7033 "sub%?\\t%0, %1, %3%S2"
7034 [(set_attr "predicable" "yes")
7035 (set_attr "shift" "3")
7039 (define_insn "*sub_shiftsi_compare0"
7040 [(set (reg:CC_NOOV CC_REGNUM)
7042 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7043 (match_operator:SI 2 "shift_operator"
7044 [(match_operand:SI 3 "s_register_operand" "r")
7045 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7047 (set (match_operand:SI 0 "s_register_operand" "=r")
7048 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7051 "sub%?s\\t%0, %1, %3%S2"
7052 [(set_attr "conds" "set")
7053 (set_attr "shift" "3")
7057 (define_insn "*sub_shiftsi_compare0_scratch"
7058 [(set (reg:CC_NOOV CC_REGNUM)
7060 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7061 (match_operator:SI 2 "shift_operator"
7062 [(match_operand:SI 3 "s_register_operand" "r")
7063 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7065 (clobber (match_scratch:SI 0 "=r"))]
7067 "sub%?s\\t%0, %1, %3%S2"
7068 [(set_attr "conds" "set")
7069 (set_attr "shift" "3")
7075 (define_insn "*and_scc"
7076 [(set (match_operand:SI 0 "s_register_operand" "=r")
7077 (and:SI (match_operator:SI 1 "arm_comparison_operator"
7078 [(match_operand 3 "cc_register" "") (const_int 0)])
7079 (match_operand:SI 2 "s_register_operand" "r")))]
7081 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7082 [(set_attr "conds" "use")
7083 (set_attr "length" "8")]
7086 (define_insn "*ior_scc"
7087 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7088 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
7089 [(match_operand 3 "cc_register" "") (const_int 0)])
7090 (match_operand:SI 1 "s_register_operand" "0,?r")))]
7094 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7095 [(set_attr "conds" "use")
7096 (set_attr "length" "4,8")]
7099 (define_insn "*compare_scc"
7100 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7101 (match_operator:SI 1 "arm_comparison_operator"
7102 [(match_operand:SI 2 "s_register_operand" "r,r")
7103 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7104 (clobber (reg:CC CC_REGNUM))]
7107 if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
7108 return \"mov\\t%0, %2, lsr #31\";
7110 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
7111 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7113 if (GET_CODE (operands[1]) == NE)
7115 if (which_alternative == 1)
7116 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7117 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7119 if (which_alternative == 1)
7120 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7122 output_asm_insn (\"cmp\\t%2, %3\", operands);
7123 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7125 [(set_attr "conds" "clob")
7126 (set_attr "length" "12")]
7129 (define_insn "*cond_move"
7130 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7131 (if_then_else:SI (match_operator 3 "equality_operator"
7132 [(match_operator 4 "arm_comparison_operator"
7133 [(match_operand 5 "cc_register" "") (const_int 0)])
7135 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7136 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7139 if (GET_CODE (operands[3]) == NE)
7141 if (which_alternative != 1)
7142 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7143 if (which_alternative != 0)
7144 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7147 if (which_alternative != 0)
7148 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7149 if (which_alternative != 1)
7150 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7153 [(set_attr "conds" "use")
7154 (set_attr "length" "4,4,8")]
7157 (define_insn "*cond_arith"
7158 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7159 (match_operator:SI 5 "shiftable_operator"
7160 [(match_operator:SI 4 "arm_comparison_operator"
7161 [(match_operand:SI 2 "s_register_operand" "r,r")
7162 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7163 (match_operand:SI 1 "s_register_operand" "0,?r")]))
7164 (clobber (reg:CC CC_REGNUM))]
7167 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7168 return \"%i5\\t%0, %1, %2, lsr #31\";
7170 output_asm_insn (\"cmp\\t%2, %3\", operands);
7171 if (GET_CODE (operands[5]) == AND)
7172 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7173 else if (GET_CODE (operands[5]) == MINUS)
7174 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7175 else if (which_alternative != 0)
7176 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7177 return \"%i5%d4\\t%0, %1, #1\";
7179 [(set_attr "conds" "clob")
7180 (set_attr "length" "12")]
7183 (define_insn "*cond_sub"
7184 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7185 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7186 (match_operator:SI 4 "arm_comparison_operator"
7187 [(match_operand:SI 2 "s_register_operand" "r,r")
7188 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7189 (clobber (reg:CC CC_REGNUM))]
7192 output_asm_insn (\"cmp\\t%2, %3\", operands);
7193 if (which_alternative != 0)
7194 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7195 return \"sub%d4\\t%0, %1, #1\";
7197 [(set_attr "conds" "clob")
7198 (set_attr "length" "8,12")]
7201 (define_insn "*cmp_ite0"
7202 [(set (match_operand 6 "dominant_cc_register" "")
7205 (match_operator 4 "arm_comparison_operator"
7206 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7207 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7208 (match_operator:SI 5 "arm_comparison_operator"
7209 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7210 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7216 static const char * const opcodes[4][2] =
7218 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7219 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7220 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7221 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7222 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7223 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7224 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7225 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7228 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7230 return opcodes[which_alternative][swap];
7232 [(set_attr "conds" "set")
7233 (set_attr "length" "8")]
7236 (define_insn "*cmp_ite1"
7237 [(set (match_operand 6 "dominant_cc_register" "")
7240 (match_operator 4 "arm_comparison_operator"
7241 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7242 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7243 (match_operator:SI 5 "arm_comparison_operator"
7244 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7245 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7251 static const char * const opcodes[4][2] =
7253 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7254 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7255 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7256 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7257 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7258 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7259 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7260 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7263 comparison_dominates_p (GET_CODE (operands[5]),
7264 reverse_condition (GET_CODE (operands[4])));
7266 return opcodes[which_alternative][swap];
7268 [(set_attr "conds" "set")
7269 (set_attr "length" "8")]
7272 (define_insn "*cmp_and"
7273 [(set (match_operand 6 "dominant_cc_register" "")
7276 (match_operator 4 "arm_comparison_operator"
7277 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7278 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7279 (match_operator:SI 5 "arm_comparison_operator"
7280 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7281 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7286 static const char *const opcodes[4][2] =
7288 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7289 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7290 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7291 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7292 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7293 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7294 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7295 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7298 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7300 return opcodes[which_alternative][swap];
7302 [(set_attr "conds" "set")
7303 (set_attr "predicable" "no")
7304 (set_attr "length" "8")]
7307 (define_insn "*cmp_ior"
7308 [(set (match_operand 6 "dominant_cc_register" "")
7311 (match_operator 4 "arm_comparison_operator"
7312 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7313 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7314 (match_operator:SI 5 "arm_comparison_operator"
7315 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7316 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7321 static const char *const opcodes[4][2] =
7323 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7324 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7325 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7326 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7327 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7328 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7329 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7330 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7333 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7335 return opcodes[which_alternative][swap];
7338 [(set_attr "conds" "set")
7339 (set_attr "length" "8")]
7342 (define_insn "*negscc"
7343 [(set (match_operand:SI 0 "s_register_operand" "=r")
7344 (neg:SI (match_operator 3 "arm_comparison_operator"
7345 [(match_operand:SI 1 "s_register_operand" "r")
7346 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7347 (clobber (reg:CC CC_REGNUM))]
7350 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7351 return \"mov\\t%0, %1, asr #31\";
7353 if (GET_CODE (operands[3]) == NE)
7354 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7356 if (GET_CODE (operands[3]) == GT)
7357 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7359 output_asm_insn (\"cmp\\t%1, %2\", operands);
7360 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7361 return \"mvn%d3\\t%0, #0\";
7363 [(set_attr "conds" "clob")
7364 (set_attr "length" "12")]
7367 (define_insn "movcond"
7368 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7370 (match_operator 5 "arm_comparison_operator"
7371 [(match_operand:SI 3 "s_register_operand" "r,r,r")
7372 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7373 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7374 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
7375 (clobber (reg:CC CC_REGNUM))]
7378 if (GET_CODE (operands[5]) == LT
7379 && (operands[4] == const0_rtx))
7381 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7383 if (operands[2] == const0_rtx)
7384 return \"and\\t%0, %1, %3, asr #31\";
7385 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
7387 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7389 if (operands[1] == const0_rtx)
7390 return \"bic\\t%0, %2, %3, asr #31\";
7391 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
7393 /* The only case that falls through to here is when both ops 1 & 2
7397 if (GET_CODE (operands[5]) == GE
7398 && (operands[4] == const0_rtx))
7400 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7402 if (operands[2] == const0_rtx)
7403 return \"bic\\t%0, %1, %3, asr #31\";
7404 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7406 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7408 if (operands[1] == const0_rtx)
7409 return \"and\\t%0, %2, %3, asr #31\";
7410 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7412 /* The only case that falls through to here is when both ops 1 & 2
7415 if (GET_CODE (operands[4]) == CONST_INT
7416 && !const_ok_for_arm (INTVAL (operands[4])))
7417 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7419 output_asm_insn (\"cmp\\t%3, %4\", operands);
7420 if (which_alternative != 0)
7421 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7422 if (which_alternative != 1)
7423 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7426 [(set_attr "conds" "clob")
7427 (set_attr "length" "8,8,12")]
7430 (define_insn "*ifcompare_plus_move"
7431 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7432 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7433 [(match_operand:SI 4 "s_register_operand" "r,r")
7434 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7436 (match_operand:SI 2 "s_register_operand" "r,r")
7437 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7438 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7439 (clobber (reg:CC CC_REGNUM))]
7442 [(set_attr "conds" "clob")
7443 (set_attr "length" "8,12")]
7446 (define_insn "*if_plus_move"
7447 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7449 (match_operator 4 "arm_comparison_operator"
7450 [(match_operand 5 "cc_register" "") (const_int 0)])
7452 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7453 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7454 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7458 sub%d4\\t%0, %2, #%n3
7459 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7460 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7461 [(set_attr "conds" "use")
7462 (set_attr "length" "4,4,8,8")
7463 (set_attr "type" "*,*,*,*")]
7466 (define_insn "*ifcompare_move_plus"
7467 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7468 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7469 [(match_operand:SI 4 "s_register_operand" "r,r")
7470 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7471 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7473 (match_operand:SI 2 "s_register_operand" "r,r")
7474 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7475 (clobber (reg:CC CC_REGNUM))]
7478 [(set_attr "conds" "clob")
7479 (set_attr "length" "8,12")]
7482 (define_insn "*if_move_plus"
7483 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7485 (match_operator 4 "arm_comparison_operator"
7486 [(match_operand 5 "cc_register" "") (const_int 0)])
7487 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7489 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7490 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7494 sub%D4\\t%0, %2, #%n3
7495 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7496 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7497 [(set_attr "conds" "use")
7498 (set_attr "length" "4,4,8,8")
7499 (set_attr "type" "*,*,*,*")]
7502 (define_insn "*ifcompare_arith_arith"
7503 [(set (match_operand:SI 0 "s_register_operand" "=r")
7504 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7505 [(match_operand:SI 5 "s_register_operand" "r")
7506 (match_operand:SI 6 "arm_add_operand" "rIL")])
7507 (match_operator:SI 8 "shiftable_operator"
7508 [(match_operand:SI 1 "s_register_operand" "r")
7509 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7510 (match_operator:SI 7 "shiftable_operator"
7511 [(match_operand:SI 3 "s_register_operand" "r")
7512 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7513 (clobber (reg:CC CC_REGNUM))]
7516 [(set_attr "conds" "clob")
7517 (set_attr "length" "12")]
7520 (define_insn "*if_arith_arith"
7521 [(set (match_operand:SI 0 "s_register_operand" "=r")
7522 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7523 [(match_operand 8 "cc_register" "") (const_int 0)])
7524 (match_operator:SI 6 "shiftable_operator"
7525 [(match_operand:SI 1 "s_register_operand" "r")
7526 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7527 (match_operator:SI 7 "shiftable_operator"
7528 [(match_operand:SI 3 "s_register_operand" "r")
7529 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7531 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7532 [(set_attr "conds" "use")
7533 (set_attr "length" "8")]
7536 (define_insn "*ifcompare_arith_move"
7537 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7538 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7539 [(match_operand:SI 2 "s_register_operand" "r,r")
7540 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7541 (match_operator:SI 7 "shiftable_operator"
7542 [(match_operand:SI 4 "s_register_operand" "r,r")
7543 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7544 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7545 (clobber (reg:CC CC_REGNUM))]
7548 /* If we have an operation where (op x 0) is the identity operation and
7549 the conditional operator is LT or GE and we are comparing against zero and
7550 everything is in registers then we can do this in two instructions */
7551 if (operands[3] == const0_rtx
7552 && GET_CODE (operands[7]) != AND
7553 && GET_CODE (operands[5]) == REG
7554 && GET_CODE (operands[1]) == REG
7555 && REGNO (operands[1]) == REGNO (operands[4])
7556 && REGNO (operands[4]) != REGNO (operands[0]))
7558 if (GET_CODE (operands[6]) == LT)
7559 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7560 else if (GET_CODE (operands[6]) == GE)
7561 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7563 if (GET_CODE (operands[3]) == CONST_INT
7564 && !const_ok_for_arm (INTVAL (operands[3])))
7565 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7567 output_asm_insn (\"cmp\\t%2, %3\", operands);
7568 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7569 if (which_alternative != 0)
7570 return \"mov%D6\\t%0, %1\";
7573 [(set_attr "conds" "clob")
7574 (set_attr "length" "8,12")]
7577 (define_insn "*if_arith_move"
7578 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7579 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7580 [(match_operand 6 "cc_register" "") (const_int 0)])
7581 (match_operator:SI 5 "shiftable_operator"
7582 [(match_operand:SI 2 "s_register_operand" "r,r")
7583 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7584 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7588 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7589 [(set_attr "conds" "use")
7590 (set_attr "length" "4,8")
7591 (set_attr "type" "*,*")]
7594 (define_insn "*ifcompare_move_arith"
7595 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7596 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7597 [(match_operand:SI 4 "s_register_operand" "r,r")
7598 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7599 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7600 (match_operator:SI 7 "shiftable_operator"
7601 [(match_operand:SI 2 "s_register_operand" "r,r")
7602 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7603 (clobber (reg:CC CC_REGNUM))]
7606 /* If we have an operation where (op x 0) is the identity operation and
7607 the conditional operator is LT or GE and we are comparing against zero and
7608 everything is in registers then we can do this in two instructions */
7609 if (operands[5] == const0_rtx
7610 && GET_CODE (operands[7]) != AND
7611 && GET_CODE (operands[3]) == REG
7612 && GET_CODE (operands[1]) == REG
7613 && REGNO (operands[1]) == REGNO (operands[2])
7614 && REGNO (operands[2]) != REGNO (operands[0]))
7616 if (GET_CODE (operands[6]) == GE)
7617 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7618 else if (GET_CODE (operands[6]) == LT)
7619 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7622 if (GET_CODE (operands[5]) == CONST_INT
7623 && !const_ok_for_arm (INTVAL (operands[5])))
7624 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7626 output_asm_insn (\"cmp\\t%4, %5\", operands);
7628 if (which_alternative != 0)
7629 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7630 return \"%I7%D6\\t%0, %2, %3\";
7632 [(set_attr "conds" "clob")
7633 (set_attr "length" "8,12")]
7636 (define_insn "*if_move_arith"
7637 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7639 (match_operator 4 "arm_comparison_operator"
7640 [(match_operand 6 "cc_register" "") (const_int 0)])
7641 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7642 (match_operator:SI 5 "shiftable_operator"
7643 [(match_operand:SI 2 "s_register_operand" "r,r")
7644 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7648 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7649 [(set_attr "conds" "use")
7650 (set_attr "length" "4,8")
7651 (set_attr "type" "*,*")]
7654 (define_insn "*ifcompare_move_not"
7655 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7657 (match_operator 5 "arm_comparison_operator"
7658 [(match_operand:SI 3 "s_register_operand" "r,r")
7659 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7660 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7662 (match_operand:SI 2 "s_register_operand" "r,r"))))
7663 (clobber (reg:CC CC_REGNUM))]
7666 [(set_attr "conds" "clob")
7667 (set_attr "length" "8,12")]
7670 (define_insn "*if_move_not"
7671 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7673 (match_operator 4 "arm_comparison_operator"
7674 [(match_operand 3 "cc_register" "") (const_int 0)])
7675 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7676 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7680 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7681 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7682 [(set_attr "conds" "use")
7683 (set_attr "length" "4,8,8")]
7686 (define_insn "*ifcompare_not_move"
7687 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7689 (match_operator 5 "arm_comparison_operator"
7690 [(match_operand:SI 3 "s_register_operand" "r,r")
7691 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7693 (match_operand:SI 2 "s_register_operand" "r,r"))
7694 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7695 (clobber (reg:CC CC_REGNUM))]
7698 [(set_attr "conds" "clob")
7699 (set_attr "length" "8,12")]
7702 (define_insn "*if_not_move"
7703 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7705 (match_operator 4 "arm_comparison_operator"
7706 [(match_operand 3 "cc_register" "") (const_int 0)])
7707 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7708 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7712 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7713 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7714 [(set_attr "conds" "use")
7715 (set_attr "length" "4,8,8")]
7718 (define_insn "*ifcompare_shift_move"
7719 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7721 (match_operator 6 "arm_comparison_operator"
7722 [(match_operand:SI 4 "s_register_operand" "r,r")
7723 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7724 (match_operator:SI 7 "shift_operator"
7725 [(match_operand:SI 2 "s_register_operand" "r,r")
7726 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7727 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7728 (clobber (reg:CC CC_REGNUM))]
7731 [(set_attr "conds" "clob")
7732 (set_attr "length" "8,12")]
7735 (define_insn "*if_shift_move"
7736 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7738 (match_operator 5 "arm_comparison_operator"
7739 [(match_operand 6 "cc_register" "") (const_int 0)])
7740 (match_operator:SI 4 "shift_operator"
7741 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7742 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7743 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7747 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7748 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7749 [(set_attr "conds" "use")
7750 (set_attr "shift" "2")
7751 (set_attr "length" "4,8,8")]
7754 (define_insn "*ifcompare_move_shift"
7755 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7757 (match_operator 6 "arm_comparison_operator"
7758 [(match_operand:SI 4 "s_register_operand" "r,r")
7759 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7760 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7761 (match_operator:SI 7 "shift_operator"
7762 [(match_operand:SI 2 "s_register_operand" "r,r")
7763 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7764 (clobber (reg:CC CC_REGNUM))]
7767 [(set_attr "conds" "clob")
7768 (set_attr "length" "8,12")]
7771 (define_insn "*if_move_shift"
7772 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7774 (match_operator 5 "arm_comparison_operator"
7775 [(match_operand 6 "cc_register" "") (const_int 0)])
7776 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7777 (match_operator:SI 4 "shift_operator"
7778 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7779 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7783 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7784 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7785 [(set_attr "conds" "use")
7786 (set_attr "shift" "2")
7787 (set_attr "length" "4,8,8")]
7790 (define_insn "*ifcompare_shift_shift"
7791 [(set (match_operand:SI 0 "s_register_operand" "=r")
7793 (match_operator 7 "arm_comparison_operator"
7794 [(match_operand:SI 5 "s_register_operand" "r")
7795 (match_operand:SI 6 "arm_add_operand" "rIL")])
7796 (match_operator:SI 8 "shift_operator"
7797 [(match_operand:SI 1 "s_register_operand" "r")
7798 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7799 (match_operator:SI 9 "shift_operator"
7800 [(match_operand:SI 3 "s_register_operand" "r")
7801 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7802 (clobber (reg:CC CC_REGNUM))]
7805 [(set_attr "conds" "clob")
7806 (set_attr "length" "12")]
7809 (define_insn "*if_shift_shift"
7810 [(set (match_operand:SI 0 "s_register_operand" "=r")
7812 (match_operator 5 "arm_comparison_operator"
7813 [(match_operand 8 "cc_register" "") (const_int 0)])
7814 (match_operator:SI 6 "shift_operator"
7815 [(match_operand:SI 1 "s_register_operand" "r")
7816 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7817 (match_operator:SI 7 "shift_operator"
7818 [(match_operand:SI 3 "s_register_operand" "r")
7819 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7821 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7822 [(set_attr "conds" "use")
7823 (set_attr "shift" "1")
7824 (set_attr "length" "8")]
7827 (define_insn "*ifcompare_not_arith"
7828 [(set (match_operand:SI 0 "s_register_operand" "=r")
7830 (match_operator 6 "arm_comparison_operator"
7831 [(match_operand:SI 4 "s_register_operand" "r")
7832 (match_operand:SI 5 "arm_add_operand" "rIL")])
7833 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7834 (match_operator:SI 7 "shiftable_operator"
7835 [(match_operand:SI 2 "s_register_operand" "r")
7836 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7837 (clobber (reg:CC CC_REGNUM))]
7840 [(set_attr "conds" "clob")
7841 (set_attr "length" "12")]
7844 (define_insn "*if_not_arith"
7845 [(set (match_operand:SI 0 "s_register_operand" "=r")
7847 (match_operator 5 "arm_comparison_operator"
7848 [(match_operand 4 "cc_register" "") (const_int 0)])
7849 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7850 (match_operator:SI 6 "shiftable_operator"
7851 [(match_operand:SI 2 "s_register_operand" "r")
7852 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7854 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7855 [(set_attr "conds" "use")
7856 (set_attr "length" "8")]
7859 (define_insn "*ifcompare_arith_not"
7860 [(set (match_operand:SI 0 "s_register_operand" "=r")
7862 (match_operator 6 "arm_comparison_operator"
7863 [(match_operand:SI 4 "s_register_operand" "r")
7864 (match_operand:SI 5 "arm_add_operand" "rIL")])
7865 (match_operator:SI 7 "shiftable_operator"
7866 [(match_operand:SI 2 "s_register_operand" "r")
7867 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7868 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7869 (clobber (reg:CC CC_REGNUM))]
7872 [(set_attr "conds" "clob")
7873 (set_attr "length" "12")]
7876 (define_insn "*if_arith_not"
7877 [(set (match_operand:SI 0 "s_register_operand" "=r")
7879 (match_operator 5 "arm_comparison_operator"
7880 [(match_operand 4 "cc_register" "") (const_int 0)])
7881 (match_operator:SI 6 "shiftable_operator"
7882 [(match_operand:SI 2 "s_register_operand" "r")
7883 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7884 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7886 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7887 [(set_attr "conds" "use")
7888 (set_attr "length" "8")]
7891 (define_insn "*ifcompare_neg_move"
7892 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7894 (match_operator 5 "arm_comparison_operator"
7895 [(match_operand:SI 3 "s_register_operand" "r,r")
7896 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7897 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7898 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7899 (clobber (reg:CC CC_REGNUM))]
7902 [(set_attr "conds" "clob")
7903 (set_attr "length" "8,12")]
7906 (define_insn "*if_neg_move"
7907 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7909 (match_operator 4 "arm_comparison_operator"
7910 [(match_operand 3 "cc_register" "") (const_int 0)])
7911 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7912 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7916 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7917 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
7918 [(set_attr "conds" "use")
7919 (set_attr "length" "4,8,8")]
7922 (define_insn "*ifcompare_move_neg"
7923 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7925 (match_operator 5 "arm_comparison_operator"
7926 [(match_operand:SI 3 "s_register_operand" "r,r")
7927 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7928 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7929 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
7930 (clobber (reg:CC CC_REGNUM))]
7933 [(set_attr "conds" "clob")
7934 (set_attr "length" "8,12")]
7937 (define_insn "*if_move_neg"
7938 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7940 (match_operator 4 "arm_comparison_operator"
7941 [(match_operand 3 "cc_register" "") (const_int 0)])
7942 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7943 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7947 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
7948 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
7949 [(set_attr "conds" "use")
7950 (set_attr "length" "4,8,8")]
7953 (define_insn "*arith_adjacentmem"
7954 [(set (match_operand:SI 0 "s_register_operand" "=r")
7955 (match_operator:SI 1 "shiftable_operator"
7956 [(match_operand:SI 2 "memory_operand" "m")
7957 (match_operand:SI 3 "memory_operand" "m")]))
7958 (clobber (match_scratch:SI 4 "=r"))]
7959 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
7964 int val1 = 0, val2 = 0;
7966 if (REGNO (operands[0]) > REGNO (operands[4]))
7968 ldm[1] = operands[4];
7969 ldm[2] = operands[0];
7973 ldm[1] = operands[0];
7974 ldm[2] = operands[4];
7976 if (GET_CODE (XEXP (operands[2], 0)) != REG)
7977 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
7978 if (GET_CODE (XEXP (operands[3], 0)) != REG)
7979 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
7980 arith[0] = operands[0];
7981 arith[3] = operands[1];
7995 ldm[0] = ops[0] = operands[4];
7996 ops[1] = XEXP (XEXP (operands[2], 0), 0);
7997 ops[2] = XEXP (XEXP (operands[2], 0), 1);
7998 output_add_immediate (ops);
8000 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8002 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8006 ldm[0] = XEXP (operands[3], 0);
8008 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8010 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8014 ldm[0] = XEXP (operands[2], 0);
8016 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8018 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8020 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
8023 [(set_attr "length" "12")
8024 (set_attr "predicable" "yes")
8025 (set_attr "type" "load")]
8028 ;; the arm can support extended pre-inc instructions
8030 ;; In all these cases, we use operands 0 and 1 for the register being
8031 ;; incremented because those are the operands that local-alloc will
8032 ;; tie and these are the pair most likely to be tieable (and the ones
8033 ;; that will benefit the most).
8035 ;; We reject the frame pointer if it occurs anywhere in these patterns since
8036 ;; elimination will cause too many headaches.
8038 (define_insn "*strqi_preinc"
8039 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8040 (match_operand:SI 2 "index_operand" "rJ")))
8041 (match_operand:QI 3 "s_register_operand" "r"))
8042 (set (match_operand:SI 0 "s_register_operand" "=r")
8043 (plus:SI (match_dup 1) (match_dup 2)))]
8045 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8046 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8047 && (GET_CODE (operands[2]) != REG
8048 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8049 "str%?b\\t%3, [%0, %2]!"
8050 [(set_attr "type" "store1")
8051 (set_attr "predicable" "yes")]
8054 (define_insn "*strqi_predec"
8055 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8056 (match_operand:SI 2 "s_register_operand" "r")))
8057 (match_operand:QI 3 "s_register_operand" "r"))
8058 (set (match_operand:SI 0 "s_register_operand" "=r")
8059 (minus:SI (match_dup 1) (match_dup 2)))]
8061 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8062 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8063 && (GET_CODE (operands[2]) != REG
8064 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8065 "str%?b\\t%3, [%0, -%2]!"
8066 [(set_attr "type" "store1")
8067 (set_attr "predicable" "yes")]
8070 (define_insn "*loadqi_preinc"
8071 [(set (match_operand:QI 3 "s_register_operand" "=r")
8072 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8073 (match_operand:SI 2 "index_operand" "rJ"))))
8074 (set (match_operand:SI 0 "s_register_operand" "=r")
8075 (plus:SI (match_dup 1) (match_dup 2)))]
8077 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8078 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8079 && (GET_CODE (operands[2]) != REG
8080 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8081 "ldr%?b\\t%3, [%0, %2]!"
8082 [(set_attr "type" "load")
8083 (set_attr "predicable" "yes")]
8086 (define_insn "*loadqi_predec"
8087 [(set (match_operand:QI 3 "s_register_operand" "=r")
8088 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8089 (match_operand:SI 2 "s_register_operand" "r"))))
8090 (set (match_operand:SI 0 "s_register_operand" "=r")
8091 (minus:SI (match_dup 1) (match_dup 2)))]
8093 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8094 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8095 && (GET_CODE (operands[2]) != REG
8096 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8097 "ldr%?b\\t%3, [%0, -%2]!"
8098 [(set_attr "type" "load")
8099 (set_attr "predicable" "yes")]
8102 (define_insn "*loadqisi_preinc"
8103 [(set (match_operand:SI 3 "s_register_operand" "=r")
8105 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8106 (match_operand:SI 2 "index_operand" "rJ")))))
8107 (set (match_operand:SI 0 "s_register_operand" "=r")
8108 (plus:SI (match_dup 1) (match_dup 2)))]
8110 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8111 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8112 && (GET_CODE (operands[2]) != REG
8113 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8114 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8115 [(set_attr "type" "load")
8116 (set_attr "predicable" "yes")]
8119 (define_insn "*loadqisi_predec"
8120 [(set (match_operand:SI 3 "s_register_operand" "=r")
8122 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8123 (match_operand:SI 2 "s_register_operand" "r")))))
8124 (set (match_operand:SI 0 "s_register_operand" "=r")
8125 (minus:SI (match_dup 1) (match_dup 2)))]
8127 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8128 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8129 && (GET_CODE (operands[2]) != REG
8130 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8131 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8132 [(set_attr "type" "load")
8133 (set_attr "predicable" "yes")]
8136 (define_insn "*strsi_preinc"
8137 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8138 (match_operand:SI 2 "index_operand" "rJ")))
8139 (match_operand:SI 3 "s_register_operand" "r"))
8140 (set (match_operand:SI 0 "s_register_operand" "=r")
8141 (plus:SI (match_dup 1) (match_dup 2)))]
8143 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8144 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8145 && (GET_CODE (operands[2]) != REG
8146 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8147 "str%?\\t%3, [%0, %2]!"
8148 [(set_attr "type" "store1")
8149 (set_attr "predicable" "yes")]
8152 (define_insn "*strsi_predec"
8153 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8154 (match_operand:SI 2 "s_register_operand" "r")))
8155 (match_operand:SI 3 "s_register_operand" "r"))
8156 (set (match_operand:SI 0 "s_register_operand" "=r")
8157 (minus:SI (match_dup 1) (match_dup 2)))]
8159 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8160 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8161 && (GET_CODE (operands[2]) != REG
8162 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8163 "str%?\\t%3, [%0, -%2]!"
8164 [(set_attr "type" "store1")
8165 (set_attr "predicable" "yes")]
8168 (define_insn "*loadsi_preinc"
8169 [(set (match_operand:SI 3 "s_register_operand" "=r")
8170 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8171 (match_operand:SI 2 "index_operand" "rJ"))))
8172 (set (match_operand:SI 0 "s_register_operand" "=r")
8173 (plus:SI (match_dup 1) (match_dup 2)))]
8175 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8176 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8177 && (GET_CODE (operands[2]) != REG
8178 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8179 "ldr%?\\t%3, [%0, %2]!"
8180 [(set_attr "type" "load")
8181 (set_attr "predicable" "yes")]
8184 (define_insn "*loadsi_predec"
8185 [(set (match_operand:SI 3 "s_register_operand" "=r")
8186 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8187 (match_operand:SI 2 "s_register_operand" "r"))))
8188 (set (match_operand:SI 0 "s_register_operand" "=r")
8189 (minus:SI (match_dup 1) (match_dup 2)))]
8191 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8192 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8193 && (GET_CODE (operands[2]) != REG
8194 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8195 "ldr%?\\t%3, [%0, -%2]!"
8196 [(set_attr "type" "load")
8197 (set_attr "predicable" "yes")]
8200 (define_insn "*loadhi_preinc"
8201 [(set (match_operand:HI 3 "s_register_operand" "=r")
8202 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8203 (match_operand:SI 2 "index_operand" "rJ"))))
8204 (set (match_operand:SI 0 "s_register_operand" "=r")
8205 (plus:SI (match_dup 1) (match_dup 2)))]
8207 && !BYTES_BIG_ENDIAN
8208 && !TARGET_MMU_TRAPS
8210 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8211 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8212 && (GET_CODE (operands[2]) != REG
8213 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8214 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8215 [(set_attr "type" "load")
8216 (set_attr "predicable" "yes")]
8219 (define_insn "*loadhi_predec"
8220 [(set (match_operand:HI 3 "s_register_operand" "=r")
8221 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8222 (match_operand:SI 2 "s_register_operand" "r"))))
8223 (set (match_operand:SI 0 "s_register_operand" "=r")
8224 (minus:SI (match_dup 1) (match_dup 2)))]
8226 && !BYTES_BIG_ENDIAN
8227 && !TARGET_MMU_TRAPS
8229 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8230 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8231 && (GET_CODE (operands[2]) != REG
8232 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8233 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8234 [(set_attr "type" "load")
8235 (set_attr "predicable" "yes")]
8238 (define_insn "*strqi_shiftpreinc"
8239 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8240 [(match_operand:SI 3 "s_register_operand" "r")
8241 (match_operand:SI 4 "const_shift_operand" "n")])
8242 (match_operand:SI 1 "s_register_operand" "0")))
8243 (match_operand:QI 5 "s_register_operand" "r"))
8244 (set (match_operand:SI 0 "s_register_operand" "=r")
8245 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8248 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8249 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8250 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8251 "str%?b\\t%5, [%0, %3%S2]!"
8252 [(set_attr "type" "store1")
8253 (set_attr "predicable" "yes")]
8256 (define_insn "*strqi_shiftpredec"
8257 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8258 (match_operator:SI 2 "shift_operator"
8259 [(match_operand:SI 3 "s_register_operand" "r")
8260 (match_operand:SI 4 "const_shift_operand" "n")])))
8261 (match_operand:QI 5 "s_register_operand" "r"))
8262 (set (match_operand:SI 0 "s_register_operand" "=r")
8263 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8266 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8267 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8268 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8269 "str%?b\\t%5, [%0, -%3%S2]!"
8270 [(set_attr "type" "store1")
8271 (set_attr "predicable" "yes")]
8274 (define_insn "*loadqi_shiftpreinc"
8275 [(set (match_operand:QI 5 "s_register_operand" "=r")
8276 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8277 [(match_operand:SI 3 "s_register_operand" "r")
8278 (match_operand:SI 4 "const_shift_operand" "n")])
8279 (match_operand:SI 1 "s_register_operand" "0"))))
8280 (set (match_operand:SI 0 "s_register_operand" "=r")
8281 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8284 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8285 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8286 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8287 "ldr%?b\\t%5, [%0, %3%S2]!"
8288 [(set_attr "type" "load")
8289 (set_attr "predicable" "yes")]
8292 (define_insn "*loadqi_shiftpredec"
8293 [(set (match_operand:QI 5 "s_register_operand" "=r")
8294 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8295 (match_operator:SI 2 "shift_operator"
8296 [(match_operand:SI 3 "s_register_operand" "r")
8297 (match_operand:SI 4 "const_shift_operand" "n")]))))
8298 (set (match_operand:SI 0 "s_register_operand" "=r")
8299 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8302 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8303 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8304 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8305 "ldr%?b\\t%5, [%0, -%3%S2]!"
8306 [(set_attr "type" "load")
8307 (set_attr "predicable" "yes")]
8310 (define_insn "*strsi_shiftpreinc"
8311 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8312 [(match_operand:SI 3 "s_register_operand" "r")
8313 (match_operand:SI 4 "const_shift_operand" "n")])
8314 (match_operand:SI 1 "s_register_operand" "0")))
8315 (match_operand:SI 5 "s_register_operand" "r"))
8316 (set (match_operand:SI 0 "s_register_operand" "=r")
8317 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8320 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8321 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8322 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8323 "str%?\\t%5, [%0, %3%S2]!"
8324 [(set_attr "type" "store1")
8325 (set_attr "predicable" "yes")]
8328 (define_insn "*strsi_shiftpredec"
8329 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8330 (match_operator:SI 2 "shift_operator"
8331 [(match_operand:SI 3 "s_register_operand" "r")
8332 (match_operand:SI 4 "const_shift_operand" "n")])))
8333 (match_operand:SI 5 "s_register_operand" "r"))
8334 (set (match_operand:SI 0 "s_register_operand" "=r")
8335 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8338 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8339 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8340 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8341 "str%?\\t%5, [%0, -%3%S2]!"
8342 [(set_attr "type" "store1")
8343 (set_attr "predicable" "yes")]
8346 (define_insn "*loadsi_shiftpreinc"
8347 [(set (match_operand:SI 5 "s_register_operand" "=r")
8348 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8349 [(match_operand:SI 3 "s_register_operand" "r")
8350 (match_operand:SI 4 "const_shift_operand" "n")])
8351 (match_operand:SI 1 "s_register_operand" "0"))))
8352 (set (match_operand:SI 0 "s_register_operand" "=r")
8353 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8356 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8357 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8358 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8359 "ldr%?\\t%5, [%0, %3%S2]!"
8360 [(set_attr "type" "load")
8361 (set_attr "predicable" "yes")]
8364 (define_insn "*loadsi_shiftpredec"
8365 [(set (match_operand:SI 5 "s_register_operand" "=r")
8366 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8367 (match_operator:SI 2 "shift_operator"
8368 [(match_operand:SI 3 "s_register_operand" "r")
8369 (match_operand:SI 4 "const_shift_operand" "n")]))))
8370 (set (match_operand:SI 0 "s_register_operand" "=r")
8371 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8374 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8375 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8376 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8377 "ldr%?\\t%5, [%0, -%3%S2]!"
8378 [(set_attr "type" "load")
8379 (set_attr "predicable" "yes")])
8381 (define_insn "*loadhi_shiftpreinc"
8382 [(set (match_operand:HI 5 "s_register_operand" "=r")
8383 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8384 [(match_operand:SI 3 "s_register_operand" "r")
8385 (match_operand:SI 4 "const_shift_operand" "n")])
8386 (match_operand:SI 1 "s_register_operand" "0"))))
8387 (set (match_operand:SI 0 "s_register_operand" "=r")
8388 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8391 && !BYTES_BIG_ENDIAN
8392 && !TARGET_MMU_TRAPS
8394 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8395 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8396 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8397 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8398 [(set_attr "type" "load")
8399 (set_attr "predicable" "yes")]
8402 (define_insn "*loadhi_shiftpredec"
8403 [(set (match_operand:HI 5 "s_register_operand" "=r")
8404 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8405 (match_operator:SI 2 "shift_operator"
8406 [(match_operand:SI 3 "s_register_operand" "r")
8407 (match_operand:SI 4 "const_shift_operand" "n")]))))
8408 (set (match_operand:SI 0 "s_register_operand" "=r")
8409 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8412 && !BYTES_BIG_ENDIAN
8413 && !TARGET_MMU_TRAPS
8415 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8416 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8417 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8418 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8419 [(set_attr "type" "load")
8420 (set_attr "predicable" "yes")]
8423 ; It can also support extended post-inc expressions, but combine doesn't
8425 ; It doesn't seem worth adding peepholes for anything but the most common
8426 ; cases since, unlike combine, the increment must immediately follow the load
8427 ; for this pattern to match.
8428 ; We must watch to see that the source/destination register isn't also the
8429 ; same as the base address register, and that if the index is a register,
8430 ; that it is not the same as the base address register. In such cases the
8431 ; instruction that we would generate would have UNPREDICTABLE behavior so
8435 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8436 (match_operand:QI 2 "s_register_operand" "r"))
8438 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8440 && (REGNO (operands[2]) != REGNO (operands[0]))
8441 && (GET_CODE (operands[1]) != REG
8442 || (REGNO (operands[1]) != REGNO (operands[0])))"
8443 "str%?b\\t%2, [%0], %1"
8447 [(set (match_operand:QI 0 "s_register_operand" "=r")
8448 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8450 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8452 && REGNO (operands[0]) != REGNO(operands[1])
8453 && (GET_CODE (operands[2]) != REG
8454 || REGNO(operands[0]) != REGNO (operands[2]))"
8455 "ldr%?b\\t%0, [%1], %2"
8459 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8460 (match_operand:SI 2 "s_register_operand" "r"))
8462 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8464 && (REGNO (operands[2]) != REGNO (operands[0]))
8465 && (GET_CODE (operands[1]) != REG
8466 || (REGNO (operands[1]) != REGNO (operands[0])))"
8467 "str%?\\t%2, [%0], %1"
8471 [(set (match_operand:HI 0 "s_register_operand" "=r")
8472 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8474 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8476 && !BYTES_BIG_ENDIAN
8477 && !TARGET_MMU_TRAPS
8479 && REGNO (operands[0]) != REGNO(operands[1])
8480 && (GET_CODE (operands[2]) != REG
8481 || REGNO(operands[0]) != REGNO (operands[2]))"
8482 "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8486 [(set (match_operand:SI 0 "s_register_operand" "=r")
8487 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8489 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8491 && REGNO (operands[0]) != REGNO(operands[1])
8492 && (GET_CODE (operands[2]) != REG
8493 || REGNO(operands[0]) != REGNO (operands[2]))"
8494 "ldr%?\\t%0, [%1], %2"
8498 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8499 (match_operand:SI 1 "index_operand" "rJ")))
8500 (match_operand:QI 2 "s_register_operand" "r"))
8501 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8503 && (REGNO (operands[2]) != REGNO (operands[0]))
8504 && (GET_CODE (operands[1]) != REG
8505 || (REGNO (operands[1]) != REGNO (operands[0])))"
8506 "str%?b\\t%2, [%0, %1]!"
8510 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8511 [(match_operand:SI 0 "s_register_operand" "r")
8512 (match_operand:SI 1 "const_int_operand" "n")])
8513 (match_operand:SI 2 "s_register_operand" "+r")))
8514 (match_operand:QI 3 "s_register_operand" "r"))
8515 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8518 && (REGNO (operands[3]) != REGNO (operands[2]))
8519 && (REGNO (operands[0]) != REGNO (operands[2]))"
8520 "str%?b\\t%3, [%2, %0%S4]!"
8523 ; This pattern is never tried by combine, so do it as a peephole
8526 [(set (match_operand:SI 0 "s_register_operand" "")
8527 (match_operand:SI 1 "s_register_operand" ""))
8528 (set (reg:CC CC_REGNUM)
8529 (compare:CC (match_dup 1) (const_int 0)))]
8532 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8533 (set (match_dup 0) (match_dup 1))])]
8537 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8538 ; reversed, check that the memory references aren't volatile.
8541 [(set (match_operand:SI 0 "s_register_operand" "=r")
8542 (match_operand:SI 4 "memory_operand" "m"))
8543 (set (match_operand:SI 1 "s_register_operand" "=r")
8544 (match_operand:SI 5 "memory_operand" "m"))
8545 (set (match_operand:SI 2 "s_register_operand" "=r")
8546 (match_operand:SI 6 "memory_operand" "m"))
8547 (set (match_operand:SI 3 "s_register_operand" "=r")
8548 (match_operand:SI 7 "memory_operand" "m"))]
8549 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8551 return emit_ldm_seq (operands, 4);
8556 [(set (match_operand:SI 0 "s_register_operand" "=r")
8557 (match_operand:SI 3 "memory_operand" "m"))
8558 (set (match_operand:SI 1 "s_register_operand" "=r")
8559 (match_operand:SI 4 "memory_operand" "m"))
8560 (set (match_operand:SI 2 "s_register_operand" "=r")
8561 (match_operand:SI 5 "memory_operand" "m"))]
8562 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8564 return emit_ldm_seq (operands, 3);
8569 [(set (match_operand:SI 0 "s_register_operand" "=r")
8570 (match_operand:SI 2 "memory_operand" "m"))
8571 (set (match_operand:SI 1 "s_register_operand" "=r")
8572 (match_operand:SI 3 "memory_operand" "m"))]
8573 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8575 return emit_ldm_seq (operands, 2);
8580 [(set (match_operand:SI 4 "memory_operand" "=m")
8581 (match_operand:SI 0 "s_register_operand" "r"))
8582 (set (match_operand:SI 5 "memory_operand" "=m")
8583 (match_operand:SI 1 "s_register_operand" "r"))
8584 (set (match_operand:SI 6 "memory_operand" "=m")
8585 (match_operand:SI 2 "s_register_operand" "r"))
8586 (set (match_operand:SI 7 "memory_operand" "=m")
8587 (match_operand:SI 3 "s_register_operand" "r"))]
8588 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8590 return emit_stm_seq (operands, 4);
8595 [(set (match_operand:SI 3 "memory_operand" "=m")
8596 (match_operand:SI 0 "s_register_operand" "r"))
8597 (set (match_operand:SI 4 "memory_operand" "=m")
8598 (match_operand:SI 1 "s_register_operand" "r"))
8599 (set (match_operand:SI 5 "memory_operand" "=m")
8600 (match_operand:SI 2 "s_register_operand" "r"))]
8601 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8603 return emit_stm_seq (operands, 3);
8608 [(set (match_operand:SI 2 "memory_operand" "=m")
8609 (match_operand:SI 0 "s_register_operand" "r"))
8610 (set (match_operand:SI 3 "memory_operand" "=m")
8611 (match_operand:SI 1 "s_register_operand" "r"))]
8612 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8614 return emit_stm_seq (operands, 2);
8619 [(set (match_operand:SI 0 "s_register_operand" "")
8620 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8622 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8623 [(match_operand:SI 3 "s_register_operand" "")
8624 (match_operand:SI 4 "arm_rhs_operand" "")]))))
8625 (clobber (match_operand:SI 5 "s_register_operand" ""))]
8627 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8628 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8633 ;; This split can be used because CC_Z mode implies that the following
8634 ;; branch will be an equality, or an unsigned inequality, so the sign
8635 ;; extension is not needed.
8638 [(set (reg:CC_Z CC_REGNUM)
8640 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8642 (match_operand 1 "const_int_operand" "")))
8643 (clobber (match_scratch:SI 2 ""))]
8645 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8646 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8647 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8648 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8650 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8654 (define_expand "prologue"
8655 [(clobber (const_int 0))]
8658 arm_expand_prologue ();
8660 thumb_expand_prologue ();
8665 (define_expand "epilogue"
8666 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8670 thumb_expand_epilogue ();
8671 else if (USE_RETURN_INSN (FALSE))
8673 emit_jump_insn (gen_return ());
8676 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8678 gen_rtx_RETURN (VOIDmode)),
8684 (define_insn "sibcall_epilogue"
8685 [(unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)]
8688 if (USE_RETURN_INSN (FALSE))
8689 return output_return_instruction (const_true_rtx, FALSE, FALSE);
8690 return arm_output_epilogue (FALSE);
8692 ;; Length is absolute worst case
8693 [(set_attr "length" "44")
8694 (set_attr "type" "block")]
8697 (define_insn "*epilogue_insns"
8698 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8702 return arm_output_epilogue (TRUE);
8703 else /* TARGET_THUMB */
8704 return thumb_unexpanded_epilogue ();
8706 ; Length is absolute worst case
8707 [(set_attr "length" "44")
8708 (set_attr "type" "block")]
8711 (define_expand "eh_epilogue"
8712 [(use (match_operand:SI 0 "register_operand" "r"))
8713 (use (match_operand:SI 1 "register_operand" "r"))
8714 (use (match_operand:SI 2 "register_operand" "r"))]
8718 cfun->machine->eh_epilogue_sp_ofs = operands[1];
8719 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8721 rtx ra = gen_rtx_REG (Pmode, 2);
8723 emit_move_insn (ra, operands[2]);
8726 /* This is a hack -- we may have crystalized the function type too
8728 cfun->machine->func_type = 0;
8732 ;; This split is only used during output to reduce the number of patterns
8733 ;; that need assembler instructions adding to them. We allowed the setting
8734 ;; of the conditions to be implicit during rtl generation so that
8735 ;; the conditional compare patterns would work. However this conflicts to
8736 ;; some extent with the conditional data operations, so we have to split them
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 "" "")])
8744 (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_dup 7)
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]);
8754 enum rtx_code rc = GET_CODE (operands[1]);
8756 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8757 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8758 if (mode == CCFPmode || mode == CCFPEmode)
8759 rc = reverse_condition_maybe_unordered (rc);
8761 rc = reverse_condition (rc);
8763 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8768 [(set (match_operand:SI 0 "s_register_operand" "")
8769 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8770 [(match_operand 2 "" "") (match_operand 3 "" "")])
8771 (match_operand 4 "" "")
8773 (clobber (reg:CC CC_REGNUM))]
8774 "TARGET_ARM && reload_completed"
8775 [(set (match_dup 5) (match_dup 6))
8776 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8777 (set (match_dup 0) (match_dup 4)))]
8780 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8781 operands[2], operands[3]);
8783 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8784 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8789 [(set (match_operand:SI 0 "s_register_operand" "")
8790 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8791 [(match_operand 2 "" "") (match_operand 3 "" "")])
8792 (match_operand 4 "" "")
8793 (match_operand 5 "" "")))
8794 (clobber (reg:CC CC_REGNUM))]
8795 "TARGET_ARM && reload_completed"
8796 [(set (match_dup 6) (match_dup 7))
8797 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8798 (set (match_dup 0) (match_dup 4)))
8799 (cond_exec (match_dup 8)
8800 (set (match_dup 0) (match_dup 5)))]
8803 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8804 operands[2], operands[3]);
8805 enum rtx_code rc = GET_CODE (operands[1]);
8807 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8808 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8809 if (mode == CCFPmode || mode == CCFPEmode)
8810 rc = reverse_condition_maybe_unordered (rc);
8812 rc = reverse_condition (rc);
8814 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8819 [(set (match_operand:SI 0 "s_register_operand" "")
8820 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8821 [(match_operand:SI 2 "s_register_operand" "")
8822 (match_operand:SI 3 "arm_add_operand" "")])
8823 (match_operand:SI 4 "arm_rhs_operand" "")
8825 (match_operand:SI 5 "s_register_operand" ""))))
8826 (clobber (reg:CC CC_REGNUM))]
8827 "TARGET_ARM && reload_completed"
8828 [(set (match_dup 6) (match_dup 7))
8829 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8830 (set (match_dup 0) (match_dup 4)))
8831 (cond_exec (match_dup 8)
8832 (set (match_dup 0) (not:SI (match_dup 5))))]
8835 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8836 operands[2], operands[3]);
8837 enum rtx_code rc = GET_CODE (operands[1]);
8839 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8840 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8841 if (mode == CCFPmode || mode == CCFPEmode)
8842 rc = reverse_condition_maybe_unordered (rc);
8844 rc = reverse_condition (rc);
8846 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8850 (define_insn "*cond_move_not"
8851 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8852 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8853 [(match_operand 3 "cc_register" "") (const_int 0)])
8854 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8856 (match_operand:SI 2 "s_register_operand" "r,r"))))]
8860 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8861 [(set_attr "conds" "use")
8862 (set_attr "length" "4,8")]
8865 ;; The next two patterns occur when an AND operation is followed by a
8866 ;; scc insn sequence
8868 (define_insn "*sign_extract_onebit"
8869 [(set (match_operand:SI 0 "s_register_operand" "=r")
8870 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8872 (match_operand:SI 2 "const_int_operand" "n")))
8873 (clobber (reg:CC CC_REGNUM))]
8876 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8877 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8878 return \"mvnne\\t%0, #0\";
8880 [(set_attr "conds" "clob")
8881 (set_attr "length" "8")]
8884 (define_insn "*not_signextract_onebit"
8885 [(set (match_operand:SI 0 "s_register_operand" "=r")
8887 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8889 (match_operand:SI 2 "const_int_operand" "n"))))
8890 (clobber (reg:CC CC_REGNUM))]
8893 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8894 output_asm_insn (\"tst\\t%1, %2\", operands);
8895 output_asm_insn (\"mvneq\\t%0, #0\", operands);
8896 return \"movne\\t%0, #0\";
8898 [(set_attr "conds" "clob")
8899 (set_attr "length" "12")]
8902 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
8903 ;; expressions. For simplicity, the first register is also in the unspec
8905 (define_insn "*push_multi"
8906 [(match_parallel 2 "multi_register_push"
8907 [(set (match_operand:BLK 0 "memory_operand" "=m")
8908 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8909 UNSPEC_PUSH_MULT))])]
8913 int num_saves = XVECLEN (operands[2], 0);
8915 /* For the StrongARM at least it is faster to
8916 use STR to store only a single register. */
8918 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8924 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
8926 for (i = 1; i < num_saves; i++)
8928 strcat (pattern, \", %|\");
8930 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
8933 strcat (pattern, \"}\");
8934 output_asm_insn (pattern, operands);
8939 [(set_attr "type" "store4")]
8942 (define_insn "stack_tie"
8943 [(set (mem:BLK (scratch))
8944 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
8945 (match_operand:SI 1 "s_register_operand" "r")]
8949 [(set_attr "length" "0")]
8952 ;; Similarly for the floating point registers
8953 (define_insn "*push_fp_multi"
8954 [(match_parallel 2 "multi_register_push"
8955 [(set (match_operand:BLK 0 "memory_operand" "=m")
8956 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
8957 UNSPEC_PUSH_MULT))])]
8963 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
8964 output_asm_insn (pattern, operands);
8967 [(set_attr "type" "f_store")]
8970 ;; Special patterns for dealing with the constant pool
8972 (define_insn "align_4"
8973 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
8976 assemble_align (32);
8981 (define_insn "consttable_end"
8982 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
8985 making_const_table = FALSE;
8990 (define_insn "consttable_1"
8991 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
8994 making_const_table = TRUE;
8995 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
8999 [(set_attr "length" "4")]
9002 (define_insn "consttable_2"
9003 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9006 making_const_table = TRUE;
9007 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9011 [(set_attr "length" "4")]
9014 (define_insn "consttable_4"
9015 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9019 making_const_table = TRUE;
9020 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9025 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9026 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9030 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9035 [(set_attr "length" "4")]
9038 (define_insn "consttable_8"
9039 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9043 making_const_table = TRUE;
9044 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9049 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9050 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9054 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9059 [(set_attr "length" "8")]
9062 ;; Miscellaneous Thumb patterns
9064 (define_expand "tablejump"
9065 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9066 (use (label_ref (match_operand 1 "" "")))])]
9071 /* Hopefully, CSE will eliminate this copy. */
9072 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
9073 rtx reg2 = gen_reg_rtx (SImode);
9075 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
9081 (define_insn "*thumb_tablejump"
9082 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9083 (use (label_ref (match_operand 1 "" "")))]
9086 [(set_attr "length" "2")]
9092 [(set (match_operand:SI 0 "s_register_operand" "=r")
9093 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")]
9095 "TARGET_ARM && arm_arch5"
9098 (define_expand "ffssi2"
9099 [(set (match_operand:SI 0 "s_register_operand" "")
9100 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9101 "TARGET_ARM && arm_arch5"
9106 t1 = gen_reg_rtx (SImode);
9107 t2 = gen_reg_rtx (SImode);
9108 t3 = gen_reg_rtx (SImode);
9110 emit_insn (gen_negsi2 (t1, operands[1]));
9111 emit_insn (gen_andsi3 (t2, operands[1], t1));
9112 emit_insn (gen_clz (t3, t2));
9113 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
9118 ;; V5E instructions.
9120 (define_insn "prefetch"
9121 [(prefetch (match_operand:SI 0 "address_operand" "p")
9122 (match_operand:SI 1 "" "")
9123 (match_operand:SI 2 "" ""))]
9124 "TARGET_ARM && arm_arch5e"
9127 ;; General predication pattern
9130 [(match_operator 0 "arm_comparison_operator"
9131 [(match_operand 1 "cc_register" "")
9137 (define_insn "prologue_use"
9138 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
9140 "%@ %0 needed for prologue"