1 ;;- Machine description for ARM for GNU compiler
2 ;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;; 2001, 2002 Free Software Foundation, Inc.
4 ;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;; and Martin Simmons (@harleqn.co.uk).
6 ;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
8 ;; This file is part of GNU CC.
10 ;; GNU CC is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; GNU CC is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU CC; see the file COPYING. If not, write to
22 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
27 ;; There are patterns in this file to support XFmode arithmetic.
28 ;; Unfortunately RISC iX doesn't work well with these so they are disabled.
31 ;;---------------------------------------------------------------------------
36 [(IP_REGNUM 12) ; Scratch register
37 (SP_REGNUM 13) ; Stack pointer
38 (LR_REGNUM 14) ; Return address register
39 (PC_REGNUM 15) ; Program counter
40 (CC_REGNUM 24) ; Condition code pseudo register
46 ;; Note: sin and cos are no-longer used.
49 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
50 ; operand 0 is the result,
51 ; operand 1 the parameter.
52 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
53 ; operand 0 is the result,
54 ; operand 1 the parameter.
55 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
56 ; operand 0 is the first register,
57 ; subsequent registers are in parallel (use ...)
59 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
60 ; usage, that is, we will add the pic_register
61 ; value to it before trying to dereference it.
62 (UNSPEC_PRLG_STK 4) ; A special barrier that prevents frame accesses
63 ; being scheduled before the stack adjustment insn.
64 (UNSPEC_CLZ 5) ; `clz' instruction, count leading zeros (SImode):
65 ; operand 0 is the result,
66 ; operand 1 is the parameter.
67 (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
68 ; this unspec is used to prevent the deletion of
69 ; instructions setting registers for EH handling
70 ; and stack frame generation. Operand 0 is the
75 ;; UNSPEC_VOLATILE Usage:
78 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
80 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
81 ; instruction epilogue sequence that isn't expanded
82 ; into normal RTL. Used for both normal and sibcall
84 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
85 ; for inlined constants.
86 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
88 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
90 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
92 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
94 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
99 ;;---------------------------------------------------------------------------
102 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
103 ; generating ARM code. This is used to control the length of some insn
104 ; patterns that share the same RTL in both ARM and Thumb code.
105 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
107 ; PROG_MODE attribute is used to determine whether condition codes are
108 ; clobbered by a call insn: they are if in prog32 mode. This is controlled
109 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
110 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
112 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
113 ; scheduling decisions for the load unit and the multiplier.
114 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
116 ;; Operand number of an input operand that is shifted. Zero if the
117 ;; given instruction does not shift one of its input operands.
118 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_is_xscale")))
119 (define_attr "shift" "" (const_int 0))
121 ; Floating Point Unit. If we only have floating point emulation, then there
122 ; is no point in scheduling the floating point insns. (Well, for best
123 ; performance we should try and group them together).
124 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
126 ; LENGTH of an instruction (in bytes)
127 (define_attr "length" "" (const_int 4))
129 ; POOL_RANGE is how far away from a constant pool entry that this insn
130 ; can be placed. If the distance is zero, then this insn will never
131 ; reference the pool.
132 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
133 ; before its address.
134 (define_attr "pool_range" "" (const_int 0))
135 (define_attr "neg_pool_range" "" (const_int 0))
137 ; An assembler sequence may clobber the condition codes without us knowing.
138 (define_asm_attributes
139 [(set_attr "conds" "clob")])
141 ; TYPE attribute is used to detect floating point instructions which, if
142 ; running on a co-processor can run in parallel with other, basic instructions
143 ; If write-buffer scheduling is enabled then it can also be used in the
144 ; scheduling of writes.
146 ; Classification of each insn
147 ; normal any data instruction that doesn't hit memory or fp regs
148 ; mult a multiply instruction
149 ; block blockage insn, this blocks all functional units
150 ; float a floating point arithmetic operation (subject to expansion)
151 ; fdivx XFmode floating point division
152 ; fdivd DFmode floating point division
153 ; fdivs SFmode floating point division
154 ; fmul Floating point multiply
155 ; ffmul Fast floating point multiply
156 ; farith Floating point arithmetic (4 cycle)
157 ; ffarith Fast floating point arithmetic (2 cycle)
158 ; float_em a floating point arithmetic operation that is normally emulated
159 ; even on a machine with an fpa.
160 ; f_load a floating point load from memory
161 ; f_store a floating point store to memory
162 ; f_mem_r a transfer of a floating point register to a real reg via mem
163 ; r_mem_f the reverse of f_mem_r
164 ; f_2_r fast transfer float to arm (no memory needed)
165 ; r_2_f fast transfer arm to float
166 ; call a subroutine call
167 ; load any load from memory
168 ; store1 store 1 word to memory from arm registers
169 ; store2 store 2 words
170 ; store3 store 3 words
171 ; store4 store 4 words
174 "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"
175 (const_string "normal"))
177 ; Load scheduling, set from the arm_ld_sched variable
178 ; initialised by arm_override_options()
179 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
181 ; condition codes: this one is used by final_prescan_insn to speed up
182 ; conditionalizing instructions. It saves having to scan the rtl to see if
183 ; it uses or alters the condition codes.
185 ; USE means that the condition codes are used by the insn in the process of
186 ; outputting code, this means (at present) that we can't use the insn in
189 ; SET means that the purpose of the insn is to set the condition codes in a
190 ; well defined manner.
192 ; CLOB means that the condition codes are altered in an undefined manner, if
193 ; they are altered at all
195 ; JUMP_CLOB is used when the condition cannot be represented by a single
196 ; instruction (UNEQ and LTGT). These cannot be predicated.
198 ; NOCOND means that the condition codes are neither altered nor affect the
199 ; output of this insn
201 (define_attr "conds" "use,set,clob,jump_clob,nocond"
202 (if_then_else (eq_attr "type" "call")
203 (if_then_else (eq_attr "prog_mode" "prog32")
204 (const_string "clob") (const_string "nocond"))
205 (const_string "nocond")))
207 ; Predicable means that the insn can be conditionally executed based on
208 ; an automatically added predicate (additional patterns are generated by
209 ; gen...). We default to 'no' because no Thumb patterns match this rule
210 ; and not all ARM patterns do.
211 (define_attr "predicable" "no,yes" (const_string "no"))
213 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
214 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
215 ; suffer blockages enough to warrent modelling this (and it can adversely
216 ; affect the schedule).
217 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
219 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
220 ; to stall the processor. Used with model_wbuf above.
221 (define_attr "write_conflict" "no,yes"
222 (if_then_else (eq_attr "type"
223 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
225 (const_string "no")))
227 ; Classify the insns into those that take one cycle and those that take more
228 ; than one on the main cpu execution unit.
229 (define_attr "core_cycles" "single,multi"
230 (if_then_else (eq_attr "type"
231 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
232 (const_string "single")
233 (const_string "multi")))
235 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
236 ;; distant label. Only applicable to Thumb code.
237 (define_attr "far_jump" "yes,no" (const_string "no"))
239 ;; (define_function_unit {name} {num-units} {n-users} {test}
240 ;; {ready-delay} {issue-delay} [{conflict-list}])
242 ;;--------------------------------------------------------------------
243 ;; Floating point unit (FPA)
244 ;;--------------------------------------------------------------------
245 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
246 (eq_attr "type" "fdivx")) 71 69)
248 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
249 (eq_attr "type" "fdivd")) 59 57)
251 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
252 (eq_attr "type" "fdivs")) 31 29)
254 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
255 (eq_attr "type" "fmul")) 9 7)
257 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
258 (eq_attr "type" "ffmul")) 6 4)
260 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
261 (eq_attr "type" "farith")) 4 2)
263 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
264 (eq_attr "type" "ffarith")) 2 2)
266 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
267 (eq_attr "type" "r_2_f")) 5 3)
269 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
270 (eq_attr "type" "f_2_r")) 1 2)
272 ; The fpa10 doesn't really have a memory read unit, but it can start to
273 ; speculatively execute the instruction in the pipeline, provided the data
274 ; is already loaded, so pretend reads have a delay of 2 (and that the
275 ; pipeline is infinite).
277 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
278 (eq_attr "type" "f_load")) 3 1)
280 ;;--------------------------------------------------------------------
282 ;;--------------------------------------------------------------------
283 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
285 ; The write buffer on some of the arm6 processors is hard to model exactly.
286 ; There is room in the buffer for up to two addresses and up to eight words
287 ; of memory, but the two needn't be split evenly. When writing the two
288 ; addresses are fully pipelined. However, a read from memory that is not
289 ; currently in the cache will block until the writes have completed.
290 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
291 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
292 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
293 ; cycle to add as well.
295 (define_function_unit "write_buf" 1 2
296 (and (eq_attr "model_wbuf" "yes")
297 (eq_attr "type" "store1,r_mem_f")) 5 3)
298 (define_function_unit "write_buf" 1 2
299 (and (eq_attr "model_wbuf" "yes")
300 (eq_attr "type" "store2")) 7 4)
301 (define_function_unit "write_buf" 1 2
302 (and (eq_attr "model_wbuf" "yes")
303 (eq_attr "type" "store3")) 9 5)
304 (define_function_unit "write_buf" 1 2
305 (and (eq_attr "model_wbuf" "yes")
306 (eq_attr "type" "store4")) 11 6)
308 ;;--------------------------------------------------------------------
309 ;; Write blockage unit
310 ;;--------------------------------------------------------------------
311 ; The write_blockage unit models (partially), the fact that reads will stall
312 ; until the write buffer empties.
313 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
314 ; so we don't model them here
315 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
316 (eq_attr "type" "store1")) 5 5
317 [(eq_attr "write_conflict" "yes")])
318 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
319 (eq_attr "type" "store2")) 7 7
320 [(eq_attr "write_conflict" "yes")])
321 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
322 (eq_attr "type" "store3")) 9 9
323 [(eq_attr "write_conflict" "yes")])
324 (define_function_unit "write_blockage" 1 0
325 (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
326 [(eq_attr "write_conflict" "yes")])
327 (define_function_unit "write_blockage" 1 0
328 (and (eq_attr "model_wbuf" "yes")
329 (eq_attr "write_conflict" "yes")) 1 1)
331 ;;--------------------------------------------------------------------
333 ;;--------------------------------------------------------------------
334 ; Everything must spend at least one cycle in the core unit
335 (define_function_unit "core" 1 0 (eq_attr "core_cycles" "single") 1 1)
337 (define_function_unit "core" 1 0
338 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
340 (define_function_unit "core" 1 0
341 (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
343 ;; We do not need to conditionalize the define_function_unit immediately
344 ;; above. This one will be ignored for anything other than xscale
345 ;; compiles and for xscale compiles it provides a larger delay
346 ;; and the scheduler will DTRT.
347 ;; FIXME: this test needs to be revamped to not depend on this feature
350 (define_function_unit "core" 1 0
351 (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
352 (eq_attr "is_xscale" "yes"))
355 (define_function_unit "core" 1 0
356 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
358 (define_function_unit "core" 1 0
359 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
361 (define_function_unit "core" 1 0
362 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
364 (define_function_unit "core" 1 0
365 (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
367 (define_function_unit "core" 1 0
368 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
370 (define_function_unit "core" 1 0
371 (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
373 (define_function_unit "core" 1 0
374 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
375 (eq_attr "type" "mult")) 4 4)
377 (define_function_unit "core" 1 0
378 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
379 (eq_attr "type" "mult")) 3 2)
381 (define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
383 (define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
385 (define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
387 (define_function_unit "core" 1 0
388 (and (eq_attr "core_cycles" "multi")
389 (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
391 ;;---------------------------------------------------------------------------
396 ;; Note: For DImode insns, there is normally no reason why operands should
397 ;; not be in the same register, what we don't want is for something being
398 ;; written to partially overlap something that is an input.
400 (define_expand "adddi3"
402 [(set (match_operand:DI 0 "s_register_operand" "")
403 (plus:DI (match_operand:DI 1 "s_register_operand" "")
404 (match_operand:DI 2 "s_register_operand" "")))
405 (clobber (reg:CC CC_REGNUM))])]
410 if (GET_CODE (operands[1]) != REG)
411 operands[1] = force_reg (SImode, operands[1]);
412 if (GET_CODE (operands[2]) != REG)
413 operands[2] = force_reg (SImode, operands[2]);
418 (define_insn "*thumb_adddi3"
419 [(set (match_operand:DI 0 "register_operand" "=l")
420 (plus:DI (match_operand:DI 1 "register_operand" "%0")
421 (match_operand:DI 2 "register_operand" "l")))
422 (clobber (reg:CC CC_REGNUM))
425 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
426 [(set_attr "length" "4")]
429 (define_insn_and_split "*arm_adddi3"
430 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
431 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
432 (match_operand:DI 2 "s_register_operand" "r, 0")))
433 (clobber (reg:CC CC_REGNUM))]
436 "TARGET_ARM && reload_completed"
437 [(parallel [(set (reg:CC_C CC_REGNUM)
438 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
440 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
441 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
442 (plus:SI (match_dup 4) (match_dup 5))))]
445 operands[3] = gen_highpart (SImode, operands[0]);
446 operands[0] = gen_lowpart (SImode, operands[0]);
447 operands[4] = gen_highpart (SImode, operands[1]);
448 operands[1] = gen_lowpart (SImode, operands[1]);
449 operands[5] = gen_highpart (SImode, operands[2]);
450 operands[2] = gen_lowpart (SImode, operands[2]);
452 [(set_attr "conds" "clob")
453 (set_attr "length" "8")]
456 (define_insn_and_split "*adddi_sesidi_di"
457 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
458 (plus:DI (sign_extend:DI
459 (match_operand:SI 2 "s_register_operand" "r,r"))
460 (match_operand:DI 1 "s_register_operand" "r,0")))
461 (clobber (reg:CC CC_REGNUM))]
464 "TARGET_ARM && reload_completed"
465 [(parallel [(set (reg:CC_C CC_REGNUM)
466 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
468 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
469 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
470 (plus:SI (ashiftrt:SI (match_dup 2)
475 operands[3] = gen_highpart (SImode, operands[0]);
476 operands[0] = gen_lowpart (SImode, operands[0]);
477 operands[4] = gen_highpart (SImode, operands[1]);
478 operands[1] = gen_lowpart (SImode, operands[1]);
479 operands[2] = gen_lowpart (SImode, operands[2]);
481 [(set_attr "conds" "clob")
482 (set_attr "length" "8")]
485 (define_insn_and_split "*adddi_zesidi_di"
486 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
487 (plus:DI (zero_extend:DI
488 (match_operand:SI 2 "s_register_operand" "r,r"))
489 (match_operand:DI 1 "s_register_operand" "r,0")))
490 (clobber (reg:CC CC_REGNUM))]
493 "TARGET_ARM && reload_completed"
494 [(parallel [(set (reg:CC_C CC_REGNUM)
495 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
497 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
498 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
499 (plus:SI (match_dup 4) (const_int 0))))]
502 operands[3] = gen_highpart (SImode, operands[0]);
503 operands[0] = gen_lowpart (SImode, operands[0]);
504 operands[4] = gen_highpart (SImode, operands[1]);
505 operands[1] = gen_lowpart (SImode, operands[1]);
506 operands[2] = gen_lowpart (SImode, operands[2]);
508 [(set_attr "conds" "clob")
509 (set_attr "length" "8")]
512 (define_expand "addsi3"
513 [(set (match_operand:SI 0 "s_register_operand" "")
514 (plus:SI (match_operand:SI 1 "s_register_operand" "")
515 (match_operand:SI 2 "reg_or_int_operand" "")))]
518 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
520 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
522 (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
528 ; If there is a scratch available, this will be faster than synthesising the
531 [(match_scratch:SI 3 "r")
532 (set (match_operand:SI 0 "s_register_operand" "")
533 (plus:SI (match_operand:SI 1 "s_register_operand" "")
534 (match_operand:SI 2 "const_int_operand" "")))]
536 !(const_ok_for_arm (INTVAL (operands[2]))
537 || const_ok_for_arm (-INTVAL (operands[2])))
538 && const_ok_for_arm (~INTVAL (operands[2]))"
539 [(set (match_dup 3) (match_dup 2))
540 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
544 (define_insn_and_split "*arm_addsi3"
545 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
546 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
547 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
554 GET_CODE (operands[2]) == CONST_INT
555 && !(const_ok_for_arm (INTVAL (operands[2]))
556 || const_ok_for_arm (-INTVAL (operands[2])))"
557 [(clobber (const_int 0))]
559 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
563 [(set_attr "length" "4,4,16")
564 (set_attr "predicable" "yes")]
567 ;; Register group 'k' is a single register group containing only the stack
568 ;; register. Trying to reload it will always fail catastrophically,
569 ;; so never allow those alternatives to match if reloading is needed.
571 (define_insn "*thumb_addsi3"
572 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
573 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
574 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
577 static const char * const asms[] =
579 \"add\\t%0, %0, %2\",
580 \"sub\\t%0, %0, #%n2\",
581 \"add\\t%0, %1, %2\",
582 \"add\\t%0, %0, %2\",
583 \"add\\t%0, %0, %2\",
584 \"add\\t%0, %1, %2\",
587 if ((which_alternative == 2 || which_alternative == 6)
588 && GET_CODE (operands[2]) == CONST_INT
589 && INTVAL (operands[2]) < 0)
590 return \"sub\\t%0, %1, #%n2\";
591 return asms[which_alternative];
593 [(set_attr "length" "2")]
596 ;; Reloading and elimination of the frame pointer can
597 ;; sometimes cause this optimization to be missed.
599 [(set (match_operand:SI 0 "register_operand" "")
600 (match_operand:SI 1 "const_int_operand" ""))
602 (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
604 && REGNO (operands[2]) == STACK_POINTER_REGNUM
605 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
606 && (INTVAL (operands[1]) & 3) == 0"
607 [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
611 (define_insn "*addsi3_compare0"
612 [(set (reg:CC_NOOV CC_REGNUM)
614 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
615 (match_operand:SI 2 "arm_add_operand" "rI,L"))
617 (set (match_operand:SI 0 "s_register_operand" "=r,r")
618 (plus:SI (match_dup 1) (match_dup 2)))]
622 sub%?s\\t%0, %1, #%n2"
623 [(set_attr "conds" "set")]
626 (define_insn "*addsi3_compare0_scratch"
627 [(set (reg:CC_NOOV CC_REGNUM)
629 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
630 (match_operand:SI 1 "arm_add_operand" "rI,L"))
636 [(set_attr "conds" "set")]
639 ;; These patterns are the same ones as the two regular addsi3_compare0
640 ;; patterns, except we write them slightly different - the combiner
641 ;; tends to generate them this way.
642 (define_insn "*addsi3_compare0_for_combiner"
643 [(set (reg:CC CC_REGNUM)
645 (match_operand:SI 1 "s_register_operand" "r,r")
646 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
647 (set (match_operand:SI 0 "s_register_operand" "=r,r")
648 (plus:SI (match_dup 1) (match_dup 2)))]
652 sub%?s\\t%0, %1, #%n2"
653 [(set_attr "conds" "set")]
656 (define_insn "*addsi3_compare0_scratch_for_combiner"
657 [(set (reg:CC CC_REGNUM)
659 (match_operand:SI 0 "s_register_operand" "r,r")
660 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
665 [(set_attr "conds" "set")]
668 ;; The next four insns work because they compare the result with one of
669 ;; the operands, and we know that the use of the condition code is
670 ;; either GEU or LTU, so we can use the carry flag from the addition
671 ;; instead of doing the compare a second time.
672 (define_insn "*addsi3_compare_op1"
673 [(set (reg:CC_C CC_REGNUM)
675 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
676 (match_operand:SI 2 "arm_add_operand" "rI,L"))
678 (set (match_operand:SI 0 "s_register_operand" "=r,r")
679 (plus:SI (match_dup 1) (match_dup 2)))]
683 sub%?s\\t%0, %1, #%n2"
684 [(set_attr "conds" "set")]
687 (define_insn "*addsi3_compare_op2"
688 [(set (reg:CC_C CC_REGNUM)
690 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
691 (match_operand:SI 2 "arm_add_operand" "rI,L"))
693 (set (match_operand:SI 0 "s_register_operand" "=r,r")
694 (plus:SI (match_dup 1) (match_dup 2)))]
698 sub%?s\\t%0, %1, #%n2"
699 [(set_attr "conds" "set")]
702 (define_insn "*compare_addsi2_op0"
703 [(set (reg:CC_C CC_REGNUM)
705 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
706 (match_operand:SI 1 "arm_add_operand" "rI,L"))
712 [(set_attr "conds" "set")]
715 (define_insn "*compare_addsi2_op1"
716 [(set (reg:CC_C CC_REGNUM)
718 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
719 (match_operand:SI 1 "arm_add_operand" "rI,L"))
725 [(set_attr "conds" "set")]
728 (define_insn "*addsi3_carryin"
729 [(set (match_operand:SI 0 "s_register_operand" "=r")
730 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
731 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
732 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
735 [(set_attr "conds" "use")]
738 (define_insn "*addsi3_carryin_shift"
739 [(set (match_operand:SI 0 "s_register_operand" "")
740 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
742 (match_operator:SI 2 "shift_operator"
743 [(match_operand:SI 3 "s_register_operand" "")
744 (match_operand:SI 4 "reg_or_int_operand" "")])
745 (match_operand:SI 1 "s_register_operand" ""))))]
747 "adc%?\\t%0, %1, %3%S2"
748 [(set_attr "conds" "use")]
751 (define_insn "*addsi3_carryin_alt1"
752 [(set (match_operand:SI 0 "s_register_operand" "=r")
753 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
754 (match_operand:SI 2 "arm_rhs_operand" "rI"))
755 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
758 [(set_attr "conds" "use")]
761 (define_insn "*addsi3_carryin_alt2"
762 [(set (match_operand:SI 0 "s_register_operand" "=r")
763 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
764 (match_operand:SI 1 "s_register_operand" "r"))
765 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
768 [(set_attr "conds" "use")]
771 (define_insn "*addsi3_carryin_alt3"
772 [(set (match_operand:SI 0 "s_register_operand" "=r")
773 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
774 (match_operand:SI 2 "arm_rhs_operand" "rI"))
775 (match_operand:SI 1 "s_register_operand" "r")))]
778 [(set_attr "conds" "use")]
781 (define_insn "incscc"
782 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
783 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
784 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
785 (match_operand:SI 1 "s_register_operand" "0,?r")))]
789 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
790 [(set_attr "conds" "use")
791 (set_attr "length" "4,8")]
794 (define_insn "addsf3"
795 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
796 (plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
797 (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
798 "TARGET_ARM && TARGET_HARD_FLOAT"
801 suf%?s\\t%0, %1, #%N2"
802 [(set_attr "type" "farith")
803 (set_attr "predicable" "yes")]
806 (define_insn "adddf3"
807 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
808 (plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
809 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
810 "TARGET_ARM && TARGET_HARD_FLOAT"
813 suf%?d\\t%0, %1, #%N2"
814 [(set_attr "type" "farith")
815 (set_attr "predicable" "yes")]
818 (define_insn "*adddf_esfdf_df"
819 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
820 (plus:DF (float_extend:DF
821 (match_operand:SF 1 "s_register_operand" "f,f"))
822 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
823 "TARGET_ARM && TARGET_HARD_FLOAT"
826 suf%?d\\t%0, %1, #%N2"
827 [(set_attr "type" "farith")
828 (set_attr "predicable" "yes")]
831 (define_insn "*adddf_df_esfdf"
832 [(set (match_operand:DF 0 "s_register_operand" "=f")
833 (plus:DF (match_operand:DF 1 "s_register_operand" "f")
835 (match_operand:SF 2 "s_register_operand" "f"))))]
836 "TARGET_ARM && TARGET_HARD_FLOAT"
837 "adf%?d\\t%0, %1, %2"
838 [(set_attr "type" "farith")
839 (set_attr "predicable" "yes")]
842 (define_insn "*adddf_esfdf_esfdf"
843 [(set (match_operand:DF 0 "s_register_operand" "=f")
844 (plus:DF (float_extend:DF
845 (match_operand:SF 1 "s_register_operand" "f"))
847 (match_operand:SF 2 "s_register_operand" "f"))))]
848 "TARGET_ARM && TARGET_HARD_FLOAT"
849 "adf%?d\\t%0, %1, %2"
850 [(set_attr "type" "farith")
851 (set_attr "predicable" "yes")]
854 (define_insn "addxf3"
855 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
856 (plus:XF (match_operand:XF 1 "s_register_operand" "f,f")
857 (match_operand:XF 2 "fpu_add_operand" "fG,H")))]
858 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
861 suf%?e\\t%0, %1, #%N2"
862 [(set_attr "type" "farith")
863 (set_attr "predicable" "yes")]
866 (define_expand "subdi3"
868 [(set (match_operand:DI 0 "s_register_operand" "")
869 (minus:DI (match_operand:DI 1 "s_register_operand" "")
870 (match_operand:DI 2 "s_register_operand" "")))
871 (clobber (reg:CC CC_REGNUM))])]
876 if (GET_CODE (operands[1]) != REG)
877 operands[1] = force_reg (SImode, operands[1]);
878 if (GET_CODE (operands[2]) != REG)
879 operands[2] = force_reg (SImode, operands[2]);
884 (define_insn "*arm_subdi3"
885 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
886 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
887 (match_operand:DI 2 "s_register_operand" "r,0,0")))
888 (clobber (reg:CC CC_REGNUM))]
890 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
891 [(set_attr "conds" "clob")
892 (set_attr "length" "8")]
895 (define_insn "*thumb_subdi3"
896 [(set (match_operand:DI 0 "register_operand" "=l")
897 (minus:DI (match_operand:DI 1 "register_operand" "0")
898 (match_operand:DI 2 "register_operand" "l")))
899 (clobber (reg:CC CC_REGNUM))]
901 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
902 [(set_attr "length" "4")]
905 (define_insn "*subdi_di_zesidi"
906 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
907 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
909 (match_operand:SI 2 "s_register_operand" "r,r"))))
910 (clobber (reg:CC CC_REGNUM))]
912 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
913 [(set_attr "conds" "clob")
914 (set_attr "length" "8")]
917 (define_insn "*subdi_di_sesidi"
918 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
919 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
921 (match_operand:SI 2 "s_register_operand" "r,r"))))
922 (clobber (reg:CC CC_REGNUM))]
924 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
925 [(set_attr "conds" "clob")
926 (set_attr "length" "8")]
929 (define_insn "*subdi_zesidi_di"
930 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
931 (minus:DI (zero_extend:DI
932 (match_operand:SI 2 "s_register_operand" "r,r"))
933 (match_operand:DI 1 "s_register_operand" "?r,0")))
934 (clobber (reg:CC CC_REGNUM))]
936 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
937 [(set_attr "conds" "clob")
938 (set_attr "length" "8")]
941 (define_insn "*subdi_sesidi_di"
942 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
943 (minus:DI (sign_extend:DI
944 (match_operand:SI 2 "s_register_operand" "r,r"))
945 (match_operand:DI 1 "s_register_operand" "?r,0")))
946 (clobber (reg:CC CC_REGNUM))]
948 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
949 [(set_attr "conds" "clob")
950 (set_attr "length" "8")]
953 (define_insn "*subdi_zesidi_zesidi"
954 [(set (match_operand:DI 0 "s_register_operand" "=r")
955 (minus:DI (zero_extend:DI
956 (match_operand:SI 1 "s_register_operand" "r"))
958 (match_operand:SI 2 "s_register_operand" "r"))))
959 (clobber (reg:CC CC_REGNUM))]
961 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
962 [(set_attr "conds" "clob")
963 (set_attr "length" "8")]
966 (define_expand "subsi3"
967 [(set (match_operand:SI 0 "s_register_operand" "")
968 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
969 (match_operand:SI 2 "s_register_operand" "")))]
972 if (GET_CODE (operands[1]) == CONST_INT)
976 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
979 : preserve_subexpressions_p ()));
982 else /* TARGET_THUMB */
983 operands[1] = force_reg (SImode, operands[1]);
988 (define_insn "*thumb_subsi3_insn"
989 [(set (match_operand:SI 0 "register_operand" "=l")
990 (minus:SI (match_operand:SI 1 "register_operand" "l")
991 (match_operand:SI 2 "register_operand" "l")))]
994 [(set_attr "length" "2")]
997 (define_insn_and_split "*arm_subsi3_insn"
998 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
999 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
1000 (match_operand:SI 2 "s_register_operand" "r,r")))]
1006 && GET_CODE (operands[1]) == CONST_INT
1007 && !const_ok_for_arm (INTVAL (operands[1]))"
1008 [(clobber (const_int 0))]
1010 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1014 [(set_attr "length" "4,16")
1015 (set_attr "predicable" "yes")]
1019 [(match_scratch:SI 3 "r")
1020 (set (match_operand:SI 0 "s_register_operand" "")
1021 (minus:SI (match_operand:SI 1 "const_int_operand" "")
1022 (match_operand:SI 2 "s_register_operand" "")))]
1024 && !const_ok_for_arm (INTVAL (operands[1]))
1025 && const_ok_for_arm (~INTVAL (operands[1]))"
1026 [(set (match_dup 3) (match_dup 1))
1027 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1031 (define_insn "*subsi3_compare0"
1032 [(set (reg:CC_NOOV CC_REGNUM)
1034 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1035 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1037 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1038 (minus:SI (match_dup 1) (match_dup 2)))]
1042 rsb%?s\\t%0, %2, %1"
1043 [(set_attr "conds" "set")]
1046 (define_insn "decscc"
1047 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1048 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1049 (match_operator:SI 2 "arm_comparison_operator"
1050 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1054 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1055 [(set_attr "conds" "use")
1056 (set_attr "length" "*,8")]
1059 (define_insn "subsf3"
1060 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1061 (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1062 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1063 "TARGET_ARM && TARGET_HARD_FLOAT"
1066 rsf%?s\\t%0, %2, %1"
1067 [(set_attr "type" "farith")]
1070 (define_insn "subdf3"
1071 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1072 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1073 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1074 "TARGET_ARM && TARGET_HARD_FLOAT"
1077 rsf%?d\\t%0, %2, %1"
1078 [(set_attr "type" "farith")
1079 (set_attr "predicable" "yes")]
1082 (define_insn "*subdf_esfdf_df"
1083 [(set (match_operand:DF 0 "s_register_operand" "=f")
1084 (minus:DF (float_extend:DF
1085 (match_operand:SF 1 "s_register_operand" "f"))
1086 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1087 "TARGET_ARM && TARGET_HARD_FLOAT"
1088 "suf%?d\\t%0, %1, %2"
1089 [(set_attr "type" "farith")
1090 (set_attr "predicable" "yes")]
1093 (define_insn "*subdf_df_esfdf"
1094 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1095 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1097 (match_operand:SF 2 "s_register_operand" "f,f"))))]
1098 "TARGET_ARM && TARGET_HARD_FLOAT"
1101 rsf%?d\\t%0, %2, %1"
1102 [(set_attr "type" "farith")
1103 (set_attr "predicable" "yes")]
1106 (define_insn "*subdf_esfdf_esfdf"
1107 [(set (match_operand:DF 0 "s_register_operand" "=f")
1108 (minus:DF (float_extend:DF
1109 (match_operand:SF 1 "s_register_operand" "f"))
1111 (match_operand:SF 2 "s_register_operand" "f"))))]
1112 "TARGET_ARM && TARGET_HARD_FLOAT"
1113 "suf%?d\\t%0, %1, %2"
1114 [(set_attr "type" "farith")
1115 (set_attr "predicable" "yes")]
1118 (define_insn "subxf3"
1119 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1120 (minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1121 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1122 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1125 rsf%?e\\t%0, %2, %1"
1126 [(set_attr "type" "farith")
1127 (set_attr "predicable" "yes")]
1130 ;; Multiplication insns
1132 (define_expand "mulsi3"
1133 [(set (match_operand:SI 0 "s_register_operand" "")
1134 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1135 (match_operand:SI 1 "s_register_operand" "")))]
1140 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1141 (define_insn "*arm_mulsi3"
1142 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1143 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1144 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1146 "mul%?\\t%0, %2, %1"
1147 [(set_attr "type" "mult")
1148 (set_attr "predicable" "yes")]
1151 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1152 ; 1 and 2; are the same, because reload will make operand 0 match
1153 ; operand 1 without realizing that this conflicts with operand 2. We fix
1154 ; this by adding another alternative to match this case, and then `reload'
1155 ; it ourselves. This alternative must come first.
1156 (define_insn "*thumb_mulsi3"
1157 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1158 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1159 (match_operand:SI 2 "register_operand" "l,l,l")))]
1162 if (which_alternative < 2)
1163 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1165 return \"mul\\t%0, %0, %2\";
1167 [(set_attr "length" "4,4,2")
1168 (set_attr "type" "mult")]
1171 (define_insn "*mulsi3_compare0"
1172 [(set (reg:CC_NOOV CC_REGNUM)
1173 (compare:CC_NOOV (mult:SI
1174 (match_operand:SI 2 "s_register_operand" "r,r")
1175 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1177 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1178 (mult:SI (match_dup 2) (match_dup 1)))]
1179 "TARGET_ARM && !arm_is_xscale"
1180 "mul%?s\\t%0, %2, %1"
1181 [(set_attr "conds" "set")
1182 (set_attr "type" "mult")]
1185 (define_insn "*mulsi_compare0_scratch"
1186 [(set (reg:CC_NOOV CC_REGNUM)
1187 (compare:CC_NOOV (mult:SI
1188 (match_operand:SI 2 "s_register_operand" "r,r")
1189 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1191 (clobber (match_scratch:SI 0 "=&r,&r"))]
1192 "TARGET_ARM && !arm_is_xscale"
1193 "mul%?s\\t%0, %2, %1"
1194 [(set_attr "conds" "set")
1195 (set_attr "type" "mult")]
1198 ;; Unnamed templates to match MLA instruction.
1200 (define_insn "*mulsi3addsi"
1201 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1203 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1204 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1205 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1207 "mla%?\\t%0, %2, %1, %3"
1208 [(set_attr "type" "mult")
1209 (set_attr "predicable" "yes")]
1212 (define_insn "*mulsi3addsi_compare0"
1213 [(set (reg:CC_NOOV CC_REGNUM)
1216 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1217 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1218 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1220 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1221 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1223 "TARGET_ARM && !arm_is_xscale"
1224 "mla%?s\\t%0, %2, %1, %3"
1225 [(set_attr "conds" "set")
1226 (set_attr "type" "mult")]
1229 (define_insn "*mulsi3addsi_compare0_scratch"
1230 [(set (reg:CC_NOOV CC_REGNUM)
1233 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1234 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1235 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1237 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1238 "TARGET_ARM && !arm_is_xscale"
1239 "mla%?s\\t%0, %2, %1, %3"
1240 [(set_attr "conds" "set")
1241 (set_attr "type" "mult")]
1244 ;; Unnamed template to match long long multiply-accumlate (smlal)
1246 (define_insn "*mulsidi3adddi"
1247 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1250 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1251 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1252 (match_operand:DI 1 "s_register_operand" "0")))]
1253 "TARGET_ARM && arm_fast_multiply"
1254 "smlal%?\\t%Q0, %R0, %3, %2"
1255 [(set_attr "type" "mult")
1256 (set_attr "predicable" "yes")]
1259 (define_insn "mulsidi3"
1260 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1262 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1263 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1264 "TARGET_ARM && arm_fast_multiply"
1265 "smull%?\\t%Q0, %R0, %1, %2"
1266 [(set_attr "type" "mult")
1267 (set_attr "predicable" "yes")]
1270 (define_insn "umulsidi3"
1271 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1273 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1274 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1275 "TARGET_ARM && arm_fast_multiply"
1276 "umull%?\\t%Q0, %R0, %1, %2"
1277 [(set_attr "type" "mult")
1278 (set_attr "predicable" "yes")]
1281 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1283 (define_insn "*umulsidi3adddi"
1284 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1287 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1288 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1289 (match_operand:DI 1 "s_register_operand" "0")))]
1290 "TARGET_ARM && arm_fast_multiply"
1291 "umlal%?\\t%Q0, %R0, %3, %2"
1292 [(set_attr "type" "mult")
1293 (set_attr "predicable" "yes")]
1296 (define_insn "smulsi3_highpart"
1297 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1301 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1302 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1304 (clobber (match_scratch:SI 3 "=&r,&r"))]
1305 "TARGET_ARM && arm_fast_multiply"
1306 "smull%?\\t%3, %0, %2, %1"
1307 [(set_attr "type" "mult")
1308 (set_attr "predicable" "yes")]
1311 (define_insn "umulsi3_highpart"
1312 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1316 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1317 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1319 (clobber (match_scratch:SI 3 "=&r,&r"))]
1320 "TARGET_ARM && arm_fast_multiply"
1321 "umull%?\\t%3, %0, %2, %1"
1322 [(set_attr "type" "mult")
1323 (set_attr "predicable" "yes")]
1326 (define_insn "mulhisi3"
1327 [(set (match_operand:SI 0 "s_register_operand" "=r")
1328 (mult:SI (sign_extend:SI
1329 (match_operand:HI 1 "s_register_operand" "%r"))
1331 (match_operand:HI 2 "s_register_operand" "r"))))]
1332 "TARGET_ARM && arm_is_xscale"
1333 "smulbb%?\\t%0, %1, %2"
1334 [(set_attr "type" "mult")]
1337 (define_insn "*mulhisi3addsi"
1338 [(set (match_operand:SI 0 "s_register_operand" "=r")
1339 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1340 (mult:SI (sign_extend:SI
1341 (match_operand:HI 2 "s_register_operand" "%r"))
1343 (match_operand:HI 3 "s_register_operand" "r")))))]
1344 "TARGET_ARM && arm_is_xscale"
1345 "smlabb%?\\t%0, %2, %3, %1"
1346 [(set_attr "type" "mult")]
1349 (define_insn "*mulhidi3adddi"
1350 [(set (match_operand:DI 0 "s_register_operand" "=r")
1352 (match_operand:DI 1 "s_register_operand" "0")
1353 (mult:DI (sign_extend:DI
1354 (match_operand:HI 2 "s_register_operand" "%r"))
1356 (match_operand:HI 3 "s_register_operand" "r")))))]
1357 "TARGET_ARM && arm_is_xscale"
1358 "smlalbb%?\\t%Q0, %R0, %2, %3"
1359 [(set_attr "type" "mult")])
1361 (define_insn "mulsf3"
1362 [(set (match_operand:SF 0 "s_register_operand" "=f")
1363 (mult:SF (match_operand:SF 1 "s_register_operand" "f")
1364 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1365 "TARGET_ARM && TARGET_HARD_FLOAT"
1366 "fml%?s\\t%0, %1, %2"
1367 [(set_attr "type" "ffmul")
1368 (set_attr "predicable" "yes")]
1371 (define_insn "muldf3"
1372 [(set (match_operand:DF 0 "s_register_operand" "=f")
1373 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1374 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1375 "TARGET_ARM && TARGET_HARD_FLOAT"
1376 "muf%?d\\t%0, %1, %2"
1377 [(set_attr "type" "fmul")
1378 (set_attr "predicable" "yes")]
1381 (define_insn "*muldf_esfdf_df"
1382 [(set (match_operand:DF 0 "s_register_operand" "=f")
1383 (mult:DF (float_extend:DF
1384 (match_operand:SF 1 "s_register_operand" "f"))
1385 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1386 "TARGET_ARM && TARGET_HARD_FLOAT"
1387 "muf%?d\\t%0, %1, %2"
1388 [(set_attr "type" "fmul")
1389 (set_attr "predicable" "yes")]
1392 (define_insn "*muldf_df_esfdf"
1393 [(set (match_operand:DF 0 "s_register_operand" "=f")
1394 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1396 (match_operand:SF 2 "s_register_operand" "f"))))]
1397 "TARGET_ARM && TARGET_HARD_FLOAT"
1398 "muf%?d\\t%0, %1, %2"
1399 [(set_attr "type" "fmul")
1400 (set_attr "predicable" "yes")]
1403 (define_insn "*muldf_esfdf_esfdf"
1404 [(set (match_operand:DF 0 "s_register_operand" "=f")
1406 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f"))
1407 (float_extend:DF (match_operand:SF 2 "s_register_operand" "f"))))]
1408 "TARGET_ARM && TARGET_HARD_FLOAT"
1409 "muf%?d\\t%0, %1, %2"
1410 [(set_attr "type" "fmul")
1411 (set_attr "predicable" "yes")]
1414 (define_insn "mulxf3"
1415 [(set (match_operand:XF 0 "s_register_operand" "=f")
1416 (mult:XF (match_operand:XF 1 "s_register_operand" "f")
1417 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1418 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1419 "muf%?e\\t%0, %1, %2"
1420 [(set_attr "type" "fmul")
1421 (set_attr "predicable" "yes")]
1426 (define_insn "divsf3"
1427 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1428 (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1429 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1430 "TARGET_ARM && TARGET_HARD_FLOAT"
1433 frd%?s\\t%0, %2, %1"
1434 [(set_attr "type" "fdivs")
1435 (set_attr "predicable" "yes")]
1438 (define_insn "divdf3"
1439 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1440 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1441 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1442 "TARGET_ARM && TARGET_HARD_FLOAT"
1445 rdf%?d\\t%0, %2, %1"
1446 [(set_attr "type" "fdivd")
1447 (set_attr "predicable" "yes")]
1450 (define_insn "*divdf_esfdf_df"
1451 [(set (match_operand:DF 0 "s_register_operand" "=f")
1452 (div:DF (float_extend:DF
1453 (match_operand:SF 1 "s_register_operand" "f"))
1454 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1455 "TARGET_ARM && TARGET_HARD_FLOAT"
1456 "dvf%?d\\t%0, %1, %2"
1457 [(set_attr "type" "fdivd")
1458 (set_attr "predicable" "yes")]
1461 (define_insn "*divdf_df_esfdf"
1462 [(set (match_operand:DF 0 "s_register_operand" "=f")
1463 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1465 (match_operand:SF 2 "s_register_operand" "f"))))]
1466 "TARGET_ARM && TARGET_HARD_FLOAT"
1467 "rdf%?d\\t%0, %2, %1"
1468 [(set_attr "type" "fdivd")
1469 (set_attr "predicable" "yes")]
1472 (define_insn "*divdf_esfdf_esfdf"
1473 [(set (match_operand:DF 0 "s_register_operand" "=f")
1474 (div:DF (float_extend:DF
1475 (match_operand:SF 1 "s_register_operand" "f"))
1477 (match_operand:SF 2 "s_register_operand" "f"))))]
1478 "TARGET_ARM && TARGET_HARD_FLOAT"
1479 "dvf%?d\\t%0, %1, %2"
1480 [(set_attr "type" "fdivd")
1481 (set_attr "predicable" "yes")]
1484 (define_insn "divxf3"
1485 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1486 (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1487 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1488 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1491 rdf%?e\\t%0, %2, %1"
1492 [(set_attr "type" "fdivx")
1493 (set_attr "predicable" "yes")]
1498 (define_insn "modsf3"
1499 [(set (match_operand:SF 0 "s_register_operand" "=f")
1500 (mod:SF (match_operand:SF 1 "s_register_operand" "f")
1501 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1502 "TARGET_ARM && TARGET_HARD_FLOAT"
1503 "rmf%?s\\t%0, %1, %2"
1504 [(set_attr "type" "fdivs")
1505 (set_attr "predicable" "yes")]
1508 (define_insn "moddf3"
1509 [(set (match_operand:DF 0 "s_register_operand" "=f")
1510 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1511 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1512 "TARGET_ARM && TARGET_HARD_FLOAT"
1513 "rmf%?d\\t%0, %1, %2"
1514 [(set_attr "type" "fdivd")
1515 (set_attr "predicable" "yes")]
1518 (define_insn "*moddf_esfdf_df"
1519 [(set (match_operand:DF 0 "s_register_operand" "=f")
1520 (mod:DF (float_extend:DF
1521 (match_operand:SF 1 "s_register_operand" "f"))
1522 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1523 "TARGET_ARM && TARGET_HARD_FLOAT"
1524 "rmf%?d\\t%0, %1, %2"
1525 [(set_attr "type" "fdivd")
1526 (set_attr "predicable" "yes")]
1529 (define_insn "*moddf_df_esfdf"
1530 [(set (match_operand:DF 0 "s_register_operand" "=f")
1531 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1533 (match_operand:SF 2 "s_register_operand" "f"))))]
1534 "TARGET_ARM && TARGET_HARD_FLOAT"
1535 "rmf%?d\\t%0, %1, %2"
1536 [(set_attr "type" "fdivd")
1537 (set_attr "predicable" "yes")]
1540 (define_insn "*moddf_esfdf_esfdf"
1541 [(set (match_operand:DF 0 "s_register_operand" "=f")
1542 (mod:DF (float_extend:DF
1543 (match_operand:SF 1 "s_register_operand" "f"))
1545 (match_operand:SF 2 "s_register_operand" "f"))))]
1546 "TARGET_ARM && TARGET_HARD_FLOAT"
1547 "rmf%?d\\t%0, %1, %2"
1548 [(set_attr "type" "fdivd")
1549 (set_attr "predicable" "yes")]
1552 (define_insn "modxf3"
1553 [(set (match_operand:XF 0 "s_register_operand" "=f")
1554 (mod:XF (match_operand:XF 1 "s_register_operand" "f")
1555 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1556 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1557 "rmf%?e\\t%0, %1, %2"
1558 [(set_attr "type" "fdivx")
1559 (set_attr "predicable" "yes")]
1562 ;; Boolean and,ior,xor insns
1564 ;; Split up double word logical operations
1566 ;; Split up simple DImode logical operations. Simply perform the logical
1567 ;; operation on the upper and lower halves of the registers.
1569 [(set (match_operand:DI 0 "s_register_operand" "")
1570 (match_operator:DI 6 "logical_binary_operator"
1571 [(match_operand:DI 1 "s_register_operand" "")
1572 (match_operand:DI 2 "s_register_operand" "")]))]
1573 "TARGET_ARM && reload_completed"
1574 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1575 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1578 operands[3] = gen_highpart (SImode, operands[0]);
1579 operands[0] = gen_lowpart (SImode, operands[0]);
1580 operands[4] = gen_highpart (SImode, operands[1]);
1581 operands[1] = gen_lowpart (SImode, operands[1]);
1582 operands[5] = gen_highpart (SImode, operands[2]);
1583 operands[2] = gen_lowpart (SImode, operands[2]);
1588 [(set (match_operand:DI 0 "s_register_operand" "")
1589 (match_operator:DI 6 "logical_binary_operator"
1590 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1591 (match_operand:DI 1 "s_register_operand" "")]))]
1592 "TARGET_ARM && reload_completed"
1593 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1594 (set (match_dup 3) (match_op_dup:SI 6
1595 [(ashiftrt:SI (match_dup 2) (const_int 31))
1599 operands[3] = gen_highpart (SImode, operands[0]);
1600 operands[0] = gen_lowpart (SImode, operands[0]);
1601 operands[4] = gen_highpart (SImode, operands[1]);
1602 operands[1] = gen_lowpart (SImode, operands[1]);
1603 operands[5] = gen_highpart (SImode, operands[2]);
1604 operands[2] = gen_lowpart (SImode, operands[2]);
1608 ;; The zero extend of operand 2 means we can just copy the high part of
1609 ;; operand1 into operand0.
1611 [(set (match_operand:DI 0 "s_register_operand" "")
1613 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1614 (match_operand:DI 1 "s_register_operand" "")))]
1615 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1616 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1617 (set (match_dup 3) (match_dup 4))]
1620 operands[4] = gen_highpart (SImode, operands[1]);
1621 operands[3] = gen_highpart (SImode, operands[0]);
1622 operands[0] = gen_lowpart (SImode, operands[0]);
1623 operands[1] = gen_lowpart (SImode, operands[1]);
1627 ;; The zero extend of operand 2 means we can just copy the high part of
1628 ;; operand1 into operand0.
1630 [(set (match_operand:DI 0 "s_register_operand" "")
1632 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1633 (match_operand:DI 1 "s_register_operand" "")))]
1634 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1635 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1636 (set (match_dup 3) (match_dup 4))]
1639 operands[4] = gen_highpart (SImode, operands[1]);
1640 operands[3] = gen_highpart (SImode, operands[0]);
1641 operands[0] = gen_lowpart (SImode, operands[0]);
1642 operands[1] = gen_lowpart (SImode, operands[1]);
1646 (define_insn "anddi3"
1647 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1648 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1649 (match_operand:DI 2 "s_register_operand" "r,r")))]
1652 [(set_attr "length" "8")]
1655 (define_insn_and_split "*anddi_zesidi_di"
1656 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1657 (and:DI (zero_extend:DI
1658 (match_operand:SI 2 "s_register_operand" "r,r"))
1659 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1662 "TARGET_ARM && reload_completed"
1663 ; The zero extend of operand 2 clears the high word of the output
1665 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1666 (set (match_dup 3) (const_int 0))]
1669 operands[3] = gen_highpart (SImode, operands[0]);
1670 operands[0] = gen_lowpart (SImode, operands[0]);
1671 operands[1] = gen_lowpart (SImode, operands[1]);
1673 [(set_attr "length" "8")]
1676 (define_insn "*anddi_sesdi_di"
1677 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1678 (and:DI (sign_extend:DI
1679 (match_operand:SI 2 "s_register_operand" "r,r"))
1680 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1683 [(set_attr "length" "8")]
1686 (define_expand "andsi3"
1687 [(set (match_operand:SI 0 "s_register_operand" "")
1688 (and:SI (match_operand:SI 1 "s_register_operand" "")
1689 (match_operand:SI 2 "reg_or_int_operand" "")))]
1694 if (GET_CODE (operands[2]) == CONST_INT)
1696 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1699 ? 0 : preserve_subexpressions_p ()));
1703 else /* TARGET_THUMB */
1705 if (GET_CODE (operands[2]) != CONST_INT)
1706 operands[2] = force_reg (SImode, operands[2]);
1711 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1713 operands[2] = force_reg (SImode,
1714 GEN_INT (~INTVAL (operands[2])));
1716 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1721 for (i = 9; i <= 31; i++)
1723 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1725 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1729 else if ((((HOST_WIDE_INT) 1) << i) - 1
1730 == ~INTVAL (operands[2]))
1732 rtx shift = GEN_INT (i);
1733 rtx reg = gen_reg_rtx (SImode);
1735 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1736 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1742 operands[2] = force_reg (SImode, operands[2]);
1748 (define_insn_and_split "*arm_andsi3_insn"
1749 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1750 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1751 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1755 bic%?\\t%0, %1, #%B2
1758 && GET_CODE (operands[2]) == CONST_INT
1759 && !(const_ok_for_arm (INTVAL (operands[2]))
1760 || const_ok_for_arm (~INTVAL (operands[2])))"
1761 [(clobber (const_int 0))]
1763 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1767 [(set_attr "length" "4,4,16")
1768 (set_attr "predicable" "yes")]
1771 (define_insn "*thumb_andsi3_insn"
1772 [(set (match_operand:SI 0 "register_operand" "=l")
1773 (and:SI (match_operand:SI 1 "register_operand" "%0")
1774 (match_operand:SI 2 "register_operand" "l")))]
1777 [(set_attr "length" "2")]
1780 (define_insn "*andsi3_compare0"
1781 [(set (reg:CC_NOOV CC_REGNUM)
1783 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1784 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1786 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1787 (and:SI (match_dup 1) (match_dup 2)))]
1791 bic%?s\\t%0, %1, #%B2"
1792 [(set_attr "conds" "set")]
1795 (define_insn "*andsi3_compare0_scratch"
1796 [(set (reg:CC_NOOV CC_REGNUM)
1798 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1799 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1801 (clobber (match_scratch:SI 2 "=X,r"))]
1805 bic%?s\\t%2, %0, #%B1"
1806 [(set_attr "conds" "set")]
1809 (define_insn "*zeroextractsi_compare0_scratch"
1810 [(set (reg:CC_NOOV CC_REGNUM)
1811 (compare:CC_NOOV (zero_extract:SI
1812 (match_operand:SI 0 "s_register_operand" "r")
1813 (match_operand 1 "const_int_operand" "n")
1814 (match_operand 2 "const_int_operand" "n"))
1817 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1818 && INTVAL (operands[1]) > 0
1819 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1820 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1822 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1823 << INTVAL (operands[2]));
1824 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1827 [(set_attr "conds" "set")]
1830 (define_insn "*ne_zeroextractsi"
1831 [(set (match_operand:SI 0 "s_register_operand" "=r")
1832 (ne:SI (zero_extract:SI
1833 (match_operand:SI 1 "s_register_operand" "r")
1834 (match_operand:SI 2 "const_int_operand" "n")
1835 (match_operand:SI 3 "const_int_operand" "n"))
1838 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1839 && INTVAL (operands[2]) > 0
1840 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1841 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1843 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1844 << INTVAL (operands[3]));
1845 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1846 return \"movne\\t%0, #1\";
1848 [(set_attr "conds" "clob")
1849 (set_attr "length" "8")]
1852 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1853 ;;; represented by the bitfield, then this will produce incorrect results.
1854 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1855 ;;; which have a real bitfield insert instruction, the truncation happens
1856 ;;; in the bitfield insert instruction itself. Since arm does not have a
1857 ;;; bitfield insert instruction, we would have to emit code here to truncate
1858 ;;; the value before we insert. This loses some of the advantage of having
1859 ;;; this insv pattern, so this pattern needs to be reevalutated.
1861 (define_expand "insv"
1862 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1863 (match_operand:SI 1 "general_operand" "")
1864 (match_operand:SI 2 "general_operand" ""))
1865 (match_operand:SI 3 "nonmemory_operand" ""))]
1869 int start_bit = INTVAL (operands[2]);
1870 int width = INTVAL (operands[1]);
1871 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1872 rtx target, subtarget;
1874 target = operands[0];
1875 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1876 subreg as the final target. */
1877 if (GET_CODE (target) == SUBREG)
1879 subtarget = gen_reg_rtx (SImode);
1880 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1881 < GET_MODE_SIZE (SImode))
1882 target = SUBREG_REG (target);
1887 if (GET_CODE (operands[3]) == CONST_INT)
1889 /* Since we are inserting a known constant, we may be able to
1890 reduce the number of bits that we have to clear so that
1891 the mask becomes simple. */
1892 /* ??? This code does not check to see if the new mask is actually
1893 simpler. It may not be. */
1894 rtx op1 = gen_reg_rtx (SImode);
1895 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1896 start of this pattern. */
1897 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1898 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1900 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1901 emit_insn (gen_iorsi3 (subtarget, op1,
1902 GEN_INT (op3_value << start_bit)));
1904 else if (start_bit == 0
1905 && !(const_ok_for_arm (mask)
1906 || const_ok_for_arm (~mask)))
1908 /* A Trick, since we are setting the bottom bits in the word,
1909 we can shift operand[3] up, operand[0] down, OR them together
1910 and rotate the result back again. This takes 3 insns, and
1911 the third might be mergable into another op. */
1912 /* The shift up copes with the possibility that operand[3] is
1913 wider than the bitfield. */
1914 rtx op0 = gen_reg_rtx (SImode);
1915 rtx op1 = gen_reg_rtx (SImode);
1917 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1918 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1919 emit_insn (gen_iorsi3 (op1, op1, op0));
1920 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1922 else if ((width + start_bit == 32)
1923 && !(const_ok_for_arm (mask)
1924 || const_ok_for_arm (~mask)))
1926 /* Similar trick, but slightly less efficient. */
1928 rtx op0 = gen_reg_rtx (SImode);
1929 rtx op1 = gen_reg_rtx (SImode);
1931 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1932 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1933 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1934 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1938 rtx op0 = GEN_INT (mask);
1939 rtx op1 = gen_reg_rtx (SImode);
1940 rtx op2 = gen_reg_rtx (SImode);
1942 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1944 rtx tmp = gen_reg_rtx (SImode);
1946 emit_insn (gen_movsi (tmp, op0));
1950 /* Mask out any bits in operand[3] that are not needed. */
1951 emit_insn (gen_andsi3 (op1, operands[3], op0));
1953 if (GET_CODE (op0) == CONST_INT
1954 && (const_ok_for_arm (mask << start_bit)
1955 || const_ok_for_arm (~(mask << start_bit))))
1957 op0 = GEN_INT (~(mask << start_bit));
1958 emit_insn (gen_andsi3 (op2, operands[0], op0));
1962 if (GET_CODE (op0) == CONST_INT)
1964 rtx tmp = gen_reg_rtx (SImode);
1966 emit_insn (gen_movsi (tmp, op0));
1971 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1973 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1977 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1979 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1982 if (subtarget != target)
1984 /* If TARGET is still a SUBREG, then it must be wider than a word,
1985 so we must be careful only to set the subword we were asked to. */
1986 if (GET_CODE (target) == SUBREG)
1987 emit_move_insn (target, subtarget);
1989 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1996 ; constants for op 2 will never be given to these patterns.
1997 (define_insn_and_split "*anddi_notdi_di"
1998 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1999 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2000 (match_operand:DI 2 "s_register_operand" "0,r")))]
2003 "TARGET_ARM && reload_completed"
2004 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2005 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2008 operands[3] = gen_highpart (SImode, operands[0]);
2009 operands[0] = gen_lowpart (SImode, operands[0]);
2010 operands[4] = gen_highpart (SImode, operands[1]);
2011 operands[1] = gen_lowpart (SImode, operands[1]);
2012 operands[5] = gen_highpart (SImode, operands[2]);
2013 operands[2] = gen_lowpart (SImode, operands[2]);
2015 [(set_attr "length" "8")
2016 (set_attr "predicable" "yes")]
2019 (define_insn_and_split "*anddi_notzesidi_di"
2020 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2021 (and:DI (not:DI (zero_extend:DI
2022 (match_operand:SI 2 "s_register_operand" "r,r")))
2023 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2026 bic%?\\t%Q0, %Q1, %2
2028 ; (not (zero_extend ...)) allows us to just copy the high word from
2029 ; operand1 to operand0.
2032 && operands[0] != operands[1]"
2033 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2034 (set (match_dup 3) (match_dup 4))]
2037 operands[3] = gen_highpart (SImode, operands[0]);
2038 operands[0] = gen_lowpart (SImode, operands[0]);
2039 operands[4] = gen_highpart (SImode, operands[1]);
2040 operands[1] = gen_lowpart (SImode, operands[1]);
2042 [(set_attr "length" "4,8")
2043 (set_attr "predicable" "yes")]
2046 (define_insn_and_split "*anddi_notsesidi_di"
2047 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2048 (and:DI (not:DI (sign_extend:DI
2049 (match_operand:SI 2 "s_register_operand" "r,r")))
2050 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2053 "TARGET_ARM && reload_completed"
2054 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2055 (set (match_dup 3) (and:SI (not:SI
2056 (ashiftrt:SI (match_dup 2) (const_int 31)))
2060 operands[3] = gen_highpart (SImode, operands[0]);
2061 operands[0] = gen_lowpart (SImode, operands[0]);
2062 operands[4] = gen_highpart (SImode, operands[1]);
2063 operands[1] = gen_lowpart (SImode, operands[1]);
2065 [(set_attr "length" "8")
2066 (set_attr "predicable" "yes")]
2069 (define_insn "andsi_notsi_si"
2070 [(set (match_operand:SI 0 "s_register_operand" "=r")
2071 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2072 (match_operand:SI 1 "s_register_operand" "r")))]
2074 "bic%?\\t%0, %1, %2"
2075 [(set_attr "predicable" "yes")]
2078 (define_insn "bicsi3"
2079 [(set (match_operand:SI 0 "register_operand" "=l")
2080 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2081 (match_operand:SI 2 "register_operand" "0")))]
2084 [(set_attr "length" "2")]
2087 (define_insn "andsi_not_shiftsi_si"
2088 [(set (match_operand:SI 0 "s_register_operand" "=r")
2089 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2090 [(match_operand:SI 2 "s_register_operand" "r")
2091 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2092 (match_operand:SI 1 "s_register_operand" "r")))]
2094 "bic%?\\t%0, %1, %2%S4"
2095 [(set_attr "predicable" "yes")
2096 (set_attr "shift" "2")
2100 (define_insn "*andsi_notsi_si_compare0"
2101 [(set (reg:CC_NOOV CC_REGNUM)
2103 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2104 (match_operand:SI 1 "s_register_operand" "r"))
2106 (set (match_operand:SI 0 "s_register_operand" "=r")
2107 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2109 "bic%?s\\t%0, %1, %2"
2110 [(set_attr "conds" "set")]
2113 (define_insn "*andsi_notsi_si_compare0_scratch"
2114 [(set (reg:CC_NOOV CC_REGNUM)
2116 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2117 (match_operand:SI 1 "s_register_operand" "r"))
2119 (clobber (match_scratch:SI 0 "=r"))]
2121 "bic%?s\\t%0, %1, %2"
2122 [(set_attr "conds" "set")]
2125 (define_insn "iordi3"
2126 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2127 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2128 (match_operand:DI 2 "s_register_operand" "r,r")))]
2131 [(set_attr "length" "8")
2132 (set_attr "predicable" "yes")]
2135 (define_insn "*iordi_zesidi_di"
2136 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2137 (ior:DI (zero_extend:DI
2138 (match_operand:SI 2 "s_register_operand" "r,r"))
2139 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2142 orr%?\\t%Q0, %Q1, %2
2144 [(set_attr "length" "4,8")
2145 (set_attr "predicable" "yes")]
2148 (define_insn "*iordi_sesidi_di"
2149 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2150 (ior:DI (sign_extend:DI
2151 (match_operand:SI 2 "s_register_operand" "r,r"))
2152 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2155 [(set_attr "length" "8")
2156 (set_attr "predicable" "yes")]
2159 (define_expand "iorsi3"
2160 [(set (match_operand:SI 0 "s_register_operand" "")
2161 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2162 (match_operand:SI 2 "reg_or_int_operand" "")))]
2165 if (GET_CODE (operands[2]) == CONST_INT)
2169 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2172 ? 0 : preserve_subexpressions_p ()));
2175 else /* TARGET_THUMB */
2176 operands [2] = force_reg (SImode, operands [2]);
2181 (define_insn_and_split "*arm_iorsi3"
2182 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2183 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2184 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2190 && GET_CODE (operands[2]) == CONST_INT
2191 && !const_ok_for_arm (INTVAL (operands[2]))"
2192 [(clobber (const_int 0))]
2194 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2198 [(set_attr "length" "4,16")
2199 (set_attr "predicable" "yes")]
2202 (define_insn "*thumb_iorsi3"
2203 [(set (match_operand:SI 0 "register_operand" "=l")
2204 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2205 (match_operand:SI 2 "register_operand" "l")))]
2208 [(set_attr "length" "2")]
2212 [(match_scratch:SI 3 "r")
2213 (set (match_operand:SI 0 "s_register_operand" "")
2214 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2215 (match_operand:SI 2 "const_int_operand" "")))]
2217 && !const_ok_for_arm (INTVAL (operands[2]))
2218 && const_ok_for_arm (~INTVAL (operands[2]))"
2219 [(set (match_dup 3) (match_dup 2))
2220 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2224 (define_insn "*iorsi3_compare0"
2225 [(set (reg:CC_NOOV CC_REGNUM)
2226 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2227 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2229 (set (match_operand:SI 0 "s_register_operand" "=r")
2230 (ior:SI (match_dup 1) (match_dup 2)))]
2232 "orr%?s\\t%0, %1, %2"
2233 [(set_attr "conds" "set")]
2236 (define_insn "*iorsi3_compare0_scratch"
2237 [(set (reg:CC_NOOV CC_REGNUM)
2238 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2239 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2241 (clobber (match_scratch:SI 0 "=r"))]
2243 "orr%?s\\t%0, %1, %2"
2244 [(set_attr "conds" "set")]
2247 (define_insn "xordi3"
2248 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2249 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2250 (match_operand:DI 2 "s_register_operand" "r,r")))]
2253 [(set_attr "length" "8")
2254 (set_attr "predicable" "yes")]
2257 (define_insn "*xordi_zesidi_di"
2258 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2259 (xor:DI (zero_extend:DI
2260 (match_operand:SI 2 "s_register_operand" "r,r"))
2261 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2264 eor%?\\t%Q0, %Q1, %2
2266 [(set_attr "length" "4,8")
2267 (set_attr "predicable" "yes")]
2270 (define_insn "*xordi_sesidi_di"
2271 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2272 (xor:DI (sign_extend:DI
2273 (match_operand:SI 2 "s_register_operand" "r,r"))
2274 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2277 [(set_attr "length" "8")
2278 (set_attr "predicable" "yes")]
2281 (define_expand "xorsi3"
2282 [(set (match_operand:SI 0 "s_register_operand" "")
2283 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2284 (match_operand:SI 2 "arm_rhs_operand" "")))]
2287 if (GET_CODE (operands[2]) == CONST_INT)
2288 operands[2] = force_reg (SImode, operands[2]);
2292 (define_insn "*arm_xorsi3"
2293 [(set (match_operand:SI 0 "s_register_operand" "=r")
2294 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2295 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2297 "eor%?\\t%0, %1, %2"
2298 [(set_attr "predicable" "yes")]
2301 (define_insn "*thumb_xorsi3"
2302 [(set (match_operand:SI 0 "register_operand" "=l")
2303 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2304 (match_operand:SI 2 "register_operand" "l")))]
2307 [(set_attr "length" "2")]
2310 (define_insn "*xorsi3_compare0"
2311 [(set (reg:CC_NOOV CC_REGNUM)
2312 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2313 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2315 (set (match_operand:SI 0 "s_register_operand" "=r")
2316 (xor:SI (match_dup 1) (match_dup 2)))]
2318 "eor%?s\\t%0, %1, %2"
2319 [(set_attr "conds" "set")]
2322 (define_insn "*xorsi3_compare0_scratch"
2323 [(set (reg:CC_NOOV CC_REGNUM)
2324 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2325 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2329 [(set_attr "conds" "set")]
2332 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2333 ; (NOT D) we can sometimes merge the final NOT into one of the following
2337 [(set (match_operand:SI 0 "s_register_operand" "")
2338 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2339 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2340 (match_operand:SI 3 "arm_rhs_operand" "")))
2341 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2343 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2344 (not:SI (match_dup 3))))
2345 (set (match_dup 0) (not:SI (match_dup 4)))]
2349 (define_insn "*andsi_iorsi3_notsi"
2350 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2351 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2352 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2353 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2355 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2356 [(set_attr "length" "8")
2357 (set_attr "predicable" "yes")]
2362 ;; Minimum and maximum insns
2364 (define_insn "smaxsi3"
2365 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2366 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2367 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2368 (clobber (reg:CC CC_REGNUM))]
2371 cmp\\t%1, %2\;movlt\\t%0, %2
2372 cmp\\t%1, %2\;movge\\t%0, %1
2373 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2374 [(set_attr "conds" "clob")
2375 (set_attr "length" "8,8,12")]
2378 (define_insn "sminsi3"
2379 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2380 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2381 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2382 (clobber (reg:CC CC_REGNUM))]
2385 cmp\\t%1, %2\;movge\\t%0, %2
2386 cmp\\t%1, %2\;movlt\\t%0, %1
2387 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2388 [(set_attr "conds" "clob")
2389 (set_attr "length" "8,8,12")]
2392 (define_insn "umaxsi3"
2393 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2394 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2395 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2396 (clobber (reg:CC CC_REGNUM))]
2399 cmp\\t%1, %2\;movcc\\t%0, %2
2400 cmp\\t%1, %2\;movcs\\t%0, %1
2401 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2402 [(set_attr "conds" "clob")
2403 (set_attr "length" "8,8,12")]
2406 (define_insn "uminsi3"
2407 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2408 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2409 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2410 (clobber (reg:CC CC_REGNUM))]
2413 cmp\\t%1, %2\;movcs\\t%0, %2
2414 cmp\\t%1, %2\;movcc\\t%0, %1
2415 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2416 [(set_attr "conds" "clob")
2417 (set_attr "length" "8,8,12")]
2420 (define_insn "*store_minmaxsi"
2421 [(set (match_operand:SI 0 "memory_operand" "=m")
2422 (match_operator:SI 3 "minmax_operator"
2423 [(match_operand:SI 1 "s_register_operand" "r")
2424 (match_operand:SI 2 "s_register_operand" "r")]))
2425 (clobber (reg:CC CC_REGNUM))]
2428 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2430 output_asm_insn (\"cmp\\t%1, %2\", operands);
2431 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2432 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2435 [(set_attr "conds" "clob")
2436 (set_attr "length" "12")
2437 (set_attr "type" "store1")]
2440 ; Reject the frame pointer in operand[1], since reloading this after
2441 ; it has been eliminated can cause carnage.
2442 (define_insn "*minmax_arithsi"
2443 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2444 (match_operator:SI 4 "shiftable_operator"
2445 [(match_operator:SI 5 "minmax_operator"
2446 [(match_operand:SI 2 "s_register_operand" "r,r")
2447 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2448 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2449 (clobber (reg:CC CC_REGNUM))]
2451 && (GET_CODE (operands[1]) != REG
2452 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2453 && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2456 enum rtx_code code = GET_CODE (operands[4]);
2458 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2460 output_asm_insn (\"cmp\\t%2, %3\", operands);
2461 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2462 if (which_alternative != 0 || operands[3] != const0_rtx
2463 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2464 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2467 [(set_attr "conds" "clob")
2468 (set_attr "length" "12")]
2472 ;; Shift and rotation insns
2474 (define_expand "ashlsi3"
2475 [(set (match_operand:SI 0 "s_register_operand" "")
2476 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2477 (match_operand:SI 2 "arm_rhs_operand" "")))]
2480 if (GET_CODE (operands[2]) == CONST_INT
2481 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2483 emit_insn (gen_movsi (operands[0], const0_rtx));
2489 (define_insn "*thumb_ashlsi3"
2490 [(set (match_operand:SI 0 "register_operand" "=l,l")
2491 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2492 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2495 [(set_attr "length" "2")]
2498 (define_expand "ashrsi3"
2499 [(set (match_operand:SI 0 "s_register_operand" "")
2500 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2501 (match_operand:SI 2 "arm_rhs_operand" "")))]
2504 if (GET_CODE (operands[2]) == CONST_INT
2505 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2506 operands[2] = GEN_INT (31);
2510 (define_insn "*thumb_ashrsi3"
2511 [(set (match_operand:SI 0 "register_operand" "=l,l")
2512 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2513 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2516 [(set_attr "length" "2")]
2519 (define_expand "lshrsi3"
2520 [(set (match_operand:SI 0 "s_register_operand" "")
2521 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2522 (match_operand:SI 2 "arm_rhs_operand" "")))]
2525 if (GET_CODE (operands[2]) == CONST_INT
2526 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2528 emit_insn (gen_movsi (operands[0], const0_rtx));
2534 (define_insn "*thumb_lshrsi3"
2535 [(set (match_operand:SI 0 "register_operand" "=l,l")
2536 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2537 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2540 [(set_attr "length" "2")]
2543 (define_expand "rotlsi3"
2544 [(set (match_operand:SI 0 "s_register_operand" "")
2545 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2546 (match_operand:SI 2 "reg_or_int_operand" "")))]
2549 if (GET_CODE (operands[2]) == CONST_INT)
2550 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2553 rtx reg = gen_reg_rtx (SImode);
2554 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2560 (define_expand "rotrsi3"
2561 [(set (match_operand:SI 0 "s_register_operand" "")
2562 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2563 (match_operand:SI 2 "arm_rhs_operand" "")))]
2568 if (GET_CODE (operands[2]) == CONST_INT
2569 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2570 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2572 else /* TARGET_THUMB */
2574 if (GET_CODE (operands [2]) == CONST_INT)
2575 operands [2] = force_reg (SImode, operands[2]);
2580 (define_insn "*thumb_rotrsi3"
2581 [(set (match_operand:SI 0 "register_operand" "=l")
2582 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2583 (match_operand:SI 2 "register_operand" "l")))]
2586 [(set_attr "length" "2")]
2589 (define_insn "*arm_shiftsi3"
2590 [(set (match_operand:SI 0 "s_register_operand" "=r")
2591 (match_operator:SI 3 "shift_operator"
2592 [(match_operand:SI 1 "s_register_operand" "r")
2593 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2596 [(set_attr "predicable" "yes")
2597 (set_attr "shift" "1")
2601 (define_insn "*shiftsi3_compare0"
2602 [(set (reg:CC_NOOV CC_REGNUM)
2603 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2604 [(match_operand:SI 1 "s_register_operand" "r")
2605 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2607 (set (match_operand:SI 0 "s_register_operand" "=r")
2608 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2610 "mov%?s\\t%0, %1%S3"
2611 [(set_attr "conds" "set")
2612 (set_attr "shift" "1")
2616 (define_insn "*shiftsi3_compare0_scratch"
2617 [(set (reg:CC_NOOV CC_REGNUM)
2618 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2619 [(match_operand:SI 1 "s_register_operand" "r")
2620 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2622 (clobber (match_scratch:SI 0 "=r"))]
2624 "mov%?s\\t%0, %1%S3"
2625 [(set_attr "conds" "set")
2626 (set_attr "shift" "1")
2630 (define_insn "*notsi_shiftsi"
2631 [(set (match_operand:SI 0 "s_register_operand" "=r")
2632 (not:SI (match_operator:SI 3 "shift_operator"
2633 [(match_operand:SI 1 "s_register_operand" "r")
2634 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2637 [(set_attr "predicable" "yes")
2638 (set_attr "shift" "1")
2642 (define_insn "*notsi_shiftsi_compare0"
2643 [(set (reg:CC_NOOV CC_REGNUM)
2644 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2645 [(match_operand:SI 1 "s_register_operand" "r")
2646 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2648 (set (match_operand:SI 0 "s_register_operand" "=r")
2649 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2651 "mvn%?s\\t%0, %1%S3"
2652 [(set_attr "conds" "set")
2653 (set_attr "shift" "1")
2657 (define_insn "*not_shiftsi_compare0_scratch"
2658 [(set (reg:CC_NOOV CC_REGNUM)
2659 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2660 [(match_operand:SI 1 "s_register_operand" "r")
2661 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2663 (clobber (match_scratch:SI 0 "=r"))]
2665 "mvn%?s\\t%0, %1%S3"
2666 [(set_attr "conds" "set")
2667 (set_attr "shift" "1")
2671 ;; We don't really have extzv, but defining this using shifts helps
2672 ;; to reduce register pressure later on.
2674 (define_expand "extzv"
2676 (ashift:SI (match_operand:SI 1 "register_operand" "")
2677 (match_operand:SI 2 "const_int_operand" "")))
2678 (set (match_operand:SI 0 "register_operand" "")
2679 (lshiftrt:SI (match_dup 4)
2680 (match_operand:SI 3 "const_int_operand" "")))]
2684 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2685 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2687 operands[3] = GEN_INT (rshift);
2691 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2695 operands[2] = GEN_INT (lshift);
2696 operands[4] = gen_reg_rtx (SImode);
2701 ;; Unary arithmetic insns
2703 (define_expand "negdi2"
2705 [(set (match_operand:DI 0 "s_register_operand" "")
2706 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2707 (clobber (reg:CC CC_REGNUM))])]
2712 if (GET_CODE (operands[1]) != REG)
2713 operands[1] = force_reg (SImode, operands[1]);
2718 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2719 ;; The second alternative is to allow the common case of a *full* overlap.
2720 (define_insn "*arm_negdi2"
2721 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2722 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2723 (clobber (reg:CC CC_REGNUM))]
2725 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2726 [(set_attr "conds" "clob")
2727 (set_attr "length" "8")]
2730 (define_insn "*thumb_negdi2"
2731 [(set (match_operand:DI 0 "register_operand" "=&l")
2732 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2733 (clobber (reg:CC CC_REGNUM))]
2735 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2736 [(set_attr "length" "6")]
2739 (define_expand "negsi2"
2740 [(set (match_operand:SI 0 "s_register_operand" "")
2741 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2746 (define_insn "*arm_negsi2"
2747 [(set (match_operand:SI 0 "s_register_operand" "=r")
2748 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2750 "rsb%?\\t%0, %1, #0"
2751 [(set_attr "predicable" "yes")]
2754 (define_insn "*thumb_negsi2"
2755 [(set (match_operand:SI 0 "register_operand" "=l")
2756 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2759 [(set_attr "length" "2")]
2762 (define_insn "negsf2"
2763 [(set (match_operand:SF 0 "s_register_operand" "=f")
2764 (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
2765 "TARGET_ARM && TARGET_HARD_FLOAT"
2767 [(set_attr "type" "ffarith")
2768 (set_attr "predicable" "yes")]
2771 (define_insn "negdf2"
2772 [(set (match_operand:DF 0 "s_register_operand" "=f")
2773 (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
2774 "TARGET_ARM && TARGET_HARD_FLOAT"
2776 [(set_attr "type" "ffarith")
2777 (set_attr "predicable" "yes")]
2780 (define_insn "*negdf_esfdf"
2781 [(set (match_operand:DF 0 "s_register_operand" "=f")
2782 (neg:DF (float_extend:DF
2783 (match_operand:SF 1 "s_register_operand" "f"))))]
2784 "TARGET_ARM && TARGET_HARD_FLOAT"
2786 [(set_attr "type" "ffarith")
2787 (set_attr "predicable" "yes")]
2790 (define_insn "negxf2"
2791 [(set (match_operand:XF 0 "s_register_operand" "=f")
2792 (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
2793 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2795 [(set_attr "type" "ffarith")
2796 (set_attr "predicable" "yes")]
2799 ;; abssi2 doesn't really clobber the condition codes if a different register
2800 ;; is being set. To keep things simple, assume during rtl manipulations that
2801 ;; it does, but tell the final scan operator the truth. Similarly for
2804 (define_insn "abssi2"
2805 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2806 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2807 (clobber (reg:CC CC_REGNUM))]
2810 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2811 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2812 [(set_attr "conds" "clob,*")
2813 (set_attr "shift" "1")
2814 ;; predicable can't be set based on the variant, so left as no
2815 (set_attr "length" "8")]
2818 (define_insn "*neg_abssi2"
2819 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2820 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2821 (clobber (reg:CC CC_REGNUM))]
2824 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2825 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2826 [(set_attr "conds" "clob,*")
2827 (set_attr "shift" "1")
2828 ;; predicable can't be set based on the variant, so left as no
2829 (set_attr "length" "8")]
2832 (define_insn "abssf2"
2833 [(set (match_operand:SF 0 "s_register_operand" "=f")
2834 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
2835 "TARGET_ARM && TARGET_HARD_FLOAT"
2837 [(set_attr "type" "ffarith")
2838 (set_attr "predicable" "yes")]
2841 (define_insn "absdf2"
2842 [(set (match_operand:DF 0 "s_register_operand" "=f")
2843 (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
2844 "TARGET_ARM && TARGET_HARD_FLOAT"
2846 [(set_attr "type" "ffarith")
2847 (set_attr "predicable" "yes")]
2850 (define_insn "*absdf_esfdf"
2851 [(set (match_operand:DF 0 "s_register_operand" "=f")
2852 (abs:DF (float_extend:DF
2853 (match_operand:SF 1 "s_register_operand" "f"))))]
2854 "TARGET_ARM && TARGET_HARD_FLOAT"
2856 [(set_attr "type" "ffarith")
2857 (set_attr "predicable" "yes")]
2860 (define_insn "absxf2"
2861 [(set (match_operand:XF 0 "s_register_operand" "=f")
2862 (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
2863 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2865 [(set_attr "type" "ffarith")
2866 (set_attr "predicable" "yes")]
2869 (define_insn "sqrtsf2"
2870 [(set (match_operand:SF 0 "s_register_operand" "=f")
2871 (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
2872 "TARGET_ARM && TARGET_HARD_FLOAT"
2874 [(set_attr "type" "float_em")
2875 (set_attr "predicable" "yes")]
2878 (define_insn "sqrtdf2"
2879 [(set (match_operand:DF 0 "s_register_operand" "=f")
2880 (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
2881 "TARGET_ARM && TARGET_HARD_FLOAT"
2883 [(set_attr "type" "float_em")
2884 (set_attr "predicable" "yes")]
2887 (define_insn "*sqrtdf_esfdf"
2888 [(set (match_operand:DF 0 "s_register_operand" "=f")
2889 (sqrt:DF (float_extend:DF
2890 (match_operand:SF 1 "s_register_operand" "f"))))]
2891 "TARGET_ARM && TARGET_HARD_FLOAT"
2893 [(set_attr "type" "float_em")
2894 (set_attr "predicable" "yes")]
2897 (define_insn "sqrtxf2"
2898 [(set (match_operand:XF 0 "s_register_operand" "=f")
2899 (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
2900 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2902 [(set_attr "type" "float_em")
2903 (set_attr "predicable" "yes")]
2906 ;; SIN COS TAN and family are always emulated, so it's probably better
2907 ;; to always call a library function.
2908 ;(define_insn "sinsf2"
2909 ; [(set (match_operand:SF 0 "s_register_operand" "=f")
2910 ; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
2912 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2914 ;[(set_attr "type" "float_em")])
2916 ;(define_insn "sindf2"
2917 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2918 ; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
2920 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2922 ;[(set_attr "type" "float_em")])
2924 ;(define_insn "*sindf_esfdf"
2925 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2926 ; (unspec:DF [(float_extend:DF
2927 ; (match_operand:SF 1 "s_register_operand" "f"))]
2929 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2931 ;[(set_attr "type" "float_em")])
2933 ;(define_insn "sinxf2"
2934 ; [(set (match_operand:XF 0 "s_register_operand" "=f")
2935 ; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
2937 ; "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2939 ;[(set_attr "type" "float_em")])
2941 ;(define_insn "cossf2"
2942 ; [(set (match_operand:SF 0 "s_register_operand" "=f")
2943 ; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
2945 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2947 ;[(set_attr "type" "float_em")])
2949 ;(define_insn "cosdf2"
2950 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2951 ; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
2953 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2955 ;[(set_attr "type" "float_em")])
2957 ;(define_insn "*cosdf_esfdf"
2958 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2959 ; (unspec:DF [(float_extend:DF
2960 ; (match_operand:SF 1 "s_register_operand" "f"))]
2962 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2964 ;[(set_attr "type" "float_em")])
2966 ;(define_insn "cosxf2"
2967 ; [(set (match_operand:XF 0 "s_register_operand" "=f")
2968 ; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
2970 ; "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2972 ;[(set_attr "type" "float_em")])
2974 (define_insn_and_split "one_cmpldi2"
2975 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2976 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2979 "TARGET_ARM && reload_completed"
2980 [(set (match_dup 0) (not:SI (match_dup 1)))
2981 (set (match_dup 2) (not:SI (match_dup 3)))]
2984 operands[2] = gen_highpart (SImode, operands[0]);
2985 operands[0] = gen_lowpart (SImode, operands[0]);
2986 operands[3] = gen_highpart (SImode, operands[1]);
2987 operands[1] = gen_lowpart (SImode, operands[1]);
2989 [(set_attr "length" "8")
2990 (set_attr "predicable" "yes")]
2993 (define_expand "one_cmplsi2"
2994 [(set (match_operand:SI 0 "s_register_operand" "")
2995 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3000 (define_insn "*arm_one_cmplsi2"
3001 [(set (match_operand:SI 0 "s_register_operand" "=r")
3002 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
3005 [(set_attr "predicable" "yes")]
3008 (define_insn "*thumb_one_cmplsi2"
3009 [(set (match_operand:SI 0 "register_operand" "=l")
3010 (not:SI (match_operand:SI 1 "register_operand" "l")))]
3013 [(set_attr "length" "2")]
3016 (define_insn "*notsi_compare0"
3017 [(set (reg:CC_NOOV CC_REGNUM)
3018 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3020 (set (match_operand:SI 0 "s_register_operand" "=r")
3021 (not:SI (match_dup 1)))]
3024 [(set_attr "conds" "set")]
3027 (define_insn "*notsi_compare0_scratch"
3028 [(set (reg:CC_NOOV CC_REGNUM)
3029 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3031 (clobber (match_scratch:SI 0 "=r"))]
3034 [(set_attr "conds" "set")]
3037 ;; Fixed <--> Floating conversion insns
3039 (define_insn "floatsisf2"
3040 [(set (match_operand:SF 0 "s_register_operand" "=f")
3041 (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
3042 "TARGET_ARM && TARGET_HARD_FLOAT"
3044 [(set_attr "type" "r_2_f")
3045 (set_attr "predicable" "yes")]
3048 (define_insn "floatsidf2"
3049 [(set (match_operand:DF 0 "s_register_operand" "=f")
3050 (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
3051 "TARGET_ARM && TARGET_HARD_FLOAT"
3053 [(set_attr "type" "r_2_f")
3054 (set_attr "predicable" "yes")]
3057 (define_insn "floatsixf2"
3058 [(set (match_operand:XF 0 "s_register_operand" "=f")
3059 (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
3060 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3062 [(set_attr "type" "r_2_f")
3063 (set_attr "predicable" "yes")]
3066 (define_insn "fix_truncsfsi2"
3067 [(set (match_operand:SI 0 "s_register_operand" "=r")
3068 (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
3069 "TARGET_ARM && TARGET_HARD_FLOAT"
3071 [(set_attr "type" "f_2_r")
3072 (set_attr "predicable" "yes")]
3075 (define_insn "fix_truncdfsi2"
3076 [(set (match_operand:SI 0 "s_register_operand" "=r")
3077 (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
3078 "TARGET_ARM && TARGET_HARD_FLOAT"
3080 [(set_attr "type" "f_2_r")
3081 (set_attr "predicable" "yes")]
3084 (define_insn "fix_truncxfsi2"
3085 [(set (match_operand:SI 0 "s_register_operand" "=r")
3086 (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
3087 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3089 [(set_attr "type" "f_2_r")
3090 (set_attr "predicable" "yes")]
3095 (define_insn "truncdfsf2"
3096 [(set (match_operand:SF 0 "s_register_operand" "=f")
3098 (match_operand:DF 1 "s_register_operand" "f")))]
3099 "TARGET_ARM && TARGET_HARD_FLOAT"
3101 [(set_attr "type" "ffarith")
3102 (set_attr "predicable" "yes")]
3105 (define_insn "truncxfsf2"
3106 [(set (match_operand:SF 0 "s_register_operand" "=f")
3108 (match_operand:XF 1 "s_register_operand" "f")))]
3109 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3111 [(set_attr "type" "ffarith")
3112 (set_attr "predicable" "yes")]
3115 (define_insn "truncxfdf2"
3116 [(set (match_operand:DF 0 "s_register_operand" "=f")
3118 (match_operand:XF 1 "s_register_operand" "f")))]
3119 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3121 [(set_attr "type" "ffarith")
3122 (set_attr "predicable" "yes")]
3125 ;; Zero and sign extension instructions.
3127 (define_insn "zero_extendsidi2"
3128 [(set (match_operand:DI 0 "s_register_operand" "=r")
3129 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3132 if (REGNO (operands[1])
3133 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3134 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3135 return \"mov%?\\t%R0, #0\";
3137 [(set_attr "length" "8")
3138 (set_attr "predicable" "yes")]
3141 (define_insn "zero_extendqidi2"
3142 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
3143 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3146 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3147 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3148 [(set_attr "length" "8")
3149 (set_attr "predicable" "yes")
3150 (set_attr "type" "*,load")
3151 (set_attr "pool_range" "*,4092")
3152 (set_attr "neg_pool_range" "*,4084")]
3155 (define_insn "extendsidi2"
3156 [(set (match_operand:DI 0 "s_register_operand" "=r")
3157 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3160 if (REGNO (operands[1])
3161 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3162 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3163 return \"mov%?\\t%R0, %Q0, asr #31\";
3165 [(set_attr "length" "8")
3166 (set_attr "shift" "1")
3167 (set_attr "predicable" "yes")]
3170 (define_expand "zero_extendhisi2"
3172 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3174 (set (match_operand:SI 0 "s_register_operand" "")
3175 (lshiftrt:SI (match_dup 2) (const_int 16)))]
3181 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3183 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3184 here because the insn below will generate an LDRH instruction
3185 rather than an LDR instruction, so we cannot get an unaligned
3187 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3188 gen_rtx_ZERO_EXTEND (SImode,
3192 if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3194 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3197 if (!s_register_operand (operands[1], HImode))
3198 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3199 operands[1] = gen_lowpart (SImode, operands[1]);
3200 operands[2] = gen_reg_rtx (SImode);
3202 else /* TARGET_THUMB */
3204 if (GET_CODE (operands[1]) == MEM)
3208 tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3209 tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3216 if (!s_register_operand (operands[1], HImode))
3217 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3218 operands[1] = gen_lowpart (SImode, operands[1]);
3219 operands[2] = gen_reg_rtx (SImode);
3221 ops[0] = operands[2];
3222 ops[1] = operands[1];
3223 ops[2] = GEN_INT (16);
3225 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3226 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3228 ops[0] = operands[0];
3229 ops[1] = operands[2];
3230 ops[2] = GEN_INT (16);
3232 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3233 gen_rtx_LSHIFTRT (SImode, ops[1],
3241 (define_insn "*thumb_zero_extendhisi2"
3242 [(set (match_operand:SI 0 "register_operand" "=l")
3243 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3246 rtx mem = XEXP (operands[1], 0);
3248 if (GET_CODE (mem) == CONST)
3249 mem = XEXP (mem, 0);
3251 if (GET_CODE (mem) == LABEL_REF)
3252 return \"ldr\\t%0, %1\";
3254 if (GET_CODE (mem) == PLUS)
3256 rtx a = XEXP (mem, 0);
3257 rtx b = XEXP (mem, 1);
3259 /* This can happen due to bugs in reload. */
3260 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3263 ops[0] = operands[0];
3266 output_asm_insn (\"mov %0, %1\", ops);
3268 XEXP (mem, 0) = operands[0];
3271 else if ( GET_CODE (a) == LABEL_REF
3272 && GET_CODE (b) == CONST_INT)
3273 return \"ldr\\t%0, %1\";
3276 return \"ldrh\\t%0, %1\";
3278 [(set_attr "length" "4")
3279 (set_attr "type" "load")
3280 (set_attr "pool_range" "60")]
3283 (define_insn "*arm_zero_extendhisi2"
3284 [(set (match_operand:SI 0 "s_register_operand" "=r")
3285 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3286 "TARGET_ARM && arm_arch4"
3288 [(set_attr "type" "load")
3289 (set_attr "predicable" "yes")
3290 (set_attr "pool_range" "256")
3291 (set_attr "neg_pool_range" "244")]
3295 [(set (match_operand:SI 0 "s_register_operand" "")
3296 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3297 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3298 "TARGET_ARM && (!arm_arch4)"
3299 [(set (match_dup 2) (match_dup 1))
3300 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3302 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3308 [(set (match_operand:SI 0 "s_register_operand" "")
3309 (match_operator:SI 3 "shiftable_operator"
3310 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3311 (match_operand:SI 4 "s_register_operand" "")]))
3312 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3313 "TARGET_ARM && (!arm_arch4)"
3314 [(set (match_dup 2) (match_dup 1))
3317 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3319 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3324 (define_expand "zero_extendqisi2"
3325 [(set (match_operand:SI 0 "s_register_operand" "")
3326 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3329 if (GET_CODE (operands[1]) != MEM)
3333 emit_insn (gen_andsi3 (operands[0],
3334 gen_lowpart (SImode, operands[1]),
3337 else /* TARGET_THUMB */
3339 rtx temp = gen_reg_rtx (SImode);
3342 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3343 operands[1] = gen_lowpart (SImode, operands[1]);
3346 ops[1] = operands[1];
3347 ops[2] = GEN_INT (24);
3349 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3350 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3352 ops[0] = operands[0];
3354 ops[2] = GEN_INT (24);
3356 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3357 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3364 (define_insn "*thumb_zero_extendqisi2"
3365 [(set (match_operand:SI 0 "register_operand" "=l")
3366 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3369 [(set_attr "length" "2")
3370 (set_attr "type" "load")
3371 (set_attr "pool_range" "32")]
3374 (define_insn "*arm_zero_extendqisi2"
3375 [(set (match_operand:SI 0 "s_register_operand" "=r")
3376 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3378 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3379 [(set_attr "type" "load")
3380 (set_attr "predicable" "yes")
3381 (set_attr "pool_range" "4096")
3382 (set_attr "neg_pool_range" "4084")]
3386 [(set (match_operand:SI 0 "s_register_operand" "")
3387 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3388 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3389 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3390 [(set (match_dup 2) (match_dup 1))
3391 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3395 (define_insn "*compareqi_eq0"
3396 [(set (reg:CC_Z CC_REGNUM)
3397 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3401 [(set_attr "conds" "set")]
3404 (define_expand "extendhisi2"
3406 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3408 (set (match_operand:SI 0 "s_register_operand" "")
3409 (ashiftrt:SI (match_dup 2)
3414 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3416 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3417 here because the insn below will generate an LDRH instruction
3418 rather than an LDR instruction, so we cannot get an unaligned
3420 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3421 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3425 if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3427 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3430 if (!s_register_operand (operands[1], HImode))
3431 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3432 operands[1] = gen_lowpart (SImode, operands[1]);
3433 operands[2] = gen_reg_rtx (SImode);
3439 ops[0] = operands[2];
3440 ops[1] = operands[1];
3441 ops[2] = GEN_INT (16);
3443 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3444 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3446 ops[0] = operands[0];
3447 ops[1] = operands[2];
3448 ops[2] = GEN_INT (16);
3450 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3451 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3458 (define_insn "*thumb_extendhisi2_insn"
3459 [(set (match_operand:SI 0 "register_operand" "=l")
3460 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3461 (clobber (match_scratch:SI 2 "=&l"))]
3466 rtx mem = XEXP (operands[1], 0);
3468 /* This code used to try to use 'V', and fix the address only if it was
3469 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3470 range of QImode offsets, and offsettable_address_p does a QImode
3473 if (GET_CODE (mem) == CONST)
3474 mem = XEXP (mem, 0);
3476 if (GET_CODE (mem) == LABEL_REF)
3477 return \"ldr\\t%0, %1\";
3479 if (GET_CODE (mem) == PLUS)
3481 rtx a = XEXP (mem, 0);
3482 rtx b = XEXP (mem, 1);
3484 if (GET_CODE (a) == LABEL_REF
3485 && GET_CODE (b) == CONST_INT)
3486 return \"ldr\\t%0, %1\";
3488 if (GET_CODE (b) == REG)
3489 return \"ldrsh\\t%0, %1\";
3497 ops[2] = const0_rtx;
3500 if (GET_CODE (ops[1]) != REG)
3506 ops[0] = operands[0];
3507 ops[3] = operands[2];
3508 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3511 [(set_attr "length" "4")
3512 (set_attr "type" "load")
3513 (set_attr "pool_range" "1020")]
3516 (define_expand "extendhisi2_mem"
3517 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3519 (zero_extend:SI (match_dup 7)))
3520 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3521 (set (match_operand:SI 0 "" "")
3522 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3527 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3529 mem1 = gen_rtx_MEM (QImode, addr);
3530 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3531 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3532 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3533 operands[0] = gen_lowpart (SImode, operands[0]);
3535 operands[2] = gen_reg_rtx (SImode);
3536 operands[3] = gen_reg_rtx (SImode);
3537 operands[6] = gen_reg_rtx (SImode);
3540 if (BYTES_BIG_ENDIAN)
3542 operands[4] = operands[2];
3543 operands[5] = operands[3];
3547 operands[4] = operands[3];
3548 operands[5] = operands[2];
3553 (define_insn "*arm_extendhisi_insn"
3554 [(set (match_operand:SI 0 "s_register_operand" "=r")
3555 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3556 "TARGET_ARM && arm_arch4"
3558 [(set_attr "type" "load")
3559 (set_attr "predicable" "yes")
3560 (set_attr "pool_range" "256")
3561 (set_attr "neg_pool_range" "244")]
3565 [(set (match_operand:SI 0 "s_register_operand" "")
3566 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3567 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3568 "TARGET_ARM && (!arm_arch4)"
3569 [(set (match_dup 2) (match_dup 1))
3570 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3572 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3578 [(set (match_operand:SI 0 "s_register_operand" "")
3579 (match_operator:SI 3 "shiftable_operator"
3580 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3581 (match_operand:SI 4 "s_register_operand" "")]))
3582 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3583 "TARGET_ARM && (!arm_arch4)"
3584 [(set (match_dup 2) (match_dup 1))
3587 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3588 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3593 (define_expand "extendqihi2"
3595 (ashift:SI (match_operand:QI 1 "general_operand" "")
3597 (set (match_operand:HI 0 "s_register_operand" "")
3598 (ashiftrt:SI (match_dup 2)
3603 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3605 emit_insn (gen_rtx_SET (VOIDmode,
3607 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3610 if (!s_register_operand (operands[1], QImode))
3611 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3612 operands[0] = gen_lowpart (SImode, operands[0]);
3613 operands[1] = gen_lowpart (SImode, operands[1]);
3614 operands[2] = gen_reg_rtx (SImode);
3618 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3619 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3620 (define_insn "*extendqihi_insn"
3621 [(set (match_operand:HI 0 "s_register_operand" "=r")
3622 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3623 "TARGET_ARM && arm_arch4"
3625 /* If the address is invalid, this will split the instruction into two. */
3626 if (bad_signed_byte_operand (operands[1], VOIDmode))
3628 return \"ldr%?sb\\t%0, %1\";
3630 [(set_attr "type" "load")
3631 (set_attr "predicable" "yes")
3632 (set_attr "length" "8")
3633 (set_attr "pool_range" "256")
3634 (set_attr "neg_pool_range" "244")]
3638 [(set (match_operand:HI 0 "s_register_operand" "")
3639 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3640 "TARGET_ARM && arm_arch4 && reload_completed"
3641 [(set (match_dup 3) (match_dup 1))
3642 (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3645 HOST_WIDE_INT offset;
3647 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3648 operands[2] = gen_rtx_MEM (QImode, operands[3]);
3649 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3650 operands[1] = XEXP (operands[1], 0);
3651 if (GET_CODE (operands[1]) == PLUS
3652 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3653 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3654 || const_ok_for_arm (-offset)))
3656 HOST_WIDE_INT low = (offset > 0
3657 ? (offset & 0xff) : -((-offset) & 0xff));
3658 XEXP (operands[2], 0) = plus_constant (operands[3], low);
3659 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3661 /* Ensure the sum is in correct canonical form */
3662 else if (GET_CODE (operands[1]) == PLUS
3663 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3664 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3665 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3666 XEXP (operands[1], 1),
3667 XEXP (operands[1], 0));
3671 (define_expand "extendqisi2"
3673 (ashift:SI (match_operand:QI 1 "general_operand" "")
3675 (set (match_operand:SI 0 "s_register_operand" "")
3676 (ashiftrt:SI (match_dup 2)
3681 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3683 emit_insn (gen_rtx_SET (VOIDmode,
3685 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3688 if (!s_register_operand (operands[1], QImode))
3689 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3690 operands[1] = gen_lowpart (SImode, operands[1]);
3691 operands[2] = gen_reg_rtx (SImode);
3697 ops[0] = operands[2];
3698 ops[1] = operands[1];
3699 ops[2] = GEN_INT (24);
3701 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3702 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3704 ops[0] = operands[0];
3705 ops[1] = operands[2];
3706 ops[2] = GEN_INT (24);
3708 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3709 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3716 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3717 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3718 (define_insn "*arm_extendqisi_insn"
3719 [(set (match_operand:SI 0 "s_register_operand" "=r")
3720 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3721 "TARGET_ARM && arm_arch4"
3723 /* If the address is invalid, this will split the instruction into two. */
3724 if (bad_signed_byte_operand (operands[1], VOIDmode))
3726 return \"ldr%?sb\\t%0, %1\";
3728 [(set_attr "type" "load")
3729 (set_attr "predicable" "yes")
3730 (set_attr "length" "8")
3731 (set_attr "pool_range" "256")
3732 (set_attr "neg_pool_range" "244")]
3736 [(set (match_operand:SI 0 "s_register_operand" "")
3737 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3738 "TARGET_ARM && arm_arch4 && reload_completed"
3739 [(set (match_dup 0) (match_dup 1))
3740 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3743 HOST_WIDE_INT offset;
3745 operands[2] = gen_rtx_MEM (QImode, operands[0]);
3746 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3747 operands[1] = XEXP (operands[1], 0);
3748 if (GET_CODE (operands[1]) == PLUS
3749 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3750 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3751 || const_ok_for_arm (-offset)))
3753 HOST_WIDE_INT low = (offset > 0
3754 ? (offset & 0xff) : -((-offset) & 0xff));
3755 XEXP (operands[2], 0) = plus_constant (operands[0], low);
3756 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3758 /* Ensure the sum is in correct canonical form */
3759 else if (GET_CODE (operands[1]) == PLUS
3760 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3761 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3762 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3763 XEXP (operands[1], 1),
3764 XEXP (operands[1], 0));
3768 (define_insn "*thumb_extendqisi2_insn"
3769 [(set (match_operand:SI 0 "register_operand" "=l,l")
3770 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3775 rtx mem = XEXP (operands[1], 0);
3777 if (GET_CODE (mem) == CONST)
3778 mem = XEXP (mem, 0);
3780 if (GET_CODE (mem) == LABEL_REF)
3781 return \"ldr\\t%0, %1\";
3783 if (GET_CODE (mem) == PLUS
3784 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3785 return \"ldr\\t%0, %1\";
3787 if (which_alternative == 0)
3788 return \"ldrsb\\t%0, %1\";
3790 ops[0] = operands[0];
3792 if (GET_CODE (mem) == PLUS)
3794 rtx a = XEXP (mem, 0);
3795 rtx b = XEXP (mem, 1);
3800 if (GET_CODE (a) == REG)
3802 if (GET_CODE (b) == REG)
3803 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3804 else if (REGNO (a) == REGNO (ops[0]))
3806 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3807 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3808 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3811 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3813 else if (GET_CODE (b) != REG)
3817 if (REGNO (b) == REGNO (ops[0]))
3819 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3820 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3821 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3824 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3827 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3829 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3830 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3831 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3836 ops[2] = const0_rtx;
3838 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3842 [(set_attr "length" "2,6")
3843 (set_attr "type" "load,load")
3844 (set_attr "pool_range" "32,32")]
3847 (define_insn "extendsfdf2"
3848 [(set (match_operand:DF 0 "s_register_operand" "=f")
3849 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
3850 "TARGET_ARM && TARGET_HARD_FLOAT"
3852 [(set_attr "type" "ffarith")
3853 (set_attr "predicable" "yes")]
3856 (define_insn "extendsfxf2"
3857 [(set (match_operand:XF 0 "s_register_operand" "=f")
3858 (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
3859 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3861 [(set_attr "type" "ffarith")
3862 (set_attr "predicable" "yes")]
3865 (define_insn "extenddfxf2"
3866 [(set (match_operand:XF 0 "s_register_operand" "=f")
3867 (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
3868 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3870 [(set_attr "type" "ffarith")
3871 (set_attr "predicable" "yes")]
3875 ;; Move insns (including loads and stores)
3877 ;; XXX Just some ideas about movti.
3878 ;; I don't think these are a good idea on the arm, there just aren't enough
3880 ;;(define_expand "loadti"
3881 ;; [(set (match_operand:TI 0 "s_register_operand" "")
3882 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
3885 ;;(define_expand "storeti"
3886 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3887 ;; (match_operand:TI 1 "s_register_operand" ""))]
3890 ;;(define_expand "movti"
3891 ;; [(set (match_operand:TI 0 "general_operand" "")
3892 ;; (match_operand:TI 1 "general_operand" ""))]
3898 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3899 ;; operands[1] = copy_to_reg (operands[1]);
3900 ;; if (GET_CODE (operands[0]) == MEM)
3901 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3902 ;; else if (GET_CODE (operands[1]) == MEM)
3903 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3907 ;; emit_insn (insn);
3911 ;; Recognise garbage generated above.
3914 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3915 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3919 ;; register mem = (which_alternative < 3);
3920 ;; register const char *template;
3922 ;; operands[mem] = XEXP (operands[mem], 0);
3923 ;; switch (which_alternative)
3925 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3926 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
3927 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
3928 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
3929 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
3930 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
3932 ;; output_asm_insn (template, operands);
3936 (define_expand "movdi"
3937 [(set (match_operand:DI 0 "general_operand" "")
3938 (match_operand:DI 1 "general_operand" ""))]
3943 if (!no_new_pseudos)
3945 if (GET_CODE (operands[0]) != REG)
3946 operands[1] = force_reg (DImode, operands[1]);
3952 (define_insn "*arm_movdi"
3953 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3954 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
3957 return (output_move_double (operands));
3959 [(set_attr "length" "8")
3960 (set_attr "type" "*,load,store2")
3961 (set_attr "pool_range" "*,1020,*")
3962 (set_attr "neg_pool_range" "*,1012,*")]
3965 ;;; ??? This should have alternatives for constants.
3966 ;;; ??? This was originally identical to the movdf_insn pattern.
3967 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3968 ;;; thumb_reorg with a memory reference.
3969 (define_insn "*thumb_movdi_insn"
3970 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3971 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
3973 && ( register_operand (operands[0], DImode)
3974 || register_operand (operands[1], DImode))"
3977 switch (which_alternative)
3981 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3982 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
3983 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
3985 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3987 operands[1] = GEN_INT (- INTVAL (operands[1]));
3988 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3990 return \"ldmia\\t%1, {%0, %H0}\";
3992 return \"stmia\\t%0, {%1, %H1}\";
3994 return thumb_load_double_from_address (operands);
3996 operands[2] = gen_rtx (MEM, SImode,
3997 plus_constant (XEXP (operands[0], 0), 4));
3998 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4001 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4002 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4003 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4006 [(set_attr "length" "4,4,6,2,2,6,4,4")
4007 (set_attr "type" "*,*,*,load,store2,load,store2,*")
4008 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4011 (define_expand "movsi"
4012 [(set (match_operand:SI 0 "general_operand" "")
4013 (match_operand:SI 1 "general_operand" ""))]
4018 /* Everything except mem = const or mem = mem can be done easily */
4019 if (GET_CODE (operands[0]) == MEM)
4020 operands[1] = force_reg (SImode, operands[1]);
4021 if (GET_CODE (operands[1]) == CONST_INT
4022 && !(const_ok_for_arm (INTVAL (operands[1]))
4023 || const_ok_for_arm (~INTVAL (operands[1]))))
4025 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4028 : preserve_subexpressions_p ()));
4032 else /* TARGET_THUMB.... */
4034 if (!no_new_pseudos)
4036 if (GET_CODE (operands[0]) != REG)
4037 operands[1] = force_reg (SImode, operands[1]);
4042 && (CONSTANT_P (operands[1])
4043 || symbol_mentioned_p (operands[1])
4044 || label_mentioned_p (operands[1])))
4045 operands[1] = legitimize_pic_address (operands[1], SImode,
4046 (no_new_pseudos ? operands[0] : 0));
4050 (define_insn "*arm_movsi_insn"
4051 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4052 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
4054 && ( register_operand (operands[0], SImode)
4055 || register_operand (operands[1], SImode))"
4061 [(set_attr "type" "*,*,load,store1")
4062 (set_attr "predicable" "yes")
4063 (set_attr "pool_range" "*,*,4096,*")
4064 (set_attr "neg_pool_range" "*,*,4084,*")]
4068 [(set (match_operand:SI 0 "s_register_operand" "")
4069 (match_operand:SI 1 "const_int_operand" ""))]
4071 && (!(const_ok_for_arm (INTVAL (operands[1]))
4072 || const_ok_for_arm (~INTVAL (operands[1]))))"
4073 [(clobber (const_int 0))]
4075 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4081 (define_insn "*thumb_movsi_insn"
4082 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4083 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
4085 && ( register_operand (operands[0], SImode)
4086 || register_operand (operands[1], SImode))"
4097 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4098 (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
4099 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4103 [(set (match_operand:SI 0 "register_operand" "")
4104 (match_operand:SI 1 "const_int_operand" ""))]
4105 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4106 [(set (match_dup 0) (match_dup 1))
4107 (set (match_dup 0) (neg:SI (match_dup 0)))]
4108 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4112 [(set (match_operand:SI 0 "register_operand" "")
4113 (match_operand:SI 1 "const_int_operand" ""))]
4114 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4115 [(set (match_dup 0) (match_dup 1))
4116 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4119 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4120 unsigned HOST_WIDE_INT mask = 0xff;
4123 for (i = 0; i < 25; i++)
4124 if ((val & (mask << i)) == val)
4127 /* Shouldn't happen, but we don't want to split if the shift is zero. */
4131 operands[1] = GEN_INT (val >> i);
4132 operands[2] = GEN_INT (i);
4136 ;; When generating pic, we need to load the symbol offset into a register.
4137 ;; So that the optimizer does not confuse this with a normal symbol load
4138 ;; we use an unspec. The offset will be loaded from a constant pool entry,
4139 ;; since that is the only type of relocation we can use.
4141 ;; The rather odd constraints on the following are to force reload to leave
4142 ;; the insn alone, and to force the minipool generation pass to then move
4143 ;; the GOT symbol to memory.
4145 (define_insn "pic_load_addr_arm"
4146 [(set (match_operand:SI 0 "s_register_operand" "=r")
4147 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4148 "TARGET_ARM && flag_pic"
4150 [(set_attr "type" "load")
4151 (set (attr "pool_range") (const_int 4096))
4152 (set (attr "neg_pool_range") (const_int 4084))]
4155 (define_insn "pic_load_addr_thumb"
4156 [(set (match_operand:SI 0 "s_register_operand" "=l")
4157 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4158 "TARGET_THUMB && flag_pic"
4160 [(set_attr "type" "load")
4161 (set (attr "pool_range") (const_int 1024))]
4164 ;; This variant is used for AOF assembly, since it needs to mention the
4165 ;; pic register in the rtl.
4166 (define_expand "pic_load_addr_based"
4167 [(set (match_operand:SI 0 "s_register_operand" "=r")
4168 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4169 "TARGET_ARM && flag_pic"
4170 "operands[2] = pic_offset_table_rtx;"
4173 (define_insn "*pic_load_addr_based_insn"
4174 [(set (match_operand:SI 0 "s_register_operand" "=r")
4175 (unspec:SI [(match_operand 1 "" "")
4176 (match_operand 2 "s_register_operand" "r")]
4178 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4180 #ifdef AOF_ASSEMBLER
4181 operands[1] = aof_pic_entry (operands[1]);
4183 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4186 [(set_attr "type" "load")
4187 (set (attr "pool_range")
4188 (if_then_else (eq_attr "is_thumb" "yes")
4191 (set (attr "neg_pool_range")
4192 (if_then_else (eq_attr "is_thumb" "yes")
4197 (define_insn "pic_add_dot_plus_four"
4198 [(set (match_operand:SI 0 "register_operand" "+r")
4199 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
4200 (use (label_ref (match_operand 1 "" "")))]
4201 "TARGET_THUMB && flag_pic"
4203 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4204 CODE_LABEL_NUMBER (operands[1]));
4205 return \"add\\t%0, %|pc\";
4207 [(set_attr "length" "2")]
4210 (define_insn "pic_add_dot_plus_eight"
4211 [(set (match_operand:SI 0 "register_operand" "+r")
4212 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
4213 (use (label_ref (match_operand 1 "" "")))]
4214 "TARGET_ARM && flag_pic"
4216 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4217 CODE_LABEL_NUMBER (operands[1]));
4218 return \"add%?\\t%0, %|pc, %0\";
4220 [(set_attr "predicable" "yes")]
4223 (define_expand "builtin_setjmp_receiver"
4224 [(label_ref (match_operand 0 "" ""))]
4228 arm_finalize_pic (0);
4232 ;; If copying one reg to another we can set the condition codes according to
4233 ;; its value. Such a move is common after a return from subroutine and the
4234 ;; result is being tested against zero.
4236 (define_insn "*movsi_compare0"
4237 [(set (reg:CC CC_REGNUM)
4238 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4240 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4245 sub%?s\\t%0, %1, #0"
4246 [(set_attr "conds" "set")]
4249 ;; Subroutine to store a half word from a register into memory.
4250 ;; Operand 0 is the source register (HImode)
4251 ;; Operand 1 is the destination address in a register (SImode)
4253 ;; In both this routine and the next, we must be careful not to spill
4254 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4255 ;; can generate unrecognizable rtl.
4257 (define_expand "storehi"
4258 [;; store the low byte
4259 (set (match_operand 1 "" "") (match_dup 3))
4260 ;; extract the high byte
4262 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4263 ;; store the high byte
4264 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
4268 rtx op1 = operands[1];
4269 rtx addr = XEXP (op1, 0);
4270 enum rtx_code code = GET_CODE (addr);
4272 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4274 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4276 operands[4] = adjust_address (op1, QImode, 1);
4277 operands[1] = adjust_address (operands[1], QImode, 0);
4278 operands[3] = gen_lowpart (QImode, operands[0]);
4279 operands[0] = gen_lowpart (SImode, operands[0]);
4280 operands[2] = gen_reg_rtx (SImode);
4284 (define_expand "storehi_bigend"
4285 [(set (match_dup 4) (match_dup 3))
4287 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4288 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 3))]
4292 rtx op1 = operands[1];
4293 rtx addr = XEXP (op1, 0);
4294 enum rtx_code code = GET_CODE (addr);
4296 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4298 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4300 operands[4] = adjust_address (op1, QImode, 1);
4301 operands[1] = adjust_address (operands[1], QImode, 0);
4302 operands[3] = gen_lowpart (QImode, operands[0]);
4303 operands[0] = gen_lowpart (SImode, operands[0]);
4304 operands[2] = gen_reg_rtx (SImode);
4308 ;; Subroutine to store a half word integer constant into memory.
4309 (define_expand "storeinthi"
4310 [(set (match_operand 0 "" "")
4311 (subreg:QI (match_operand 1 "" "") 0))
4312 (set (match_dup 3) (match_dup 2))]
4316 HOST_WIDE_INT value = INTVAL (operands[1]);
4317 rtx addr = XEXP (operands[0], 0);
4318 rtx op0 = operands[0];
4319 enum rtx_code code = GET_CODE (addr);
4321 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4323 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4325 operands[1] = gen_reg_rtx (SImode);
4326 if (BYTES_BIG_ENDIAN)
4328 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4329 if ((value & 255) == ((value >> 8) & 255))
4330 operands[2] = operands[1];
4333 operands[2] = gen_reg_rtx (SImode);
4334 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4339 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4340 if ((value & 255) == ((value >> 8) & 255))
4341 operands[2] = operands[1];
4344 operands[2] = gen_reg_rtx (SImode);
4345 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4349 operands[3] = adjust_address (op0, QImode, 1);
4350 operands[0] = adjust_address (operands[0], QImode, 0);
4351 operands[2] = gen_lowpart (QImode, operands[2]);
4355 (define_expand "storehi_single_op"
4356 [(set (match_operand:HI 0 "memory_operand" "")
4357 (match_operand:HI 1 "general_operand" ""))]
4358 "TARGET_ARM && arm_arch4"
4360 if (!s_register_operand (operands[1], HImode))
4361 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4365 (define_expand "movhi"
4366 [(set (match_operand:HI 0 "general_operand" "")
4367 (match_operand:HI 1 "general_operand" ""))]
4372 if (!no_new_pseudos)
4374 if (GET_CODE (operands[0]) == MEM)
4378 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4381 if (GET_CODE (operands[1]) == CONST_INT)
4382 emit_insn (gen_storeinthi (operands[0], operands[1]));
4385 if (GET_CODE (operands[1]) == MEM)
4386 operands[1] = force_reg (HImode, operands[1]);
4387 if (BYTES_BIG_ENDIAN)
4388 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4390 emit_insn (gen_storehi (operands[1], operands[0]));
4394 /* Sign extend a constant, and keep it in an SImode reg. */
4395 else if (GET_CODE (operands[1]) == CONST_INT)
4397 rtx reg = gen_reg_rtx (SImode);
4398 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4400 /* If the constant is already valid, leave it alone. */
4401 if (!const_ok_for_arm (val))
4403 /* If setting all the top bits will make the constant
4404 loadable in a single instruction, then set them.
4405 Otherwise, sign extend the number. */
4407 if (const_ok_for_arm (~(val | ~0xffff)))
4409 else if (val & 0x8000)
4413 emit_insn (gen_movsi (reg, GEN_INT (val)));
4414 operands[1] = gen_lowpart (HImode, reg);
4416 else if (!arm_arch4)
4418 /* Note: We do not have to worry about TARGET_MMU_TRAPS
4419 for v4 and up architectures because LDRH instructions will
4420 be used to access the HI values, and these cannot generate
4421 unaligned word access faults in the MMU. */
4422 if (GET_CODE (operands[1]) == MEM)
4424 if (TARGET_MMU_TRAPS)
4427 rtx offset = const0_rtx;
4428 rtx reg = gen_reg_rtx (SImode);
4430 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4431 || (GET_CODE (base) == PLUS
4432 && (GET_CODE (offset = XEXP (base, 1))
4434 && ((INTVAL(offset) & 1) != 1)
4435 && GET_CODE (base = XEXP (base, 0)) == REG))
4436 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4438 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4441 new = gen_rtx_MEM (SImode,
4442 plus_constant (base, new_offset));
4443 MEM_COPY_ATTRIBUTES (new, operands[1]);
4444 emit_insn (gen_movsi (reg, new));
4445 if (((INTVAL (offset) & 2) != 0)
4446 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4448 rtx reg2 = gen_reg_rtx (SImode);
4450 emit_insn (gen_lshrsi3 (reg2, reg,
4456 emit_insn (gen_movhi_bytes (reg, operands[1]));
4458 operands[1] = gen_lowpart (HImode, reg);
4460 else if (BYTES_BIG_ENDIAN)
4463 rtx offset = const0_rtx;
4465 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4466 || (GET_CODE (base) == PLUS
4467 && (GET_CODE (offset = XEXP (base, 1))
4469 && GET_CODE (base = XEXP (base, 0)) == REG))
4470 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4472 rtx reg = gen_reg_rtx (SImode);
4475 if ((INTVAL (offset) & 2) == 2)
4477 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4478 new = gen_rtx_MEM (SImode,
4479 plus_constant (base,
4481 MEM_COPY_ATTRIBUTES (new, operands[1]);
4482 emit_insn (gen_movsi (reg, new));
4486 new = gen_rtx_MEM (SImode,
4487 XEXP (operands[1], 0));
4488 MEM_COPY_ATTRIBUTES (new, operands[1]);
4489 emit_insn (gen_rotated_loadsi (reg, new));
4492 operands[1] = gen_lowpart (HImode, reg);
4496 emit_insn (gen_movhi_bigend (operands[0],
4504 /* Handle loading a large integer during reload */
4505 else if (GET_CODE (operands[1]) == CONST_INT
4506 && !const_ok_for_arm (INTVAL (operands[1]))
4507 && !const_ok_for_arm (~INTVAL (operands[1])))
4509 /* Writing a constant to memory needs a scratch, which should
4510 be handled with SECONDARY_RELOADs. */
4511 if (GET_CODE (operands[0]) != REG)
4514 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4515 emit_insn (gen_movsi (operands[0], operands[1]));
4519 else /* TARGET_THUMB */
4521 if (!no_new_pseudos)
4523 if (GET_CODE (operands[0]) != REG)
4524 operands[1] = force_reg (HImode, operands[1]);
4526 /* ??? We shouldn't really get invalid addresses here, but this can
4527 happen if we are passed a SP (never OK for HImode/QImode) or
4528 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4529 HImode/QImode) relative address. */
4530 /* ??? This should perhaps be fixed elsewhere, for instance, in
4531 fixup_stack_1, by checking for other kinds of invalid addresses,
4532 e.g. a bare reference to a virtual register. This may confuse the
4533 alpha though, which must handle this case differently. */
4534 if (GET_CODE (operands[0]) == MEM
4535 && !memory_address_p (GET_MODE (operands[0]),
4536 XEXP (operands[0], 0)))
4538 = replace_equiv_address (operands[0],
4539 copy_to_reg (XEXP (operands[0], 0)));
4541 if (GET_CODE (operands[1]) == MEM
4542 && !memory_address_p (GET_MODE (operands[1]),
4543 XEXP (operands[1], 0)))
4545 = replace_equiv_address (operands[1],
4546 copy_to_reg (XEXP (operands[1], 0)));
4548 /* Handle loading a large integer during reload */
4549 else if (GET_CODE (operands[1]) == CONST_INT
4550 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4552 /* Writing a constant to memory needs a scratch, which should
4553 be handled with SECONDARY_RELOADs. */
4554 if (GET_CODE (operands[0]) != REG)
4557 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4558 emit_insn (gen_movsi (operands[0], operands[1]));
4565 (define_insn "*thumb_movhi_insn"
4566 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4567 (match_operand:HI 1 "general_operand" "l,mn,l,*h,*r,I"))]
4569 && ( register_operand (operands[0], HImode)
4570 || register_operand (operands[1], HImode))"
4572 switch (which_alternative)
4574 case 0: return \"add %0, %1, #0\";
4575 case 2: return \"strh %1, %0\";
4576 case 3: return \"mov %0, %1\";
4577 case 4: return \"mov %0, %1\";
4578 case 5: return \"mov %0, %1\";
4581 /* The stack pointer can end up being taken as an index register.
4582 Catch this case here and deal with it. */
4583 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4584 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4585 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4588 ops[0] = operands[0];
4589 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4591 output_asm_insn (\"mov %0, %1\", ops);
4593 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4596 return \"ldrh %0, %1\";
4598 [(set_attr "length" "2,4,2,2,2,2")
4599 (set_attr "type" "*,load,store1,*,*,*")
4600 (set_attr "pool_range" "*,64,*,*,*,*")]
4604 (define_insn "rotated_loadsi"
4605 [(set (match_operand:SI 0 "s_register_operand" "=r")
4606 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4608 "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4613 ops[0] = operands[0];
4614 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4615 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4618 [(set_attr "type" "load")
4619 (set_attr "predicable" "yes")]
4622 (define_expand "movhi_bytes"
4623 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4625 (zero_extend:SI (match_dup 6)))
4626 (set (match_operand:SI 0 "" "")
4627 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4632 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4634 mem1 = gen_rtx_MEM (QImode, addr);
4635 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4636 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4637 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4638 operands[0] = gen_lowpart (SImode, operands[0]);
4640 operands[2] = gen_reg_rtx (SImode);
4641 operands[3] = gen_reg_rtx (SImode);
4644 if (BYTES_BIG_ENDIAN)
4646 operands[4] = operands[2];
4647 operands[5] = operands[3];
4651 operands[4] = operands[3];
4652 operands[5] = operands[2];
4657 (define_expand "movhi_bigend"
4659 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4662 (ashiftrt:SI (match_dup 2) (const_int 16)))
4663 (set (match_operand:HI 0 "s_register_operand" "")
4664 (subreg:HI (match_dup 3) 0))]
4667 operands[2] = gen_reg_rtx (SImode);
4668 operands[3] = gen_reg_rtx (SImode);
4672 ;; Pattern to recognise insn generated default case above
4673 (define_insn "*movhi_insn_arch4"
4674 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4675 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4678 && (GET_CODE (operands[1]) != CONST_INT
4679 || const_ok_for_arm (INTVAL (operands[1]))
4680 || const_ok_for_arm (~INTVAL (operands[1])))"
4682 mov%?\\t%0, %1\\t%@ movhi
4683 mvn%?\\t%0, #%B1\\t%@ movhi
4684 str%?h\\t%1, %0\\t%@ movhi
4685 ldr%?h\\t%0, %1\\t%@ movhi"
4686 [(set_attr "type" "*,*,store1,load")
4687 (set_attr "predicable" "yes")
4688 (set_attr "pool_range" "*,*,*,256")
4689 (set_attr "neg_pool_range" "*,*,*,244")]
4692 (define_insn "*movhi_insn_littleend"
4693 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4694 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4697 && !BYTES_BIG_ENDIAN
4698 && !TARGET_MMU_TRAPS
4699 && (GET_CODE (operands[1]) != CONST_INT
4700 || const_ok_for_arm (INTVAL (operands[1]))
4701 || const_ok_for_arm (~INTVAL (operands[1])))"
4703 mov%?\\t%0, %1\\t%@ movhi
4704 mvn%?\\t%0, #%B1\\t%@ movhi
4705 ldr%?\\t%0, %1\\t%@ movhi"
4706 [(set_attr "type" "*,*,load")
4707 (set_attr "predicable" "yes")
4708 (set_attr "pool_range" "4096")
4709 (set_attr "neg_pool_range" "4084")]
4712 (define_insn "*movhi_insn_bigend"
4713 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4714 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4718 && !TARGET_MMU_TRAPS
4719 && (GET_CODE (operands[1]) != CONST_INT
4720 || const_ok_for_arm (INTVAL (operands[1]))
4721 || const_ok_for_arm (~INTVAL (operands[1])))"
4723 mov%?\\t%0, %1\\t%@ movhi
4724 mvn%?\\t%0, #%B1\\t%@ movhi
4725 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4726 [(set_attr "type" "*,*,load")
4727 (set_attr "predicable" "yes")
4728 (set_attr "length" "4,4,8")
4729 (set_attr "pool_range" "*,*,4092")
4730 (set_attr "neg_pool_range" "*,*,4084")]
4733 (define_insn "*loadhi_si_bigend"
4734 [(set (match_operand:SI 0 "s_register_operand" "=r")
4735 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
4739 && !TARGET_MMU_TRAPS"
4740 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4741 [(set_attr "type" "load")
4742 (set_attr "predicable" "yes")
4743 (set_attr "pool_range" "4096")
4744 (set_attr "neg_pool_range" "4084")]
4747 (define_insn "*movhi_bytes"
4748 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4749 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4750 "TARGET_ARM && TARGET_MMU_TRAPS"
4752 mov%?\\t%0, %1\\t%@ movhi
4753 mvn%?\\t%0, #%B1\\t%@ movhi"
4754 [(set_attr "predicable" "yes")]
4757 (define_insn "thumb_movhi_clobber"
4758 [(set (match_operand:HI 0 "memory_operand" "=m")
4759 (match_operand:HI 1 "register_operand" "l"))
4760 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4766 ;; We use a DImode scratch because we may occasionally need an additional
4767 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4768 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4769 (define_expand "reload_outhi"
4770 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4771 (match_operand:HI 1 "s_register_operand" "r")
4772 (match_operand:DI 2 "s_register_operand" "=&l")])]
4775 arm_reload_out_hi (operands);
4777 thumb_reload_out_hi (operands);
4782 (define_expand "reload_inhi"
4783 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4784 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4785 (match_operand:DI 2 "s_register_operand" "=&r")])]
4786 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4789 arm_reload_in_hi (operands);
4791 thumb_reload_out_hi (operands);
4795 (define_expand "movqi"
4796 [(set (match_operand:QI 0 "general_operand" "")
4797 (match_operand:QI 1 "general_operand" ""))]
4802 /* Everything except mem = const or mem = mem can be done easily */
4804 if (!no_new_pseudos)
4806 if (GET_CODE (operands[1]) == CONST_INT)
4808 rtx reg = gen_reg_rtx (SImode);
4810 emit_insn (gen_movsi (reg, operands[1]));
4811 operands[1] = gen_lowpart (QImode, reg);
4813 if (GET_CODE (operands[0]) == MEM)
4814 operands[1] = force_reg (QImode, operands[1]);
4817 else /* TARGET_THUMB */
4819 if (!no_new_pseudos)
4821 if (GET_CODE (operands[0]) != REG)
4822 operands[1] = force_reg (QImode, operands[1]);
4824 /* ??? We shouldn't really get invalid addresses here, but this can
4825 happen if we are passed a SP (never OK for HImode/QImode) or
4826 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4827 HImode/QImode) relative address. */
4828 /* ??? This should perhaps be fixed elsewhere, for instance, in
4829 fixup_stack_1, by checking for other kinds of invalid addresses,
4830 e.g. a bare reference to a virtual register. This may confuse the
4831 alpha though, which must handle this case differently. */
4832 if (GET_CODE (operands[0]) == MEM
4833 && !memory_address_p (GET_MODE (operands[0]),
4834 XEXP (operands[0], 0)))
4836 = replace_equiv_address (operands[0],
4837 copy_to_reg (XEXP (operands[0], 0)));
4838 if (GET_CODE (operands[1]) == MEM
4839 && !memory_address_p (GET_MODE (operands[1]),
4840 XEXP (operands[1], 0)))
4842 = replace_equiv_address (operands[1],
4843 copy_to_reg (XEXP (operands[1], 0)));
4845 /* Handle loading a large integer during reload */
4846 else if (GET_CODE (operands[1]) == CONST_INT
4847 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4849 /* Writing a constant to memory needs a scratch, which should
4850 be handled with SECONDARY_RELOADs. */
4851 if (GET_CODE (operands[0]) != REG)
4854 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4855 emit_insn (gen_movsi (operands[0], operands[1]));
4863 (define_insn "*arm_movqi_insn"
4864 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4865 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4867 && ( register_operand (operands[0], QImode)
4868 || register_operand (operands[1], QImode))"
4874 [(set_attr "type" "*,*,load,store1")
4875 (set_attr "predicable" "yes")]
4878 (define_insn "*thumb_movqi_insn"
4879 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4880 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
4882 && ( register_operand (operands[0], QImode)
4883 || register_operand (operands[1], QImode))"
4891 [(set_attr "length" "2")
4892 (set_attr "type" "*,load,store1,*,*,*")
4893 (set_attr "pool_range" "*,32,*,*,*,*")]
4896 (define_expand "movsf"
4897 [(set (match_operand:SF 0 "general_operand" "")
4898 (match_operand:SF 1 "general_operand" ""))]
4903 if (GET_CODE (operands[0]) == MEM)
4904 operands[1] = force_reg (SFmode, operands[1]);
4906 else /* TARGET_THUMB */
4908 if (!no_new_pseudos)
4910 if (GET_CODE (operands[0]) != REG)
4911 operands[1] = force_reg (SFmode, operands[1]);
4918 [(set (match_operand:SF 0 "nonimmediate_operand" "")
4919 (match_operand:SF 1 "immediate_operand" ""))]
4921 && !TARGET_HARD_FLOAT
4923 && GET_CODE (operands[1]) == CONST_DOUBLE"
4924 [(set (match_dup 2) (match_dup 3))]
4926 operands[2] = gen_lowpart (SImode, operands[0]);
4927 operands[3] = gen_lowpart (SImode, operands[1]);
4928 if (operands[2] == 0 || operands[3] == 0)
4933 (define_insn "*arm_movsf_hard_insn"
4934 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
4935 (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
4937 && TARGET_HARD_FLOAT
4938 && (GET_CODE (operands[0]) != MEM
4939 || register_operand (operands[1], SFmode))"
4945 str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
4946 stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
4948 ldr%?\\t%0, %1\\t%@ float
4949 str%?\\t%1, %0\\t%@ float"
4950 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
4951 (set_attr "predicable" "yes")
4953 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
4954 (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
4955 (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
4958 ;; Exactly the same as above, except that all `f' cases are deleted.
4959 ;; This is necessary to prevent reload from ever trying to use a `f' reg
4960 ;; when -msoft-float.
4962 (define_insn "*arm_movsf_soft_insn"
4963 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4964 (match_operand:SF 1 "general_operand" "r,mE,r"))]
4966 && TARGET_SOFT_FLOAT
4967 && (GET_CODE (operands[0]) != MEM
4968 || register_operand (operands[1], SFmode))"
4971 ldr%?\\t%0, %1\\t%@ float
4972 str%?\\t%1, %0\\t%@ float"
4973 [(set_attr "length" "4,4,4")
4974 (set_attr "predicable" "yes")
4975 (set_attr "type" "*,load,store1")
4976 (set_attr "pool_range" "*,4096,*")
4977 (set_attr "neg_pool_range" "*,4084,*")]
4980 ;;; ??? This should have alternatives for constants.
4981 (define_insn "*thumb_movsf_insn"
4982 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4983 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
4985 && ( register_operand (operands[0], SFmode)
4986 || register_operand (operands[1], SFmode))"
4995 [(set_attr "length" "2")
4996 (set_attr "type" "*,load,store1,load,store1,*,*")
4997 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5000 (define_expand "movdf"
5001 [(set (match_operand:DF 0 "general_operand" "")
5002 (match_operand:DF 1 "general_operand" ""))]
5007 if (GET_CODE (operands[0]) == MEM)
5008 operands[1] = force_reg (DFmode, operands[1]);
5010 else /* TARGET_THUMB */
5012 if (!no_new_pseudos)
5014 if (GET_CODE (operands[0]) != REG)
5015 operands[1] = force_reg (DFmode, operands[1]);
5021 ;; Reloading a df mode value stored in integer regs to memory can require a
5023 (define_expand "reload_outdf"
5024 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5025 (match_operand:DF 1 "s_register_operand" "r")
5026 (match_operand:SI 2 "s_register_operand" "=&r")]
5030 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5033 operands[2] = XEXP (operands[0], 0);
5034 else if (code == POST_INC || code == PRE_DEC)
5036 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5037 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5038 emit_insn (gen_movdi (operands[0], operands[1]));
5041 else if (code == PRE_INC)
5043 rtx reg = XEXP (XEXP (operands[0], 0), 0);
5045 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5048 else if (code == POST_DEC)
5049 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5051 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5052 XEXP (XEXP (operands[0], 0), 1)));
5054 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5057 if (code == POST_DEC)
5058 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5064 (define_insn "*movdf_hard_insn"
5065 [(set (match_operand:DF 0 "nonimmediate_operand"
5066 "=r,Q,r,m,r, f, f,f, m,!f,!r")
5067 (match_operand:DF 1 "general_operand"
5068 "Q, r,r,r,mF,fG,H,mF,f,r, f"))]
5070 && TARGET_HARD_FLOAT
5071 && (GET_CODE (operands[0]) != MEM
5072 || register_operand (operands[1], DFmode))"
5075 switch (which_alternative)
5078 case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
5079 case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
5080 case 2: case 3: case 4: return output_move_double (operands);
5081 case 5: return \"mvf%?d\\t%0, %1\";
5082 case 6: return \"mnf%?d\\t%0, #%N1\";
5083 case 7: return \"ldf%?d\\t%0, %1\";
5084 case 8: return \"stf%?d\\t%1, %0\";
5085 case 9: return output_mov_double_fpu_from_arm (operands);
5086 case 10: return output_mov_double_arm_from_fpu (operands);
5090 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
5091 (set_attr "predicable" "yes")
5093 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
5094 (set_attr "pool_range" "*,*,*,*,252,*,*,1024,*,*,*")
5095 (set_attr "neg_pool_range" "*,*,*,*,244,*,*,1012,*,*,*")]
5098 ;; Software floating point version. This is essentially the same as movdi.
5099 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
5102 (define_insn "*movdf_soft_insn"
5103 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5104 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5105 "TARGET_ARM && TARGET_SOFT_FLOAT
5107 "* return output_move_double (operands);"
5108 [(set_attr "length" "8,8,8")
5109 (set_attr "type" "*,load,store2")
5110 (set_attr "pool_range" "252")
5111 (set_attr "neg_pool_range" "244")]
5114 ;;; ??? This should have alternatives for constants.
5115 ;;; ??? This was originally identical to the movdi_insn pattern.
5116 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5117 ;;; thumb_reorg with a memory reference.
5118 (define_insn "*thumb_movdf_insn"
5119 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5120 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
5122 && ( register_operand (operands[0], DFmode)
5123 || register_operand (operands[1], DFmode))"
5125 switch (which_alternative)
5129 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5130 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5131 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5133 return \"ldmia\\t%1, {%0, %H0}\";
5135 return \"stmia\\t%0, {%1, %H1}\";
5137 return thumb_load_double_from_address (operands);
5139 operands[2] = gen_rtx (MEM, SImode,
5140 plus_constant (XEXP (operands[0], 0), 4));
5141 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5144 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5145 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5146 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5149 [(set_attr "length" "4,2,2,6,4,4")
5150 (set_attr "type" "*,load,store2,load,store2,*")
5151 (set_attr "pool_range" "*,*,*,1020,*,*")]
5155 (define_expand "movxf"
5156 [(set (match_operand:XF 0 "general_operand" "")
5157 (match_operand:XF 1 "general_operand" ""))]
5158 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5161 ;; Even when the XFmode patterns aren't enabled, we enable this after
5162 ;; reloading so that we can push floating point registers in the prologue.
5164 (define_insn "*movxf_hard_insn"
5165 [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
5166 (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
5167 "TARGET_ARM && TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
5169 switch (which_alternative)
5172 case 0: return \"mvf%?e\\t%0, %1\";
5173 case 1: return \"mnf%?e\\t%0, #%N1\";
5174 case 2: return \"ldf%?e\\t%0, %1\";
5175 case 3: return \"stf%?e\\t%1, %0\";
5176 case 4: return output_mov_long_double_fpu_from_arm (operands);
5177 case 5: return output_mov_long_double_arm_from_fpu (operands);
5178 case 6: return output_mov_long_double_arm_from_arm (operands);
5181 [(set_attr "length" "4,4,4,4,8,8,12")
5182 (set_attr "predicable" "yes")
5183 (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
5184 (set_attr "pool_range" "*,*,1024,*,*,*,*")
5185 (set_attr "neg_pool_range" "*,*,1012,*,*,*,*")]
5189 ;; load- and store-multiple insns
5190 ;; The arm can load/store any set of registers, provided that they are in
5191 ;; ascending order; but that is beyond GCC so stick with what it knows.
5193 (define_expand "load_multiple"
5194 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5195 (match_operand:SI 1 "" ""))
5196 (use (match_operand:SI 2 "" ""))])]
5199 /* Support only fixed point registers. */
5200 if (GET_CODE (operands[2]) != CONST_INT
5201 || INTVAL (operands[2]) > 14
5202 || INTVAL (operands[2]) < 2
5203 || GET_CODE (operands[1]) != MEM
5204 || GET_CODE (operands[0]) != REG
5205 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5206 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5210 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5211 force_reg (SImode, XEXP (operands[1], 0)),
5212 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5213 MEM_IN_STRUCT_P(operands[1]),
5214 MEM_SCALAR_P (operands[1]));
5218 ;; Load multiple with write-back
5220 (define_insn "*ldmsi_postinc4"
5221 [(match_parallel 0 "load_multiple_operation"
5222 [(set (match_operand:SI 1 "s_register_operand" "=r")
5223 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5225 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5226 (mem:SI (match_dup 2)))
5227 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5228 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5229 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5230 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5231 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5232 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5233 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5234 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5235 [(set_attr "type" "load")
5236 (set_attr "predicable" "yes")]
5239 (define_insn "*ldmsi_postinc3"
5240 [(match_parallel 0 "load_multiple_operation"
5241 [(set (match_operand:SI 1 "s_register_operand" "=r")
5242 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5244 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5245 (mem:SI (match_dup 2)))
5246 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5247 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5248 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5249 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5250 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5251 "ldm%?ia\\t%1!, {%3, %4, %5}"
5252 [(set_attr "type" "load")
5253 (set_attr "predicable" "yes")]
5256 (define_insn "*ldmsi_postinc2"
5257 [(match_parallel 0 "load_multiple_operation"
5258 [(set (match_operand:SI 1 "s_register_operand" "=r")
5259 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5261 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5262 (mem:SI (match_dup 2)))
5263 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5264 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5265 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5266 "ldm%?ia\\t%1!, {%3, %4}"
5267 [(set_attr "type" "load")
5268 (set_attr "predicable" "yes")]
5271 ;; Ordinary load multiple
5273 (define_insn "*ldmsi4"
5274 [(match_parallel 0 "load_multiple_operation"
5275 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5276 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5277 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5278 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5279 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5280 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5281 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5282 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5283 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5284 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5285 [(set_attr "type" "load")
5286 (set_attr "predicable" "yes")]
5289 (define_insn "*ldmsi3"
5290 [(match_parallel 0 "load_multiple_operation"
5291 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5292 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5293 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5294 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5295 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5296 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5297 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5298 "ldm%?ia\\t%1, {%2, %3, %4}"
5299 [(set_attr "type" "load")
5300 (set_attr "predicable" "yes")]
5303 (define_insn "*ldmsi2"
5304 [(match_parallel 0 "load_multiple_operation"
5305 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5306 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5307 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5308 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5309 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5310 "ldm%?ia\\t%1, {%2, %3}"
5311 [(set_attr "type" "load")
5312 (set_attr "predicable" "yes")]
5315 (define_expand "store_multiple"
5316 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5317 (match_operand:SI 1 "" ""))
5318 (use (match_operand:SI 2 "" ""))])]
5321 /* Support only fixed point registers */
5322 if (GET_CODE (operands[2]) != CONST_INT
5323 || INTVAL (operands[2]) > 14
5324 || INTVAL (operands[2]) < 2
5325 || GET_CODE (operands[1]) != REG
5326 || GET_CODE (operands[0]) != MEM
5327 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5328 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5332 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5333 force_reg (SImode, XEXP (operands[0], 0)),
5334 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5335 MEM_IN_STRUCT_P(operands[0]),
5336 MEM_SCALAR_P (operands[0]));
5340 ;; Store multiple with write-back
5342 (define_insn "*stmsi_postinc4"
5343 [(match_parallel 0 "store_multiple_operation"
5344 [(set (match_operand:SI 1 "s_register_operand" "=r")
5345 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5347 (set (mem:SI (match_dup 2))
5348 (match_operand:SI 3 "arm_hard_register_operand" ""))
5349 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5350 (match_operand:SI 4 "arm_hard_register_operand" ""))
5351 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5352 (match_operand:SI 5 "arm_hard_register_operand" ""))
5353 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5354 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5355 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5356 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5357 [(set_attr "predicable" "yes")
5358 (set_attr "type" "store4")]
5361 (define_insn "*stmsi_postinc3"
5362 [(match_parallel 0 "store_multiple_operation"
5363 [(set (match_operand:SI 1 "s_register_operand" "=r")
5364 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5366 (set (mem:SI (match_dup 2))
5367 (match_operand:SI 3 "arm_hard_register_operand" ""))
5368 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5369 (match_operand:SI 4 "arm_hard_register_operand" ""))
5370 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5371 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5372 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5373 "stm%?ia\\t%1!, {%3, %4, %5}"
5374 [(set_attr "predicable" "yes")
5375 (set_attr "type" "store3")]
5378 (define_insn "*stmsi_postinc2"
5379 [(match_parallel 0 "store_multiple_operation"
5380 [(set (match_operand:SI 1 "s_register_operand" "=r")
5381 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5383 (set (mem:SI (match_dup 2))
5384 (match_operand:SI 3 "arm_hard_register_operand" ""))
5385 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5386 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5387 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5388 "stm%?ia\\t%1!, {%3, %4}"
5389 [(set_attr "predicable" "yes")
5390 (set_attr "type" "store2")]
5393 ;; Ordinary store multiple
5395 (define_insn "*stmsi4"
5396 [(match_parallel 0 "store_multiple_operation"
5397 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5398 (match_operand:SI 2 "arm_hard_register_operand" ""))
5399 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5400 (match_operand:SI 3 "arm_hard_register_operand" ""))
5401 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5402 (match_operand:SI 4 "arm_hard_register_operand" ""))
5403 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5404 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5405 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5406 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5407 [(set_attr "predicable" "yes")
5408 (set_attr "type" "store4")]
5411 (define_insn "*stmsi3"
5412 [(match_parallel 0 "store_multiple_operation"
5413 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5414 (match_operand:SI 2 "arm_hard_register_operand" ""))
5415 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5416 (match_operand:SI 3 "arm_hard_register_operand" ""))
5417 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5418 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5419 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5420 "stm%?ia\\t%1, {%2, %3, %4}"
5421 [(set_attr "predicable" "yes")
5422 (set_attr "type" "store3")]
5425 (define_insn "*stmsi2"
5426 [(match_parallel 0 "store_multiple_operation"
5427 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5428 (match_operand:SI 2 "arm_hard_register_operand" ""))
5429 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5430 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5431 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5432 "stm%?ia\\t%1, {%2, %3}"
5433 [(set_attr "predicable" "yes")
5434 (set_attr "type" "store2")]
5437 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5438 ;; We could let this apply for blocks of less than this, but it clobbers so
5439 ;; many registers that there is then probably a better way.
5441 (define_expand "movstrqi"
5442 [(match_operand:BLK 0 "general_operand" "")
5443 (match_operand:BLK 1 "general_operand" "")
5444 (match_operand:SI 2 "const_int_operand" "")
5445 (match_operand:SI 3 "const_int_operand" "")]
5450 if (arm_gen_movstrqi (operands))
5454 else /* TARGET_THUMB */
5456 if ( INTVAL (operands[3]) != 4
5457 || INTVAL (operands[2]) > 48)
5460 thumb_expand_movstrqi (operands);
5466 ;; Thumb block-move insns
5468 (define_insn "movmem12b"
5469 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5470 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5471 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5472 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5473 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5474 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5475 (set (match_operand:SI 0 "register_operand" "=l")
5476 (plus:SI (match_dup 2) (const_int 12)))
5477 (set (match_operand:SI 1 "register_operand" "=l")
5478 (plus:SI (match_dup 3) (const_int 12)))
5479 (clobber (match_scratch:SI 4 "=&l"))
5480 (clobber (match_scratch:SI 5 "=&l"))
5481 (clobber (match_scratch:SI 6 "=&l"))]
5483 "* return thumb_output_move_mem_multiple (3, operands);"
5484 [(set_attr "length" "4")
5485 ; This isn't entirely accurate... It loads as well, but in terms of
5486 ; scheduling the following insn it is better to consider it as a store
5487 (set_attr "type" "store3")]
5490 (define_insn "movmem8b"
5491 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5492 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5493 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5494 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5495 (set (match_operand:SI 0 "register_operand" "=l")
5496 (plus:SI (match_dup 2) (const_int 8)))
5497 (set (match_operand:SI 1 "register_operand" "=l")
5498 (plus:SI (match_dup 3) (const_int 8)))
5499 (clobber (match_scratch:SI 4 "=&l"))
5500 (clobber (match_scratch:SI 5 "=&l"))]
5502 "* return thumb_output_move_mem_multiple (2, operands);"
5503 [(set_attr "length" "4")
5504 ; This isn't entirely accurate... It loads as well, but in terms of
5505 ; scheduling the following insn it is better to consider it as a store
5506 (set_attr "type" "store2")]
5511 ;; Compare & branch insns
5512 ;; The range calcualations are based as follows:
5513 ;; For forward branches, the address calculation returns the address of
5514 ;; the next instruction. This is 2 beyond the branch instruction.
5515 ;; For backward branches, the address calculation returns the address of
5516 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5517 ;; instruction for the shortest sequence, and 4 before the branch instruction
5518 ;; if we have to jump around an unconditional branch.
5519 ;; To the basic branch range the PC offset must be added (this is +4).
5520 ;; So for forward branches we have
5521 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5522 ;; And for backward branches we have
5523 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5525 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5526 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5528 (define_insn "cbranchsi4"
5531 (match_operator 0 "arm_comparison_operator"
5532 [(match_operand:SI 1 "register_operand" "l,r")
5533 (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5534 (label_ref (match_operand 3 "" ""))
5538 output_asm_insn (\"cmp\\t%1, %2\", operands);
5539 switch (get_attr_length (insn))
5541 case 4: return \"b%d0\\t%l3\";
5542 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5543 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5546 [(set (attr "far_jump")
5548 (eq_attr "length" "8")
5549 (const_string "yes")
5550 (const_string "no")))
5551 (set (attr "length")
5553 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5554 (le (minus (match_dup 3) (pc)) (const_int 256)))
5557 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5558 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5563 (define_insn "*negated_cbranchsi4"
5566 (match_operator 0 "arm_comparison_operator"
5567 [(match_operand:SI 1 "register_operand" "l")
5568 (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5569 (label_ref (match_operand 3 "" ""))
5573 output_asm_insn (\"cmn\\t%1, %2\", operands);
5574 switch (get_attr_length (insn))
5576 case 4: return \"b%d0\\t%l3\";
5577 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5578 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5581 [(set (attr "far_jump")
5583 (eq_attr "length" "8")
5584 (const_string "yes")
5585 (const_string "no")))
5586 (set (attr "length")
5588 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5589 (le (minus (match_dup 3) (pc)) (const_int 256)))
5592 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5593 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5599 ;; Comparison and test insns
5601 (define_expand "cmpsi"
5602 [(match_operand:SI 0 "s_register_operand" "")
5603 (match_operand:SI 1 "arm_add_operand" "")]
5606 arm_compare_op0 = operands[0];
5607 arm_compare_op1 = operands[1];
5612 (define_expand "cmpsf"
5613 [(match_operand:SF 0 "s_register_operand" "")
5614 (match_operand:SF 1 "fpu_rhs_operand" "")]
5615 "TARGET_ARM && TARGET_HARD_FLOAT"
5617 arm_compare_op0 = operands[0];
5618 arm_compare_op1 = operands[1];
5623 (define_expand "cmpdf"
5624 [(match_operand:DF 0 "s_register_operand" "")
5625 (match_operand:DF 1 "fpu_rhs_operand" "")]
5626 "TARGET_ARM && TARGET_HARD_FLOAT"
5628 arm_compare_op0 = operands[0];
5629 arm_compare_op1 = operands[1];
5634 (define_expand "cmpxf"
5635 [(match_operand:XF 0 "s_register_operand" "")
5636 (match_operand:XF 1 "fpu_rhs_operand" "")]
5637 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5639 arm_compare_op0 = operands[0];
5640 arm_compare_op1 = operands[1];
5645 (define_insn "*arm_cmpsi_insn"
5646 [(set (reg:CC CC_REGNUM)
5647 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5648 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
5653 [(set_attr "conds" "set")]
5656 (define_insn "*cmpsi_shiftsi"
5657 [(set (reg:CC CC_REGNUM)
5658 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5659 (match_operator:SI 3 "shift_operator"
5660 [(match_operand:SI 1 "s_register_operand" "r")
5661 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
5664 [(set_attr "conds" "set")
5665 (set_attr "shift" "1")
5669 (define_insn "*cmpsi_shiftsi_swp"
5670 [(set (reg:CC_SWP CC_REGNUM)
5671 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5672 [(match_operand:SI 1 "s_register_operand" "r")
5673 (match_operand:SI 2 "reg_or_int_operand" "rM")])
5674 (match_operand:SI 0 "s_register_operand" "r")))]
5677 [(set_attr "conds" "set")
5678 (set_attr "shift" "1")
5682 (define_insn "*cmpsi_neg_shiftsi"
5683 [(set (reg:CC CC_REGNUM)
5684 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5685 (neg:SI (match_operator:SI 3 "shift_operator"
5686 [(match_operand:SI 1 "s_register_operand" "r")
5687 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5690 [(set_attr "conds" "set")
5691 (set_attr "shift" "1")
5695 (define_insn "*cmpsf_insn"
5696 [(set (reg:CCFP CC_REGNUM)
5697 (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
5698 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5699 "TARGET_ARM && TARGET_HARD_FLOAT"
5703 [(set_attr "conds" "set")
5704 (set_attr "type" "f_2_r")]
5707 (define_insn "*cmpdf_insn"
5708 [(set (reg:CCFP CC_REGNUM)
5709 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
5710 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5711 "TARGET_ARM && TARGET_HARD_FLOAT"
5715 [(set_attr "conds" "set")
5716 (set_attr "type" "f_2_r")]
5719 (define_insn "*cmpesfdf_df"
5720 [(set (reg:CCFP CC_REGNUM)
5721 (compare:CCFP (float_extend:DF
5722 (match_operand:SF 0 "s_register_operand" "f,f"))
5723 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5724 "TARGET_ARM && TARGET_HARD_FLOAT"
5728 [(set_attr "conds" "set")
5729 (set_attr "type" "f_2_r")]
5732 (define_insn "*cmpdf_esfdf"
5733 [(set (reg:CCFP CC_REGNUM)
5734 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5736 (match_operand:SF 1 "s_register_operand" "f"))))]
5737 "TARGET_ARM && TARGET_HARD_FLOAT"
5739 [(set_attr "conds" "set")
5740 (set_attr "type" "f_2_r")]
5743 (define_insn "*cmpxf_insn"
5744 [(set (reg:CCFP CC_REGNUM)
5745 (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
5746 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5747 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5751 [(set_attr "conds" "set")
5752 (set_attr "type" "f_2_r")]
5755 (define_insn "*cmpsf_trap"
5756 [(set (reg:CCFPE CC_REGNUM)
5757 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
5758 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5759 "TARGET_ARM && TARGET_HARD_FLOAT"
5763 [(set_attr "conds" "set")
5764 (set_attr "type" "f_2_r")]
5767 (define_insn "*cmpdf_trap"
5768 [(set (reg:CCFPE CC_REGNUM)
5769 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
5770 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5771 "TARGET_ARM && TARGET_HARD_FLOAT"
5775 [(set_attr "conds" "set")
5776 (set_attr "type" "f_2_r")]
5779 (define_insn "*cmp_esfdf_df_trap"
5780 [(set (reg:CCFPE CC_REGNUM)
5781 (compare:CCFPE (float_extend:DF
5782 (match_operand:SF 0 "s_register_operand" "f,f"))
5783 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5784 "TARGET_ARM && TARGET_HARD_FLOAT"
5788 [(set_attr "conds" "set")
5789 (set_attr "type" "f_2_r")]
5792 (define_insn "*cmp_df_esfdf_trap"
5793 [(set (reg:CCFPE CC_REGNUM)
5794 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
5796 (match_operand:SF 1 "s_register_operand" "f"))))]
5797 "TARGET_ARM && TARGET_HARD_FLOAT"
5799 [(set_attr "conds" "set")
5800 (set_attr "type" "f_2_r")]
5803 (define_insn "*cmpxf_trap"
5804 [(set (reg:CCFPE CC_REGNUM)
5805 (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
5806 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5807 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5811 [(set_attr "conds" "set")
5812 (set_attr "type" "f_2_r")]
5815 ; This insn allows redundant compares to be removed by cse, nothing should
5816 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5817 ; is deleted later on. The match_dup will match the mode here, so that
5818 ; mode changes of the condition codes aren't lost by this even though we don't
5819 ; specify what they are.
5821 (define_insn "*deleted_compare"
5822 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5824 "\\t%@ deleted compare"
5825 [(set_attr "conds" "set")
5826 (set_attr "length" "0")]
5830 ;; Conditional branch insns
5832 (define_expand "beq"
5834 (if_then_else (eq (match_dup 1) (const_int 0))
5835 (label_ref (match_operand 0 "" ""))
5838 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5841 (define_expand "bne"
5843 (if_then_else (ne (match_dup 1) (const_int 0))
5844 (label_ref (match_operand 0 "" ""))
5847 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5850 (define_expand "bgt"
5852 (if_then_else (gt (match_dup 1) (const_int 0))
5853 (label_ref (match_operand 0 "" ""))
5856 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5859 (define_expand "ble"
5861 (if_then_else (le (match_dup 1) (const_int 0))
5862 (label_ref (match_operand 0 "" ""))
5865 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5868 (define_expand "bge"
5870 (if_then_else (ge (match_dup 1) (const_int 0))
5871 (label_ref (match_operand 0 "" ""))
5874 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5877 (define_expand "blt"
5879 (if_then_else (lt (match_dup 1) (const_int 0))
5880 (label_ref (match_operand 0 "" ""))
5883 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5886 (define_expand "bgtu"
5888 (if_then_else (gtu (match_dup 1) (const_int 0))
5889 (label_ref (match_operand 0 "" ""))
5892 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5895 (define_expand "bleu"
5897 (if_then_else (leu (match_dup 1) (const_int 0))
5898 (label_ref (match_operand 0 "" ""))
5901 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5904 (define_expand "bgeu"
5906 (if_then_else (geu (match_dup 1) (const_int 0))
5907 (label_ref (match_operand 0 "" ""))
5910 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5913 (define_expand "bltu"
5915 (if_then_else (ltu (match_dup 1) (const_int 0))
5916 (label_ref (match_operand 0 "" ""))
5919 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5922 (define_expand "bunordered"
5924 (if_then_else (unordered (match_dup 1) (const_int 0))
5925 (label_ref (match_operand 0 "" ""))
5927 "TARGET_ARM && TARGET_HARD_FLOAT"
5928 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5932 (define_expand "bordered"
5934 (if_then_else (ordered (match_dup 1) (const_int 0))
5935 (label_ref (match_operand 0 "" ""))
5937 "TARGET_ARM && TARGET_HARD_FLOAT"
5938 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5942 (define_expand "bungt"
5944 (if_then_else (ungt (match_dup 1) (const_int 0))
5945 (label_ref (match_operand 0 "" ""))
5947 "TARGET_ARM && TARGET_HARD_FLOAT"
5948 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5951 (define_expand "bunlt"
5953 (if_then_else (unlt (match_dup 1) (const_int 0))
5954 (label_ref (match_operand 0 "" ""))
5956 "TARGET_ARM && TARGET_HARD_FLOAT"
5957 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5960 (define_expand "bunge"
5962 (if_then_else (unge (match_dup 1) (const_int 0))
5963 (label_ref (match_operand 0 "" ""))
5965 "TARGET_ARM && TARGET_HARD_FLOAT"
5966 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5969 (define_expand "bunle"
5971 (if_then_else (unle (match_dup 1) (const_int 0))
5972 (label_ref (match_operand 0 "" ""))
5974 "TARGET_ARM && TARGET_HARD_FLOAT"
5975 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5978 ;; The following two patterns need two branch instructions, since there is
5979 ;; no single instruction that will handle all cases.
5980 (define_expand "buneq"
5982 (if_then_else (uneq (match_dup 1) (const_int 0))
5983 (label_ref (match_operand 0 "" ""))
5985 "TARGET_ARM && TARGET_HARD_FLOAT"
5986 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
5989 (define_expand "bltgt"
5991 (if_then_else (ltgt (match_dup 1) (const_int 0))
5992 (label_ref (match_operand 0 "" ""))
5994 "TARGET_ARM && TARGET_HARD_FLOAT"
5995 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
5999 ;; Patterns to match conditional branch insns.
6002 ; Special pattern to match UNEQ.
6003 (define_insn "*arm_buneq"
6005 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6006 (label_ref (match_operand 0 "" ""))
6008 "TARGET_ARM && TARGET_HARD_FLOAT"
6010 if (arm_ccfsm_state != 0)
6013 return \"bvs\\t%l0;beq\\t%l0\";
6015 [(set_attr "conds" "jump_clob")
6016 (set_attr "length" "8")]
6019 ; Special pattern to match LTGT.
6020 (define_insn "*arm_bltgt"
6022 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6023 (label_ref (match_operand 0 "" ""))
6025 "TARGET_ARM && TARGET_HARD_FLOAT"
6027 if (arm_ccfsm_state != 0)
6030 return \"bmi\\t%l0;bgt\\t%l0\";
6032 [(set_attr "conds" "jump_clob")
6033 (set_attr "length" "8")]
6036 (define_insn "*arm_cond_branch"
6038 (if_then_else (match_operator 1 "arm_comparison_operator"
6039 [(match_operand 2 "cc_register" "") (const_int 0)])
6040 (label_ref (match_operand 0 "" ""))
6044 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6046 arm_ccfsm_state += 2;
6049 return \"b%d1\\t%l0\";
6051 [(set_attr "conds" "use")]
6054 ; Special pattern to match reversed UNEQ.
6055 (define_insn "*arm_buneq_reversed"
6057 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6059 (label_ref (match_operand 0 "" ""))))]
6060 "TARGET_ARM && TARGET_HARD_FLOAT"
6062 if (arm_ccfsm_state != 0)
6065 return \"bmi\\t%l0;bgt\\t%l0\";
6067 [(set_attr "conds" "jump_clob")
6068 (set_attr "length" "8")]
6071 ; Special pattern to match reversed LTGT.
6072 (define_insn "*arm_bltgt_reversed"
6074 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6076 (label_ref (match_operand 0 "" ""))))]
6077 "TARGET_ARM && TARGET_HARD_FLOAT"
6079 if (arm_ccfsm_state != 0)
6082 return \"bvs\\t%l0;beq\\t%l0\";
6084 [(set_attr "conds" "jump_clob")
6085 (set_attr "length" "8")]
6088 (define_insn "*arm_cond_branch_reversed"
6090 (if_then_else (match_operator 1 "arm_comparison_operator"
6091 [(match_operand 2 "cc_register" "") (const_int 0)])
6093 (label_ref (match_operand 0 "" ""))))]
6096 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6098 arm_ccfsm_state += 2;
6101 return \"b%D1\\t%l0\";
6103 [(set_attr "conds" "use")]
6110 (define_expand "seq"
6111 [(set (match_operand:SI 0 "s_register_operand" "=r")
6112 (eq:SI (match_dup 1) (const_int 0)))]
6114 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6117 (define_expand "sne"
6118 [(set (match_operand:SI 0 "s_register_operand" "=r")
6119 (ne:SI (match_dup 1) (const_int 0)))]
6121 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6124 (define_expand "sgt"
6125 [(set (match_operand:SI 0 "s_register_operand" "=r")
6126 (gt:SI (match_dup 1) (const_int 0)))]
6128 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6131 (define_expand "sle"
6132 [(set (match_operand:SI 0 "s_register_operand" "=r")
6133 (le:SI (match_dup 1) (const_int 0)))]
6135 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6138 (define_expand "sge"
6139 [(set (match_operand:SI 0 "s_register_operand" "=r")
6140 (ge:SI (match_dup 1) (const_int 0)))]
6142 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6145 (define_expand "slt"
6146 [(set (match_operand:SI 0 "s_register_operand" "=r")
6147 (lt:SI (match_dup 1) (const_int 0)))]
6149 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6152 (define_expand "sgtu"
6153 [(set (match_operand:SI 0 "s_register_operand" "=r")
6154 (gtu:SI (match_dup 1) (const_int 0)))]
6156 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6159 (define_expand "sleu"
6160 [(set (match_operand:SI 0 "s_register_operand" "=r")
6161 (leu:SI (match_dup 1) (const_int 0)))]
6163 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6166 (define_expand "sgeu"
6167 [(set (match_operand:SI 0 "s_register_operand" "=r")
6168 (geu:SI (match_dup 1) (const_int 0)))]
6170 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6173 (define_expand "sltu"
6174 [(set (match_operand:SI 0 "s_register_operand" "=r")
6175 (ltu:SI (match_dup 1) (const_int 0)))]
6177 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6180 (define_expand "sunordered"
6181 [(set (match_operand:SI 0 "s_register_operand" "=r")
6182 (unordered:SI (match_dup 1) (const_int 0)))]
6183 "TARGET_ARM && TARGET_HARD_FLOAT"
6184 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6188 (define_expand "sordered"
6189 [(set (match_operand:SI 0 "s_register_operand" "=r")
6190 (ordered:SI (match_dup 1) (const_int 0)))]
6191 "TARGET_ARM && TARGET_HARD_FLOAT"
6192 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6196 (define_expand "sungt"
6197 [(set (match_operand:SI 0 "s_register_operand" "=r")
6198 (ungt:SI (match_dup 1) (const_int 0)))]
6199 "TARGET_ARM && TARGET_HARD_FLOAT"
6200 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6204 (define_expand "sunge"
6205 [(set (match_operand:SI 0 "s_register_operand" "=r")
6206 (unge:SI (match_dup 1) (const_int 0)))]
6207 "TARGET_ARM && TARGET_HARD_FLOAT"
6208 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6212 (define_expand "sunlt"
6213 [(set (match_operand:SI 0 "s_register_operand" "=r")
6214 (unlt:SI (match_dup 1) (const_int 0)))]
6215 "TARGET_ARM && TARGET_HARD_FLOAT"
6216 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6220 (define_expand "sunle"
6221 [(set (match_operand:SI 0 "s_register_operand" "=r")
6222 (unle:SI (match_dup 1) (const_int 0)))]
6223 "TARGET_ARM && TARGET_HARD_FLOAT"
6224 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6228 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6229 ;;; simple ARM instructions.
6231 ; (define_expand "suneq"
6232 ; [(set (match_operand:SI 0 "s_register_operand" "=r")
6233 ; (uneq:SI (match_dup 1) (const_int 0)))]
6234 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6238 ; (define_expand "sltgt"
6239 ; [(set (match_operand:SI 0 "s_register_operand" "=r")
6240 ; (ltgt:SI (match_dup 1) (const_int 0)))]
6241 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6245 (define_insn "*mov_scc"
6246 [(set (match_operand:SI 0 "s_register_operand" "=r")
6247 (match_operator:SI 1 "arm_comparison_operator"
6248 [(match_operand 2 "cc_register" "") (const_int 0)]))]
6250 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6251 [(set_attr "conds" "use")
6252 (set_attr "length" "8")]
6255 (define_insn "*mov_negscc"
6256 [(set (match_operand:SI 0 "s_register_operand" "=r")
6257 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
6258 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6260 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6261 [(set_attr "conds" "use")
6262 (set_attr "length" "8")]
6265 (define_insn "*mov_notscc"
6266 [(set (match_operand:SI 0 "s_register_operand" "=r")
6267 (not:SI (match_operator:SI 1 "arm_comparison_operator"
6268 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6270 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6271 [(set_attr "conds" "use")
6272 (set_attr "length" "8")]
6276 ;; Conditional move insns
6278 (define_expand "movsicc"
6279 [(set (match_operand:SI 0 "s_register_operand" "")
6280 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6281 (match_operand:SI 2 "arm_not_operand" "")
6282 (match_operand:SI 3 "arm_not_operand" "")))]
6286 enum rtx_code code = GET_CODE (operands[1]);
6287 rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6289 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6293 (define_expand "movsfcc"
6294 [(set (match_operand:SF 0 "s_register_operand" "")
6295 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6296 (match_operand:SF 2 "s_register_operand" "")
6297 (match_operand:SF 3 "nonmemory_operand" "")))]
6301 enum rtx_code code = GET_CODE (operands[1]);
6304 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
6305 Otherwise, ensure it is a valid FP add operand */
6306 if ((!TARGET_HARD_FLOAT)
6307 || (!fpu_add_operand (operands[3], SFmode)))
6308 operands[3] = force_reg (SFmode, operands[3]);
6310 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6311 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6315 (define_expand "movdfcc"
6316 [(set (match_operand:DF 0 "s_register_operand" "")
6317 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6318 (match_operand:DF 2 "s_register_operand" "")
6319 (match_operand:DF 3 "fpu_add_operand" "")))]
6320 "TARGET_ARM && TARGET_HARD_FLOAT"
6323 enum rtx_code code = GET_CODE (operands[1]);
6324 rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6326 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6330 (define_insn "*movsicc_insn"
6331 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6333 (match_operator 3 "arm_comparison_operator"
6334 [(match_operand 4 "cc_register" "") (const_int 0)])
6335 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6336 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6343 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6344 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6345 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6346 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6347 [(set_attr "length" "4,4,4,4,8,8,8,8")
6348 (set_attr "conds" "use")]
6351 (define_insn "*movsfcc_hard_insn"
6352 [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6354 (match_operator 3 "arm_comparison_operator"
6355 [(match_operand 4 "cc_register" "") (const_int 0)])
6356 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6357 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6358 "TARGET_ARM && TARGET_HARD_FLOAT"
6364 mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
6365 mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
6366 mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
6367 mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
6368 [(set_attr "length" "4,4,4,4,8,8,8,8")
6369 (set_attr "type" "ffarith")
6370 (set_attr "conds" "use")]
6373 (define_insn "*movsfcc_soft_insn"
6374 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6375 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
6376 [(match_operand 4 "cc_register" "") (const_int 0)])
6377 (match_operand:SF 1 "s_register_operand" "0,r")
6378 (match_operand:SF 2 "s_register_operand" "r,0")))]
6379 "TARGET_ARM && TARGET_SOFT_FLOAT"
6383 [(set_attr "conds" "use")]
6386 (define_insn "*movdfcc_insn"
6387 [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6389 (match_operator 3 "arm_comparison_operator"
6390 [(match_operand 4 "cc_register" "") (const_int 0)])
6391 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6392 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6393 "TARGET_ARM && TARGET_HARD_FLOAT"
6399 mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
6400 mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
6401 mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
6402 mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
6403 [(set_attr "length" "4,4,4,4,8,8,8,8")
6404 (set_attr "type" "ffarith")
6405 (set_attr "conds" "use")]
6409 ;; Jump and linkage insns
6411 (define_expand "jump"
6413 (label_ref (match_operand 0 "" "")))]
6418 (define_insn "*arm_jump"
6420 (label_ref (match_operand 0 "" "")))]
6424 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6426 arm_ccfsm_state += 2;
6429 return \"b%?\\t%l0\";
6432 [(set_attr "predicable" "yes")]
6435 (define_insn "*thumb_jump"
6437 (label_ref (match_operand 0 "" "")))]
6440 if (get_attr_length (insn) == 2)
6442 return \"bl\\t%l0\\t%@ far jump\";
6444 [(set (attr "far_jump")
6446 (eq_attr "length" "4")
6447 (const_string "yes")
6448 (const_string "no")))
6449 (set (attr "length")
6451 (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6452 (le (minus (match_dup 0) (pc)) (const_int 2044)))
6457 (define_expand "call"
6458 [(parallel [(call (match_operand 0 "memory_operand" "")
6459 (match_operand 1 "general_operand" ""))
6460 (use (match_operand 2 "" ""))
6461 (clobber (reg:SI LR_REGNUM))])]
6467 /* In an untyped call, we can get NULL for operand 2. */
6468 if (operands[2] == NULL_RTX)
6469 operands[2] = const0_rtx;
6471 /* This is to decide if we should generate indirect calls by loading the
6472 32 bit address of the callee into a register before performing the
6473 branch and link. operand[2] encodes the long_call/short_call
6474 attribute of the function being called. This attribute is set whenever
6475 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6476 is used, and the short_call attribute can also be set if function is
6477 declared as static or if it has already been defined in the current
6478 compilation unit. See arm.c and arm.h for info about this. The third
6479 parameter to arm_is_longcall_p is used to tell it which pattern
6481 callee = XEXP (operands[0], 0);
6483 if (GET_CODE (callee) != REG
6484 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6485 XEXP (operands[0], 0) = force_reg (Pmode, callee);
6489 (define_insn "*call_reg"
6490 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
6491 (match_operand 1 "" ""))
6492 (use (match_operand 2 "" ""))
6493 (clobber (reg:SI LR_REGNUM))]
6496 return output_call (operands);
6498 ;; length is worst case, normally it is only two
6499 [(set_attr "length" "12")
6500 (set_attr "type" "call")]
6503 (define_insn "*call_mem"
6504 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
6505 (match_operand 1 "" ""))
6506 (use (match_operand 2 "" ""))
6507 (clobber (reg:SI LR_REGNUM))]
6510 return output_call_mem (operands);
6512 [(set_attr "length" "12")
6513 (set_attr "type" "call")]
6516 (define_insn "*call_indirect"
6517 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6518 (match_operand 1 "" ""))
6519 (use (match_operand 2 "" ""))
6520 (clobber (reg:SI LR_REGNUM))]
6524 if (TARGET_CALLER_INTERWORKING)
6525 return \"bl\\t%__interwork_call_via_%0\";
6527 return \"bl\\t%__call_via_%0\";
6529 [(set_attr "type" "call")]
6532 (define_insn "*call_value_indirect"
6533 [(set (match_operand 0 "" "=l")
6534 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6535 (match_operand 2 "" "")))
6536 (use (match_operand 3 "" ""))
6537 (clobber (reg:SI LR_REGNUM))]
6541 if (TARGET_CALLER_INTERWORKING)
6542 return \"bl\\t%__interwork_call_via_%1\";
6544 return \"bl\\t%__call_via_%1\";
6546 [(set_attr "type" "call")]
6549 (define_expand "call_value"
6550 [(parallel [(set (match_operand 0 "" "")
6551 (call (match_operand 1 "memory_operand" "")
6552 (match_operand 2 "general_operand" "")))
6553 (use (match_operand 3 "" ""))
6554 (clobber (reg:SI LR_REGNUM))])]
6558 rtx callee = XEXP (operands[1], 0);
6560 /* In an untyped call, we can get NULL for operand 2. */
6561 if (operands[3] == 0)
6562 operands[3] = const0_rtx;
6564 /* See the comment in define_expand \"call\". */
6565 if (GET_CODE (callee) != REG
6566 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6567 XEXP (operands[1], 0) = force_reg (Pmode, callee);
6571 (define_insn "*call_value_reg"
6572 [(set (match_operand 0 "" "=r,f")
6573 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r"))
6574 (match_operand 2 "" "")))
6575 (use (match_operand 3 "" ""))
6576 (clobber (reg:SI LR_REGNUM))]
6579 return output_call (&operands[1]);
6581 [(set_attr "length" "12")
6582 (set_attr "type" "call")]
6585 (define_insn "*call_value_mem"
6586 [(set (match_operand 0 "" "=r,f")
6587 (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m"))
6588 (match_operand 2 "" "")))
6589 (use (match_operand 3 "" ""))
6590 (clobber (reg:SI LR_REGNUM))]
6591 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6593 return output_call_mem (&operands[1]);
6595 [(set_attr "length" "12")
6596 (set_attr "type" "call")]
6599 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6600 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6602 (define_insn "*call_symbol"
6603 [(call (mem:SI (match_operand:SI 0 "" "X"))
6604 (match_operand 1 "" ""))
6605 (use (match_operand 2 "" ""))
6606 (clobber (reg:SI LR_REGNUM))]
6608 && (GET_CODE (operands[0]) == SYMBOL_REF)
6609 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6612 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6614 [(set_attr "type" "call")]
6617 (define_insn "*call_value_symbol"
6618 [(set (match_operand 0 "s_register_operand" "=r,f")
6619 (call (mem:SI (match_operand:SI 1 "" "X,X"))
6620 (match_operand:SI 2 "" "")))
6621 (use (match_operand 3 "" ""))
6622 (clobber (reg:SI LR_REGNUM))]
6624 && (GET_CODE (operands[1]) == SYMBOL_REF)
6625 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6628 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6630 [(set_attr "type" "call")]
6633 (define_insn "*call_insn"
6634 [(call (mem:SI (match_operand:SI 0 "" "X"))
6635 (match_operand:SI 1 "" ""))
6636 (use (match_operand 2 "" ""))
6637 (clobber (reg:SI LR_REGNUM))]
6639 && GET_CODE (operands[0]) == SYMBOL_REF
6640 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6642 [(set_attr "length" "4")
6643 (set_attr "type" "call")]
6646 (define_insn "*call_value_insn"
6647 [(set (match_operand 0 "register_operand" "=l")
6648 (call (mem:SI (match_operand 1 "" "X"))
6649 (match_operand 2 "" "")))
6650 (use (match_operand 3 "" ""))
6651 (clobber (reg:SI LR_REGNUM))]
6653 && GET_CODE (operands[1]) == SYMBOL_REF
6654 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6656 [(set_attr "length" "4")
6657 (set_attr "type" "call")]
6660 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6661 (define_expand "sibcall"
6662 [(parallel [(call (match_operand 0 "memory_operand" "")
6663 (match_operand 1 "general_operand" ""))
6664 (use (match_operand 2 "" ""))
6665 (use (reg:SI LR_REGNUM))])]
6669 if (operands[2] == NULL_RTX)
6670 operands[2] = const0_rtx;
6674 (define_expand "sibcall_value"
6675 [(parallel [(set (match_operand 0 "register_operand" "")
6676 (call (match_operand 1 "memory_operand" "")
6677 (match_operand 2 "general_operand" "")))
6678 (use (match_operand 3 "" ""))
6679 (use (reg:SI LR_REGNUM))])]
6683 if (operands[3] == NULL_RTX)
6684 operands[3] = const0_rtx;
6688 (define_insn "*sibcall_insn"
6689 [(call (mem:SI (match_operand:SI 0 "" "X"))
6690 (match_operand 1 "" ""))
6691 (use (match_operand 2 "" ""))
6692 (use (reg:SI LR_REGNUM))]
6693 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6695 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6697 [(set_attr "type" "call")]
6700 (define_insn "*sibcall_value_insn"
6701 [(set (match_operand 0 "s_register_operand" "=r,f")
6702 (call (mem:SI (match_operand:SI 1 "" "X,X"))
6703 (match_operand 2 "" "")))
6704 (use (match_operand 3 "" ""))
6705 (use (reg:SI LR_REGNUM))]
6706 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6708 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6710 [(set_attr "type" "call")]
6713 ;; Often the return insn will be the same as loading from memory, so set attr
6714 (define_insn "return"
6716 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6719 if (arm_ccfsm_state == 2)
6721 arm_ccfsm_state += 2;
6724 return output_return_instruction (NULL, TRUE, FALSE);
6726 [(set_attr "type" "load")
6727 (set_attr "predicable" "yes")]
6730 (define_insn "*cond_return"
6732 (if_then_else (match_operator 0 "arm_comparison_operator"
6733 [(match_operand 1 "cc_register" "") (const_int 0)])
6736 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6739 if (arm_ccfsm_state == 2)
6741 arm_ccfsm_state += 2;
6744 return output_return_instruction (operands[0], TRUE, FALSE);
6746 [(set_attr "conds" "use")
6747 (set_attr "type" "load")]
6750 (define_insn "*cond_return_inverted"
6752 (if_then_else (match_operator 0 "arm_comparison_operator"
6753 [(match_operand 1 "cc_register" "") (const_int 0)])
6756 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6759 if (arm_ccfsm_state == 2)
6761 arm_ccfsm_state += 2;
6764 return output_return_instruction (operands[0], TRUE, TRUE);
6766 [(set_attr "conds" "use")
6767 (set_attr "type" "load")]
6770 ;; Call subroutine returning any type.
6772 (define_expand "untyped_call"
6773 [(parallel [(call (match_operand 0 "" "")
6775 (match_operand 1 "" "")
6776 (match_operand 2 "" "")])]
6782 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6784 for (i = 0; i < XVECLEN (operands[2], 0); i++)
6786 rtx set = XVECEXP (operands[2], 0, i);
6788 emit_move_insn (SET_DEST (set), SET_SRC (set));
6791 /* The optimizer does not know that the call sets the function value
6792 registers we stored in the result block. We avoid problems by
6793 claiming that all hard registers are used and clobbered at this
6795 emit_insn (gen_blockage ());
6801 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6802 ;; all of memory. This blocks insns from being moved across this point.
6804 (define_insn "blockage"
6805 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6808 [(set_attr "length" "0")
6809 (set_attr "type" "block")]
6812 (define_expand "casesi"
6813 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6814 (match_operand:SI 1 "const_int_operand" "") ; lower bound
6815 (match_operand:SI 2 "const_int_operand" "") ; total range
6816 (match_operand:SI 3 "" "") ; table label
6817 (match_operand:SI 4 "" "")] ; Out of range label
6822 if (operands[1] != const0_rtx)
6824 reg = gen_reg_rtx (SImode);
6826 emit_insn (gen_addsi3 (reg, operands[0],
6827 GEN_INT (-INTVAL (operands[1]))));
6831 if (!const_ok_for_arm (INTVAL (operands[2])))
6832 operands[2] = force_reg (SImode, operands[2]);
6834 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6840 ;; The USE in this pattern is needed to tell flow analysis that this is
6841 ;; a CASESI insn. It has no other purpose.
6842 (define_insn "casesi_internal"
6843 [(parallel [(set (pc)
6845 (leu (match_operand:SI 0 "s_register_operand" "r")
6846 (match_operand:SI 1 "arm_rhs_operand" "rI"))
6847 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6848 (label_ref (match_operand 2 "" ""))))
6849 (label_ref (match_operand 3 "" ""))))
6850 (clobber (reg:CC CC_REGNUM))
6851 (use (label_ref (match_dup 2)))])]
6855 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6856 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6858 [(set_attr "conds" "clob")
6859 (set_attr "length" "12")]
6862 (define_expand "indirect_jump"
6864 (match_operand:SI 0 "s_register_operand" ""))]
6869 (define_insn "*arm_indirect_jump"
6871 (match_operand:SI 0 "s_register_operand" "r"))]
6873 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6874 [(set_attr "predicable" "yes")]
6877 ;; Although not supported by the define_expand above,
6878 ;; cse/combine may generate this form.
6879 (define_insn "*load_indirect_jump"
6881 (match_operand:SI 0 "memory_operand" "m"))]
6883 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6884 [(set_attr "type" "load")
6885 (set_attr "pool_range" "4096")
6886 (set_attr "neg_pool_range" "4084")
6887 (set_attr "predicable" "yes")]
6890 (define_insn "*thumb_indirect_jump"
6892 (match_operand:SI 0 "register_operand" "l*r"))]
6895 [(set_attr "conds" "clob")
6896 (set_attr "length" "2")]
6907 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6908 return \"mov\\tr8, r8\";
6910 [(set (attr "length")
6911 (if_then_else (eq_attr "is_thumb" "yes")
6917 ;; Patterns to allow combination of arithmetic, cond code and shifts
6919 (define_insn "*arith_shiftsi"
6920 [(set (match_operand:SI 0 "s_register_operand" "=r")
6921 (match_operator:SI 1 "shiftable_operator"
6922 [(match_operator:SI 3 "shift_operator"
6923 [(match_operand:SI 4 "s_register_operand" "r")
6924 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6925 (match_operand:SI 2 "s_register_operand" "r")]))]
6927 "%i1%?\\t%0, %2, %4%S3"
6928 [(set_attr "predicable" "yes")
6929 (set_attr "shift" "4")
6933 (define_insn "*arith_shiftsi_compare0"
6934 [(set (reg:CC_NOOV CC_REGNUM)
6935 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6936 [(match_operator:SI 3 "shift_operator"
6937 [(match_operand:SI 4 "s_register_operand" "r")
6938 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6939 (match_operand:SI 2 "s_register_operand" "r")])
6941 (set (match_operand:SI 0 "s_register_operand" "=r")
6942 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6945 "%i1%?s\\t%0, %2, %4%S3"
6946 [(set_attr "conds" "set")
6947 (set_attr "shift" "4")
6951 (define_insn "*arith_shiftsi_compare0_scratch"
6952 [(set (reg:CC_NOOV CC_REGNUM)
6953 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6954 [(match_operator:SI 3 "shift_operator"
6955 [(match_operand:SI 4 "s_register_operand" "r")
6956 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6957 (match_operand:SI 2 "s_register_operand" "r")])
6959 (clobber (match_scratch:SI 0 "=r"))]
6961 "%i1%?s\\t%0, %2, %4%S3"
6962 [(set_attr "conds" "set")
6963 (set_attr "shift" "4")
6967 (define_insn "*sub_shiftsi"
6968 [(set (match_operand:SI 0 "s_register_operand" "=r")
6969 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6970 (match_operator:SI 2 "shift_operator"
6971 [(match_operand:SI 3 "s_register_operand" "r")
6972 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
6974 "sub%?\\t%0, %1, %3%S2"
6975 [(set_attr "predicable" "yes")
6976 (set_attr "shift" "3")
6980 (define_insn "*sub_shiftsi_compare0"
6981 [(set (reg:CC_NOOV CC_REGNUM)
6983 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6984 (match_operator:SI 2 "shift_operator"
6985 [(match_operand:SI 3 "s_register_operand" "r")
6986 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6988 (set (match_operand:SI 0 "s_register_operand" "=r")
6989 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6992 "sub%?s\\t%0, %1, %3%S2"
6993 [(set_attr "conds" "set")
6994 (set_attr "shift" "3")
6998 (define_insn "*sub_shiftsi_compare0_scratch"
6999 [(set (reg:CC_NOOV CC_REGNUM)
7001 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7002 (match_operator:SI 2 "shift_operator"
7003 [(match_operand:SI 3 "s_register_operand" "r")
7004 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7006 (clobber (match_scratch:SI 0 "=r"))]
7008 "sub%?s\\t%0, %1, %3%S2"
7009 [(set_attr "conds" "set")
7010 (set_attr "shift" "3")
7014 ;; These variants of the above insns can occur if the first operand is the
7015 ;; frame pointer and we eliminate that. This is a kludge, but there doesn't
7016 ;; seem to be a way around it. Most of the predicates have to be null
7017 ;; because the format can be generated part way through reload, so
7018 ;; if we don't match it as soon as it becomes available, reload doesn't know
7019 ;; how to reload pseudos that haven't got hard registers; the constraints will
7020 ;; sort everything out.
7022 (define_insn "*reload_mulsi3"
7023 [(set (match_operand:SI 0 "" "=&r")
7024 (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
7025 [(match_operand:SI 3 "" "r")
7026 (match_operand:SI 4 "" "rM")])
7027 (match_operand:SI 2 "" "r"))
7028 (match_operand:SI 1 "const_int_operand" "n")))]
7029 "TARGET_ARM && reload_in_progress"
7031 output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
7032 operands[2] = operands[1];
7033 operands[1] = operands[0];
7034 return output_add_immediate (operands);
7037 ; we have no idea how long the add_immediate is, it could be up to 4.
7038 (set_attr "length" "20")]
7041 (define_insn "*reload_mulsi_compare0"
7042 [(set (reg:CC_NOOV CC_REGNUM)
7043 (compare:CC_NOOV (plus:SI
7045 (match_operator:SI 5 "shift_operator"
7046 [(match_operand:SI 3 "" "r")
7047 (match_operand:SI 4 "" "rM")])
7048 (match_operand:SI 1 "" "r"))
7049 (match_operand:SI 2 "const_int_operand" "n"))
7051 (set (match_operand:SI 0 "" "=&r")
7052 (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
7055 "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7057 output_add_immediate (operands);
7058 return \"add%?s\\t%0, %0, %3%S5\";
7060 [(set_attr "conds" "set")
7061 (set_attr "shift" "3")
7062 (set_attr "length" "20")]
7065 (define_insn "*reload_mulsi_compare0_scratch"
7066 [(set (reg:CC_NOOV CC_REGNUM)
7067 (compare:CC_NOOV (plus:SI
7069 (match_operator:SI 5 "shift_operator"
7070 [(match_operand:SI 3 "" "r")
7071 (match_operand:SI 4 "" "rM")])
7072 (match_operand:SI 1 "" "r"))
7073 (match_operand:SI 2 "const_int_operand" "n"))
7075 (clobber (match_scratch:SI 0 "=&r"))]
7076 "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7078 output_add_immediate (operands);
7079 return \"add%?s\\t%0, %0, %3%S5\";
7081 [(set_attr "conds" "set")
7082 (set_attr "shift" "3")
7083 (set_attr "length" "20")]
7086 ;; These are similar, but are needed when the mla pattern contains the
7087 ;; eliminated register as operand 3.
7089 (define_insn "*reload_muladdsi"
7090 [(set (match_operand:SI 0 "" "=&r,&r")
7091 (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
7092 (match_operand:SI 2 "" "r,r"))
7093 (match_operand:SI 3 "" "r,r"))
7094 (match_operand:SI 4 "const_int_operand" "n,n")))]
7095 "TARGET_ARM && reload_in_progress"
7097 output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
7098 operands[2] = operands[4];
7099 operands[1] = operands[0];
7100 return output_add_immediate (operands);
7102 [(set_attr "length" "20")
7103 (set_attr "type" "mult")]
7106 (define_insn "*reload_muladdsi_compare0"
7107 [(set (reg:CC_NOOV CC_REGNUM)
7108 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
7109 (match_operand:SI 3 "" "r")
7110 (match_operand:SI 4 "" "r"))
7111 (match_operand:SI 1 "" "r"))
7112 (match_operand:SI 2 "const_int_operand" "n"))
7114 (set (match_operand:SI 0 "" "=&r")
7115 (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
7117 "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7119 output_add_immediate (operands);
7120 output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
7123 [(set_attr "length" "20")
7124 (set_attr "conds" "set")
7125 (set_attr "type" "mult")]
7128 (define_insn "*reload_muladdsi_compare0_scratch"
7129 [(set (reg:CC_NOOV CC_REGNUM)
7130 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
7131 (match_operand:SI 3 "" "r")
7132 (match_operand:SI 4 "" "r"))
7133 (match_operand:SI 1 "" "r"))
7134 (match_operand:SI 2 "const_int_operand" "n"))
7136 (clobber (match_scratch:SI 0 "=&r"))]
7137 "TARGET_ARM && reload_in_progress"
7139 output_add_immediate (operands);
7140 return \"mla%?s\\t%0, %3, %4, %0\";
7142 [(set_attr "length" "20")
7143 (set_attr "conds" "set")
7144 (set_attr "type" "mult")]
7149 (define_insn "*and_scc"
7150 [(set (match_operand:SI 0 "s_register_operand" "=r")
7151 (and:SI (match_operator:SI 1 "arm_comparison_operator"
7152 [(match_operand 3 "cc_register" "") (const_int 0)])
7153 (match_operand:SI 2 "s_register_operand" "r")))]
7155 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7156 [(set_attr "conds" "use")
7157 (set_attr "length" "8")]
7160 (define_insn "*ior_scc"
7161 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7162 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
7163 [(match_operand 3 "cc_register" "") (const_int 0)])
7164 (match_operand:SI 1 "s_register_operand" "0,?r")))]
7168 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7169 [(set_attr "conds" "use")
7170 (set_attr "length" "4,8")]
7173 (define_insn "*compare_scc"
7174 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7175 (match_operator:SI 1 "arm_comparison_operator"
7176 [(match_operand:SI 2 "s_register_operand" "r,r")
7177 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7178 (clobber (reg:CC CC_REGNUM))]
7181 if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
7182 return \"mov\\t%0, %2, lsr #31\";
7184 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
7185 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7187 if (GET_CODE (operands[1]) == NE)
7189 if (which_alternative == 1)
7190 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7191 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7193 if (which_alternative == 1)
7194 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7196 output_asm_insn (\"cmp\\t%2, %3\", operands);
7197 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7199 [(set_attr "conds" "clob")
7200 (set_attr "length" "12")]
7203 (define_insn "*cond_move"
7204 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7205 (if_then_else:SI (match_operator 3 "equality_operator"
7206 [(match_operator 4 "arm_comparison_operator"
7207 [(match_operand 5 "cc_register" "") (const_int 0)])
7209 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7210 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7213 if (GET_CODE (operands[3]) == NE)
7215 if (which_alternative != 1)
7216 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7217 if (which_alternative != 0)
7218 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7221 if (which_alternative != 0)
7222 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7223 if (which_alternative != 1)
7224 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7227 [(set_attr "conds" "use")
7228 (set_attr "length" "4,4,8")]
7231 (define_insn "*cond_arith"
7232 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7233 (match_operator:SI 5 "shiftable_operator"
7234 [(match_operator:SI 4 "arm_comparison_operator"
7235 [(match_operand:SI 2 "s_register_operand" "r,r")
7236 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7237 (match_operand:SI 1 "s_register_operand" "0,?r")]))
7238 (clobber (reg:CC CC_REGNUM))]
7241 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7242 return \"%i5\\t%0, %1, %2, lsr #31\";
7244 output_asm_insn (\"cmp\\t%2, %3\", operands);
7245 if (GET_CODE (operands[5]) == AND)
7246 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7247 else if (GET_CODE (operands[5]) == MINUS)
7248 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7249 else if (which_alternative != 0)
7250 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7251 return \"%i5%d4\\t%0, %1, #1\";
7253 [(set_attr "conds" "clob")
7254 (set_attr "length" "12")]
7257 (define_insn "*cond_sub"
7258 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7259 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7260 (match_operator:SI 4 "arm_comparison_operator"
7261 [(match_operand:SI 2 "s_register_operand" "r,r")
7262 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7263 (clobber (reg:CC CC_REGNUM))]
7266 output_asm_insn (\"cmp\\t%2, %3\", operands);
7267 if (which_alternative != 0)
7268 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7269 return \"sub%d4\\t%0, %1, #1\";
7271 [(set_attr "conds" "clob")
7272 (set_attr "length" "8,12")]
7275 (define_insn "*cmp_ite0"
7276 [(set (match_operand 6 "dominant_cc_register" "")
7279 (match_operator 4 "arm_comparison_operator"
7280 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7281 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7282 (match_operator:SI 5 "arm_comparison_operator"
7283 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7284 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7290 static const char * const opcodes[4][2] =
7292 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7293 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7294 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7295 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7296 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7297 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7298 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7299 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7302 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7304 return opcodes[which_alternative][swap];
7306 [(set_attr "conds" "set")
7307 (set_attr "length" "8")]
7310 (define_insn "*cmp_ite1"
7311 [(set (match_operand 6 "dominant_cc_register" "")
7314 (match_operator 4 "arm_comparison_operator"
7315 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7316 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7317 (match_operator:SI 5 "arm_comparison_operator"
7318 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7319 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7325 static const char * const opcodes[4][2] =
7327 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7328 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7329 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7330 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7331 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7332 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7333 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7334 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7337 comparison_dominates_p (GET_CODE (operands[5]),
7338 reverse_condition (GET_CODE (operands[4])));
7340 return opcodes[which_alternative][swap];
7342 [(set_attr "conds" "set")
7343 (set_attr "length" "8")]
7346 (define_insn "*cmp_and"
7347 [(set (match_operand 6 "dominant_cc_register" "")
7350 (match_operator 4 "arm_comparison_operator"
7351 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7352 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7353 (match_operator:SI 5 "arm_comparison_operator"
7354 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7355 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7360 static const char *const opcodes[4][2] =
7362 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7363 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7364 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7365 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7366 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7367 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7368 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7369 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7372 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7374 return opcodes[which_alternative][swap];
7376 [(set_attr "conds" "set")
7377 (set_attr "predicable" "no")
7378 (set_attr "length" "8")]
7381 (define_insn "*cmp_ior"
7382 [(set (match_operand 6 "dominant_cc_register" "")
7385 (match_operator 4 "arm_comparison_operator"
7386 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7387 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7388 (match_operator:SI 5 "arm_comparison_operator"
7389 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7390 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7395 static const char *const opcodes[4][2] =
7397 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7398 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7399 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7400 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7401 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7402 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7403 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7404 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7407 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7409 return opcodes[which_alternative][swap];
7412 [(set_attr "conds" "set")
7413 (set_attr "length" "8")]
7416 (define_insn "*negscc"
7417 [(set (match_operand:SI 0 "s_register_operand" "=r")
7418 (neg:SI (match_operator 3 "arm_comparison_operator"
7419 [(match_operand:SI 1 "s_register_operand" "r")
7420 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7421 (clobber (reg:CC CC_REGNUM))]
7424 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7425 return \"mov\\t%0, %1, asr #31\";
7427 if (GET_CODE (operands[3]) == NE)
7428 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7430 if (GET_CODE (operands[3]) == GT)
7431 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7433 output_asm_insn (\"cmp\\t%1, %2\", operands);
7434 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7435 return \"mvn%d3\\t%0, #0\";
7437 [(set_attr "conds" "clob")
7438 (set_attr "length" "12")]
7441 (define_insn "movcond"
7442 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7444 (match_operator 5 "arm_comparison_operator"
7445 [(match_operand:SI 3 "s_register_operand" "r,r,r")
7446 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7447 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7448 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
7449 (clobber (reg:CC CC_REGNUM))]
7452 if (GET_CODE (operands[5]) == LT
7453 && (operands[4] == const0_rtx))
7455 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7457 if (operands[2] == const0_rtx)
7458 return \"and\\t%0, %1, %3, asr #31\";
7459 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
7461 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7463 if (operands[1] == const0_rtx)
7464 return \"bic\\t%0, %2, %3, asr #31\";
7465 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
7467 /* The only case that falls through to here is when both ops 1 & 2
7471 if (GET_CODE (operands[5]) == GE
7472 && (operands[4] == const0_rtx))
7474 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7476 if (operands[2] == const0_rtx)
7477 return \"bic\\t%0, %1, %3, asr #31\";
7478 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7480 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7482 if (operands[1] == const0_rtx)
7483 return \"and\\t%0, %2, %3, asr #31\";
7484 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7486 /* The only case that falls through to here is when both ops 1 & 2
7489 if (GET_CODE (operands[4]) == CONST_INT
7490 && !const_ok_for_arm (INTVAL (operands[4])))
7491 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7493 output_asm_insn (\"cmp\\t%3, %4\", operands);
7494 if (which_alternative != 0)
7495 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7496 if (which_alternative != 1)
7497 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7500 [(set_attr "conds" "clob")
7501 (set_attr "length" "8,8,12")]
7504 (define_insn "*ifcompare_plus_move"
7505 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7506 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7507 [(match_operand:SI 4 "s_register_operand" "r,r")
7508 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7510 (match_operand:SI 2 "s_register_operand" "r,r")
7511 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7512 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7513 (clobber (reg:CC CC_REGNUM))]
7516 [(set_attr "conds" "clob")
7517 (set_attr "length" "8,12")]
7520 (define_insn "*if_plus_move"
7521 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7523 (match_operator 4 "arm_comparison_operator"
7524 [(match_operand 5 "cc_register" "") (const_int 0)])
7526 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7527 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7528 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7532 sub%d4\\t%0, %2, #%n3
7533 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7534 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7535 [(set_attr "conds" "use")
7536 (set_attr "length" "4,4,8,8")
7537 (set_attr "type" "*,*,*,*")]
7540 (define_insn "*ifcompare_move_plus"
7541 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7542 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7543 [(match_operand:SI 4 "s_register_operand" "r,r")
7544 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7545 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7547 (match_operand:SI 2 "s_register_operand" "r,r")
7548 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7549 (clobber (reg:CC CC_REGNUM))]
7552 [(set_attr "conds" "clob")
7553 (set_attr "length" "8,12")]
7556 (define_insn "*if_move_plus"
7557 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7559 (match_operator 4 "arm_comparison_operator"
7560 [(match_operand 5 "cc_register" "") (const_int 0)])
7561 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7563 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7564 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7568 sub%D4\\t%0, %2, #%n3
7569 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7570 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7571 [(set_attr "conds" "use")
7572 (set_attr "length" "4,4,8,8")
7573 (set_attr "type" "*,*,*,*")]
7576 (define_insn "*ifcompare_arith_arith"
7577 [(set (match_operand:SI 0 "s_register_operand" "=r")
7578 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7579 [(match_operand:SI 5 "s_register_operand" "r")
7580 (match_operand:SI 6 "arm_add_operand" "rIL")])
7581 (match_operator:SI 8 "shiftable_operator"
7582 [(match_operand:SI 1 "s_register_operand" "r")
7583 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7584 (match_operator:SI 7 "shiftable_operator"
7585 [(match_operand:SI 3 "s_register_operand" "r")
7586 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7587 (clobber (reg:CC CC_REGNUM))]
7590 [(set_attr "conds" "clob")
7591 (set_attr "length" "12")]
7594 (define_insn "*if_arith_arith"
7595 [(set (match_operand:SI 0 "s_register_operand" "=r")
7596 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7597 [(match_operand 8 "cc_register" "") (const_int 0)])
7598 (match_operator:SI 6 "shiftable_operator"
7599 [(match_operand:SI 1 "s_register_operand" "r")
7600 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7601 (match_operator:SI 7 "shiftable_operator"
7602 [(match_operand:SI 3 "s_register_operand" "r")
7603 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7605 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7606 [(set_attr "conds" "use")
7607 (set_attr "length" "8")]
7610 (define_insn "*ifcompare_arith_move"
7611 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7612 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7613 [(match_operand:SI 2 "s_register_operand" "r,r")
7614 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7615 (match_operator:SI 7 "shiftable_operator"
7616 [(match_operand:SI 4 "s_register_operand" "r,r")
7617 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7618 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7619 (clobber (reg:CC CC_REGNUM))]
7622 /* If we have an operation where (op x 0) is the identity operation and
7623 the conditional operator is LT or GE and we are comparing against zero and
7624 everything is in registers then we can do this in two instructions */
7625 if (operands[3] == const0_rtx
7626 && GET_CODE (operands[7]) != AND
7627 && GET_CODE (operands[5]) == REG
7628 && GET_CODE (operands[1]) == REG
7629 && REGNO (operands[1]) == REGNO (operands[4])
7630 && REGNO (operands[4]) != REGNO (operands[0]))
7632 if (GET_CODE (operands[6]) == LT)
7633 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7634 else if (GET_CODE (operands[6]) == GE)
7635 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7637 if (GET_CODE (operands[3]) == CONST_INT
7638 && !const_ok_for_arm (INTVAL (operands[3])))
7639 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7641 output_asm_insn (\"cmp\\t%2, %3\", operands);
7642 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7643 if (which_alternative != 0)
7644 return \"mov%D6\\t%0, %1\";
7647 [(set_attr "conds" "clob")
7648 (set_attr "length" "8,12")]
7651 (define_insn "*if_arith_move"
7652 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7653 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7654 [(match_operand 6 "cc_register" "") (const_int 0)])
7655 (match_operator:SI 5 "shiftable_operator"
7656 [(match_operand:SI 2 "s_register_operand" "r,r")
7657 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7658 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7662 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7663 [(set_attr "conds" "use")
7664 (set_attr "length" "4,8")
7665 (set_attr "type" "*,*")]
7668 (define_insn "*ifcompare_move_arith"
7669 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7670 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7671 [(match_operand:SI 4 "s_register_operand" "r,r")
7672 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7673 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7674 (match_operator:SI 7 "shiftable_operator"
7675 [(match_operand:SI 2 "s_register_operand" "r,r")
7676 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7677 (clobber (reg:CC CC_REGNUM))]
7680 /* If we have an operation where (op x 0) is the identity operation and
7681 the conditional operator is LT or GE and we are comparing against zero and
7682 everything is in registers then we can do this in two instructions */
7683 if (operands[5] == const0_rtx
7684 && GET_CODE (operands[7]) != AND
7685 && GET_CODE (operands[3]) == REG
7686 && GET_CODE (operands[1]) == REG
7687 && REGNO (operands[1]) == REGNO (operands[2])
7688 && REGNO (operands[2]) != REGNO (operands[0]))
7690 if (GET_CODE (operands[6]) == GE)
7691 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7692 else if (GET_CODE (operands[6]) == LT)
7693 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7696 if (GET_CODE (operands[5]) == CONST_INT
7697 && !const_ok_for_arm (INTVAL (operands[5])))
7698 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7700 output_asm_insn (\"cmp\\t%4, %5\", operands);
7702 if (which_alternative != 0)
7703 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7704 return \"%I7%D6\\t%0, %2, %3\";
7706 [(set_attr "conds" "clob")
7707 (set_attr "length" "8,12")]
7710 (define_insn "*if_move_arith"
7711 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7713 (match_operator 4 "arm_comparison_operator"
7714 [(match_operand 6 "cc_register" "") (const_int 0)])
7715 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7716 (match_operator:SI 5 "shiftable_operator"
7717 [(match_operand:SI 2 "s_register_operand" "r,r")
7718 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7722 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7723 [(set_attr "conds" "use")
7724 (set_attr "length" "4,8")
7725 (set_attr "type" "*,*")]
7728 (define_insn "*ifcompare_move_not"
7729 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7731 (match_operator 5 "arm_comparison_operator"
7732 [(match_operand:SI 3 "s_register_operand" "r,r")
7733 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7734 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7736 (match_operand:SI 2 "s_register_operand" "r,r"))))
7737 (clobber (reg:CC CC_REGNUM))]
7740 [(set_attr "conds" "clob")
7741 (set_attr "length" "8,12")]
7744 (define_insn "*if_move_not"
7745 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7747 (match_operator 4 "arm_comparison_operator"
7748 [(match_operand 3 "cc_register" "") (const_int 0)])
7749 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7750 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7754 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7755 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7756 [(set_attr "conds" "use")
7757 (set_attr "length" "4,8,8")]
7760 (define_insn "*ifcompare_not_move"
7761 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7763 (match_operator 5 "arm_comparison_operator"
7764 [(match_operand:SI 3 "s_register_operand" "r,r")
7765 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7767 (match_operand:SI 2 "s_register_operand" "r,r"))
7768 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7769 (clobber (reg:CC CC_REGNUM))]
7772 [(set_attr "conds" "clob")
7773 (set_attr "length" "8,12")]
7776 (define_insn "*if_not_move"
7777 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7779 (match_operator 4 "arm_comparison_operator"
7780 [(match_operand 3 "cc_register" "") (const_int 0)])
7781 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7782 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7786 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7787 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7788 [(set_attr "conds" "use")
7789 (set_attr "length" "4,8,8")]
7792 (define_insn "*ifcompare_shift_move"
7793 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7795 (match_operator 6 "arm_comparison_operator"
7796 [(match_operand:SI 4 "s_register_operand" "r,r")
7797 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7798 (match_operator:SI 7 "shift_operator"
7799 [(match_operand:SI 2 "s_register_operand" "r,r")
7800 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7801 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7802 (clobber (reg:CC CC_REGNUM))]
7805 [(set_attr "conds" "clob")
7806 (set_attr "length" "8,12")]
7809 (define_insn "*if_shift_move"
7810 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7812 (match_operator 5 "arm_comparison_operator"
7813 [(match_operand 6 "cc_register" "") (const_int 0)])
7814 (match_operator:SI 4 "shift_operator"
7815 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7816 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7817 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7821 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7822 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7823 [(set_attr "conds" "use")
7824 (set_attr "shift" "2")
7825 (set_attr "length" "4,8,8")]
7828 (define_insn "*ifcompare_move_shift"
7829 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7831 (match_operator 6 "arm_comparison_operator"
7832 [(match_operand:SI 4 "s_register_operand" "r,r")
7833 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7834 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7835 (match_operator:SI 7 "shift_operator"
7836 [(match_operand:SI 2 "s_register_operand" "r,r")
7837 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7838 (clobber (reg:CC CC_REGNUM))]
7841 [(set_attr "conds" "clob")
7842 (set_attr "length" "8,12")]
7845 (define_insn "*if_move_shift"
7846 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7848 (match_operator 5 "arm_comparison_operator"
7849 [(match_operand 6 "cc_register" "") (const_int 0)])
7850 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7851 (match_operator:SI 4 "shift_operator"
7852 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7853 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7857 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7858 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7859 [(set_attr "conds" "use")
7860 (set_attr "shift" "2")
7861 (set_attr "length" "4,8,8")]
7864 (define_insn "*ifcompare_shift_shift"
7865 [(set (match_operand:SI 0 "s_register_operand" "=r")
7867 (match_operator 7 "arm_comparison_operator"
7868 [(match_operand:SI 5 "s_register_operand" "r")
7869 (match_operand:SI 6 "arm_add_operand" "rIL")])
7870 (match_operator:SI 8 "shift_operator"
7871 [(match_operand:SI 1 "s_register_operand" "r")
7872 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7873 (match_operator:SI 9 "shift_operator"
7874 [(match_operand:SI 3 "s_register_operand" "r")
7875 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7876 (clobber (reg:CC CC_REGNUM))]
7879 [(set_attr "conds" "clob")
7880 (set_attr "length" "12")]
7883 (define_insn "*if_shift_shift"
7884 [(set (match_operand:SI 0 "s_register_operand" "=r")
7886 (match_operator 5 "arm_comparison_operator"
7887 [(match_operand 8 "cc_register" "") (const_int 0)])
7888 (match_operator:SI 6 "shift_operator"
7889 [(match_operand:SI 1 "s_register_operand" "r")
7890 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7891 (match_operator:SI 7 "shift_operator"
7892 [(match_operand:SI 3 "s_register_operand" "r")
7893 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7895 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7896 [(set_attr "conds" "use")
7897 (set_attr "shift" "1")
7898 (set_attr "length" "8")]
7901 (define_insn "*ifcompare_not_arith"
7902 [(set (match_operand:SI 0 "s_register_operand" "=r")
7904 (match_operator 6 "arm_comparison_operator"
7905 [(match_operand:SI 4 "s_register_operand" "r")
7906 (match_operand:SI 5 "arm_add_operand" "rIL")])
7907 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7908 (match_operator:SI 7 "shiftable_operator"
7909 [(match_operand:SI 2 "s_register_operand" "r")
7910 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7911 (clobber (reg:CC CC_REGNUM))]
7914 [(set_attr "conds" "clob")
7915 (set_attr "length" "12")]
7918 (define_insn "*if_not_arith"
7919 [(set (match_operand:SI 0 "s_register_operand" "=r")
7921 (match_operator 5 "arm_comparison_operator"
7922 [(match_operand 4 "cc_register" "") (const_int 0)])
7923 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7924 (match_operator:SI 6 "shiftable_operator"
7925 [(match_operand:SI 2 "s_register_operand" "r")
7926 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7928 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7929 [(set_attr "conds" "use")
7930 (set_attr "length" "8")]
7933 (define_insn "*ifcompare_arith_not"
7934 [(set (match_operand:SI 0 "s_register_operand" "=r")
7936 (match_operator 6 "arm_comparison_operator"
7937 [(match_operand:SI 4 "s_register_operand" "r")
7938 (match_operand:SI 5 "arm_add_operand" "rIL")])
7939 (match_operator:SI 7 "shiftable_operator"
7940 [(match_operand:SI 2 "s_register_operand" "r")
7941 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7942 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7943 (clobber (reg:CC CC_REGNUM))]
7946 [(set_attr "conds" "clob")
7947 (set_attr "length" "12")]
7950 (define_insn "*if_arith_not"
7951 [(set (match_operand:SI 0 "s_register_operand" "=r")
7953 (match_operator 5 "arm_comparison_operator"
7954 [(match_operand 4 "cc_register" "") (const_int 0)])
7955 (match_operator:SI 6 "shiftable_operator"
7956 [(match_operand:SI 2 "s_register_operand" "r")
7957 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7958 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7960 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7961 [(set_attr "conds" "use")
7962 (set_attr "length" "8")]
7965 (define_insn "*ifcompare_neg_move"
7966 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7968 (match_operator 5 "arm_comparison_operator"
7969 [(match_operand:SI 3 "s_register_operand" "r,r")
7970 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7971 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7972 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7973 (clobber (reg:CC CC_REGNUM))]
7976 [(set_attr "conds" "clob")
7977 (set_attr "length" "8,12")]
7980 (define_insn "*if_neg_move"
7981 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7983 (match_operator 4 "arm_comparison_operator"
7984 [(match_operand 3 "cc_register" "") (const_int 0)])
7985 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7986 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7990 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7991 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
7992 [(set_attr "conds" "use")
7993 (set_attr "length" "4,8,8")]
7996 (define_insn "*ifcompare_move_neg"
7997 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7999 (match_operator 5 "arm_comparison_operator"
8000 [(match_operand:SI 3 "s_register_operand" "r,r")
8001 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8002 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8003 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
8004 (clobber (reg:CC CC_REGNUM))]
8007 [(set_attr "conds" "clob")
8008 (set_attr "length" "8,12")]
8011 (define_insn "*if_move_neg"
8012 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8014 (match_operator 4 "arm_comparison_operator"
8015 [(match_operand 3 "cc_register" "") (const_int 0)])
8016 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8017 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8021 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
8022 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
8023 [(set_attr "conds" "use")
8024 (set_attr "length" "4,8,8")]
8027 (define_insn "*arith_adjacentmem"
8028 [(set (match_operand:SI 0 "s_register_operand" "=r")
8029 (match_operator:SI 1 "shiftable_operator"
8030 [(match_operand:SI 2 "memory_operand" "m")
8031 (match_operand:SI 3 "memory_operand" "m")]))
8032 (clobber (match_scratch:SI 4 "=r"))]
8033 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
8038 int val1 = 0, val2 = 0;
8040 if (REGNO (operands[0]) > REGNO (operands[4]))
8042 ldm[1] = operands[4];
8043 ldm[2] = operands[0];
8047 ldm[1] = operands[0];
8048 ldm[2] = operands[4];
8050 if (GET_CODE (XEXP (operands[2], 0)) != REG)
8051 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
8052 if (GET_CODE (XEXP (operands[3], 0)) != REG)
8053 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
8054 arith[0] = operands[0];
8055 arith[3] = operands[1];
8069 ldm[0] = ops[0] = operands[4];
8070 ops[1] = XEXP (XEXP (operands[2], 0), 0);
8071 ops[2] = XEXP (XEXP (operands[2], 0), 1);
8072 output_add_immediate (ops);
8074 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8076 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8080 ldm[0] = XEXP (operands[3], 0);
8082 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8084 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8088 ldm[0] = XEXP (operands[2], 0);
8090 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8092 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8094 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
8097 [(set_attr "length" "12")
8098 (set_attr "predicable" "yes")
8099 (set_attr "type" "load")]
8102 ;; the arm can support extended pre-inc instructions
8104 ;; In all these cases, we use operands 0 and 1 for the register being
8105 ;; incremented because those are the operands that local-alloc will
8106 ;; tie and these are the pair most likely to be tieable (and the ones
8107 ;; that will benefit the most).
8109 ;; We reject the frame pointer if it occurs anywhere in these patterns since
8110 ;; elimination will cause too many headaches.
8112 (define_insn "*strqi_preinc"
8113 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8114 (match_operand:SI 2 "index_operand" "rJ")))
8115 (match_operand:QI 3 "s_register_operand" "r"))
8116 (set (match_operand:SI 0 "s_register_operand" "=r")
8117 (plus:SI (match_dup 1) (match_dup 2)))]
8119 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8120 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8121 && (GET_CODE (operands[2]) != REG
8122 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8123 "str%?b\\t%3, [%0, %2]!"
8124 [(set_attr "type" "store1")
8125 (set_attr "predicable" "yes")]
8128 (define_insn "*strqi_predec"
8129 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8130 (match_operand:SI 2 "s_register_operand" "r")))
8131 (match_operand:QI 3 "s_register_operand" "r"))
8132 (set (match_operand:SI 0 "s_register_operand" "=r")
8133 (minus:SI (match_dup 1) (match_dup 2)))]
8135 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8136 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8137 && (GET_CODE (operands[2]) != REG
8138 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8139 "str%?b\\t%3, [%0, -%2]!"
8140 [(set_attr "type" "store1")
8141 (set_attr "predicable" "yes")]
8144 (define_insn "*loadqi_preinc"
8145 [(set (match_operand:QI 3 "s_register_operand" "=r")
8146 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8147 (match_operand:SI 2 "index_operand" "rJ"))))
8148 (set (match_operand:SI 0 "s_register_operand" "=r")
8149 (plus:SI (match_dup 1) (match_dup 2)))]
8151 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8152 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8153 && (GET_CODE (operands[2]) != REG
8154 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8155 "ldr%?b\\t%3, [%0, %2]!"
8156 [(set_attr "type" "load")
8157 (set_attr "predicable" "yes")]
8160 (define_insn "*loadqi_predec"
8161 [(set (match_operand:QI 3 "s_register_operand" "=r")
8162 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8163 (match_operand:SI 2 "s_register_operand" "r"))))
8164 (set (match_operand:SI 0 "s_register_operand" "=r")
8165 (minus:SI (match_dup 1) (match_dup 2)))]
8167 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8168 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8169 && (GET_CODE (operands[2]) != REG
8170 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8171 "ldr%?b\\t%3, [%0, -%2]!"
8172 [(set_attr "type" "load")
8173 (set_attr "predicable" "yes")]
8176 (define_insn "*loadqisi_preinc"
8177 [(set (match_operand:SI 3 "s_register_operand" "=r")
8179 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8180 (match_operand:SI 2 "index_operand" "rJ")))))
8181 (set (match_operand:SI 0 "s_register_operand" "=r")
8182 (plus:SI (match_dup 1) (match_dup 2)))]
8184 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8185 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8186 && (GET_CODE (operands[2]) != REG
8187 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8188 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8189 [(set_attr "type" "load")
8190 (set_attr "predicable" "yes")]
8193 (define_insn "*loadqisi_predec"
8194 [(set (match_operand:SI 3 "s_register_operand" "=r")
8196 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8197 (match_operand:SI 2 "s_register_operand" "r")))))
8198 (set (match_operand:SI 0 "s_register_operand" "=r")
8199 (minus:SI (match_dup 1) (match_dup 2)))]
8201 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8202 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8203 && (GET_CODE (operands[2]) != REG
8204 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8205 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8206 [(set_attr "type" "load")
8207 (set_attr "predicable" "yes")]
8210 (define_insn "*strsi_preinc"
8211 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8212 (match_operand:SI 2 "index_operand" "rJ")))
8213 (match_operand:SI 3 "s_register_operand" "r"))
8214 (set (match_operand:SI 0 "s_register_operand" "=r")
8215 (plus:SI (match_dup 1) (match_dup 2)))]
8217 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8218 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8219 && (GET_CODE (operands[2]) != REG
8220 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8221 "str%?\\t%3, [%0, %2]!"
8222 [(set_attr "type" "store1")
8223 (set_attr "predicable" "yes")]
8226 (define_insn "*strsi_predec"
8227 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8228 (match_operand:SI 2 "s_register_operand" "r")))
8229 (match_operand:SI 3 "s_register_operand" "r"))
8230 (set (match_operand:SI 0 "s_register_operand" "=r")
8231 (minus:SI (match_dup 1) (match_dup 2)))]
8233 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8234 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8235 && (GET_CODE (operands[2]) != REG
8236 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8237 "str%?\\t%3, [%0, -%2]!"
8238 [(set_attr "type" "store1")
8239 (set_attr "predicable" "yes")]
8242 (define_insn "*loadsi_preinc"
8243 [(set (match_operand:SI 3 "s_register_operand" "=r")
8244 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8245 (match_operand:SI 2 "index_operand" "rJ"))))
8246 (set (match_operand:SI 0 "s_register_operand" "=r")
8247 (plus:SI (match_dup 1) (match_dup 2)))]
8249 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8250 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8251 && (GET_CODE (operands[2]) != REG
8252 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8253 "ldr%?\\t%3, [%0, %2]!"
8254 [(set_attr "type" "load")
8255 (set_attr "predicable" "yes")]
8258 (define_insn "*loadsi_predec"
8259 [(set (match_operand:SI 3 "s_register_operand" "=r")
8260 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8261 (match_operand:SI 2 "s_register_operand" "r"))))
8262 (set (match_operand:SI 0 "s_register_operand" "=r")
8263 (minus:SI (match_dup 1) (match_dup 2)))]
8265 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8266 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8267 && (GET_CODE (operands[2]) != REG
8268 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8269 "ldr%?\\t%3, [%0, -%2]!"
8270 [(set_attr "type" "load")
8271 (set_attr "predicable" "yes")]
8274 (define_insn "*loadhi_preinc"
8275 [(set (match_operand:HI 3 "s_register_operand" "=r")
8276 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8277 (match_operand:SI 2 "index_operand" "rJ"))))
8278 (set (match_operand:SI 0 "s_register_operand" "=r")
8279 (plus:SI (match_dup 1) (match_dup 2)))]
8281 && !BYTES_BIG_ENDIAN
8282 && !TARGET_MMU_TRAPS
8283 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8284 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8285 && (GET_CODE (operands[2]) != REG
8286 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8287 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8288 [(set_attr "type" "load")
8289 (set_attr "predicable" "yes")]
8292 (define_insn "*loadhi_predec"
8293 [(set (match_operand:HI 3 "s_register_operand" "=r")
8294 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8295 (match_operand:SI 2 "s_register_operand" "r"))))
8296 (set (match_operand:SI 0 "s_register_operand" "=r")
8297 (minus:SI (match_dup 1) (match_dup 2)))]
8299 && !BYTES_BIG_ENDIAN
8300 && !TARGET_MMU_TRAPS
8301 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8302 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8303 && (GET_CODE (operands[2]) != REG
8304 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8305 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8306 [(set_attr "type" "load")
8307 (set_attr "predicable" "yes")]
8310 (define_insn "*strqi_shiftpreinc"
8311 [(set (mem:QI (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:QI 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%?b\\t%5, [%0, %3%S2]!"
8324 [(set_attr "type" "store1")
8325 (set_attr "predicable" "yes")]
8328 (define_insn "*strqi_shiftpredec"
8329 [(set (mem:QI (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:QI 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%?b\\t%5, [%0, -%3%S2]!"
8342 [(set_attr "type" "store1")
8343 (set_attr "predicable" "yes")]
8346 (define_insn "*loadqi_shiftpreinc"
8347 [(set (match_operand:QI 5 "s_register_operand" "=r")
8348 (mem:QI (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%?b\\t%5, [%0, %3%S2]!"
8360 [(set_attr "type" "load")
8361 (set_attr "predicable" "yes")]
8364 (define_insn "*loadqi_shiftpredec"
8365 [(set (match_operand:QI 5 "s_register_operand" "=r")
8366 (mem:QI (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%?b\\t%5, [%0, -%3%S2]!"
8378 [(set_attr "type" "load")
8379 (set_attr "predicable" "yes")]
8382 (define_insn "*strsi_shiftpreinc"
8383 [(set (mem:SI (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 (match_operand:SI 5 "s_register_operand" "r"))
8388 (set (match_operand:SI 0 "s_register_operand" "=r")
8389 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8392 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8393 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8394 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8395 "str%?\\t%5, [%0, %3%S2]!"
8396 [(set_attr "type" "store1")
8397 (set_attr "predicable" "yes")]
8400 (define_insn "*strsi_shiftpredec"
8401 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8402 (match_operator:SI 2 "shift_operator"
8403 [(match_operand:SI 3 "s_register_operand" "r")
8404 (match_operand:SI 4 "const_shift_operand" "n")])))
8405 (match_operand:SI 5 "s_register_operand" "r"))
8406 (set (match_operand:SI 0 "s_register_operand" "=r")
8407 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8410 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8411 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8412 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8413 "str%?\\t%5, [%0, -%3%S2]!"
8414 [(set_attr "type" "store1")
8415 (set_attr "predicable" "yes")]
8418 (define_insn "*loadsi_shiftpreinc"
8419 [(set (match_operand:SI 5 "s_register_operand" "=r")
8420 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8421 [(match_operand:SI 3 "s_register_operand" "r")
8422 (match_operand:SI 4 "const_shift_operand" "n")])
8423 (match_operand:SI 1 "s_register_operand" "0"))))
8424 (set (match_operand:SI 0 "s_register_operand" "=r")
8425 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8428 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8429 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8430 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8431 "ldr%?\\t%5, [%0, %3%S2]!"
8432 [(set_attr "type" "load")
8433 (set_attr "predicable" "yes")]
8436 (define_insn "*loadsi_shiftpredec"
8437 [(set (match_operand:SI 5 "s_register_operand" "=r")
8438 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8439 (match_operator:SI 2 "shift_operator"
8440 [(match_operand:SI 3 "s_register_operand" "r")
8441 (match_operand:SI 4 "const_shift_operand" "n")]))))
8442 (set (match_operand:SI 0 "s_register_operand" "=r")
8443 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8446 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8447 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8448 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8449 "ldr%?\\t%5, [%0, -%3%S2]!"
8450 [(set_attr "type" "load")
8451 (set_attr "predicable" "yes")])
8453 (define_insn "*loadhi_shiftpreinc"
8454 [(set (match_operand:HI 5 "s_register_operand" "=r")
8455 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8456 [(match_operand:SI 3 "s_register_operand" "r")
8457 (match_operand:SI 4 "const_shift_operand" "n")])
8458 (match_operand:SI 1 "s_register_operand" "0"))))
8459 (set (match_operand:SI 0 "s_register_operand" "=r")
8460 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8463 && !BYTES_BIG_ENDIAN
8464 && !TARGET_MMU_TRAPS
8465 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8466 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8467 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8468 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8469 [(set_attr "type" "load")
8470 (set_attr "predicable" "yes")]
8473 (define_insn "*loadhi_shiftpredec"
8474 [(set (match_operand:HI 5 "s_register_operand" "=r")
8475 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8476 (match_operator:SI 2 "shift_operator"
8477 [(match_operand:SI 3 "s_register_operand" "r")
8478 (match_operand:SI 4 "const_shift_operand" "n")]))))
8479 (set (match_operand:SI 0 "s_register_operand" "=r")
8480 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8483 && !BYTES_BIG_ENDIAN
8484 && !TARGET_MMU_TRAPS
8485 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8486 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8487 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8488 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8489 [(set_attr "type" "load")
8490 (set_attr "predicable" "yes")]
8493 ; It can also support extended post-inc expressions, but combine doesn't
8495 ; It doesn't seem worth adding peepholes for anything but the most common
8496 ; cases since, unlike combine, the increment must immediately follow the load
8497 ; for this pattern to match.
8498 ; We must watch to see that the source/destination register isn't also the
8499 ; same as the base address register, and that if the index is a register,
8500 ; that it is not the same as the base address register. In such cases the
8501 ; instruction that we would generate would have UNPREDICTABLE behaviour so
8505 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8506 (match_operand:QI 2 "s_register_operand" "r"))
8508 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8510 && (REGNO (operands[2]) != REGNO (operands[0]))
8511 && (GET_CODE (operands[1]) != REG
8512 || (REGNO (operands[1]) != REGNO (operands[0])))"
8513 "str%?b\\t%2, [%0], %1"
8517 [(set (match_operand:QI 0 "s_register_operand" "=r")
8518 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8520 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8522 && REGNO (operands[0]) != REGNO(operands[1])
8523 && (GET_CODE (operands[2]) != REG
8524 || REGNO(operands[0]) != REGNO (operands[2]))"
8525 "ldr%?b\\t%0, [%1], %2"
8529 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8530 (match_operand:SI 2 "s_register_operand" "r"))
8532 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8534 && (REGNO (operands[2]) != REGNO (operands[0]))
8535 && (GET_CODE (operands[1]) != REG
8536 || (REGNO (operands[1]) != REGNO (operands[0])))"
8537 "str%?\\t%2, [%0], %1"
8541 [(set (match_operand:HI 0 "s_register_operand" "=r")
8542 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8544 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8546 && !BYTES_BIG_ENDIAN
8547 && !TARGET_MMU_TRAPS
8548 && REGNO (operands[0]) != REGNO(operands[1])
8549 && (GET_CODE (operands[2]) != REG
8550 || REGNO(operands[0]) != REGNO (operands[2]))"
8551 "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8555 [(set (match_operand:SI 0 "s_register_operand" "=r")
8556 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8558 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8560 && REGNO (operands[0]) != REGNO(operands[1])
8561 && (GET_CODE (operands[2]) != REG
8562 || REGNO(operands[0]) != REGNO (operands[2]))"
8563 "ldr%?\\t%0, [%1], %2"
8567 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8568 (match_operand:SI 1 "index_operand" "rJ")))
8569 (match_operand:QI 2 "s_register_operand" "r"))
8570 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8572 && (REGNO (operands[2]) != REGNO (operands[0]))
8573 && (GET_CODE (operands[1]) != REG
8574 || (REGNO (operands[1]) != REGNO (operands[0])))"
8575 "str%?b\\t%2, [%0, %1]!"
8579 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8580 [(match_operand:SI 0 "s_register_operand" "r")
8581 (match_operand:SI 1 "const_int_operand" "n")])
8582 (match_operand:SI 2 "s_register_operand" "+r")))
8583 (match_operand:QI 3 "s_register_operand" "r"))
8584 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8587 && (REGNO (operands[3]) != REGNO (operands[2]))
8588 && (REGNO (operands[0]) != REGNO (operands[2]))"
8589 "str%?b\\t%3, [%2, %0%S4]!"
8592 ; This pattern is never tried by combine, so do it as a peephole
8595 [(set (match_operand:SI 0 "s_register_operand" "")
8596 (match_operand:SI 1 "s_register_operand" ""))
8597 (set (reg:CC CC_REGNUM)
8598 (compare:CC (match_dup 1) (const_int 0)))]
8601 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8602 (set (match_dup 0) (match_dup 1))])]
8606 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8607 ; reversed, check that the memory references aren't volatile.
8610 [(set (match_operand:SI 0 "s_register_operand" "=r")
8611 (match_operand:SI 4 "memory_operand" "m"))
8612 (set (match_operand:SI 1 "s_register_operand" "=r")
8613 (match_operand:SI 5 "memory_operand" "m"))
8614 (set (match_operand:SI 2 "s_register_operand" "=r")
8615 (match_operand:SI 6 "memory_operand" "m"))
8616 (set (match_operand:SI 3 "s_register_operand" "=r")
8617 (match_operand:SI 7 "memory_operand" "m"))]
8618 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8620 return emit_ldm_seq (operands, 4);
8625 [(set (match_operand:SI 0 "s_register_operand" "=r")
8626 (match_operand:SI 3 "memory_operand" "m"))
8627 (set (match_operand:SI 1 "s_register_operand" "=r")
8628 (match_operand:SI 4 "memory_operand" "m"))
8629 (set (match_operand:SI 2 "s_register_operand" "=r")
8630 (match_operand:SI 5 "memory_operand" "m"))]
8631 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8633 return emit_ldm_seq (operands, 3);
8638 [(set (match_operand:SI 0 "s_register_operand" "=r")
8639 (match_operand:SI 2 "memory_operand" "m"))
8640 (set (match_operand:SI 1 "s_register_operand" "=r")
8641 (match_operand:SI 3 "memory_operand" "m"))]
8642 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8644 return emit_ldm_seq (operands, 2);
8649 [(set (match_operand:SI 4 "memory_operand" "=m")
8650 (match_operand:SI 0 "s_register_operand" "r"))
8651 (set (match_operand:SI 5 "memory_operand" "=m")
8652 (match_operand:SI 1 "s_register_operand" "r"))
8653 (set (match_operand:SI 6 "memory_operand" "=m")
8654 (match_operand:SI 2 "s_register_operand" "r"))
8655 (set (match_operand:SI 7 "memory_operand" "=m")
8656 (match_operand:SI 3 "s_register_operand" "r"))]
8657 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8659 return emit_stm_seq (operands, 4);
8664 [(set (match_operand:SI 3 "memory_operand" "=m")
8665 (match_operand:SI 0 "s_register_operand" "r"))
8666 (set (match_operand:SI 4 "memory_operand" "=m")
8667 (match_operand:SI 1 "s_register_operand" "r"))
8668 (set (match_operand:SI 5 "memory_operand" "=m")
8669 (match_operand:SI 2 "s_register_operand" "r"))]
8670 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8672 return emit_stm_seq (operands, 3);
8677 [(set (match_operand:SI 2 "memory_operand" "=m")
8678 (match_operand:SI 0 "s_register_operand" "r"))
8679 (set (match_operand:SI 3 "memory_operand" "=m")
8680 (match_operand:SI 1 "s_register_operand" "r"))]
8681 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8683 return emit_stm_seq (operands, 2);
8688 [(set (match_operand:SI 0 "s_register_operand" "")
8689 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8691 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8692 [(match_operand:SI 3 "s_register_operand" "")
8693 (match_operand:SI 4 "arm_rhs_operand" "")]))))
8694 (clobber (match_operand:SI 5 "s_register_operand" ""))]
8696 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8697 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8702 ;; This split can be used because CC_Z mode implies that the following
8703 ;; branch will be an equality, or an unsigned inequality, so the sign
8704 ;; extension is not needed.
8707 [(set (reg:CC_Z CC_REGNUM)
8709 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8711 (match_operand 1 "const_int_operand" "")))
8712 (clobber (match_scratch:SI 2 ""))]
8714 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8715 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8716 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8717 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8719 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8723 (define_expand "prologue"
8724 [(clobber (const_int 0))]
8727 arm_expand_prologue ();
8729 thumb_expand_prologue ();
8734 (define_expand "epilogue"
8735 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8739 thumb_expand_epilogue ();
8740 else if (USE_RETURN_INSN (FALSE))
8742 emit_jump_insn (gen_return ());
8745 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8747 gen_rtx_RETURN (VOIDmode)),
8753 (define_insn "sibcall_epilogue"
8754 [(unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)]
8757 output_asm_insn (\"%@ Sibcall epilogue\", operands);
8758 if (USE_RETURN_INSN (FALSE))
8759 return output_return_instruction (NULL, FALSE, FALSE);
8760 return arm_output_epilogue (FALSE);
8762 ;; Length is absolute worst case
8763 [(set_attr "length" "44")
8764 (set_attr "type" "block")]
8767 (define_insn "*epilogue_insns"
8768 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8772 return arm_output_epilogue (TRUE);
8773 else /* TARGET_THUMB */
8774 return thumb_unexpanded_epilogue ();
8776 ; Length is absolute worst case
8777 [(set_attr "length" "44")
8778 (set_attr "type" "block")]
8781 (define_expand "eh_epilogue"
8782 [(use (match_operand:SI 0 "register_operand" "r"))
8783 (use (match_operand:SI 1 "register_operand" "r"))
8784 (use (match_operand:SI 2 "register_operand" "r"))]
8788 cfun->machine->eh_epilogue_sp_ofs = operands[1];
8789 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8791 rtx ra = gen_rtx_REG (Pmode, 2);
8793 emit_move_insn (ra, operands[2]);
8796 /* This is a hack -- we may have crystalized the function type too
8798 cfun->machine->func_type = 0;
8802 ;; This split is only used during output to reduce the number of patterns
8803 ;; that need assembler instructions adding to them. We allowed the setting
8804 ;; of the conditions to be implicit during rtl generation so that
8805 ;; the conditional compare patterns would work. However this conflicts to
8806 ;; some extent with the conditional data operations, so we have to split them
8810 [(set (match_operand:SI 0 "s_register_operand" "")
8811 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8812 [(match_operand 2 "" "") (match_operand 3 "" "")])
8814 (match_operand 4 "" "")))
8815 (clobber (reg:CC CC_REGNUM))]
8816 "TARGET_ARM && reload_completed"
8817 [(set (match_dup 5) (match_dup 6))
8818 (cond_exec (match_dup 7)
8819 (set (match_dup 0) (match_dup 4)))]
8822 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8823 operands[2], operands[3]);
8824 enum rtx_code rc = GET_CODE (operands[1]);
8826 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8827 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8828 if (mode == CCFPmode || mode == CCFPEmode)
8829 rc = reverse_condition_maybe_unordered (rc);
8831 rc = reverse_condition (rc);
8833 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8838 [(set (match_operand:SI 0 "s_register_operand" "")
8839 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8840 [(match_operand 2 "" "") (match_operand 3 "" "")])
8841 (match_operand 4 "" "")
8843 (clobber (reg:CC CC_REGNUM))]
8844 "TARGET_ARM && reload_completed"
8845 [(set (match_dup 5) (match_dup 6))
8846 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8847 (set (match_dup 0) (match_dup 4)))]
8850 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8851 operands[2], operands[3]);
8853 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8854 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8859 [(set (match_operand:SI 0 "s_register_operand" "")
8860 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8861 [(match_operand 2 "" "") (match_operand 3 "" "")])
8862 (match_operand 4 "" "")
8863 (match_operand 5 "" "")))
8864 (clobber (reg:CC CC_REGNUM))]
8865 "TARGET_ARM && reload_completed"
8866 [(set (match_dup 6) (match_dup 7))
8867 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8868 (set (match_dup 0) (match_dup 4)))
8869 (cond_exec (match_dup 8)
8870 (set (match_dup 0) (match_dup 5)))]
8873 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8874 operands[2], operands[3]);
8875 enum rtx_code rc = GET_CODE (operands[1]);
8877 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8878 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8879 if (mode == CCFPmode || mode == CCFPEmode)
8880 rc = reverse_condition_maybe_unordered (rc);
8882 rc = reverse_condition (rc);
8884 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8889 [(set (match_operand:SI 0 "s_register_operand" "")
8890 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8891 [(match_operand:SI 2 "s_register_operand" "")
8892 (match_operand:SI 3 "arm_add_operand" "")])
8893 (match_operand:SI 4 "arm_rhs_operand" "")
8895 (match_operand:SI 5 "s_register_operand" ""))))
8896 (clobber (reg:CC CC_REGNUM))]
8897 "TARGET_ARM && reload_completed"
8898 [(set (match_dup 6) (match_dup 7))
8899 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8900 (set (match_dup 0) (match_dup 4)))
8901 (cond_exec (match_dup 8)
8902 (set (match_dup 0) (not:SI (match_dup 5))))]
8905 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8906 operands[2], operands[3]);
8907 enum rtx_code rc = GET_CODE (operands[1]);
8909 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8910 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8911 if (mode == CCFPmode || mode == CCFPEmode)
8912 rc = reverse_condition_maybe_unordered (rc);
8914 rc = reverse_condition (rc);
8916 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8920 (define_insn "*cond_move_not"
8921 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8922 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8923 [(match_operand 3 "cc_register" "") (const_int 0)])
8924 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8926 (match_operand:SI 2 "s_register_operand" "r,r"))))]
8930 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8931 [(set_attr "conds" "use")
8932 (set_attr "length" "4,8")]
8935 ;; The next two patterns occur when an AND operation is followed by a
8936 ;; scc insn sequence
8938 (define_insn "*sign_extract_onebit"
8939 [(set (match_operand:SI 0 "s_register_operand" "=r")
8940 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8942 (match_operand:SI 2 "const_int_operand" "n")))]
8945 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8946 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8947 return \"mvnne\\t%0, #0\";
8949 [(set_attr "conds" "clob")
8950 (set_attr "length" "8")]
8953 (define_insn "*not_signextract_onebit"
8954 [(set (match_operand:SI 0 "s_register_operand" "=r")
8956 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8958 (match_operand:SI 2 "const_int_operand" "n"))))]
8961 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8962 output_asm_insn (\"tst\\t%1, %2\", operands);
8963 output_asm_insn (\"mvneq\\t%0, #0\", operands);
8964 return \"movne\\t%0, #0\";
8966 [(set_attr "conds" "clob")
8967 (set_attr "length" "12")]
8970 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
8971 ;; expressions. For simplicity, the first register is also in the unspec
8973 (define_insn "*push_multi"
8974 [(match_parallel 2 "multi_register_push"
8975 [(set (match_operand:BLK 0 "memory_operand" "=m")
8976 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8977 UNSPEC_PUSH_MULT))])]
8981 int num_saves = XVECLEN (operands[2], 0);
8983 /* For the StrongARM at least it is faster to
8984 use STR to store only a single register. */
8986 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8992 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
8994 for (i = 1; i < num_saves; i++)
8996 strcat (pattern, \", %|\");
8998 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9001 strcat (pattern, \"}\");
9002 output_asm_insn (pattern, operands);
9007 [(set_attr "type" "store4")]
9010 ;; Similarly for the floating point registers
9011 (define_insn "*push_fp_multi"
9012 [(match_parallel 2 "multi_register_push"
9013 [(set (match_operand:BLK 0 "memory_operand" "=m")
9014 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9015 UNSPEC_PUSH_MULT))])]
9021 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9022 output_asm_insn (pattern, operands);
9025 [(set_attr "type" "f_store")]
9028 ;; Special patterns for dealing with the constant pool
9030 (define_insn "align_4"
9031 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9034 assemble_align (32);
9039 (define_insn "consttable_end"
9040 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9043 making_const_table = FALSE;
9048 (define_insn "consttable_1"
9049 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9052 making_const_table = TRUE;
9053 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9057 [(set_attr "length" "4")]
9060 (define_insn "consttable_2"
9061 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9064 making_const_table = TRUE;
9065 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9069 [(set_attr "length" "4")]
9072 (define_insn "consttable_4"
9073 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9077 making_const_table = TRUE;
9078 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9082 union real_extract u;
9083 memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
9084 assemble_real (u.d, GET_MODE (operands[0]), BITS_PER_WORD);
9088 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9093 [(set_attr "length" "4")]
9096 (define_insn "consttable_8"
9097 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9101 making_const_table = TRUE;
9102 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9106 union real_extract u;
9107 memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
9108 assemble_real (u.d, GET_MODE (operands[0]), BITS_PER_WORD);
9112 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9117 [(set_attr "length" "8")]
9120 ;; Miscellaneous Thumb patterns
9122 (define_expand "tablejump"
9123 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9124 (use (label_ref (match_operand 1 "" "")))])]
9129 /* Hopefully, CSE will eliminate this copy. */
9130 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
9131 rtx reg2 = gen_reg_rtx (SImode);
9133 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
9139 (define_insn "*thumb_tablejump"
9140 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9141 (use (label_ref (match_operand 1 "" "")))]
9144 [(set_attr "length" "2")]
9150 [(set (match_operand:SI 0 "s_register_operand" "=r")
9151 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")]
9153 "TARGET_ARM && arm_arch5"
9156 (define_expand "ffssi2"
9157 [(set (match_operand:SI 0 "s_register_operand" "")
9158 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9159 "TARGET_ARM && arm_arch5"
9164 t1 = gen_reg_rtx (SImode);
9165 t2 = gen_reg_rtx (SImode);
9166 t3 = gen_reg_rtx (SImode);
9168 emit_insn (gen_negsi2 (t1, operands[1]));
9169 emit_insn (gen_andsi3 (t2, operands[1], t1));
9170 emit_insn (gen_clz (t3, t2));
9171 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
9176 ;; V5E instructions.
9178 (define_insn "prefetch"
9179 [(prefetch (match_operand:SI 0 "address_operand" "p")
9180 (match_operand:SI 1 "" "")
9181 (match_operand:SI 2 "" ""))]
9182 "TARGET_ARM && arm_arch5e"
9185 ;; General predication pattern
9188 [(match_operator 0 "arm_comparison_operator"
9189 [(match_operand 1 "cc_register" "")
9195 (define_insn "prologue_use"
9196 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
9198 "%@ %0 needed for prologue"