1 ;;- Machine description for ARM for GNU compiler
2 ;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;; 2001, 2002 Free Software Foundation, Inc.
4 ;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;; and Martin Simmons (@harleqn.co.uk).
6 ;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
8 ;; This file is part of GNU CC.
10 ;; GNU CC is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; GNU CC is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU CC; see the file COPYING. If not, write to
22 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
27 ;; There are patterns in this file to support XFmode arithmetic.
28 ;; Unfortunately RISC iX doesn't work well with these so they are disabled.
31 ;;---------------------------------------------------------------------------
36 [(IP_REGNUM 12) ; Scratch register
37 (SP_REGNUM 13) ; Stack pointer
38 (LR_REGNUM 14) ; Return address register
39 (PC_REGNUM 15) ; Program counter
40 (CC_REGNUM 24) ; Condition code pseudo register
46 ;; Note: sin and cos are no-longer used.
49 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
50 ; operand 0 is the result,
51 ; operand 1 the parameter.
52 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
53 ; operand 0 is the result,
54 ; operand 1 the parameter.
55 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
56 ; operand 0 is the first register,
57 ; subsequent registers are in parallel (use ...)
59 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
60 ; usage, that is, we will add the pic_register
61 ; value to it before trying to dereference it.
62 (UNSPEC_PRLG_STK 4) ; A special barrier that prevents frame accesses
63 ; being scheduled before the stack adjustment insn.
64 (UNSPEC_CLZ 5) ; `clz' instruction, count leading zeros (SImode):
65 ; operand 0 is the result,
66 ; operand 1 is the parameter.
67 (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
68 ; this unspec is used to prevent the deletion of
69 ; instructions setting registers for EH handling
70 ; and stack frame generation. Operand 0 is the
72 (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
76 ;; UNSPEC_VOLATILE Usage:
79 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
81 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
82 ; instruction epilogue sequence that isn't expanded
83 ; into normal RTL. Used for both normal and sibcall
85 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
86 ; for inlined constants.
87 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
89 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
91 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
93 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
95 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
100 ;;---------------------------------------------------------------------------
103 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
104 ; generating ARM code. This is used to control the length of some insn
105 ; patterns that share the same RTL in both ARM and Thumb code.
106 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
108 ; PROG_MODE attribute is used to determine whether condition codes are
109 ; clobbered by a call insn: they are if in prog32 mode. This is controlled
110 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
111 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
113 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
114 ; scheduling decisions for the load unit and the multiplier.
115 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
117 ;; Operand number of an input operand that is shifted. Zero if the
118 ;; given instruction does not shift one of its input operands.
119 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_is_xscale")))
120 (define_attr "shift" "" (const_int 0))
122 ; Floating Point Unit. If we only have floating point emulation, then there
123 ; is no point in scheduling the floating point insns. (Well, for best
124 ; performance we should try and group them together).
125 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
127 ; LENGTH of an instruction (in bytes)
128 (define_attr "length" "" (const_int 4))
130 ; POOL_RANGE is how far away from a constant pool entry that this insn
131 ; can be placed. If the distance is zero, then this insn will never
132 ; reference the pool.
133 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
134 ; before its address.
135 (define_attr "pool_range" "" (const_int 0))
136 (define_attr "neg_pool_range" "" (const_int 0))
138 ; An assembler sequence may clobber the condition codes without us knowing.
139 ; If such an insn references the pool, then we have no way of knowing how,
140 ; so use the most conservative value for pool_range.
141 (define_asm_attributes
142 [(set_attr "conds" "clob")
143 (set_attr "length" "4")
144 (set_attr "pool_range" "250")])
146 ; TYPE attribute is used to detect floating point instructions which, if
147 ; running on a co-processor can run in parallel with other, basic instructions
148 ; If write-buffer scheduling is enabled then it can also be used in the
149 ; scheduling of writes.
151 ; Classification of each insn
152 ; normal any data instruction that doesn't hit memory or fp regs
153 ; mult a multiply instruction
154 ; block blockage insn, this blocks all functional units
155 ; float a floating point arithmetic operation (subject to expansion)
156 ; fdivx XFmode floating point division
157 ; fdivd DFmode floating point division
158 ; fdivs SFmode floating point division
159 ; fmul Floating point multiply
160 ; ffmul Fast floating point multiply
161 ; farith Floating point arithmetic (4 cycle)
162 ; ffarith Fast floating point arithmetic (2 cycle)
163 ; float_em a floating point arithmetic operation that is normally emulated
164 ; even on a machine with an fpa.
165 ; f_load a floating point load from memory
166 ; f_store a floating point store to memory
167 ; f_mem_r a transfer of a floating point register to a real reg via mem
168 ; r_mem_f the reverse of f_mem_r
169 ; f_2_r fast transfer float to arm (no memory needed)
170 ; r_2_f fast transfer arm to float
171 ; call a subroutine call
172 ; load any load from memory
173 ; store1 store 1 word to memory from arm registers
174 ; store2 store 2 words
175 ; store3 store 3 words
176 ; store4 store 4 words
179 "normal,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,call,load,store1,store2,store3,store4"
180 (const_string "normal"))
182 ; Load scheduling, set from the arm_ld_sched variable
183 ; initialized by arm_override_options()
184 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
186 ; condition codes: this one is used by final_prescan_insn to speed up
187 ; conditionalizing instructions. It saves having to scan the rtl to see if
188 ; it uses or alters the condition codes.
190 ; USE means that the condition codes are used by the insn in the process of
191 ; outputting code, this means (at present) that we can't use the insn in
194 ; SET means that the purpose of the insn is to set the condition codes in a
195 ; well defined manner.
197 ; CLOB means that the condition codes are altered in an undefined manner, if
198 ; they are altered at all
200 ; JUMP_CLOB is used when the condition cannot be represented by a single
201 ; instruction (UNEQ and LTGT). These cannot be predicated.
203 ; NOCOND means that the condition codes are neither altered nor affect the
204 ; output of this insn
206 (define_attr "conds" "use,set,clob,jump_clob,nocond"
207 (if_then_else (eq_attr "type" "call")
208 (if_then_else (eq_attr "prog_mode" "prog32")
209 (const_string "clob") (const_string "nocond"))
210 (const_string "nocond")))
212 ; Predicable means that the insn can be conditionally executed based on
213 ; an automatically added predicate (additional patterns are generated by
214 ; gen...). We default to 'no' because no Thumb patterns match this rule
215 ; and not all ARM patterns do.
216 (define_attr "predicable" "no,yes" (const_string "no"))
218 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
219 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
220 ; suffer blockages enough to warrent modelling this (and it can adversely
221 ; affect the schedule).
222 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
224 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
225 ; to stall the processor. Used with model_wbuf above.
226 (define_attr "write_conflict" "no,yes"
227 (if_then_else (eq_attr "type"
228 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
230 (const_string "no")))
232 ; Classify the insns into those that take one cycle and those that take more
233 ; than one on the main cpu execution unit.
234 (define_attr "core_cycles" "single,multi"
235 (if_then_else (eq_attr "type"
236 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
237 (const_string "single")
238 (const_string "multi")))
240 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
241 ;; distant label. Only applicable to Thumb code.
242 (define_attr "far_jump" "yes,no" (const_string "no"))
244 ;; (define_function_unit {name} {num-units} {n-users} {test}
245 ;; {ready-delay} {issue-delay} [{conflict-list}])
247 ;;--------------------------------------------------------------------
248 ;; Floating point unit (FPA)
249 ;;--------------------------------------------------------------------
250 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
251 (eq_attr "type" "fdivx")) 71 69)
253 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
254 (eq_attr "type" "fdivd")) 59 57)
256 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
257 (eq_attr "type" "fdivs")) 31 29)
259 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
260 (eq_attr "type" "fmul")) 9 7)
262 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
263 (eq_attr "type" "ffmul")) 6 4)
265 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
266 (eq_attr "type" "farith")) 4 2)
268 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
269 (eq_attr "type" "ffarith")) 2 2)
271 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
272 (eq_attr "type" "r_2_f")) 5 3)
274 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
275 (eq_attr "type" "f_2_r")) 1 2)
277 ; The fpa10 doesn't really have a memory read unit, but it can start to
278 ; speculatively execute the instruction in the pipeline, provided the data
279 ; is already loaded, so pretend reads have a delay of 2 (and that the
280 ; pipeline is infinite).
282 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
283 (eq_attr "type" "f_load")) 3 1)
285 ;;--------------------------------------------------------------------
287 ;;--------------------------------------------------------------------
288 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
290 ; The write buffer on some of the arm6 processors is hard to model exactly.
291 ; There is room in the buffer for up to two addresses and up to eight words
292 ; of memory, but the two needn't be split evenly. When writing the two
293 ; addresses are fully pipelined. However, a read from memory that is not
294 ; currently in the cache will block until the writes have completed.
295 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
296 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
297 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
298 ; cycle to add as well.
300 (define_function_unit "write_buf" 1 2
301 (and (eq_attr "model_wbuf" "yes")
302 (eq_attr "type" "store1,r_mem_f")) 5 3)
303 (define_function_unit "write_buf" 1 2
304 (and (eq_attr "model_wbuf" "yes")
305 (eq_attr "type" "store2")) 7 4)
306 (define_function_unit "write_buf" 1 2
307 (and (eq_attr "model_wbuf" "yes")
308 (eq_attr "type" "store3")) 9 5)
309 (define_function_unit "write_buf" 1 2
310 (and (eq_attr "model_wbuf" "yes")
311 (eq_attr "type" "store4")) 11 6)
313 ;;--------------------------------------------------------------------
314 ;; Write blockage unit
315 ;;--------------------------------------------------------------------
316 ; The write_blockage unit models (partially), the fact that reads will stall
317 ; until the write buffer empties.
318 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
319 ; so we don't model them here
320 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
321 (eq_attr "type" "store1")) 5 5
322 [(eq_attr "write_conflict" "yes")])
323 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
324 (eq_attr "type" "store2")) 7 7
325 [(eq_attr "write_conflict" "yes")])
326 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
327 (eq_attr "type" "store3")) 9 9
328 [(eq_attr "write_conflict" "yes")])
329 (define_function_unit "write_blockage" 1 0
330 (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
331 [(eq_attr "write_conflict" "yes")])
332 (define_function_unit "write_blockage" 1 0
333 (and (eq_attr "model_wbuf" "yes")
334 (eq_attr "write_conflict" "yes")) 1 1)
336 ;;--------------------------------------------------------------------
338 ;;--------------------------------------------------------------------
339 ; Everything must spend at least one cycle in the core unit
340 (define_function_unit "core" 1 0 (eq_attr "core_cycles" "single") 1 1)
342 (define_function_unit "core" 1 0
343 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
345 (define_function_unit "core" 1 0
346 (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
348 ;; We do not need to conditionalize the define_function_unit immediately
349 ;; above. This one will be ignored for anything other than xscale
350 ;; compiles and for xscale compiles it provides a larger delay
351 ;; and the scheduler will DTRT.
352 ;; FIXME: this test needs to be revamped to not depend on this feature
355 (define_function_unit "core" 1 0
356 (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
357 (eq_attr "is_xscale" "yes"))
360 (define_function_unit "core" 1 0
361 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
363 (define_function_unit "core" 1 0
364 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
366 (define_function_unit "core" 1 0
367 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
369 (define_function_unit "core" 1 0
370 (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
372 (define_function_unit "core" 1 0
373 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
375 (define_function_unit "core" 1 0
376 (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
378 (define_function_unit "core" 1 0
379 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
380 (eq_attr "type" "mult")) 4 4)
382 (define_function_unit "core" 1 0
383 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
384 (eq_attr "type" "mult")) 3 2)
386 (define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
388 (define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
390 (define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
392 (define_function_unit "core" 1 0
393 (and (eq_attr "core_cycles" "multi")
394 (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
396 ;;---------------------------------------------------------------------------
401 ;; Note: For DImode insns, there is normally no reason why operands should
402 ;; not be in the same register, what we don't want is for something being
403 ;; written to partially overlap something that is an input.
405 (define_expand "adddi3"
407 [(set (match_operand:DI 0 "s_register_operand" "")
408 (plus:DI (match_operand:DI 1 "s_register_operand" "")
409 (match_operand:DI 2 "s_register_operand" "")))
410 (clobber (reg:CC CC_REGNUM))])]
415 if (GET_CODE (operands[1]) != REG)
416 operands[1] = force_reg (SImode, operands[1]);
417 if (GET_CODE (operands[2]) != REG)
418 operands[2] = force_reg (SImode, operands[2]);
423 (define_insn "*thumb_adddi3"
424 [(set (match_operand:DI 0 "register_operand" "=l")
425 (plus:DI (match_operand:DI 1 "register_operand" "%0")
426 (match_operand:DI 2 "register_operand" "l")))
427 (clobber (reg:CC CC_REGNUM))
430 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
431 [(set_attr "length" "4")]
434 (define_insn_and_split "*arm_adddi3"
435 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
436 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
437 (match_operand:DI 2 "s_register_operand" "r, 0")))
438 (clobber (reg:CC CC_REGNUM))]
441 "TARGET_ARM && reload_completed"
442 [(parallel [(set (reg:CC_C CC_REGNUM)
443 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
445 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
446 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
447 (plus:SI (match_dup 4) (match_dup 5))))]
450 operands[3] = gen_highpart (SImode, operands[0]);
451 operands[0] = gen_lowpart (SImode, operands[0]);
452 operands[4] = gen_highpart (SImode, operands[1]);
453 operands[1] = gen_lowpart (SImode, operands[1]);
454 operands[5] = gen_highpart (SImode, operands[2]);
455 operands[2] = gen_lowpart (SImode, operands[2]);
457 [(set_attr "conds" "clob")
458 (set_attr "length" "8")]
461 (define_insn_and_split "*adddi_sesidi_di"
462 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
463 (plus:DI (sign_extend:DI
464 (match_operand:SI 2 "s_register_operand" "r,r"))
465 (match_operand:DI 1 "s_register_operand" "r,0")))
466 (clobber (reg:CC CC_REGNUM))]
469 "TARGET_ARM && reload_completed"
470 [(parallel [(set (reg:CC_C CC_REGNUM)
471 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
473 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
474 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
475 (plus:SI (ashiftrt:SI (match_dup 2)
480 operands[3] = gen_highpart (SImode, operands[0]);
481 operands[0] = gen_lowpart (SImode, operands[0]);
482 operands[4] = gen_highpart (SImode, operands[1]);
483 operands[1] = gen_lowpart (SImode, operands[1]);
484 operands[2] = gen_lowpart (SImode, operands[2]);
486 [(set_attr "conds" "clob")
487 (set_attr "length" "8")]
490 (define_insn_and_split "*adddi_zesidi_di"
491 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
492 (plus:DI (zero_extend:DI
493 (match_operand:SI 2 "s_register_operand" "r,r"))
494 (match_operand:DI 1 "s_register_operand" "r,0")))
495 (clobber (reg:CC CC_REGNUM))]
498 "TARGET_ARM && reload_completed"
499 [(parallel [(set (reg:CC_C CC_REGNUM)
500 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
502 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
503 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
504 (plus:SI (match_dup 4) (const_int 0))))]
507 operands[3] = gen_highpart (SImode, operands[0]);
508 operands[0] = gen_lowpart (SImode, operands[0]);
509 operands[4] = gen_highpart (SImode, operands[1]);
510 operands[1] = gen_lowpart (SImode, operands[1]);
511 operands[2] = gen_lowpart (SImode, operands[2]);
513 [(set_attr "conds" "clob")
514 (set_attr "length" "8")]
517 (define_expand "addsi3"
518 [(set (match_operand:SI 0 "s_register_operand" "")
519 (plus:SI (match_operand:SI 1 "s_register_operand" "")
520 (match_operand:SI 2 "reg_or_int_operand" "")))]
523 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
525 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
527 (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
533 ; If there is a scratch available, this will be faster than synthesising the
536 [(match_scratch:SI 3 "r")
537 (set (match_operand:SI 0 "s_register_operand" "")
538 (plus:SI (match_operand:SI 1 "s_register_operand" "")
539 (match_operand:SI 2 "const_int_operand" "")))]
541 !(const_ok_for_arm (INTVAL (operands[2]))
542 || const_ok_for_arm (-INTVAL (operands[2])))
543 && const_ok_for_arm (~INTVAL (operands[2]))"
544 [(set (match_dup 3) (match_dup 2))
545 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
549 (define_insn_and_split "*arm_addsi3"
550 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
551 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
552 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
559 GET_CODE (operands[2]) == CONST_INT
560 && !(const_ok_for_arm (INTVAL (operands[2]))
561 || const_ok_for_arm (-INTVAL (operands[2])))"
562 [(clobber (const_int 0))]
564 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
568 [(set_attr "length" "4,4,16")
569 (set_attr "predicable" "yes")]
572 ;; Register group 'k' is a single register group containing only the stack
573 ;; register. Trying to reload it will always fail catastrophically,
574 ;; so never allow those alternatives to match if reloading is needed.
576 (define_insn "*thumb_addsi3"
577 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
578 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
579 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
582 static const char * const asms[] =
584 \"add\\t%0, %0, %2\",
585 \"sub\\t%0, %0, #%n2\",
586 \"add\\t%0, %1, %2\",
587 \"add\\t%0, %0, %2\",
588 \"add\\t%0, %0, %2\",
589 \"add\\t%0, %1, %2\",
592 if ((which_alternative == 2 || which_alternative == 6)
593 && GET_CODE (operands[2]) == CONST_INT
594 && INTVAL (operands[2]) < 0)
595 return \"sub\\t%0, %1, #%n2\";
596 return asms[which_alternative];
598 [(set_attr "length" "2")]
601 ;; Reloading and elimination of the frame pointer can
602 ;; sometimes cause this optimization to be missed.
604 [(set (match_operand:SI 0 "register_operand" "")
605 (match_operand:SI 1 "const_int_operand" ""))
607 (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
609 && REGNO (operands[2]) == STACK_POINTER_REGNUM
610 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
611 && (INTVAL (operands[1]) & 3) == 0"
612 [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
616 (define_insn "*addsi3_compare0"
617 [(set (reg:CC_NOOV CC_REGNUM)
619 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
620 (match_operand:SI 2 "arm_add_operand" "rI,L"))
622 (set (match_operand:SI 0 "s_register_operand" "=r,r")
623 (plus:SI (match_dup 1) (match_dup 2)))]
627 sub%?s\\t%0, %1, #%n2"
628 [(set_attr "conds" "set")]
631 (define_insn "*addsi3_compare0_scratch"
632 [(set (reg:CC_NOOV CC_REGNUM)
634 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
635 (match_operand:SI 1 "arm_add_operand" "rI,L"))
641 [(set_attr "conds" "set")]
644 ;; These patterns are the same ones as the two regular addsi3_compare0
645 ;; patterns, except we write them slightly different - the combiner
646 ;; tends to generate them this way.
647 (define_insn "*addsi3_compare0_for_combiner"
648 [(set (reg:CC CC_REGNUM)
650 (match_operand:SI 1 "s_register_operand" "r,r")
651 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
652 (set (match_operand:SI 0 "s_register_operand" "=r,r")
653 (plus:SI (match_dup 1) (match_dup 2)))]
657 sub%?s\\t%0, %1, #%n2"
658 [(set_attr "conds" "set")]
661 (define_insn "*addsi3_compare0_scratch_for_combiner"
662 [(set (reg:CC CC_REGNUM)
664 (match_operand:SI 0 "s_register_operand" "r,r")
665 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
670 [(set_attr "conds" "set")]
673 ;; The next four insns work because they compare the result with one of
674 ;; the operands, and we know that the use of the condition code is
675 ;; either GEU or LTU, so we can use the carry flag from the addition
676 ;; instead of doing the compare a second time.
677 (define_insn "*addsi3_compare_op1"
678 [(set (reg:CC_C CC_REGNUM)
680 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
681 (match_operand:SI 2 "arm_add_operand" "rI,L"))
683 (set (match_operand:SI 0 "s_register_operand" "=r,r")
684 (plus:SI (match_dup 1) (match_dup 2)))]
688 sub%?s\\t%0, %1, #%n2"
689 [(set_attr "conds" "set")]
692 (define_insn "*addsi3_compare_op2"
693 [(set (reg:CC_C CC_REGNUM)
695 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
696 (match_operand:SI 2 "arm_add_operand" "rI,L"))
698 (set (match_operand:SI 0 "s_register_operand" "=r,r")
699 (plus:SI (match_dup 1) (match_dup 2)))]
703 sub%?s\\t%0, %1, #%n2"
704 [(set_attr "conds" "set")]
707 (define_insn "*compare_addsi2_op0"
708 [(set (reg:CC_C CC_REGNUM)
710 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
711 (match_operand:SI 1 "arm_add_operand" "rI,L"))
717 [(set_attr "conds" "set")]
720 (define_insn "*compare_addsi2_op1"
721 [(set (reg:CC_C CC_REGNUM)
723 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
724 (match_operand:SI 1 "arm_add_operand" "rI,L"))
730 [(set_attr "conds" "set")]
733 (define_insn "*addsi3_carryin"
734 [(set (match_operand:SI 0 "s_register_operand" "=r")
735 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
736 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
737 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
740 [(set_attr "conds" "use")]
743 (define_insn "*addsi3_carryin_shift"
744 [(set (match_operand:SI 0 "s_register_operand" "")
745 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
747 (match_operator:SI 2 "shift_operator"
748 [(match_operand:SI 3 "s_register_operand" "")
749 (match_operand:SI 4 "reg_or_int_operand" "")])
750 (match_operand:SI 1 "s_register_operand" ""))))]
752 "adc%?\\t%0, %1, %3%S2"
753 [(set_attr "conds" "use")]
756 (define_insn "*addsi3_carryin_alt1"
757 [(set (match_operand:SI 0 "s_register_operand" "=r")
758 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
759 (match_operand:SI 2 "arm_rhs_operand" "rI"))
760 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
763 [(set_attr "conds" "use")]
766 (define_insn "*addsi3_carryin_alt2"
767 [(set (match_operand:SI 0 "s_register_operand" "=r")
768 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
769 (match_operand:SI 1 "s_register_operand" "r"))
770 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
773 [(set_attr "conds" "use")]
776 (define_insn "*addsi3_carryin_alt3"
777 [(set (match_operand:SI 0 "s_register_operand" "=r")
778 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
779 (match_operand:SI 2 "arm_rhs_operand" "rI"))
780 (match_operand:SI 1 "s_register_operand" "r")))]
783 [(set_attr "conds" "use")]
786 (define_insn "incscc"
787 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
788 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
789 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
790 (match_operand:SI 1 "s_register_operand" "0,?r")))]
794 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
795 [(set_attr "conds" "use")
796 (set_attr "length" "4,8")]
799 (define_insn "addsf3"
800 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
801 (plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
802 (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
803 "TARGET_ARM && TARGET_HARD_FLOAT"
806 suf%?s\\t%0, %1, #%N2"
807 [(set_attr "type" "farith")
808 (set_attr "predicable" "yes")]
811 (define_insn "adddf3"
812 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
813 (plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
814 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
815 "TARGET_ARM && TARGET_HARD_FLOAT"
818 suf%?d\\t%0, %1, #%N2"
819 [(set_attr "type" "farith")
820 (set_attr "predicable" "yes")]
823 (define_insn "*adddf_esfdf_df"
824 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
825 (plus:DF (float_extend:DF
826 (match_operand:SF 1 "s_register_operand" "f,f"))
827 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
828 "TARGET_ARM && TARGET_HARD_FLOAT"
831 suf%?d\\t%0, %1, #%N2"
832 [(set_attr "type" "farith")
833 (set_attr "predicable" "yes")]
836 (define_insn "*adddf_df_esfdf"
837 [(set (match_operand:DF 0 "s_register_operand" "=f")
838 (plus:DF (match_operand:DF 1 "s_register_operand" "f")
840 (match_operand:SF 2 "s_register_operand" "f"))))]
841 "TARGET_ARM && TARGET_HARD_FLOAT"
842 "adf%?d\\t%0, %1, %2"
843 [(set_attr "type" "farith")
844 (set_attr "predicable" "yes")]
847 (define_insn "*adddf_esfdf_esfdf"
848 [(set (match_operand:DF 0 "s_register_operand" "=f")
849 (plus:DF (float_extend:DF
850 (match_operand:SF 1 "s_register_operand" "f"))
852 (match_operand:SF 2 "s_register_operand" "f"))))]
853 "TARGET_ARM && TARGET_HARD_FLOAT"
854 "adf%?d\\t%0, %1, %2"
855 [(set_attr "type" "farith")
856 (set_attr "predicable" "yes")]
859 (define_insn "addxf3"
860 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
861 (plus:XF (match_operand:XF 1 "s_register_operand" "f,f")
862 (match_operand:XF 2 "fpu_add_operand" "fG,H")))]
863 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
866 suf%?e\\t%0, %1, #%N2"
867 [(set_attr "type" "farith")
868 (set_attr "predicable" "yes")]
871 (define_expand "subdi3"
873 [(set (match_operand:DI 0 "s_register_operand" "")
874 (minus:DI (match_operand:DI 1 "s_register_operand" "")
875 (match_operand:DI 2 "s_register_operand" "")))
876 (clobber (reg:CC CC_REGNUM))])]
881 if (GET_CODE (operands[1]) != REG)
882 operands[1] = force_reg (SImode, operands[1]);
883 if (GET_CODE (operands[2]) != REG)
884 operands[2] = force_reg (SImode, operands[2]);
889 (define_insn "*arm_subdi3"
890 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
891 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
892 (match_operand:DI 2 "s_register_operand" "r,0,0")))
893 (clobber (reg:CC CC_REGNUM))]
895 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
896 [(set_attr "conds" "clob")
897 (set_attr "length" "8")]
900 (define_insn "*thumb_subdi3"
901 [(set (match_operand:DI 0 "register_operand" "=l")
902 (minus:DI (match_operand:DI 1 "register_operand" "0")
903 (match_operand:DI 2 "register_operand" "l")))
904 (clobber (reg:CC CC_REGNUM))]
906 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
907 [(set_attr "length" "4")]
910 (define_insn "*subdi_di_zesidi"
911 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
912 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
914 (match_operand:SI 2 "s_register_operand" "r,r"))))
915 (clobber (reg:CC CC_REGNUM))]
917 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
918 [(set_attr "conds" "clob")
919 (set_attr "length" "8")]
922 (define_insn "*subdi_di_sesidi"
923 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
924 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
926 (match_operand:SI 2 "s_register_operand" "r,r"))))
927 (clobber (reg:CC CC_REGNUM))]
929 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
930 [(set_attr "conds" "clob")
931 (set_attr "length" "8")]
934 (define_insn "*subdi_zesidi_di"
935 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
936 (minus:DI (zero_extend:DI
937 (match_operand:SI 2 "s_register_operand" "r,r"))
938 (match_operand:DI 1 "s_register_operand" "?r,0")))
939 (clobber (reg:CC CC_REGNUM))]
941 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
942 [(set_attr "conds" "clob")
943 (set_attr "length" "8")]
946 (define_insn "*subdi_sesidi_di"
947 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
948 (minus:DI (sign_extend:DI
949 (match_operand:SI 2 "s_register_operand" "r,r"))
950 (match_operand:DI 1 "s_register_operand" "?r,0")))
951 (clobber (reg:CC CC_REGNUM))]
953 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
954 [(set_attr "conds" "clob")
955 (set_attr "length" "8")]
958 (define_insn "*subdi_zesidi_zesidi"
959 [(set (match_operand:DI 0 "s_register_operand" "=r")
960 (minus:DI (zero_extend:DI
961 (match_operand:SI 1 "s_register_operand" "r"))
963 (match_operand:SI 2 "s_register_operand" "r"))))
964 (clobber (reg:CC CC_REGNUM))]
966 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
967 [(set_attr "conds" "clob")
968 (set_attr "length" "8")]
971 (define_expand "subsi3"
972 [(set (match_operand:SI 0 "s_register_operand" "")
973 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
974 (match_operand:SI 2 "s_register_operand" "")))]
977 if (GET_CODE (operands[1]) == CONST_INT)
981 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
984 : preserve_subexpressions_p ()));
987 else /* TARGET_THUMB */
988 operands[1] = force_reg (SImode, operands[1]);
993 (define_insn "*thumb_subsi3_insn"
994 [(set (match_operand:SI 0 "register_operand" "=l")
995 (minus:SI (match_operand:SI 1 "register_operand" "l")
996 (match_operand:SI 2 "register_operand" "l")))]
999 [(set_attr "length" "2")]
1002 (define_insn_and_split "*arm_subsi3_insn"
1003 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1004 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
1005 (match_operand:SI 2 "s_register_operand" "r,r")))]
1011 && GET_CODE (operands[1]) == CONST_INT
1012 && !const_ok_for_arm (INTVAL (operands[1]))"
1013 [(clobber (const_int 0))]
1015 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1019 [(set_attr "length" "4,16")
1020 (set_attr "predicable" "yes")]
1024 [(match_scratch:SI 3 "r")
1025 (set (match_operand:SI 0 "s_register_operand" "")
1026 (minus:SI (match_operand:SI 1 "const_int_operand" "")
1027 (match_operand:SI 2 "s_register_operand" "")))]
1029 && !const_ok_for_arm (INTVAL (operands[1]))
1030 && const_ok_for_arm (~INTVAL (operands[1]))"
1031 [(set (match_dup 3) (match_dup 1))
1032 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1036 (define_insn "*subsi3_compare0"
1037 [(set (reg:CC_NOOV CC_REGNUM)
1039 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1040 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1042 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1043 (minus:SI (match_dup 1) (match_dup 2)))]
1047 rsb%?s\\t%0, %2, %1"
1048 [(set_attr "conds" "set")]
1051 (define_insn "decscc"
1052 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1053 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1054 (match_operator:SI 2 "arm_comparison_operator"
1055 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1059 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1060 [(set_attr "conds" "use")
1061 (set_attr "length" "*,8")]
1064 (define_insn "subsf3"
1065 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1066 (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1067 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1068 "TARGET_ARM && TARGET_HARD_FLOAT"
1071 rsf%?s\\t%0, %2, %1"
1072 [(set_attr "type" "farith")]
1075 (define_insn "subdf3"
1076 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1077 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1078 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1079 "TARGET_ARM && TARGET_HARD_FLOAT"
1082 rsf%?d\\t%0, %2, %1"
1083 [(set_attr "type" "farith")
1084 (set_attr "predicable" "yes")]
1087 (define_insn "*subdf_esfdf_df"
1088 [(set (match_operand:DF 0 "s_register_operand" "=f")
1089 (minus:DF (float_extend:DF
1090 (match_operand:SF 1 "s_register_operand" "f"))
1091 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1092 "TARGET_ARM && TARGET_HARD_FLOAT"
1093 "suf%?d\\t%0, %1, %2"
1094 [(set_attr "type" "farith")
1095 (set_attr "predicable" "yes")]
1098 (define_insn "*subdf_df_esfdf"
1099 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1100 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1102 (match_operand:SF 2 "s_register_operand" "f,f"))))]
1103 "TARGET_ARM && TARGET_HARD_FLOAT"
1106 rsf%?d\\t%0, %2, %1"
1107 [(set_attr "type" "farith")
1108 (set_attr "predicable" "yes")]
1111 (define_insn "*subdf_esfdf_esfdf"
1112 [(set (match_operand:DF 0 "s_register_operand" "=f")
1113 (minus:DF (float_extend:DF
1114 (match_operand:SF 1 "s_register_operand" "f"))
1116 (match_operand:SF 2 "s_register_operand" "f"))))]
1117 "TARGET_ARM && TARGET_HARD_FLOAT"
1118 "suf%?d\\t%0, %1, %2"
1119 [(set_attr "type" "farith")
1120 (set_attr "predicable" "yes")]
1123 (define_insn "subxf3"
1124 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1125 (minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1126 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1127 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1130 rsf%?e\\t%0, %2, %1"
1131 [(set_attr "type" "farith")
1132 (set_attr "predicable" "yes")]
1135 ;; Multiplication insns
1137 (define_expand "mulsi3"
1138 [(set (match_operand:SI 0 "s_register_operand" "")
1139 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1140 (match_operand:SI 1 "s_register_operand" "")))]
1145 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1146 (define_insn "*arm_mulsi3"
1147 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1148 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1149 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1151 "mul%?\\t%0, %2, %1"
1152 [(set_attr "type" "mult")
1153 (set_attr "predicable" "yes")]
1156 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1157 ; 1 and 2; are the same, because reload will make operand 0 match
1158 ; operand 1 without realizing that this conflicts with operand 2. We fix
1159 ; this by adding another alternative to match this case, and then `reload'
1160 ; it ourselves. This alternative must come first.
1161 (define_insn "*thumb_mulsi3"
1162 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1163 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1164 (match_operand:SI 2 "register_operand" "l,l,l")))]
1167 if (which_alternative < 2)
1168 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1170 return \"mul\\t%0, %0, %2\";
1172 [(set_attr "length" "4,4,2")
1173 (set_attr "type" "mult")]
1176 (define_insn "*mulsi3_compare0"
1177 [(set (reg:CC_NOOV CC_REGNUM)
1178 (compare:CC_NOOV (mult:SI
1179 (match_operand:SI 2 "s_register_operand" "r,r")
1180 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1182 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1183 (mult:SI (match_dup 2) (match_dup 1)))]
1184 "TARGET_ARM && !arm_is_xscale"
1185 "mul%?s\\t%0, %2, %1"
1186 [(set_attr "conds" "set")
1187 (set_attr "type" "mult")]
1190 (define_insn "*mulsi_compare0_scratch"
1191 [(set (reg:CC_NOOV CC_REGNUM)
1192 (compare:CC_NOOV (mult:SI
1193 (match_operand:SI 2 "s_register_operand" "r,r")
1194 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1196 (clobber (match_scratch:SI 0 "=&r,&r"))]
1197 "TARGET_ARM && !arm_is_xscale"
1198 "mul%?s\\t%0, %2, %1"
1199 [(set_attr "conds" "set")
1200 (set_attr "type" "mult")]
1203 ;; Unnamed templates to match MLA instruction.
1205 (define_insn "*mulsi3addsi"
1206 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1208 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1209 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1210 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1212 "mla%?\\t%0, %2, %1, %3"
1213 [(set_attr "type" "mult")
1214 (set_attr "predicable" "yes")]
1217 (define_insn "*mulsi3addsi_compare0"
1218 [(set (reg:CC_NOOV CC_REGNUM)
1221 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1222 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1223 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1225 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1226 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1228 "TARGET_ARM && !arm_is_xscale"
1229 "mla%?s\\t%0, %2, %1, %3"
1230 [(set_attr "conds" "set")
1231 (set_attr "type" "mult")]
1234 (define_insn "*mulsi3addsi_compare0_scratch"
1235 [(set (reg:CC_NOOV CC_REGNUM)
1238 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1239 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1240 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1242 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1243 "TARGET_ARM && !arm_is_xscale"
1244 "mla%?s\\t%0, %2, %1, %3"
1245 [(set_attr "conds" "set")
1246 (set_attr "type" "mult")]
1249 ;; Unnamed template to match long long multiply-accumlate (smlal)
1251 (define_insn "*mulsidi3adddi"
1252 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1255 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1256 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1257 (match_operand:DI 1 "s_register_operand" "0")))]
1258 "TARGET_ARM && arm_fast_multiply"
1259 "smlal%?\\t%Q0, %R0, %3, %2"
1260 [(set_attr "type" "mult")
1261 (set_attr "predicable" "yes")]
1264 (define_insn "mulsidi3"
1265 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1267 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1268 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1269 "TARGET_ARM && arm_fast_multiply"
1270 "smull%?\\t%Q0, %R0, %1, %2"
1271 [(set_attr "type" "mult")
1272 (set_attr "predicable" "yes")]
1275 (define_insn "umulsidi3"
1276 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1278 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1279 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1280 "TARGET_ARM && arm_fast_multiply"
1281 "umull%?\\t%Q0, %R0, %1, %2"
1282 [(set_attr "type" "mult")
1283 (set_attr "predicable" "yes")]
1286 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1288 (define_insn "*umulsidi3adddi"
1289 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1292 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1293 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1294 (match_operand:DI 1 "s_register_operand" "0")))]
1295 "TARGET_ARM && arm_fast_multiply"
1296 "umlal%?\\t%Q0, %R0, %3, %2"
1297 [(set_attr "type" "mult")
1298 (set_attr "predicable" "yes")]
1301 (define_insn "smulsi3_highpart"
1302 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1306 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1307 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1309 (clobber (match_scratch:SI 3 "=&r,&r"))]
1310 "TARGET_ARM && arm_fast_multiply"
1311 "smull%?\\t%3, %0, %2, %1"
1312 [(set_attr "type" "mult")
1313 (set_attr "predicable" "yes")]
1316 (define_insn "umulsi3_highpart"
1317 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1321 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1322 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1324 (clobber (match_scratch:SI 3 "=&r,&r"))]
1325 "TARGET_ARM && arm_fast_multiply"
1326 "umull%?\\t%3, %0, %2, %1"
1327 [(set_attr "type" "mult")
1328 (set_attr "predicable" "yes")]
1331 (define_insn "mulhisi3"
1332 [(set (match_operand:SI 0 "s_register_operand" "=r")
1333 (mult:SI (sign_extend:SI
1334 (match_operand:HI 1 "s_register_operand" "%r"))
1336 (match_operand:HI 2 "s_register_operand" "r"))))]
1337 "TARGET_ARM && arm_is_xscale"
1338 "smulbb%?\\t%0, %1, %2"
1339 [(set_attr "type" "mult")]
1342 (define_insn "*mulhisi3addsi"
1343 [(set (match_operand:SI 0 "s_register_operand" "=r")
1344 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1345 (mult:SI (sign_extend:SI
1346 (match_operand:HI 2 "s_register_operand" "%r"))
1348 (match_operand:HI 3 "s_register_operand" "r")))))]
1349 "TARGET_ARM && arm_is_xscale"
1350 "smlabb%?\\t%0, %2, %3, %1"
1351 [(set_attr "type" "mult")]
1354 (define_insn "*mulhidi3adddi"
1355 [(set (match_operand:DI 0 "s_register_operand" "=r")
1357 (match_operand:DI 1 "s_register_operand" "0")
1358 (mult:DI (sign_extend:DI
1359 (match_operand:HI 2 "s_register_operand" "%r"))
1361 (match_operand:HI 3 "s_register_operand" "r")))))]
1362 "TARGET_ARM && arm_is_xscale"
1363 "smlalbb%?\\t%Q0, %R0, %2, %3"
1364 [(set_attr "type" "mult")])
1366 (define_insn "mulsf3"
1367 [(set (match_operand:SF 0 "s_register_operand" "=f")
1368 (mult:SF (match_operand:SF 1 "s_register_operand" "f")
1369 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1370 "TARGET_ARM && TARGET_HARD_FLOAT"
1371 "fml%?s\\t%0, %1, %2"
1372 [(set_attr "type" "ffmul")
1373 (set_attr "predicable" "yes")]
1376 (define_insn "muldf3"
1377 [(set (match_operand:DF 0 "s_register_operand" "=f")
1378 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1379 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1380 "TARGET_ARM && TARGET_HARD_FLOAT"
1381 "muf%?d\\t%0, %1, %2"
1382 [(set_attr "type" "fmul")
1383 (set_attr "predicable" "yes")]
1386 (define_insn "*muldf_esfdf_df"
1387 [(set (match_operand:DF 0 "s_register_operand" "=f")
1388 (mult:DF (float_extend:DF
1389 (match_operand:SF 1 "s_register_operand" "f"))
1390 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1391 "TARGET_ARM && TARGET_HARD_FLOAT"
1392 "muf%?d\\t%0, %1, %2"
1393 [(set_attr "type" "fmul")
1394 (set_attr "predicable" "yes")]
1397 (define_insn "*muldf_df_esfdf"
1398 [(set (match_operand:DF 0 "s_register_operand" "=f")
1399 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1401 (match_operand:SF 2 "s_register_operand" "f"))))]
1402 "TARGET_ARM && TARGET_HARD_FLOAT"
1403 "muf%?d\\t%0, %1, %2"
1404 [(set_attr "type" "fmul")
1405 (set_attr "predicable" "yes")]
1408 (define_insn "*muldf_esfdf_esfdf"
1409 [(set (match_operand:DF 0 "s_register_operand" "=f")
1411 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f"))
1412 (float_extend:DF (match_operand:SF 2 "s_register_operand" "f"))))]
1413 "TARGET_ARM && TARGET_HARD_FLOAT"
1414 "muf%?d\\t%0, %1, %2"
1415 [(set_attr "type" "fmul")
1416 (set_attr "predicable" "yes")]
1419 (define_insn "mulxf3"
1420 [(set (match_operand:XF 0 "s_register_operand" "=f")
1421 (mult:XF (match_operand:XF 1 "s_register_operand" "f")
1422 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1423 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1424 "muf%?e\\t%0, %1, %2"
1425 [(set_attr "type" "fmul")
1426 (set_attr "predicable" "yes")]
1431 (define_insn "divsf3"
1432 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1433 (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1434 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1435 "TARGET_ARM && TARGET_HARD_FLOAT"
1438 frd%?s\\t%0, %2, %1"
1439 [(set_attr "type" "fdivs")
1440 (set_attr "predicable" "yes")]
1443 (define_insn "divdf3"
1444 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1445 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1446 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1447 "TARGET_ARM && TARGET_HARD_FLOAT"
1450 rdf%?d\\t%0, %2, %1"
1451 [(set_attr "type" "fdivd")
1452 (set_attr "predicable" "yes")]
1455 (define_insn "*divdf_esfdf_df"
1456 [(set (match_operand:DF 0 "s_register_operand" "=f")
1457 (div:DF (float_extend:DF
1458 (match_operand:SF 1 "s_register_operand" "f"))
1459 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1460 "TARGET_ARM && TARGET_HARD_FLOAT"
1461 "dvf%?d\\t%0, %1, %2"
1462 [(set_attr "type" "fdivd")
1463 (set_attr "predicable" "yes")]
1466 (define_insn "*divdf_df_esfdf"
1467 [(set (match_operand:DF 0 "s_register_operand" "=f")
1468 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1470 (match_operand:SF 2 "s_register_operand" "f"))))]
1471 "TARGET_ARM && TARGET_HARD_FLOAT"
1472 "rdf%?d\\t%0, %2, %1"
1473 [(set_attr "type" "fdivd")
1474 (set_attr "predicable" "yes")]
1477 (define_insn "*divdf_esfdf_esfdf"
1478 [(set (match_operand:DF 0 "s_register_operand" "=f")
1479 (div:DF (float_extend:DF
1480 (match_operand:SF 1 "s_register_operand" "f"))
1482 (match_operand:SF 2 "s_register_operand" "f"))))]
1483 "TARGET_ARM && TARGET_HARD_FLOAT"
1484 "dvf%?d\\t%0, %1, %2"
1485 [(set_attr "type" "fdivd")
1486 (set_attr "predicable" "yes")]
1489 (define_insn "divxf3"
1490 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1491 (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1492 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1493 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1496 rdf%?e\\t%0, %2, %1"
1497 [(set_attr "type" "fdivx")
1498 (set_attr "predicable" "yes")]
1503 (define_insn "modsf3"
1504 [(set (match_operand:SF 0 "s_register_operand" "=f")
1505 (mod:SF (match_operand:SF 1 "s_register_operand" "f")
1506 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1507 "TARGET_ARM && TARGET_HARD_FLOAT"
1508 "rmf%?s\\t%0, %1, %2"
1509 [(set_attr "type" "fdivs")
1510 (set_attr "predicable" "yes")]
1513 (define_insn "moddf3"
1514 [(set (match_operand:DF 0 "s_register_operand" "=f")
1515 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1516 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1517 "TARGET_ARM && TARGET_HARD_FLOAT"
1518 "rmf%?d\\t%0, %1, %2"
1519 [(set_attr "type" "fdivd")
1520 (set_attr "predicable" "yes")]
1523 (define_insn "*moddf_esfdf_df"
1524 [(set (match_operand:DF 0 "s_register_operand" "=f")
1525 (mod:DF (float_extend:DF
1526 (match_operand:SF 1 "s_register_operand" "f"))
1527 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1528 "TARGET_ARM && TARGET_HARD_FLOAT"
1529 "rmf%?d\\t%0, %1, %2"
1530 [(set_attr "type" "fdivd")
1531 (set_attr "predicable" "yes")]
1534 (define_insn "*moddf_df_esfdf"
1535 [(set (match_operand:DF 0 "s_register_operand" "=f")
1536 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1538 (match_operand:SF 2 "s_register_operand" "f"))))]
1539 "TARGET_ARM && TARGET_HARD_FLOAT"
1540 "rmf%?d\\t%0, %1, %2"
1541 [(set_attr "type" "fdivd")
1542 (set_attr "predicable" "yes")]
1545 (define_insn "*moddf_esfdf_esfdf"
1546 [(set (match_operand:DF 0 "s_register_operand" "=f")
1547 (mod:DF (float_extend:DF
1548 (match_operand:SF 1 "s_register_operand" "f"))
1550 (match_operand:SF 2 "s_register_operand" "f"))))]
1551 "TARGET_ARM && TARGET_HARD_FLOAT"
1552 "rmf%?d\\t%0, %1, %2"
1553 [(set_attr "type" "fdivd")
1554 (set_attr "predicable" "yes")]
1557 (define_insn "modxf3"
1558 [(set (match_operand:XF 0 "s_register_operand" "=f")
1559 (mod:XF (match_operand:XF 1 "s_register_operand" "f")
1560 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1561 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1562 "rmf%?e\\t%0, %1, %2"
1563 [(set_attr "type" "fdivx")
1564 (set_attr "predicable" "yes")]
1567 ;; Boolean and,ior,xor insns
1569 ;; Split up double word logical operations
1571 ;; Split up simple DImode logical operations. Simply perform the logical
1572 ;; operation on the upper and lower halves of the registers.
1574 [(set (match_operand:DI 0 "s_register_operand" "")
1575 (match_operator:DI 6 "logical_binary_operator"
1576 [(match_operand:DI 1 "s_register_operand" "")
1577 (match_operand:DI 2 "s_register_operand" "")]))]
1578 "TARGET_ARM && reload_completed"
1579 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1580 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1583 operands[3] = gen_highpart (SImode, operands[0]);
1584 operands[0] = gen_lowpart (SImode, operands[0]);
1585 operands[4] = gen_highpart (SImode, operands[1]);
1586 operands[1] = gen_lowpart (SImode, operands[1]);
1587 operands[5] = gen_highpart (SImode, operands[2]);
1588 operands[2] = gen_lowpart (SImode, operands[2]);
1593 [(set (match_operand:DI 0 "s_register_operand" "")
1594 (match_operator:DI 6 "logical_binary_operator"
1595 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1596 (match_operand:DI 1 "s_register_operand" "")]))]
1597 "TARGET_ARM && reload_completed"
1598 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1599 (set (match_dup 3) (match_op_dup:SI 6
1600 [(ashiftrt:SI (match_dup 2) (const_int 31))
1604 operands[3] = gen_highpart (SImode, operands[0]);
1605 operands[0] = gen_lowpart (SImode, operands[0]);
1606 operands[4] = gen_highpart (SImode, operands[1]);
1607 operands[1] = gen_lowpart (SImode, operands[1]);
1608 operands[5] = gen_highpart (SImode, operands[2]);
1609 operands[2] = gen_lowpart (SImode, operands[2]);
1613 ;; The zero extend of operand 2 means we can just copy the high part of
1614 ;; operand1 into operand0.
1616 [(set (match_operand:DI 0 "s_register_operand" "")
1618 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1619 (match_operand:DI 1 "s_register_operand" "")))]
1620 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1621 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1622 (set (match_dup 3) (match_dup 4))]
1625 operands[4] = gen_highpart (SImode, operands[1]);
1626 operands[3] = gen_highpart (SImode, operands[0]);
1627 operands[0] = gen_lowpart (SImode, operands[0]);
1628 operands[1] = gen_lowpart (SImode, operands[1]);
1632 ;; The zero extend of operand 2 means we can just copy the high part of
1633 ;; operand1 into operand0.
1635 [(set (match_operand:DI 0 "s_register_operand" "")
1637 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1638 (match_operand:DI 1 "s_register_operand" "")))]
1639 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1640 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1641 (set (match_dup 3) (match_dup 4))]
1644 operands[4] = gen_highpart (SImode, operands[1]);
1645 operands[3] = gen_highpart (SImode, operands[0]);
1646 operands[0] = gen_lowpart (SImode, operands[0]);
1647 operands[1] = gen_lowpart (SImode, operands[1]);
1651 (define_insn "anddi3"
1652 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1653 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1654 (match_operand:DI 2 "s_register_operand" "r,r")))]
1657 [(set_attr "length" "8")]
1660 (define_insn_and_split "*anddi_zesidi_di"
1661 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1662 (and:DI (zero_extend:DI
1663 (match_operand:SI 2 "s_register_operand" "r,r"))
1664 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1667 "TARGET_ARM && reload_completed"
1668 ; The zero extend of operand 2 clears the high word of the output
1670 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1671 (set (match_dup 3) (const_int 0))]
1674 operands[3] = gen_highpart (SImode, operands[0]);
1675 operands[0] = gen_lowpart (SImode, operands[0]);
1676 operands[1] = gen_lowpart (SImode, operands[1]);
1678 [(set_attr "length" "8")]
1681 (define_insn "*anddi_sesdi_di"
1682 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1683 (and:DI (sign_extend:DI
1684 (match_operand:SI 2 "s_register_operand" "r,r"))
1685 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1688 [(set_attr "length" "8")]
1691 (define_expand "andsi3"
1692 [(set (match_operand:SI 0 "s_register_operand" "")
1693 (and:SI (match_operand:SI 1 "s_register_operand" "")
1694 (match_operand:SI 2 "reg_or_int_operand" "")))]
1699 if (GET_CODE (operands[2]) == CONST_INT)
1701 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1704 ? 0 : preserve_subexpressions_p ()));
1708 else /* TARGET_THUMB */
1710 if (GET_CODE (operands[2]) != CONST_INT)
1711 operands[2] = force_reg (SImode, operands[2]);
1716 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1718 operands[2] = force_reg (SImode,
1719 GEN_INT (~INTVAL (operands[2])));
1721 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1726 for (i = 9; i <= 31; i++)
1728 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1730 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1734 else if ((((HOST_WIDE_INT) 1) << i) - 1
1735 == ~INTVAL (operands[2]))
1737 rtx shift = GEN_INT (i);
1738 rtx reg = gen_reg_rtx (SImode);
1740 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1741 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1747 operands[2] = force_reg (SImode, operands[2]);
1753 (define_insn_and_split "*arm_andsi3_insn"
1754 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1755 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1756 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1760 bic%?\\t%0, %1, #%B2
1763 && GET_CODE (operands[2]) == CONST_INT
1764 && !(const_ok_for_arm (INTVAL (operands[2]))
1765 || const_ok_for_arm (~INTVAL (operands[2])))"
1766 [(clobber (const_int 0))]
1768 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1772 [(set_attr "length" "4,4,16")
1773 (set_attr "predicable" "yes")]
1776 (define_insn "*thumb_andsi3_insn"
1777 [(set (match_operand:SI 0 "register_operand" "=l")
1778 (and:SI (match_operand:SI 1 "register_operand" "%0")
1779 (match_operand:SI 2 "register_operand" "l")))]
1782 [(set_attr "length" "2")]
1785 (define_insn "*andsi3_compare0"
1786 [(set (reg:CC_NOOV CC_REGNUM)
1788 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1789 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1791 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1792 (and:SI (match_dup 1) (match_dup 2)))]
1796 bic%?s\\t%0, %1, #%B2"
1797 [(set_attr "conds" "set")]
1800 (define_insn "*andsi3_compare0_scratch"
1801 [(set (reg:CC_NOOV CC_REGNUM)
1803 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1804 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1806 (clobber (match_scratch:SI 2 "=X,r"))]
1810 bic%?s\\t%2, %0, #%B1"
1811 [(set_attr "conds" "set")]
1814 (define_insn "*zeroextractsi_compare0_scratch"
1815 [(set (reg:CC_NOOV CC_REGNUM)
1816 (compare:CC_NOOV (zero_extract:SI
1817 (match_operand:SI 0 "s_register_operand" "r")
1818 (match_operand 1 "const_int_operand" "n")
1819 (match_operand 2 "const_int_operand" "n"))
1822 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1823 && INTVAL (operands[1]) > 0
1824 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1825 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1827 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1828 << INTVAL (operands[2]));
1829 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1832 [(set_attr "conds" "set")]
1835 (define_insn "*ne_zeroextractsi"
1836 [(set (match_operand:SI 0 "s_register_operand" "=r")
1837 (ne:SI (zero_extract:SI
1838 (match_operand:SI 1 "s_register_operand" "r")
1839 (match_operand:SI 2 "const_int_operand" "n")
1840 (match_operand:SI 3 "const_int_operand" "n"))
1843 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1844 && INTVAL (operands[2]) > 0
1845 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1846 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1848 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1849 << INTVAL (operands[3]));
1850 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1851 return \"movne\\t%0, #1\";
1853 [(set_attr "conds" "clob")
1854 (set_attr "length" "8")]
1857 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1858 ;;; represented by the bitfield, then this will produce incorrect results.
1859 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1860 ;;; which have a real bitfield insert instruction, the truncation happens
1861 ;;; in the bitfield insert instruction itself. Since arm does not have a
1862 ;;; bitfield insert instruction, we would have to emit code here to truncate
1863 ;;; the value before we insert. This loses some of the advantage of having
1864 ;;; this insv pattern, so this pattern needs to be reevalutated.
1866 (define_expand "insv"
1867 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1868 (match_operand:SI 1 "general_operand" "")
1869 (match_operand:SI 2 "general_operand" ""))
1870 (match_operand:SI 3 "reg_or_int_operand" ""))]
1874 int start_bit = INTVAL (operands[2]);
1875 int width = INTVAL (operands[1]);
1876 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1877 rtx target, subtarget;
1879 target = operands[0];
1880 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1881 subreg as the final target. */
1882 if (GET_CODE (target) == SUBREG)
1884 subtarget = gen_reg_rtx (SImode);
1885 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1886 < GET_MODE_SIZE (SImode))
1887 target = SUBREG_REG (target);
1892 if (GET_CODE (operands[3]) == CONST_INT)
1894 /* Since we are inserting a known constant, we may be able to
1895 reduce the number of bits that we have to clear so that
1896 the mask becomes simple. */
1897 /* ??? This code does not check to see if the new mask is actually
1898 simpler. It may not be. */
1899 rtx op1 = gen_reg_rtx (SImode);
1900 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1901 start of this pattern. */
1902 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1903 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1905 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1906 emit_insn (gen_iorsi3 (subtarget, op1,
1907 GEN_INT (op3_value << start_bit)));
1909 else if (start_bit == 0
1910 && !(const_ok_for_arm (mask)
1911 || const_ok_for_arm (~mask)))
1913 /* A Trick, since we are setting the bottom bits in the word,
1914 we can shift operand[3] up, operand[0] down, OR them together
1915 and rotate the result back again. This takes 3 insns, and
1916 the third might be mergable into another op. */
1917 /* The shift up copes with the possibility that operand[3] is
1918 wider than the bitfield. */
1919 rtx op0 = gen_reg_rtx (SImode);
1920 rtx op1 = gen_reg_rtx (SImode);
1922 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1923 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1924 emit_insn (gen_iorsi3 (op1, op1, op0));
1925 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1927 else if ((width + start_bit == 32)
1928 && !(const_ok_for_arm (mask)
1929 || const_ok_for_arm (~mask)))
1931 /* Similar trick, but slightly less efficient. */
1933 rtx op0 = gen_reg_rtx (SImode);
1934 rtx op1 = gen_reg_rtx (SImode);
1936 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1937 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1938 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1939 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1943 rtx op0 = GEN_INT (mask);
1944 rtx op1 = gen_reg_rtx (SImode);
1945 rtx op2 = gen_reg_rtx (SImode);
1947 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1949 rtx tmp = gen_reg_rtx (SImode);
1951 emit_insn (gen_movsi (tmp, op0));
1955 /* Mask out any bits in operand[3] that are not needed. */
1956 emit_insn (gen_andsi3 (op1, operands[3], op0));
1958 if (GET_CODE (op0) == CONST_INT
1959 && (const_ok_for_arm (mask << start_bit)
1960 || const_ok_for_arm (~(mask << start_bit))))
1962 op0 = GEN_INT (~(mask << start_bit));
1963 emit_insn (gen_andsi3 (op2, operands[0], op0));
1967 if (GET_CODE (op0) == CONST_INT)
1969 rtx tmp = gen_reg_rtx (SImode);
1971 emit_insn (gen_movsi (tmp, op0));
1976 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1978 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1982 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1984 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1987 if (subtarget != target)
1989 /* If TARGET is still a SUBREG, then it must be wider than a word,
1990 so we must be careful only to set the subword we were asked to. */
1991 if (GET_CODE (target) == SUBREG)
1992 emit_move_insn (target, subtarget);
1994 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2001 ; constants for op 2 will never be given to these patterns.
2002 (define_insn_and_split "*anddi_notdi_di"
2003 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2004 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2005 (match_operand:DI 2 "s_register_operand" "0,r")))]
2008 "TARGET_ARM && reload_completed"
2009 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2010 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2013 operands[3] = gen_highpart (SImode, operands[0]);
2014 operands[0] = gen_lowpart (SImode, operands[0]);
2015 operands[4] = gen_highpart (SImode, operands[1]);
2016 operands[1] = gen_lowpart (SImode, operands[1]);
2017 operands[5] = gen_highpart (SImode, operands[2]);
2018 operands[2] = gen_lowpart (SImode, operands[2]);
2020 [(set_attr "length" "8")
2021 (set_attr "predicable" "yes")]
2024 (define_insn_and_split "*anddi_notzesidi_di"
2025 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2026 (and:DI (not:DI (zero_extend:DI
2027 (match_operand:SI 2 "s_register_operand" "r,r")))
2028 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2031 bic%?\\t%Q0, %Q1, %2
2033 ; (not (zero_extend ...)) allows us to just copy the high word from
2034 ; operand1 to operand0.
2037 && operands[0] != operands[1]"
2038 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2039 (set (match_dup 3) (match_dup 4))]
2042 operands[3] = gen_highpart (SImode, operands[0]);
2043 operands[0] = gen_lowpart (SImode, operands[0]);
2044 operands[4] = gen_highpart (SImode, operands[1]);
2045 operands[1] = gen_lowpart (SImode, operands[1]);
2047 [(set_attr "length" "4,8")
2048 (set_attr "predicable" "yes")]
2051 (define_insn_and_split "*anddi_notsesidi_di"
2052 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2053 (and:DI (not:DI (sign_extend:DI
2054 (match_operand:SI 2 "s_register_operand" "r,r")))
2055 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2058 "TARGET_ARM && reload_completed"
2059 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2060 (set (match_dup 3) (and:SI (not:SI
2061 (ashiftrt:SI (match_dup 2) (const_int 31)))
2065 operands[3] = gen_highpart (SImode, operands[0]);
2066 operands[0] = gen_lowpart (SImode, operands[0]);
2067 operands[4] = gen_highpart (SImode, operands[1]);
2068 operands[1] = gen_lowpart (SImode, operands[1]);
2070 [(set_attr "length" "8")
2071 (set_attr "predicable" "yes")]
2074 (define_insn "andsi_notsi_si"
2075 [(set (match_operand:SI 0 "s_register_operand" "=r")
2076 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2077 (match_operand:SI 1 "s_register_operand" "r")))]
2079 "bic%?\\t%0, %1, %2"
2080 [(set_attr "predicable" "yes")]
2083 (define_insn "bicsi3"
2084 [(set (match_operand:SI 0 "register_operand" "=l")
2085 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2086 (match_operand:SI 2 "register_operand" "0")))]
2089 [(set_attr "length" "2")]
2092 (define_insn "andsi_not_shiftsi_si"
2093 [(set (match_operand:SI 0 "s_register_operand" "=r")
2094 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2095 [(match_operand:SI 2 "s_register_operand" "r")
2096 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2097 (match_operand:SI 1 "s_register_operand" "r")))]
2099 "bic%?\\t%0, %1, %2%S4"
2100 [(set_attr "predicable" "yes")
2101 (set_attr "shift" "2")
2105 (define_insn "*andsi_notsi_si_compare0"
2106 [(set (reg:CC_NOOV CC_REGNUM)
2108 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2109 (match_operand:SI 1 "s_register_operand" "r"))
2111 (set (match_operand:SI 0 "s_register_operand" "=r")
2112 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2114 "bic%?s\\t%0, %1, %2"
2115 [(set_attr "conds" "set")]
2118 (define_insn "*andsi_notsi_si_compare0_scratch"
2119 [(set (reg:CC_NOOV CC_REGNUM)
2121 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2122 (match_operand:SI 1 "s_register_operand" "r"))
2124 (clobber (match_scratch:SI 0 "=r"))]
2126 "bic%?s\\t%0, %1, %2"
2127 [(set_attr "conds" "set")]
2130 (define_insn "iordi3"
2131 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2132 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2133 (match_operand:DI 2 "s_register_operand" "r,r")))]
2136 [(set_attr "length" "8")
2137 (set_attr "predicable" "yes")]
2140 (define_insn "*iordi_zesidi_di"
2141 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2142 (ior:DI (zero_extend:DI
2143 (match_operand:SI 2 "s_register_operand" "r,r"))
2144 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2147 orr%?\\t%Q0, %Q1, %2
2149 [(set_attr "length" "4,8")
2150 (set_attr "predicable" "yes")]
2153 (define_insn "*iordi_sesidi_di"
2154 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2155 (ior:DI (sign_extend:DI
2156 (match_operand:SI 2 "s_register_operand" "r,r"))
2157 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2160 [(set_attr "length" "8")
2161 (set_attr "predicable" "yes")]
2164 (define_expand "iorsi3"
2165 [(set (match_operand:SI 0 "s_register_operand" "")
2166 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2167 (match_operand:SI 2 "reg_or_int_operand" "")))]
2170 if (GET_CODE (operands[2]) == CONST_INT)
2174 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2177 ? 0 : preserve_subexpressions_p ()));
2180 else /* TARGET_THUMB */
2181 operands [2] = force_reg (SImode, operands [2]);
2186 (define_insn_and_split "*arm_iorsi3"
2187 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2188 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2189 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2195 && GET_CODE (operands[2]) == CONST_INT
2196 && !const_ok_for_arm (INTVAL (operands[2]))"
2197 [(clobber (const_int 0))]
2199 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2203 [(set_attr "length" "4,16")
2204 (set_attr "predicable" "yes")]
2207 (define_insn "*thumb_iorsi3"
2208 [(set (match_operand:SI 0 "register_operand" "=l")
2209 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2210 (match_operand:SI 2 "register_operand" "l")))]
2213 [(set_attr "length" "2")]
2217 [(match_scratch:SI 3 "r")
2218 (set (match_operand:SI 0 "s_register_operand" "")
2219 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2220 (match_operand:SI 2 "const_int_operand" "")))]
2222 && !const_ok_for_arm (INTVAL (operands[2]))
2223 && const_ok_for_arm (~INTVAL (operands[2]))"
2224 [(set (match_dup 3) (match_dup 2))
2225 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2229 (define_insn "*iorsi3_compare0"
2230 [(set (reg:CC_NOOV CC_REGNUM)
2231 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2232 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2234 (set (match_operand:SI 0 "s_register_operand" "=r")
2235 (ior:SI (match_dup 1) (match_dup 2)))]
2237 "orr%?s\\t%0, %1, %2"
2238 [(set_attr "conds" "set")]
2241 (define_insn "*iorsi3_compare0_scratch"
2242 [(set (reg:CC_NOOV CC_REGNUM)
2243 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2244 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2246 (clobber (match_scratch:SI 0 "=r"))]
2248 "orr%?s\\t%0, %1, %2"
2249 [(set_attr "conds" "set")]
2252 (define_insn "xordi3"
2253 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2254 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2255 (match_operand:DI 2 "s_register_operand" "r,r")))]
2258 [(set_attr "length" "8")
2259 (set_attr "predicable" "yes")]
2262 (define_insn "*xordi_zesidi_di"
2263 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2264 (xor:DI (zero_extend:DI
2265 (match_operand:SI 2 "s_register_operand" "r,r"))
2266 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2269 eor%?\\t%Q0, %Q1, %2
2271 [(set_attr "length" "4,8")
2272 (set_attr "predicable" "yes")]
2275 (define_insn "*xordi_sesidi_di"
2276 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2277 (xor:DI (sign_extend:DI
2278 (match_operand:SI 2 "s_register_operand" "r,r"))
2279 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2282 [(set_attr "length" "8")
2283 (set_attr "predicable" "yes")]
2286 (define_expand "xorsi3"
2287 [(set (match_operand:SI 0 "s_register_operand" "")
2288 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2289 (match_operand:SI 2 "arm_rhs_operand" "")))]
2292 if (GET_CODE (operands[2]) == CONST_INT)
2293 operands[2] = force_reg (SImode, operands[2]);
2297 (define_insn "*arm_xorsi3"
2298 [(set (match_operand:SI 0 "s_register_operand" "=r")
2299 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2300 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2302 "eor%?\\t%0, %1, %2"
2303 [(set_attr "predicable" "yes")]
2306 (define_insn "*thumb_xorsi3"
2307 [(set (match_operand:SI 0 "register_operand" "=l")
2308 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2309 (match_operand:SI 2 "register_operand" "l")))]
2312 [(set_attr "length" "2")]
2315 (define_insn "*xorsi3_compare0"
2316 [(set (reg:CC_NOOV CC_REGNUM)
2317 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2318 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2320 (set (match_operand:SI 0 "s_register_operand" "=r")
2321 (xor:SI (match_dup 1) (match_dup 2)))]
2323 "eor%?s\\t%0, %1, %2"
2324 [(set_attr "conds" "set")]
2327 (define_insn "*xorsi3_compare0_scratch"
2328 [(set (reg:CC_NOOV CC_REGNUM)
2329 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2330 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2334 [(set_attr "conds" "set")]
2337 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2338 ; (NOT D) we can sometimes merge the final NOT into one of the following
2342 [(set (match_operand:SI 0 "s_register_operand" "")
2343 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2344 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2345 (match_operand:SI 3 "arm_rhs_operand" "")))
2346 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2348 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2349 (not:SI (match_dup 3))))
2350 (set (match_dup 0) (not:SI (match_dup 4)))]
2354 (define_insn "*andsi_iorsi3_notsi"
2355 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2356 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2357 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2358 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2360 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2361 [(set_attr "length" "8")
2362 (set_attr "predicable" "yes")]
2367 ;; Minimum and maximum insns
2369 (define_insn "smaxsi3"
2370 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2371 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2372 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2373 (clobber (reg:CC CC_REGNUM))]
2376 cmp\\t%1, %2\;movlt\\t%0, %2
2377 cmp\\t%1, %2\;movge\\t%0, %1
2378 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2379 [(set_attr "conds" "clob")
2380 (set_attr "length" "8,8,12")]
2383 (define_insn "sminsi3"
2384 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2385 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2386 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2387 (clobber (reg:CC CC_REGNUM))]
2390 cmp\\t%1, %2\;movge\\t%0, %2
2391 cmp\\t%1, %2\;movlt\\t%0, %1
2392 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2393 [(set_attr "conds" "clob")
2394 (set_attr "length" "8,8,12")]
2397 (define_insn "umaxsi3"
2398 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2399 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2400 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2401 (clobber (reg:CC CC_REGNUM))]
2404 cmp\\t%1, %2\;movcc\\t%0, %2
2405 cmp\\t%1, %2\;movcs\\t%0, %1
2406 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2407 [(set_attr "conds" "clob")
2408 (set_attr "length" "8,8,12")]
2411 (define_insn "uminsi3"
2412 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2413 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2414 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2415 (clobber (reg:CC CC_REGNUM))]
2418 cmp\\t%1, %2\;movcs\\t%0, %2
2419 cmp\\t%1, %2\;movcc\\t%0, %1
2420 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2421 [(set_attr "conds" "clob")
2422 (set_attr "length" "8,8,12")]
2425 (define_insn "*store_minmaxsi"
2426 [(set (match_operand:SI 0 "memory_operand" "=m")
2427 (match_operator:SI 3 "minmax_operator"
2428 [(match_operand:SI 1 "s_register_operand" "r")
2429 (match_operand:SI 2 "s_register_operand" "r")]))
2430 (clobber (reg:CC CC_REGNUM))]
2433 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2435 output_asm_insn (\"cmp\\t%1, %2\", operands);
2436 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2437 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2440 [(set_attr "conds" "clob")
2441 (set_attr "length" "12")
2442 (set_attr "type" "store1")]
2445 ; Reject the frame pointer in operand[1], since reloading this after
2446 ; it has been eliminated can cause carnage.
2447 (define_insn "*minmax_arithsi"
2448 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2449 (match_operator:SI 4 "shiftable_operator"
2450 [(match_operator:SI 5 "minmax_operator"
2451 [(match_operand:SI 2 "s_register_operand" "r,r")
2452 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2453 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2454 (clobber (reg:CC CC_REGNUM))]
2456 && (GET_CODE (operands[1]) != REG
2457 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2458 && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2461 enum rtx_code code = GET_CODE (operands[4]);
2463 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2465 output_asm_insn (\"cmp\\t%2, %3\", operands);
2466 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2467 if (which_alternative != 0 || operands[3] != const0_rtx
2468 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2469 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2472 [(set_attr "conds" "clob")
2473 (set_attr "length" "12")]
2477 ;; Shift and rotation insns
2479 (define_expand "ashlsi3"
2480 [(set (match_operand:SI 0 "s_register_operand" "")
2481 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2482 (match_operand:SI 2 "arm_rhs_operand" "")))]
2485 if (GET_CODE (operands[2]) == CONST_INT
2486 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2488 emit_insn (gen_movsi (operands[0], const0_rtx));
2494 (define_insn "*thumb_ashlsi3"
2495 [(set (match_operand:SI 0 "register_operand" "=l,l")
2496 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2497 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2500 [(set_attr "length" "2")]
2503 (define_expand "ashrsi3"
2504 [(set (match_operand:SI 0 "s_register_operand" "")
2505 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2506 (match_operand:SI 2 "arm_rhs_operand" "")))]
2509 if (GET_CODE (operands[2]) == CONST_INT
2510 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2511 operands[2] = GEN_INT (31);
2515 (define_insn "*thumb_ashrsi3"
2516 [(set (match_operand:SI 0 "register_operand" "=l,l")
2517 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2518 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2521 [(set_attr "length" "2")]
2524 (define_expand "lshrsi3"
2525 [(set (match_operand:SI 0 "s_register_operand" "")
2526 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2527 (match_operand:SI 2 "arm_rhs_operand" "")))]
2530 if (GET_CODE (operands[2]) == CONST_INT
2531 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2533 emit_insn (gen_movsi (operands[0], const0_rtx));
2539 (define_insn "*thumb_lshrsi3"
2540 [(set (match_operand:SI 0 "register_operand" "=l,l")
2541 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2542 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2545 [(set_attr "length" "2")]
2548 (define_expand "rotlsi3"
2549 [(set (match_operand:SI 0 "s_register_operand" "")
2550 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2551 (match_operand:SI 2 "reg_or_int_operand" "")))]
2554 if (GET_CODE (operands[2]) == CONST_INT)
2555 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2558 rtx reg = gen_reg_rtx (SImode);
2559 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2565 (define_expand "rotrsi3"
2566 [(set (match_operand:SI 0 "s_register_operand" "")
2567 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2568 (match_operand:SI 2 "arm_rhs_operand" "")))]
2573 if (GET_CODE (operands[2]) == CONST_INT
2574 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2575 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2577 else /* TARGET_THUMB */
2579 if (GET_CODE (operands [2]) == CONST_INT)
2580 operands [2] = force_reg (SImode, operands[2]);
2585 (define_insn "*thumb_rotrsi3"
2586 [(set (match_operand:SI 0 "register_operand" "=l")
2587 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2588 (match_operand:SI 2 "register_operand" "l")))]
2591 [(set_attr "length" "2")]
2594 (define_insn "*arm_shiftsi3"
2595 [(set (match_operand:SI 0 "s_register_operand" "=r")
2596 (match_operator:SI 3 "shift_operator"
2597 [(match_operand:SI 1 "s_register_operand" "r")
2598 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2601 [(set_attr "predicable" "yes")
2602 (set_attr "shift" "1")
2606 (define_insn "*shiftsi3_compare0"
2607 [(set (reg:CC_NOOV CC_REGNUM)
2608 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2609 [(match_operand:SI 1 "s_register_operand" "r")
2610 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2612 (set (match_operand:SI 0 "s_register_operand" "=r")
2613 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2615 "mov%?s\\t%0, %1%S3"
2616 [(set_attr "conds" "set")
2617 (set_attr "shift" "1")
2621 (define_insn "*shiftsi3_compare0_scratch"
2622 [(set (reg:CC_NOOV CC_REGNUM)
2623 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2624 [(match_operand:SI 1 "s_register_operand" "r")
2625 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2627 (clobber (match_scratch:SI 0 "=r"))]
2629 "mov%?s\\t%0, %1%S3"
2630 [(set_attr "conds" "set")
2631 (set_attr "shift" "1")
2635 (define_insn "*notsi_shiftsi"
2636 [(set (match_operand:SI 0 "s_register_operand" "=r")
2637 (not:SI (match_operator:SI 3 "shift_operator"
2638 [(match_operand:SI 1 "s_register_operand" "r")
2639 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2642 [(set_attr "predicable" "yes")
2643 (set_attr "shift" "1")
2647 (define_insn "*notsi_shiftsi_compare0"
2648 [(set (reg:CC_NOOV CC_REGNUM)
2649 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2650 [(match_operand:SI 1 "s_register_operand" "r")
2651 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2653 (set (match_operand:SI 0 "s_register_operand" "=r")
2654 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2656 "mvn%?s\\t%0, %1%S3"
2657 [(set_attr "conds" "set")
2658 (set_attr "shift" "1")
2662 (define_insn "*not_shiftsi_compare0_scratch"
2663 [(set (reg:CC_NOOV CC_REGNUM)
2664 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2665 [(match_operand:SI 1 "s_register_operand" "r")
2666 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2668 (clobber (match_scratch:SI 0 "=r"))]
2670 "mvn%?s\\t%0, %1%S3"
2671 [(set_attr "conds" "set")
2672 (set_attr "shift" "1")
2676 ;; We don't really have extzv, but defining this using shifts helps
2677 ;; to reduce register pressure later on.
2679 (define_expand "extzv"
2681 (ashift:SI (match_operand:SI 1 "register_operand" "")
2682 (match_operand:SI 2 "const_int_operand" "")))
2683 (set (match_operand:SI 0 "register_operand" "")
2684 (lshiftrt:SI (match_dup 4)
2685 (match_operand:SI 3 "const_int_operand" "")))]
2689 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2690 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2692 operands[3] = GEN_INT (rshift);
2696 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2700 operands[2] = GEN_INT (lshift);
2701 operands[4] = gen_reg_rtx (SImode);
2706 ;; Unary arithmetic insns
2708 (define_expand "negdi2"
2710 [(set (match_operand:DI 0 "s_register_operand" "")
2711 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2712 (clobber (reg:CC CC_REGNUM))])]
2717 if (GET_CODE (operands[1]) != REG)
2718 operands[1] = force_reg (SImode, operands[1]);
2723 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2724 ;; The second alternative is to allow the common case of a *full* overlap.
2725 (define_insn "*arm_negdi2"
2726 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2727 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2728 (clobber (reg:CC CC_REGNUM))]
2730 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2731 [(set_attr "conds" "clob")
2732 (set_attr "length" "8")]
2735 (define_insn "*thumb_negdi2"
2736 [(set (match_operand:DI 0 "register_operand" "=&l")
2737 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2738 (clobber (reg:CC CC_REGNUM))]
2740 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2741 [(set_attr "length" "6")]
2744 (define_expand "negsi2"
2745 [(set (match_operand:SI 0 "s_register_operand" "")
2746 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2751 (define_insn "*arm_negsi2"
2752 [(set (match_operand:SI 0 "s_register_operand" "=r")
2753 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2755 "rsb%?\\t%0, %1, #0"
2756 [(set_attr "predicable" "yes")]
2759 (define_insn "*thumb_negsi2"
2760 [(set (match_operand:SI 0 "register_operand" "=l")
2761 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2764 [(set_attr "length" "2")]
2767 (define_insn "negsf2"
2768 [(set (match_operand:SF 0 "s_register_operand" "=f")
2769 (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
2770 "TARGET_ARM && TARGET_HARD_FLOAT"
2772 [(set_attr "type" "ffarith")
2773 (set_attr "predicable" "yes")]
2776 (define_insn "negdf2"
2777 [(set (match_operand:DF 0 "s_register_operand" "=f")
2778 (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
2779 "TARGET_ARM && TARGET_HARD_FLOAT"
2781 [(set_attr "type" "ffarith")
2782 (set_attr "predicable" "yes")]
2785 (define_insn "*negdf_esfdf"
2786 [(set (match_operand:DF 0 "s_register_operand" "=f")
2787 (neg:DF (float_extend:DF
2788 (match_operand:SF 1 "s_register_operand" "f"))))]
2789 "TARGET_ARM && TARGET_HARD_FLOAT"
2791 [(set_attr "type" "ffarith")
2792 (set_attr "predicable" "yes")]
2795 (define_insn "negxf2"
2796 [(set (match_operand:XF 0 "s_register_operand" "=f")
2797 (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
2798 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2800 [(set_attr "type" "ffarith")
2801 (set_attr "predicable" "yes")]
2804 ;; abssi2 doesn't really clobber the condition codes if a different register
2805 ;; is being set. To keep things simple, assume during rtl manipulations that
2806 ;; it does, but tell the final scan operator the truth. Similarly for
2809 (define_insn "abssi2"
2810 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2811 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2812 (clobber (reg:CC CC_REGNUM))]
2815 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2816 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2817 [(set_attr "conds" "clob,*")
2818 (set_attr "shift" "1")
2819 ;; predicable can't be set based on the variant, so left as no
2820 (set_attr "length" "8")]
2823 (define_insn "*neg_abssi2"
2824 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2825 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2826 (clobber (reg:CC CC_REGNUM))]
2829 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2830 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2831 [(set_attr "conds" "clob,*")
2832 (set_attr "shift" "1")
2833 ;; predicable can't be set based on the variant, so left as no
2834 (set_attr "length" "8")]
2837 (define_insn "abssf2"
2838 [(set (match_operand:SF 0 "s_register_operand" "=f")
2839 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
2840 "TARGET_ARM && TARGET_HARD_FLOAT"
2842 [(set_attr "type" "ffarith")
2843 (set_attr "predicable" "yes")]
2846 (define_insn "absdf2"
2847 [(set (match_operand:DF 0 "s_register_operand" "=f")
2848 (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
2849 "TARGET_ARM && TARGET_HARD_FLOAT"
2851 [(set_attr "type" "ffarith")
2852 (set_attr "predicable" "yes")]
2855 (define_insn "*absdf_esfdf"
2856 [(set (match_operand:DF 0 "s_register_operand" "=f")
2857 (abs:DF (float_extend:DF
2858 (match_operand:SF 1 "s_register_operand" "f"))))]
2859 "TARGET_ARM && TARGET_HARD_FLOAT"
2861 [(set_attr "type" "ffarith")
2862 (set_attr "predicable" "yes")]
2865 (define_insn "absxf2"
2866 [(set (match_operand:XF 0 "s_register_operand" "=f")
2867 (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
2868 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2870 [(set_attr "type" "ffarith")
2871 (set_attr "predicable" "yes")]
2874 (define_insn "sqrtsf2"
2875 [(set (match_operand:SF 0 "s_register_operand" "=f")
2876 (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
2877 "TARGET_ARM && TARGET_HARD_FLOAT"
2879 [(set_attr "type" "float_em")
2880 (set_attr "predicable" "yes")]
2883 (define_insn "sqrtdf2"
2884 [(set (match_operand:DF 0 "s_register_operand" "=f")
2885 (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
2886 "TARGET_ARM && TARGET_HARD_FLOAT"
2888 [(set_attr "type" "float_em")
2889 (set_attr "predicable" "yes")]
2892 (define_insn "*sqrtdf_esfdf"
2893 [(set (match_operand:DF 0 "s_register_operand" "=f")
2894 (sqrt:DF (float_extend:DF
2895 (match_operand:SF 1 "s_register_operand" "f"))))]
2896 "TARGET_ARM && TARGET_HARD_FLOAT"
2898 [(set_attr "type" "float_em")
2899 (set_attr "predicable" "yes")]
2902 (define_insn "sqrtxf2"
2903 [(set (match_operand:XF 0 "s_register_operand" "=f")
2904 (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
2905 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2907 [(set_attr "type" "float_em")
2908 (set_attr "predicable" "yes")]
2911 ;; SIN COS TAN and family are always emulated, so it's probably better
2912 ;; to always call a library function.
2913 ;(define_insn "sinsf2"
2914 ; [(set (match_operand:SF 0 "s_register_operand" "=f")
2915 ; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
2917 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2919 ;[(set_attr "type" "float_em")])
2921 ;(define_insn "sindf2"
2922 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2923 ; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
2925 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2927 ;[(set_attr "type" "float_em")])
2929 ;(define_insn "*sindf_esfdf"
2930 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2931 ; (unspec:DF [(float_extend:DF
2932 ; (match_operand:SF 1 "s_register_operand" "f"))]
2934 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2936 ;[(set_attr "type" "float_em")])
2938 ;(define_insn "sinxf2"
2939 ; [(set (match_operand:XF 0 "s_register_operand" "=f")
2940 ; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
2942 ; "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2944 ;[(set_attr "type" "float_em")])
2946 ;(define_insn "cossf2"
2947 ; [(set (match_operand:SF 0 "s_register_operand" "=f")
2948 ; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
2950 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2952 ;[(set_attr "type" "float_em")])
2954 ;(define_insn "cosdf2"
2955 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2956 ; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
2958 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2960 ;[(set_attr "type" "float_em")])
2962 ;(define_insn "*cosdf_esfdf"
2963 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2964 ; (unspec:DF [(float_extend:DF
2965 ; (match_operand:SF 1 "s_register_operand" "f"))]
2967 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2969 ;[(set_attr "type" "float_em")])
2971 ;(define_insn "cosxf2"
2972 ; [(set (match_operand:XF 0 "s_register_operand" "=f")
2973 ; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
2975 ; "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2977 ;[(set_attr "type" "float_em")])
2979 (define_insn_and_split "one_cmpldi2"
2980 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2981 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2984 "TARGET_ARM && reload_completed"
2985 [(set (match_dup 0) (not:SI (match_dup 1)))
2986 (set (match_dup 2) (not:SI (match_dup 3)))]
2989 operands[2] = gen_highpart (SImode, operands[0]);
2990 operands[0] = gen_lowpart (SImode, operands[0]);
2991 operands[3] = gen_highpart (SImode, operands[1]);
2992 operands[1] = gen_lowpart (SImode, operands[1]);
2994 [(set_attr "length" "8")
2995 (set_attr "predicable" "yes")]
2998 (define_expand "one_cmplsi2"
2999 [(set (match_operand:SI 0 "s_register_operand" "")
3000 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3005 (define_insn "*arm_one_cmplsi2"
3006 [(set (match_operand:SI 0 "s_register_operand" "=r")
3007 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
3010 [(set_attr "predicable" "yes")]
3013 (define_insn "*thumb_one_cmplsi2"
3014 [(set (match_operand:SI 0 "register_operand" "=l")
3015 (not:SI (match_operand:SI 1 "register_operand" "l")))]
3018 [(set_attr "length" "2")]
3021 (define_insn "*notsi_compare0"
3022 [(set (reg:CC_NOOV CC_REGNUM)
3023 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3025 (set (match_operand:SI 0 "s_register_operand" "=r")
3026 (not:SI (match_dup 1)))]
3029 [(set_attr "conds" "set")]
3032 (define_insn "*notsi_compare0_scratch"
3033 [(set (reg:CC_NOOV CC_REGNUM)
3034 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3036 (clobber (match_scratch:SI 0 "=r"))]
3039 [(set_attr "conds" "set")]
3042 ;; Fixed <--> Floating conversion insns
3044 (define_insn "floatsisf2"
3045 [(set (match_operand:SF 0 "s_register_operand" "=f")
3046 (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
3047 "TARGET_ARM && TARGET_HARD_FLOAT"
3049 [(set_attr "type" "r_2_f")
3050 (set_attr "predicable" "yes")]
3053 (define_insn "floatsidf2"
3054 [(set (match_operand:DF 0 "s_register_operand" "=f")
3055 (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
3056 "TARGET_ARM && TARGET_HARD_FLOAT"
3058 [(set_attr "type" "r_2_f")
3059 (set_attr "predicable" "yes")]
3062 (define_insn "floatsixf2"
3063 [(set (match_operand:XF 0 "s_register_operand" "=f")
3064 (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
3065 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3067 [(set_attr "type" "r_2_f")
3068 (set_attr "predicable" "yes")]
3071 (define_insn "fix_truncsfsi2"
3072 [(set (match_operand:SI 0 "s_register_operand" "=r")
3073 (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
3074 "TARGET_ARM && TARGET_HARD_FLOAT"
3076 [(set_attr "type" "f_2_r")
3077 (set_attr "predicable" "yes")]
3080 (define_insn "fix_truncdfsi2"
3081 [(set (match_operand:SI 0 "s_register_operand" "=r")
3082 (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
3083 "TARGET_ARM && TARGET_HARD_FLOAT"
3085 [(set_attr "type" "f_2_r")
3086 (set_attr "predicable" "yes")]
3089 (define_insn "fix_truncxfsi2"
3090 [(set (match_operand:SI 0 "s_register_operand" "=r")
3091 (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
3092 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3094 [(set_attr "type" "f_2_r")
3095 (set_attr "predicable" "yes")]
3100 (define_insn "truncdfsf2"
3101 [(set (match_operand:SF 0 "s_register_operand" "=f")
3103 (match_operand:DF 1 "s_register_operand" "f")))]
3104 "TARGET_ARM && TARGET_HARD_FLOAT"
3106 [(set_attr "type" "ffarith")
3107 (set_attr "predicable" "yes")]
3110 (define_insn "truncxfsf2"
3111 [(set (match_operand:SF 0 "s_register_operand" "=f")
3113 (match_operand:XF 1 "s_register_operand" "f")))]
3114 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3116 [(set_attr "type" "ffarith")
3117 (set_attr "predicable" "yes")]
3120 (define_insn "truncxfdf2"
3121 [(set (match_operand:DF 0 "s_register_operand" "=f")
3123 (match_operand:XF 1 "s_register_operand" "f")))]
3124 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3126 [(set_attr "type" "ffarith")
3127 (set_attr "predicable" "yes")]
3130 ;; Zero and sign extension instructions.
3132 (define_insn "zero_extendsidi2"
3133 [(set (match_operand:DI 0 "s_register_operand" "=r")
3134 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3137 if (REGNO (operands[1])
3138 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3139 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3140 return \"mov%?\\t%R0, #0\";
3142 [(set_attr "length" "8")
3143 (set_attr "predicable" "yes")]
3146 (define_insn "zero_extendqidi2"
3147 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
3148 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3151 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3152 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3153 [(set_attr "length" "8")
3154 (set_attr "predicable" "yes")
3155 (set_attr "type" "*,load")
3156 (set_attr "pool_range" "*,4092")
3157 (set_attr "neg_pool_range" "*,4084")]
3160 (define_insn "extendsidi2"
3161 [(set (match_operand:DI 0 "s_register_operand" "=r")
3162 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3165 if (REGNO (operands[1])
3166 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3167 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3168 return \"mov%?\\t%R0, %Q0, asr #31\";
3170 [(set_attr "length" "8")
3171 (set_attr "shift" "1")
3172 (set_attr "predicable" "yes")]
3175 (define_expand "zero_extendhisi2"
3177 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3179 (set (match_operand:SI 0 "s_register_operand" "")
3180 (lshiftrt:SI (match_dup 2) (const_int 16)))]
3186 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3188 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3189 here because the insn below will generate an LDRH instruction
3190 rather than an LDR instruction, so we cannot get an unaligned
3192 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3193 gen_rtx_ZERO_EXTEND (SImode,
3197 if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3199 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3202 if (!s_register_operand (operands[1], HImode))
3203 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3204 operands[1] = gen_lowpart (SImode, operands[1]);
3205 operands[2] = gen_reg_rtx (SImode);
3207 else /* TARGET_THUMB */
3209 if (GET_CODE (operands[1]) == MEM)
3213 tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3214 tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3221 if (!s_register_operand (operands[1], HImode))
3222 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3223 operands[1] = gen_lowpart (SImode, operands[1]);
3224 operands[2] = gen_reg_rtx (SImode);
3226 ops[0] = operands[2];
3227 ops[1] = operands[1];
3228 ops[2] = GEN_INT (16);
3230 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3231 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3233 ops[0] = operands[0];
3234 ops[1] = operands[2];
3235 ops[2] = GEN_INT (16);
3237 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3238 gen_rtx_LSHIFTRT (SImode, ops[1],
3246 (define_insn "*thumb_zero_extendhisi2"
3247 [(set (match_operand:SI 0 "register_operand" "=l")
3248 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3251 rtx mem = XEXP (operands[1], 0);
3253 if (GET_CODE (mem) == CONST)
3254 mem = XEXP (mem, 0);
3256 if (GET_CODE (mem) == LABEL_REF)
3257 return \"ldr\\t%0, %1\";
3259 if (GET_CODE (mem) == PLUS)
3261 rtx a = XEXP (mem, 0);
3262 rtx b = XEXP (mem, 1);
3264 /* This can happen due to bugs in reload. */
3265 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3268 ops[0] = operands[0];
3271 output_asm_insn (\"mov %0, %1\", ops);
3273 XEXP (mem, 0) = operands[0];
3276 else if ( GET_CODE (a) == LABEL_REF
3277 && GET_CODE (b) == CONST_INT)
3278 return \"ldr\\t%0, %1\";
3281 return \"ldrh\\t%0, %1\";
3283 [(set_attr "length" "4")
3284 (set_attr "type" "load")
3285 (set_attr "pool_range" "60")]
3288 (define_insn "*arm_zero_extendhisi2"
3289 [(set (match_operand:SI 0 "s_register_operand" "=r")
3290 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3291 "TARGET_ARM && arm_arch4"
3293 [(set_attr "type" "load")
3294 (set_attr "predicable" "yes")
3295 (set_attr "pool_range" "256")
3296 (set_attr "neg_pool_range" "244")]
3300 [(set (match_operand:SI 0 "s_register_operand" "")
3301 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3302 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3303 "TARGET_ARM && (!arm_arch4)"
3304 [(set (match_dup 2) (match_dup 1))
3305 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3307 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3313 [(set (match_operand:SI 0 "s_register_operand" "")
3314 (match_operator:SI 3 "shiftable_operator"
3315 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3316 (match_operand:SI 4 "s_register_operand" "")]))
3317 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3318 "TARGET_ARM && (!arm_arch4)"
3319 [(set (match_dup 2) (match_dup 1))
3322 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3324 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3329 (define_expand "zero_extendqisi2"
3330 [(set (match_operand:SI 0 "s_register_operand" "")
3331 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3334 if (GET_CODE (operands[1]) != MEM)
3338 emit_insn (gen_andsi3 (operands[0],
3339 gen_lowpart (SImode, operands[1]),
3342 else /* TARGET_THUMB */
3344 rtx temp = gen_reg_rtx (SImode);
3347 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3348 operands[1] = gen_lowpart (SImode, operands[1]);
3351 ops[1] = operands[1];
3352 ops[2] = GEN_INT (24);
3354 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3355 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3357 ops[0] = operands[0];
3359 ops[2] = GEN_INT (24);
3361 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3362 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3369 (define_insn "*thumb_zero_extendqisi2"
3370 [(set (match_operand:SI 0 "register_operand" "=l")
3371 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3374 [(set_attr "length" "2")
3375 (set_attr "type" "load")
3376 (set_attr "pool_range" "32")]
3379 (define_insn "*arm_zero_extendqisi2"
3380 [(set (match_operand:SI 0 "s_register_operand" "=r")
3381 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3383 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3384 [(set_attr "type" "load")
3385 (set_attr "predicable" "yes")
3386 (set_attr "pool_range" "4096")
3387 (set_attr "neg_pool_range" "4084")]
3391 [(set (match_operand:SI 0 "s_register_operand" "")
3392 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3393 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3394 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3395 [(set (match_dup 2) (match_dup 1))
3396 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3400 (define_insn "*compareqi_eq0"
3401 [(set (reg:CC_Z CC_REGNUM)
3402 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3406 [(set_attr "conds" "set")]
3409 (define_expand "extendhisi2"
3411 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3413 (set (match_operand:SI 0 "s_register_operand" "")
3414 (ashiftrt:SI (match_dup 2)
3419 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3421 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3422 here because the insn below will generate an LDRH instruction
3423 rather than an LDR instruction, so we cannot get an unaligned
3425 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3426 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3430 if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3432 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3435 if (!s_register_operand (operands[1], HImode))
3436 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3437 operands[1] = gen_lowpart (SImode, operands[1]);
3438 operands[2] = gen_reg_rtx (SImode);
3444 ops[0] = operands[2];
3445 ops[1] = operands[1];
3446 ops[2] = GEN_INT (16);
3448 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3449 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3451 ops[0] = operands[0];
3452 ops[1] = operands[2];
3453 ops[2] = GEN_INT (16);
3455 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3456 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3463 (define_insn "*thumb_extendhisi2_insn"
3464 [(set (match_operand:SI 0 "register_operand" "=l")
3465 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3466 (clobber (match_scratch:SI 2 "=&l"))]
3471 rtx mem = XEXP (operands[1], 0);
3473 /* This code used to try to use 'V', and fix the address only if it was
3474 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3475 range of QImode offsets, and offsettable_address_p does a QImode
3478 if (GET_CODE (mem) == CONST)
3479 mem = XEXP (mem, 0);
3481 if (GET_CODE (mem) == LABEL_REF)
3482 return \"ldr\\t%0, %1\";
3484 if (GET_CODE (mem) == PLUS)
3486 rtx a = XEXP (mem, 0);
3487 rtx b = XEXP (mem, 1);
3489 if (GET_CODE (a) == LABEL_REF
3490 && GET_CODE (b) == CONST_INT)
3491 return \"ldr\\t%0, %1\";
3493 if (GET_CODE (b) == REG)
3494 return \"ldrsh\\t%0, %1\";
3502 ops[2] = const0_rtx;
3505 if (GET_CODE (ops[1]) != REG)
3511 ops[0] = operands[0];
3512 ops[3] = operands[2];
3513 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3516 [(set_attr "length" "4")
3517 (set_attr "type" "load")
3518 (set_attr "pool_range" "1020")]
3521 (define_expand "extendhisi2_mem"
3522 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3524 (zero_extend:SI (match_dup 7)))
3525 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3526 (set (match_operand:SI 0 "" "")
3527 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3532 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3534 mem1 = gen_rtx_MEM (QImode, addr);
3535 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3536 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3537 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3538 operands[0] = gen_lowpart (SImode, operands[0]);
3540 operands[2] = gen_reg_rtx (SImode);
3541 operands[3] = gen_reg_rtx (SImode);
3542 operands[6] = gen_reg_rtx (SImode);
3545 if (BYTES_BIG_ENDIAN)
3547 operands[4] = operands[2];
3548 operands[5] = operands[3];
3552 operands[4] = operands[3];
3553 operands[5] = operands[2];
3558 (define_insn "*arm_extendhisi_insn"
3559 [(set (match_operand:SI 0 "s_register_operand" "=r")
3560 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3561 "TARGET_ARM && arm_arch4"
3563 [(set_attr "type" "load")
3564 (set_attr "predicable" "yes")
3565 (set_attr "pool_range" "256")
3566 (set_attr "neg_pool_range" "244")]
3570 [(set (match_operand:SI 0 "s_register_operand" "")
3571 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3572 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3573 "TARGET_ARM && (!arm_arch4)"
3574 [(set (match_dup 2) (match_dup 1))
3575 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3577 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3583 [(set (match_operand:SI 0 "s_register_operand" "")
3584 (match_operator:SI 3 "shiftable_operator"
3585 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3586 (match_operand:SI 4 "s_register_operand" "")]))
3587 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3588 "TARGET_ARM && (!arm_arch4)"
3589 [(set (match_dup 2) (match_dup 1))
3592 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3593 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3598 (define_expand "extendqihi2"
3600 (ashift:SI (match_operand:QI 1 "general_operand" "")
3602 (set (match_operand:HI 0 "s_register_operand" "")
3603 (ashiftrt:SI (match_dup 2)
3608 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3610 emit_insn (gen_rtx_SET (VOIDmode,
3612 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3615 if (!s_register_operand (operands[1], QImode))
3616 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3617 operands[0] = gen_lowpart (SImode, operands[0]);
3618 operands[1] = gen_lowpart (SImode, operands[1]);
3619 operands[2] = gen_reg_rtx (SImode);
3623 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3624 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3625 (define_insn "*extendqihi_insn"
3626 [(set (match_operand:HI 0 "s_register_operand" "=r")
3627 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3628 "TARGET_ARM && arm_arch4"
3630 /* If the address is invalid, this will split the instruction into two. */
3631 if (bad_signed_byte_operand (operands[1], VOIDmode))
3633 return \"ldr%?sb\\t%0, %1\";
3635 [(set_attr "type" "load")
3636 (set_attr "predicable" "yes")
3637 (set_attr "length" "8")
3638 (set_attr "pool_range" "256")
3639 (set_attr "neg_pool_range" "244")]
3643 [(set (match_operand:HI 0 "s_register_operand" "")
3644 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3645 "TARGET_ARM && arm_arch4 && reload_completed"
3646 [(set (match_dup 3) (match_dup 1))
3647 (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3650 HOST_WIDE_INT offset;
3652 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3653 operands[2] = gen_rtx_MEM (QImode, operands[3]);
3654 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3655 operands[1] = XEXP (operands[1], 0);
3656 if (GET_CODE (operands[1]) == PLUS
3657 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3658 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3659 || const_ok_for_arm (-offset)))
3661 HOST_WIDE_INT low = (offset > 0
3662 ? (offset & 0xff) : -((-offset) & 0xff));
3663 XEXP (operands[2], 0) = plus_constant (operands[3], low);
3664 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3666 /* Ensure the sum is in correct canonical form */
3667 else if (GET_CODE (operands[1]) == PLUS
3668 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3669 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3670 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3671 XEXP (operands[1], 1),
3672 XEXP (operands[1], 0));
3676 (define_expand "extendqisi2"
3678 (ashift:SI (match_operand:QI 1 "general_operand" "")
3680 (set (match_operand:SI 0 "s_register_operand" "")
3681 (ashiftrt:SI (match_dup 2)
3686 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3688 emit_insn (gen_rtx_SET (VOIDmode,
3690 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3693 if (!s_register_operand (operands[1], QImode))
3694 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3695 operands[1] = gen_lowpart (SImode, operands[1]);
3696 operands[2] = gen_reg_rtx (SImode);
3702 ops[0] = operands[2];
3703 ops[1] = operands[1];
3704 ops[2] = GEN_INT (24);
3706 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3707 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3709 ops[0] = operands[0];
3710 ops[1] = operands[2];
3711 ops[2] = GEN_INT (24);
3713 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3714 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3721 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3722 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3723 (define_insn "*arm_extendqisi_insn"
3724 [(set (match_operand:SI 0 "s_register_operand" "=r")
3725 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3726 "TARGET_ARM && arm_arch4"
3728 /* If the address is invalid, this will split the instruction into two. */
3729 if (bad_signed_byte_operand (operands[1], VOIDmode))
3731 return \"ldr%?sb\\t%0, %1\";
3733 [(set_attr "type" "load")
3734 (set_attr "predicable" "yes")
3735 (set_attr "length" "8")
3736 (set_attr "pool_range" "256")
3737 (set_attr "neg_pool_range" "244")]
3741 [(set (match_operand:SI 0 "s_register_operand" "")
3742 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3743 "TARGET_ARM && arm_arch4 && reload_completed"
3744 [(set (match_dup 0) (match_dup 1))
3745 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3748 HOST_WIDE_INT offset;
3750 operands[2] = gen_rtx_MEM (QImode, operands[0]);
3751 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3752 operands[1] = XEXP (operands[1], 0);
3753 if (GET_CODE (operands[1]) == PLUS
3754 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3755 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3756 || const_ok_for_arm (-offset)))
3758 HOST_WIDE_INT low = (offset > 0
3759 ? (offset & 0xff) : -((-offset) & 0xff));
3760 XEXP (operands[2], 0) = plus_constant (operands[0], low);
3761 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3763 /* Ensure the sum is in correct canonical form */
3764 else if (GET_CODE (operands[1]) == PLUS
3765 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3766 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3767 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3768 XEXP (operands[1], 1),
3769 XEXP (operands[1], 0));
3773 (define_insn "*thumb_extendqisi2_insn"
3774 [(set (match_operand:SI 0 "register_operand" "=l,l")
3775 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3780 rtx mem = XEXP (operands[1], 0);
3782 if (GET_CODE (mem) == CONST)
3783 mem = XEXP (mem, 0);
3785 if (GET_CODE (mem) == LABEL_REF)
3786 return \"ldr\\t%0, %1\";
3788 if (GET_CODE (mem) == PLUS
3789 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3790 return \"ldr\\t%0, %1\";
3792 if (which_alternative == 0)
3793 return \"ldrsb\\t%0, %1\";
3795 ops[0] = operands[0];
3797 if (GET_CODE (mem) == PLUS)
3799 rtx a = XEXP (mem, 0);
3800 rtx b = XEXP (mem, 1);
3805 if (GET_CODE (a) == REG)
3807 if (GET_CODE (b) == REG)
3808 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3809 else if (REGNO (a) == REGNO (ops[0]))
3811 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3812 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3813 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3816 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3818 else if (GET_CODE (b) != REG)
3822 if (REGNO (b) == REGNO (ops[0]))
3824 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3825 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3826 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3829 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3832 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3834 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3835 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3836 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3841 ops[2] = const0_rtx;
3843 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3847 [(set_attr "length" "2,6")
3848 (set_attr "type" "load,load")
3849 (set_attr "pool_range" "32,32")]
3852 (define_insn "extendsfdf2"
3853 [(set (match_operand:DF 0 "s_register_operand" "=f")
3854 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
3855 "TARGET_ARM && TARGET_HARD_FLOAT"
3857 [(set_attr "type" "ffarith")
3858 (set_attr "predicable" "yes")]
3861 (define_insn "extendsfxf2"
3862 [(set (match_operand:XF 0 "s_register_operand" "=f")
3863 (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
3864 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3866 [(set_attr "type" "ffarith")
3867 (set_attr "predicable" "yes")]
3870 (define_insn "extenddfxf2"
3871 [(set (match_operand:XF 0 "s_register_operand" "=f")
3872 (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
3873 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3875 [(set_attr "type" "ffarith")
3876 (set_attr "predicable" "yes")]
3880 ;; Move insns (including loads and stores)
3882 ;; XXX Just some ideas about movti.
3883 ;; I don't think these are a good idea on the arm, there just aren't enough
3885 ;;(define_expand "loadti"
3886 ;; [(set (match_operand:TI 0 "s_register_operand" "")
3887 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
3890 ;;(define_expand "storeti"
3891 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3892 ;; (match_operand:TI 1 "s_register_operand" ""))]
3895 ;;(define_expand "movti"
3896 ;; [(set (match_operand:TI 0 "general_operand" "")
3897 ;; (match_operand:TI 1 "general_operand" ""))]
3903 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3904 ;; operands[1] = copy_to_reg (operands[1]);
3905 ;; if (GET_CODE (operands[0]) == MEM)
3906 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3907 ;; else if (GET_CODE (operands[1]) == MEM)
3908 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3912 ;; emit_insn (insn);
3916 ;; Recognise garbage generated above.
3919 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3920 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3924 ;; register mem = (which_alternative < 3);
3925 ;; register const char *template;
3927 ;; operands[mem] = XEXP (operands[mem], 0);
3928 ;; switch (which_alternative)
3930 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3931 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
3932 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
3933 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
3934 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
3935 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
3937 ;; output_asm_insn (template, operands);
3941 (define_expand "movdi"
3942 [(set (match_operand:DI 0 "general_operand" "")
3943 (match_operand:DI 1 "general_operand" ""))]
3948 if (!no_new_pseudos)
3950 if (GET_CODE (operands[0]) != REG)
3951 operands[1] = force_reg (DImode, operands[1]);
3957 (define_insn "*arm_movdi"
3958 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3959 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
3962 return (output_move_double (operands));
3964 [(set_attr "length" "8")
3965 (set_attr "type" "*,load,store2")
3966 (set_attr "pool_range" "*,1020,*")
3967 (set_attr "neg_pool_range" "*,1008,*")]
3970 ;;; ??? This should have alternatives for constants.
3971 ;;; ??? This was originally identical to the movdf_insn pattern.
3972 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3973 ;;; thumb_reorg with a memory reference.
3974 (define_insn "*thumb_movdi_insn"
3975 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3976 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
3978 && ( register_operand (operands[0], DImode)
3979 || register_operand (operands[1], DImode))"
3982 switch (which_alternative)
3986 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3987 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
3988 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
3990 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3992 operands[1] = GEN_INT (- INTVAL (operands[1]));
3993 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3995 return \"ldmia\\t%1, {%0, %H0}\";
3997 return \"stmia\\t%0, {%1, %H1}\";
3999 return thumb_load_double_from_address (operands);
4001 operands[2] = gen_rtx (MEM, SImode,
4002 plus_constant (XEXP (operands[0], 0), 4));
4003 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4006 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4007 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4008 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4011 [(set_attr "length" "4,4,6,2,2,6,4,4")
4012 (set_attr "type" "*,*,*,load,store2,load,store2,*")
4013 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4016 (define_expand "movsi"
4017 [(set (match_operand:SI 0 "general_operand" "")
4018 (match_operand:SI 1 "general_operand" ""))]
4023 /* Everything except mem = const or mem = mem can be done easily */
4024 if (GET_CODE (operands[0]) == MEM)
4025 operands[1] = force_reg (SImode, operands[1]);
4026 if (GET_CODE (operands[1]) == CONST_INT
4027 && !(const_ok_for_arm (INTVAL (operands[1]))
4028 || const_ok_for_arm (~INTVAL (operands[1]))))
4030 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4033 : preserve_subexpressions_p ()));
4037 else /* TARGET_THUMB.... */
4039 if (!no_new_pseudos)
4041 if (GET_CODE (operands[0]) != REG)
4042 operands[1] = force_reg (SImode, operands[1]);
4047 && (CONSTANT_P (operands[1])
4048 || symbol_mentioned_p (operands[1])
4049 || label_mentioned_p (operands[1])))
4050 operands[1] = legitimize_pic_address (operands[1], SImode,
4051 (no_new_pseudos ? operands[0] : 0));
4055 (define_insn "*arm_movsi_insn"
4056 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4057 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
4059 && ( register_operand (operands[0], SImode)
4060 || register_operand (operands[1], SImode))"
4066 [(set_attr "type" "*,*,load,store1")
4067 (set_attr "predicable" "yes")
4068 (set_attr "pool_range" "*,*,4096,*")
4069 (set_attr "neg_pool_range" "*,*,4084,*")]
4073 [(set (match_operand:SI 0 "s_register_operand" "")
4074 (match_operand:SI 1 "const_int_operand" ""))]
4076 && (!(const_ok_for_arm (INTVAL (operands[1]))
4077 || const_ok_for_arm (~INTVAL (operands[1]))))"
4078 [(clobber (const_int 0))]
4080 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4086 (define_insn "*thumb_movsi_insn"
4087 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4088 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
4090 && ( register_operand (operands[0], SImode)
4091 || register_operand (operands[1], SImode))"
4102 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4103 (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
4104 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4108 [(set (match_operand:SI 0 "register_operand" "")
4109 (match_operand:SI 1 "const_int_operand" ""))]
4110 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4111 [(set (match_dup 0) (match_dup 1))
4112 (set (match_dup 0) (neg:SI (match_dup 0)))]
4113 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4117 [(set (match_operand:SI 0 "register_operand" "")
4118 (match_operand:SI 1 "const_int_operand" ""))]
4119 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4120 [(set (match_dup 0) (match_dup 1))
4121 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4124 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4125 unsigned HOST_WIDE_INT mask = 0xff;
4128 for (i = 0; i < 25; i++)
4129 if ((val & (mask << i)) == val)
4132 /* Shouldn't happen, but we don't want to split if the shift is zero. */
4136 operands[1] = GEN_INT (val >> i);
4137 operands[2] = GEN_INT (i);
4141 ;; When generating pic, we need to load the symbol offset into a register.
4142 ;; So that the optimizer does not confuse this with a normal symbol load
4143 ;; we use an unspec. The offset will be loaded from a constant pool entry,
4144 ;; since that is the only type of relocation we can use.
4146 ;; The rather odd constraints on the following are to force reload to leave
4147 ;; the insn alone, and to force the minipool generation pass to then move
4148 ;; the GOT symbol to memory.
4150 (define_insn "pic_load_addr_arm"
4151 [(set (match_operand:SI 0 "s_register_operand" "=r")
4152 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4153 "TARGET_ARM && flag_pic"
4155 [(set_attr "type" "load")
4156 (set (attr "pool_range") (const_int 4096))
4157 (set (attr "neg_pool_range") (const_int 4084))]
4160 (define_insn "pic_load_addr_thumb"
4161 [(set (match_operand:SI 0 "s_register_operand" "=l")
4162 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4163 "TARGET_THUMB && flag_pic"
4165 [(set_attr "type" "load")
4166 (set (attr "pool_range") (const_int 1024))]
4169 ;; This variant is used for AOF assembly, since it needs to mention the
4170 ;; pic register in the rtl.
4171 (define_expand "pic_load_addr_based"
4172 [(set (match_operand:SI 0 "s_register_operand" "=r")
4173 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4174 "TARGET_ARM && flag_pic"
4175 "operands[2] = pic_offset_table_rtx;"
4178 (define_insn "*pic_load_addr_based_insn"
4179 [(set (match_operand:SI 0 "s_register_operand" "=r")
4180 (unspec:SI [(match_operand 1 "" "")
4181 (match_operand 2 "s_register_operand" "r")]
4183 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4185 #ifdef AOF_ASSEMBLER
4186 operands[1] = aof_pic_entry (operands[1]);
4188 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4191 [(set_attr "type" "load")
4192 (set (attr "pool_range")
4193 (if_then_else (eq_attr "is_thumb" "yes")
4196 (set (attr "neg_pool_range")
4197 (if_then_else (eq_attr "is_thumb" "yes")
4202 (define_insn "pic_add_dot_plus_four"
4203 [(set (match_operand:SI 0 "register_operand" "+r")
4204 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
4205 (use (label_ref (match_operand 1 "" "")))]
4206 "TARGET_THUMB && flag_pic"
4208 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4209 CODE_LABEL_NUMBER (operands[1]));
4210 return \"add\\t%0, %|pc\";
4212 [(set_attr "length" "2")]
4215 (define_insn "pic_add_dot_plus_eight"
4216 [(set (match_operand:SI 0 "register_operand" "+r")
4217 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
4218 (use (label_ref (match_operand 1 "" "")))]
4219 "TARGET_ARM && flag_pic"
4221 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4222 CODE_LABEL_NUMBER (operands[1]));
4223 return \"add%?\\t%0, %|pc, %0\";
4225 [(set_attr "predicable" "yes")]
4228 (define_expand "builtin_setjmp_receiver"
4229 [(label_ref (match_operand 0 "" ""))]
4233 arm_finalize_pic (0);
4237 ;; If copying one reg to another we can set the condition codes according to
4238 ;; its value. Such a move is common after a return from subroutine and the
4239 ;; result is being tested against zero.
4241 (define_insn "*movsi_compare0"
4242 [(set (reg:CC CC_REGNUM)
4243 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4245 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4250 sub%?s\\t%0, %1, #0"
4251 [(set_attr "conds" "set")]
4254 ;; Subroutine to store a half word from a register into memory.
4255 ;; Operand 0 is the source register (HImode)
4256 ;; Operand 1 is the destination address in a register (SImode)
4258 ;; In both this routine and the next, we must be careful not to spill
4259 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4260 ;; can generate unrecognizable rtl.
4262 (define_expand "storehi"
4263 [;; store the low byte
4264 (set (match_operand 1 "" "") (match_dup 3))
4265 ;; extract the high byte
4267 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4268 ;; store the high byte
4269 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
4273 rtx op1 = operands[1];
4274 rtx addr = XEXP (op1, 0);
4275 enum rtx_code code = GET_CODE (addr);
4277 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4279 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4281 operands[4] = adjust_address (op1, QImode, 1);
4282 operands[1] = adjust_address (operands[1], QImode, 0);
4283 operands[3] = gen_lowpart (QImode, operands[0]);
4284 operands[0] = gen_lowpart (SImode, operands[0]);
4285 operands[2] = gen_reg_rtx (SImode);
4289 (define_expand "storehi_bigend"
4290 [(set (match_dup 4) (match_dup 3))
4292 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4293 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 3))]
4297 rtx op1 = operands[1];
4298 rtx addr = XEXP (op1, 0);
4299 enum rtx_code code = GET_CODE (addr);
4301 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4303 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4305 operands[4] = adjust_address (op1, QImode, 1);
4306 operands[1] = adjust_address (operands[1], QImode, 0);
4307 operands[3] = gen_lowpart (QImode, operands[0]);
4308 operands[0] = gen_lowpart (SImode, operands[0]);
4309 operands[2] = gen_reg_rtx (SImode);
4313 ;; Subroutine to store a half word integer constant into memory.
4314 (define_expand "storeinthi"
4315 [(set (match_operand 0 "" "")
4316 (subreg:QI (match_operand 1 "" "") 0))
4317 (set (match_dup 3) (match_dup 2))]
4321 HOST_WIDE_INT value = INTVAL (operands[1]);
4322 rtx addr = XEXP (operands[0], 0);
4323 rtx op0 = operands[0];
4324 enum rtx_code code = GET_CODE (addr);
4326 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4328 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4330 operands[1] = gen_reg_rtx (SImode);
4331 if (BYTES_BIG_ENDIAN)
4333 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4334 if ((value & 255) == ((value >> 8) & 255))
4335 operands[2] = operands[1];
4338 operands[2] = gen_reg_rtx (SImode);
4339 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4344 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4345 if ((value & 255) == ((value >> 8) & 255))
4346 operands[2] = operands[1];
4349 operands[2] = gen_reg_rtx (SImode);
4350 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4354 operands[3] = adjust_address (op0, QImode, 1);
4355 operands[0] = adjust_address (operands[0], QImode, 0);
4356 operands[2] = gen_lowpart (QImode, operands[2]);
4360 (define_expand "storehi_single_op"
4361 [(set (match_operand:HI 0 "memory_operand" "")
4362 (match_operand:HI 1 "general_operand" ""))]
4363 "TARGET_ARM && arm_arch4"
4365 if (!s_register_operand (operands[1], HImode))
4366 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4370 (define_expand "movhi"
4371 [(set (match_operand:HI 0 "general_operand" "")
4372 (match_operand:HI 1 "general_operand" ""))]
4377 if (!no_new_pseudos)
4379 if (GET_CODE (operands[0]) == MEM)
4383 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4386 if (GET_CODE (operands[1]) == CONST_INT)
4387 emit_insn (gen_storeinthi (operands[0], operands[1]));
4390 if (GET_CODE (operands[1]) == MEM)
4391 operands[1] = force_reg (HImode, operands[1]);
4392 if (BYTES_BIG_ENDIAN)
4393 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4395 emit_insn (gen_storehi (operands[1], operands[0]));
4399 /* Sign extend a constant, and keep it in an SImode reg. */
4400 else if (GET_CODE (operands[1]) == CONST_INT)
4402 rtx reg = gen_reg_rtx (SImode);
4403 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4405 /* If the constant is already valid, leave it alone. */
4406 if (!const_ok_for_arm (val))
4408 /* If setting all the top bits will make the constant
4409 loadable in a single instruction, then set them.
4410 Otherwise, sign extend the number. */
4412 if (const_ok_for_arm (~(val | ~0xffff)))
4414 else if (val & 0x8000)
4418 emit_insn (gen_movsi (reg, GEN_INT (val)));
4419 operands[1] = gen_lowpart (HImode, reg);
4421 else if (arm_arch4 && !no_new_pseudos && optimize > 0
4422 && GET_CODE (operands[1]) == MEM)
4424 rtx reg = gen_reg_rtx (SImode);
4426 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4427 operands[1] = gen_lowpart (HImode, reg);
4429 else if (!arm_arch4)
4431 /* Note: We do not have to worry about TARGET_MMU_TRAPS
4432 for v4 and up architectures because LDRH instructions will
4433 be used to access the HI values, and these cannot generate
4434 unaligned word access faults in the MMU. */
4435 if (GET_CODE (operands[1]) == MEM)
4437 if (TARGET_MMU_TRAPS)
4440 rtx offset = const0_rtx;
4441 rtx reg = gen_reg_rtx (SImode);
4443 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4444 || (GET_CODE (base) == PLUS
4445 && (GET_CODE (offset = XEXP (base, 1))
4447 && ((INTVAL(offset) & 1) != 1)
4448 && GET_CODE (base = XEXP (base, 0)) == REG))
4449 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4451 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4454 new = gen_rtx_MEM (SImode,
4455 plus_constant (base, new_offset));
4456 MEM_COPY_ATTRIBUTES (new, operands[1]);
4457 emit_insn (gen_movsi (reg, new));
4458 if (((INTVAL (offset) & 2) != 0)
4459 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4461 rtx reg2 = gen_reg_rtx (SImode);
4463 emit_insn (gen_lshrsi3 (reg2, reg,
4469 emit_insn (gen_movhi_bytes (reg, operands[1]));
4471 operands[1] = gen_lowpart (HImode, reg);
4473 else if (BYTES_BIG_ENDIAN)
4476 rtx offset = const0_rtx;
4478 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4479 || (GET_CODE (base) == PLUS
4480 && (GET_CODE (offset = XEXP (base, 1))
4482 && GET_CODE (base = XEXP (base, 0)) == REG))
4483 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4485 rtx reg = gen_reg_rtx (SImode);
4488 if ((INTVAL (offset) & 2) == 2)
4490 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4491 new = gen_rtx_MEM (SImode,
4492 plus_constant (base,
4494 MEM_COPY_ATTRIBUTES (new, operands[1]);
4495 emit_insn (gen_movsi (reg, new));
4499 new = gen_rtx_MEM (SImode,
4500 XEXP (operands[1], 0));
4501 MEM_COPY_ATTRIBUTES (new, operands[1]);
4502 emit_insn (gen_rotated_loadsi (reg, new));
4505 operands[1] = gen_lowpart (HImode, reg);
4509 emit_insn (gen_movhi_bigend (operands[0],
4517 /* Handle loading a large integer during reload */
4518 else if (GET_CODE (operands[1]) == CONST_INT
4519 && !const_ok_for_arm (INTVAL (operands[1]))
4520 && !const_ok_for_arm (~INTVAL (operands[1])))
4522 /* Writing a constant to memory needs a scratch, which should
4523 be handled with SECONDARY_RELOADs. */
4524 if (GET_CODE (operands[0]) != REG)
4527 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4528 emit_insn (gen_movsi (operands[0], operands[1]));
4532 else /* TARGET_THUMB */
4534 if (!no_new_pseudos)
4536 if (GET_CODE (operands[0]) != REG)
4537 operands[1] = force_reg (HImode, operands[1]);
4539 /* ??? We shouldn't really get invalid addresses here, but this can
4540 happen if we are passed a SP (never OK for HImode/QImode) or
4541 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4542 HImode/QImode) relative address. */
4543 /* ??? This should perhaps be fixed elsewhere, for instance, in
4544 fixup_stack_1, by checking for other kinds of invalid addresses,
4545 e.g. a bare reference to a virtual register. This may confuse the
4546 alpha though, which must handle this case differently. */
4547 if (GET_CODE (operands[0]) == MEM
4548 && !memory_address_p (GET_MODE (operands[0]),
4549 XEXP (operands[0], 0)))
4551 = replace_equiv_address (operands[0],
4552 copy_to_reg (XEXP (operands[0], 0)));
4554 if (GET_CODE (operands[1]) == MEM
4555 && !memory_address_p (GET_MODE (operands[1]),
4556 XEXP (operands[1], 0)))
4558 = replace_equiv_address (operands[1],
4559 copy_to_reg (XEXP (operands[1], 0)));
4561 /* Handle loading a large integer during reload */
4562 else if (GET_CODE (operands[1]) == CONST_INT
4563 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4565 /* Writing a constant to memory needs a scratch, which should
4566 be handled with SECONDARY_RELOADs. */
4567 if (GET_CODE (operands[0]) != REG)
4570 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4571 emit_insn (gen_movsi (operands[0], operands[1]));
4578 (define_insn "*thumb_movhi_insn"
4579 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4580 (match_operand:HI 1 "general_operand" "l,mn,l,*h,*r,I"))]
4582 && ( register_operand (operands[0], HImode)
4583 || register_operand (operands[1], HImode))"
4585 switch (which_alternative)
4587 case 0: return \"add %0, %1, #0\";
4588 case 2: return \"strh %1, %0\";
4589 case 3: return \"mov %0, %1\";
4590 case 4: return \"mov %0, %1\";
4591 case 5: return \"mov %0, %1\";
4594 /* The stack pointer can end up being taken as an index register.
4595 Catch this case here and deal with it. */
4596 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4597 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4598 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4601 ops[0] = operands[0];
4602 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4604 output_asm_insn (\"mov %0, %1\", ops);
4606 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4609 return \"ldrh %0, %1\";
4611 [(set_attr "length" "2,4,2,2,2,2")
4612 (set_attr "type" "*,load,store1,*,*,*")
4613 (set_attr "pool_range" "*,64,*,*,*,*")]
4617 (define_insn "rotated_loadsi"
4618 [(set (match_operand:SI 0 "s_register_operand" "=r")
4619 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4621 "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4626 ops[0] = operands[0];
4627 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4628 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4631 [(set_attr "type" "load")
4632 (set_attr "predicable" "yes")]
4635 (define_expand "movhi_bytes"
4636 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4638 (zero_extend:SI (match_dup 6)))
4639 (set (match_operand:SI 0 "" "")
4640 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4645 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4647 mem1 = gen_rtx_MEM (QImode, addr);
4648 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4649 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4650 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4651 operands[0] = gen_lowpart (SImode, operands[0]);
4653 operands[2] = gen_reg_rtx (SImode);
4654 operands[3] = gen_reg_rtx (SImode);
4657 if (BYTES_BIG_ENDIAN)
4659 operands[4] = operands[2];
4660 operands[5] = operands[3];
4664 operands[4] = operands[3];
4665 operands[5] = operands[2];
4670 (define_expand "movhi_bigend"
4672 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4675 (ashiftrt:SI (match_dup 2) (const_int 16)))
4676 (set (match_operand:HI 0 "s_register_operand" "")
4677 (subreg:HI (match_dup 3) 0))]
4680 operands[2] = gen_reg_rtx (SImode);
4681 operands[3] = gen_reg_rtx (SImode);
4685 ;; Pattern to recognise insn generated default case above
4686 (define_insn "*movhi_insn_arch4"
4687 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4688 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4691 && (GET_CODE (operands[1]) != CONST_INT
4692 || const_ok_for_arm (INTVAL (operands[1]))
4693 || const_ok_for_arm (~INTVAL (operands[1])))"
4695 mov%?\\t%0, %1\\t%@ movhi
4696 mvn%?\\t%0, #%B1\\t%@ movhi
4697 str%?h\\t%1, %0\\t%@ movhi
4698 ldr%?h\\t%0, %1\\t%@ movhi"
4699 [(set_attr "type" "*,*,store1,load")
4700 (set_attr "predicable" "yes")
4701 (set_attr "pool_range" "*,*,*,256")
4702 (set_attr "neg_pool_range" "*,*,*,244")]
4705 (define_insn "*movhi_insn_littleend"
4706 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4707 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4710 && !BYTES_BIG_ENDIAN
4711 && !TARGET_MMU_TRAPS
4712 && (GET_CODE (operands[1]) != CONST_INT
4713 || const_ok_for_arm (INTVAL (operands[1]))
4714 || const_ok_for_arm (~INTVAL (operands[1])))"
4716 mov%?\\t%0, %1\\t%@ movhi
4717 mvn%?\\t%0, #%B1\\t%@ movhi
4718 ldr%?\\t%0, %1\\t%@ movhi"
4719 [(set_attr "type" "*,*,load")
4720 (set_attr "predicable" "yes")
4721 (set_attr "pool_range" "4096")
4722 (set_attr "neg_pool_range" "4084")]
4725 (define_insn "*movhi_insn_bigend"
4726 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4727 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4731 && !TARGET_MMU_TRAPS
4732 && (GET_CODE (operands[1]) != CONST_INT
4733 || const_ok_for_arm (INTVAL (operands[1]))
4734 || const_ok_for_arm (~INTVAL (operands[1])))"
4736 mov%?\\t%0, %1\\t%@ movhi
4737 mvn%?\\t%0, #%B1\\t%@ movhi
4738 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4739 [(set_attr "type" "*,*,load")
4740 (set_attr "predicable" "yes")
4741 (set_attr "length" "4,4,8")
4742 (set_attr "pool_range" "*,*,4092")
4743 (set_attr "neg_pool_range" "*,*,4084")]
4746 (define_insn "*loadhi_si_bigend"
4747 [(set (match_operand:SI 0 "s_register_operand" "=r")
4748 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
4752 && !TARGET_MMU_TRAPS"
4753 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4754 [(set_attr "type" "load")
4755 (set_attr "predicable" "yes")
4756 (set_attr "pool_range" "4096")
4757 (set_attr "neg_pool_range" "4084")]
4760 (define_insn "*movhi_bytes"
4761 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4762 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4763 "TARGET_ARM && TARGET_MMU_TRAPS"
4765 mov%?\\t%0, %1\\t%@ movhi
4766 mvn%?\\t%0, #%B1\\t%@ movhi"
4767 [(set_attr "predicable" "yes")]
4770 (define_insn "thumb_movhi_clobber"
4771 [(set (match_operand:HI 0 "memory_operand" "=m")
4772 (match_operand:HI 1 "register_operand" "l"))
4773 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4779 ;; We use a DImode scratch because we may occasionally need an additional
4780 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4781 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4782 (define_expand "reload_outhi"
4783 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4784 (match_operand:HI 1 "s_register_operand" "r")
4785 (match_operand:DI 2 "s_register_operand" "=&l")])]
4788 arm_reload_out_hi (operands);
4790 thumb_reload_out_hi (operands);
4795 (define_expand "reload_inhi"
4796 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4797 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4798 (match_operand:DI 2 "s_register_operand" "=&r")])]
4799 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4802 arm_reload_in_hi (operands);
4804 thumb_reload_out_hi (operands);
4808 (define_expand "movqi"
4809 [(set (match_operand:QI 0 "general_operand" "")
4810 (match_operand:QI 1 "general_operand" ""))]
4815 /* Everything except mem = const or mem = mem can be done easily */
4817 if (!no_new_pseudos)
4819 if (GET_CODE (operands[1]) == CONST_INT)
4821 rtx reg = gen_reg_rtx (SImode);
4823 emit_insn (gen_movsi (reg, operands[1]));
4824 operands[1] = gen_lowpart (QImode, reg);
4826 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4828 rtx reg = gen_reg_rtx (SImode);
4830 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4831 operands[1] = gen_lowpart (QImode, reg);
4833 if (GET_CODE (operands[0]) == MEM)
4834 operands[1] = force_reg (QImode, operands[1]);
4837 else /* TARGET_THUMB */
4839 if (!no_new_pseudos)
4841 if (GET_CODE (operands[0]) != REG)
4842 operands[1] = force_reg (QImode, operands[1]);
4844 /* ??? We shouldn't really get invalid addresses here, but this can
4845 happen if we are passed a SP (never OK for HImode/QImode) or
4846 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4847 HImode/QImode) relative address. */
4848 /* ??? This should perhaps be fixed elsewhere, for instance, in
4849 fixup_stack_1, by checking for other kinds of invalid addresses,
4850 e.g. a bare reference to a virtual register. This may confuse the
4851 alpha though, which must handle this case differently. */
4852 if (GET_CODE (operands[0]) == MEM
4853 && !memory_address_p (GET_MODE (operands[0]),
4854 XEXP (operands[0], 0)))
4856 = replace_equiv_address (operands[0],
4857 copy_to_reg (XEXP (operands[0], 0)));
4858 if (GET_CODE (operands[1]) == MEM
4859 && !memory_address_p (GET_MODE (operands[1]),
4860 XEXP (operands[1], 0)))
4862 = replace_equiv_address (operands[1],
4863 copy_to_reg (XEXP (operands[1], 0)));
4865 /* Handle loading a large integer during reload */
4866 else if (GET_CODE (operands[1]) == CONST_INT
4867 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4869 /* Writing a constant to memory needs a scratch, which should
4870 be handled with SECONDARY_RELOADs. */
4871 if (GET_CODE (operands[0]) != REG)
4874 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4875 emit_insn (gen_movsi (operands[0], operands[1]));
4883 (define_insn "*arm_movqi_insn"
4884 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4885 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4887 && ( register_operand (operands[0], QImode)
4888 || register_operand (operands[1], QImode))"
4894 [(set_attr "type" "*,*,load,store1")
4895 (set_attr "predicable" "yes")]
4898 (define_insn "*thumb_movqi_insn"
4899 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4900 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
4902 && ( register_operand (operands[0], QImode)
4903 || register_operand (operands[1], QImode))"
4911 [(set_attr "length" "2")
4912 (set_attr "type" "*,load,store1,*,*,*")
4913 (set_attr "pool_range" "*,32,*,*,*,*")]
4916 (define_expand "movsf"
4917 [(set (match_operand:SF 0 "general_operand" "")
4918 (match_operand:SF 1 "general_operand" ""))]
4923 if (GET_CODE (operands[0]) == MEM)
4924 operands[1] = force_reg (SFmode, operands[1]);
4926 else /* TARGET_THUMB */
4928 if (!no_new_pseudos)
4930 if (GET_CODE (operands[0]) != REG)
4931 operands[1] = force_reg (SFmode, operands[1]);
4938 [(set (match_operand:SF 0 "nonimmediate_operand" "")
4939 (match_operand:SF 1 "immediate_operand" ""))]
4941 && !TARGET_HARD_FLOAT
4943 && GET_CODE (operands[1]) == CONST_DOUBLE"
4944 [(set (match_dup 2) (match_dup 3))]
4946 operands[2] = gen_lowpart (SImode, operands[0]);
4947 operands[3] = gen_lowpart (SImode, operands[1]);
4948 if (operands[2] == 0 || operands[3] == 0)
4953 (define_insn "*arm_movsf_hard_insn"
4954 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
4955 (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
4957 && TARGET_HARD_FLOAT
4958 && (GET_CODE (operands[0]) != MEM
4959 || register_operand (operands[1], SFmode))"
4965 str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
4966 stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
4968 ldr%?\\t%0, %1\\t%@ float
4969 str%?\\t%1, %0\\t%@ float"
4970 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
4971 (set_attr "predicable" "yes")
4973 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
4974 (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
4975 (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
4978 ;; Exactly the same as above, except that all `f' cases are deleted.
4979 ;; This is necessary to prevent reload from ever trying to use a `f' reg
4980 ;; when -msoft-float.
4982 (define_insn "*arm_movsf_soft_insn"
4983 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4984 (match_operand:SF 1 "general_operand" "r,mE,r"))]
4986 && TARGET_SOFT_FLOAT
4987 && (GET_CODE (operands[0]) != MEM
4988 || register_operand (operands[1], SFmode))"
4991 ldr%?\\t%0, %1\\t%@ float
4992 str%?\\t%1, %0\\t%@ float"
4993 [(set_attr "length" "4,4,4")
4994 (set_attr "predicable" "yes")
4995 (set_attr "type" "*,load,store1")
4996 (set_attr "pool_range" "*,4096,*")
4997 (set_attr "neg_pool_range" "*,4084,*")]
5000 ;;; ??? This should have alternatives for constants.
5001 (define_insn "*thumb_movsf_insn"
5002 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5003 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
5005 && ( register_operand (operands[0], SFmode)
5006 || register_operand (operands[1], SFmode))"
5015 [(set_attr "length" "2")
5016 (set_attr "type" "*,load,store1,load,store1,*,*")
5017 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5020 (define_expand "movdf"
5021 [(set (match_operand:DF 0 "general_operand" "")
5022 (match_operand:DF 1 "general_operand" ""))]
5027 if (GET_CODE (operands[0]) == MEM)
5028 operands[1] = force_reg (DFmode, operands[1]);
5030 else /* TARGET_THUMB */
5032 if (!no_new_pseudos)
5034 if (GET_CODE (operands[0]) != REG)
5035 operands[1] = force_reg (DFmode, operands[1]);
5041 ;; Reloading a df mode value stored in integer regs to memory can require a
5043 (define_expand "reload_outdf"
5044 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5045 (match_operand:DF 1 "s_register_operand" "r")
5046 (match_operand:SI 2 "s_register_operand" "=&r")]
5050 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5053 operands[2] = XEXP (operands[0], 0);
5054 else if (code == POST_INC || code == PRE_DEC)
5056 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5057 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5058 emit_insn (gen_movdi (operands[0], operands[1]));
5061 else if (code == PRE_INC)
5063 rtx reg = XEXP (XEXP (operands[0], 0), 0);
5065 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5068 else if (code == POST_DEC)
5069 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5071 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5072 XEXP (XEXP (operands[0], 0), 1)));
5074 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5077 if (code == POST_DEC)
5078 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5084 (define_insn "*movdf_hard_insn"
5085 [(set (match_operand:DF 0 "nonimmediate_operand"
5086 "=r,Q,r,m,r, f, f,f, m,!f,!r")
5087 (match_operand:DF 1 "general_operand"
5088 "Q, r,r,r,mF,fG,H,mF,f,r, f"))]
5090 && TARGET_HARD_FLOAT
5091 && (GET_CODE (operands[0]) != MEM
5092 || register_operand (operands[1], DFmode))"
5095 switch (which_alternative)
5098 case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
5099 case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
5100 case 2: case 3: case 4: return output_move_double (operands);
5101 case 5: return \"mvf%?d\\t%0, %1\";
5102 case 6: return \"mnf%?d\\t%0, #%N1\";
5103 case 7: return \"ldf%?d\\t%0, %1\";
5104 case 8: return \"stf%?d\\t%1, %0\";
5105 case 9: return output_mov_double_fpu_from_arm (operands);
5106 case 10: return output_mov_double_arm_from_fpu (operands);
5110 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
5111 (set_attr "predicable" "yes")
5113 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
5114 (set_attr "pool_range" "*,*,*,*,1020,*,*,1024,*,*,*")
5115 (set_attr "neg_pool_range" "*,*,*,*,1008,*,*,1008,*,*,*")]
5118 ;; Software floating point version. This is essentially the same as movdi.
5119 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
5122 (define_insn "*movdf_soft_insn"
5123 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5124 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5125 "TARGET_ARM && TARGET_SOFT_FLOAT
5127 "* return output_move_double (operands);"
5128 [(set_attr "length" "8,8,8")
5129 (set_attr "type" "*,load,store2")
5130 (set_attr "pool_range" "1020")
5131 (set_attr "neg_pool_range" "1008")]
5134 ;;; ??? This should have alternatives for constants.
5135 ;;; ??? This was originally identical to the movdi_insn pattern.
5136 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5137 ;;; thumb_reorg with a memory reference.
5138 (define_insn "*thumb_movdf_insn"
5139 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5140 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
5142 && ( register_operand (operands[0], DFmode)
5143 || register_operand (operands[1], DFmode))"
5145 switch (which_alternative)
5149 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5150 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5151 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5153 return \"ldmia\\t%1, {%0, %H0}\";
5155 return \"stmia\\t%0, {%1, %H1}\";
5157 return thumb_load_double_from_address (operands);
5159 operands[2] = gen_rtx (MEM, SImode,
5160 plus_constant (XEXP (operands[0], 0), 4));
5161 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5164 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5165 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5166 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5169 [(set_attr "length" "4,2,2,6,4,4")
5170 (set_attr "type" "*,load,store2,load,store2,*")
5171 (set_attr "pool_range" "*,*,*,1020,*,*")]
5175 (define_expand "movxf"
5176 [(set (match_operand:XF 0 "general_operand" "")
5177 (match_operand:XF 1 "general_operand" ""))]
5178 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5181 ;; Even when the XFmode patterns aren't enabled, we enable this after
5182 ;; reloading so that we can push floating point registers in the prologue.
5184 (define_insn "*movxf_hard_insn"
5185 [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
5186 (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
5187 "TARGET_ARM && TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
5189 switch (which_alternative)
5192 case 0: return \"mvf%?e\\t%0, %1\";
5193 case 1: return \"mnf%?e\\t%0, #%N1\";
5194 case 2: return \"ldf%?e\\t%0, %1\";
5195 case 3: return \"stf%?e\\t%1, %0\";
5196 case 4: return output_mov_long_double_fpu_from_arm (operands);
5197 case 5: return output_mov_long_double_arm_from_fpu (operands);
5198 case 6: return output_mov_long_double_arm_from_arm (operands);
5201 [(set_attr "length" "4,4,4,4,8,8,12")
5202 (set_attr "predicable" "yes")
5203 (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
5204 (set_attr "pool_range" "*,*,1024,*,*,*,*")
5205 (set_attr "neg_pool_range" "*,*,1004,*,*,*,*")]
5209 ;; load- and store-multiple insns
5210 ;; The arm can load/store any set of registers, provided that they are in
5211 ;; ascending order; but that is beyond GCC so stick with what it knows.
5213 (define_expand "load_multiple"
5214 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5215 (match_operand:SI 1 "" ""))
5216 (use (match_operand:SI 2 "" ""))])]
5219 /* Support only fixed point registers. */
5220 if (GET_CODE (operands[2]) != CONST_INT
5221 || INTVAL (operands[2]) > 14
5222 || INTVAL (operands[2]) < 2
5223 || GET_CODE (operands[1]) != MEM
5224 || GET_CODE (operands[0]) != REG
5225 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5226 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5230 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5231 force_reg (SImode, XEXP (operands[1], 0)),
5232 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5233 MEM_IN_STRUCT_P(operands[1]),
5234 MEM_SCALAR_P (operands[1]));
5238 ;; Load multiple with write-back
5240 (define_insn "*ldmsi_postinc4"
5241 [(match_parallel 0 "load_multiple_operation"
5242 [(set (match_operand:SI 1 "s_register_operand" "=r")
5243 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5245 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5246 (mem:SI (match_dup 2)))
5247 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5248 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5249 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5250 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5251 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5252 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5253 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5254 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5255 [(set_attr "type" "load")
5256 (set_attr "predicable" "yes")]
5259 (define_insn "*ldmsi_postinc3"
5260 [(match_parallel 0 "load_multiple_operation"
5261 [(set (match_operand:SI 1 "s_register_operand" "=r")
5262 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5264 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5265 (mem:SI (match_dup 2)))
5266 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5267 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5268 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5269 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5270 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5271 "ldm%?ia\\t%1!, {%3, %4, %5}"
5272 [(set_attr "type" "load")
5273 (set_attr "predicable" "yes")]
5276 (define_insn "*ldmsi_postinc2"
5277 [(match_parallel 0 "load_multiple_operation"
5278 [(set (match_operand:SI 1 "s_register_operand" "=r")
5279 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5281 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5282 (mem:SI (match_dup 2)))
5283 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5284 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5285 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5286 "ldm%?ia\\t%1!, {%3, %4}"
5287 [(set_attr "type" "load")
5288 (set_attr "predicable" "yes")]
5291 ;; Ordinary load multiple
5293 (define_insn "*ldmsi4"
5294 [(match_parallel 0 "load_multiple_operation"
5295 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5296 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5297 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5298 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5299 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5300 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5301 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5302 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5303 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5304 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5305 [(set_attr "type" "load")
5306 (set_attr "predicable" "yes")]
5309 (define_insn "*ldmsi3"
5310 [(match_parallel 0 "load_multiple_operation"
5311 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5312 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5313 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5314 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5315 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5316 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5317 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5318 "ldm%?ia\\t%1, {%2, %3, %4}"
5319 [(set_attr "type" "load")
5320 (set_attr "predicable" "yes")]
5323 (define_insn "*ldmsi2"
5324 [(match_parallel 0 "load_multiple_operation"
5325 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5326 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5327 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5328 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5329 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5330 "ldm%?ia\\t%1, {%2, %3}"
5331 [(set_attr "type" "load")
5332 (set_attr "predicable" "yes")]
5335 (define_expand "store_multiple"
5336 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5337 (match_operand:SI 1 "" ""))
5338 (use (match_operand:SI 2 "" ""))])]
5341 /* Support only fixed point registers */
5342 if (GET_CODE (operands[2]) != CONST_INT
5343 || INTVAL (operands[2]) > 14
5344 || INTVAL (operands[2]) < 2
5345 || GET_CODE (operands[1]) != REG
5346 || GET_CODE (operands[0]) != MEM
5347 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5348 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5352 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5353 force_reg (SImode, XEXP (operands[0], 0)),
5354 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5355 MEM_IN_STRUCT_P(operands[0]),
5356 MEM_SCALAR_P (operands[0]));
5360 ;; Store multiple with write-back
5362 (define_insn "*stmsi_postinc4"
5363 [(match_parallel 0 "store_multiple_operation"
5364 [(set (match_operand:SI 1 "s_register_operand" "=r")
5365 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5367 (set (mem:SI (match_dup 2))
5368 (match_operand:SI 3 "arm_hard_register_operand" ""))
5369 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5370 (match_operand:SI 4 "arm_hard_register_operand" ""))
5371 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5372 (match_operand:SI 5 "arm_hard_register_operand" ""))
5373 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5374 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5375 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5376 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5377 [(set_attr "predicable" "yes")
5378 (set_attr "type" "store4")]
5381 (define_insn "*stmsi_postinc3"
5382 [(match_parallel 0 "store_multiple_operation"
5383 [(set (match_operand:SI 1 "s_register_operand" "=r")
5384 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5386 (set (mem:SI (match_dup 2))
5387 (match_operand:SI 3 "arm_hard_register_operand" ""))
5388 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5389 (match_operand:SI 4 "arm_hard_register_operand" ""))
5390 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5391 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5392 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5393 "stm%?ia\\t%1!, {%3, %4, %5}"
5394 [(set_attr "predicable" "yes")
5395 (set_attr "type" "store3")]
5398 (define_insn "*stmsi_postinc2"
5399 [(match_parallel 0 "store_multiple_operation"
5400 [(set (match_operand:SI 1 "s_register_operand" "=r")
5401 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5403 (set (mem:SI (match_dup 2))
5404 (match_operand:SI 3 "arm_hard_register_operand" ""))
5405 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5406 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5407 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5408 "stm%?ia\\t%1!, {%3, %4}"
5409 [(set_attr "predicable" "yes")
5410 (set_attr "type" "store2")]
5413 ;; Ordinary store multiple
5415 (define_insn "*stmsi4"
5416 [(match_parallel 0 "store_multiple_operation"
5417 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5418 (match_operand:SI 2 "arm_hard_register_operand" ""))
5419 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5420 (match_operand:SI 3 "arm_hard_register_operand" ""))
5421 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5422 (match_operand:SI 4 "arm_hard_register_operand" ""))
5423 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5424 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5425 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5426 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5427 [(set_attr "predicable" "yes")
5428 (set_attr "type" "store4")]
5431 (define_insn "*stmsi3"
5432 [(match_parallel 0 "store_multiple_operation"
5433 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5434 (match_operand:SI 2 "arm_hard_register_operand" ""))
5435 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5436 (match_operand:SI 3 "arm_hard_register_operand" ""))
5437 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5438 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5439 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5440 "stm%?ia\\t%1, {%2, %3, %4}"
5441 [(set_attr "predicable" "yes")
5442 (set_attr "type" "store3")]
5445 (define_insn "*stmsi2"
5446 [(match_parallel 0 "store_multiple_operation"
5447 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5448 (match_operand:SI 2 "arm_hard_register_operand" ""))
5449 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5450 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5451 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5452 "stm%?ia\\t%1, {%2, %3}"
5453 [(set_attr "predicable" "yes")
5454 (set_attr "type" "store2")]
5457 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5458 ;; We could let this apply for blocks of less than this, but it clobbers so
5459 ;; many registers that there is then probably a better way.
5461 (define_expand "movstrqi"
5462 [(match_operand:BLK 0 "general_operand" "")
5463 (match_operand:BLK 1 "general_operand" "")
5464 (match_operand:SI 2 "const_int_operand" "")
5465 (match_operand:SI 3 "const_int_operand" "")]
5470 if (arm_gen_movstrqi (operands))
5474 else /* TARGET_THUMB */
5476 if ( INTVAL (operands[3]) != 4
5477 || INTVAL (operands[2]) > 48)
5480 thumb_expand_movstrqi (operands);
5486 ;; Thumb block-move insns
5488 (define_insn "movmem12b"
5489 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5490 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5491 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5492 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5493 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5494 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5495 (set (match_operand:SI 0 "register_operand" "=l")
5496 (plus:SI (match_dup 2) (const_int 12)))
5497 (set (match_operand:SI 1 "register_operand" "=l")
5498 (plus:SI (match_dup 3) (const_int 12)))
5499 (clobber (match_scratch:SI 4 "=&l"))
5500 (clobber (match_scratch:SI 5 "=&l"))
5501 (clobber (match_scratch:SI 6 "=&l"))]
5503 "* return thumb_output_move_mem_multiple (3, operands);"
5504 [(set_attr "length" "4")
5505 ; This isn't entirely accurate... It loads as well, but in terms of
5506 ; scheduling the following insn it is better to consider it as a store
5507 (set_attr "type" "store3")]
5510 (define_insn "movmem8b"
5511 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5512 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5513 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5514 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5515 (set (match_operand:SI 0 "register_operand" "=l")
5516 (plus:SI (match_dup 2) (const_int 8)))
5517 (set (match_operand:SI 1 "register_operand" "=l")
5518 (plus:SI (match_dup 3) (const_int 8)))
5519 (clobber (match_scratch:SI 4 "=&l"))
5520 (clobber (match_scratch:SI 5 "=&l"))]
5522 "* return thumb_output_move_mem_multiple (2, operands);"
5523 [(set_attr "length" "4")
5524 ; This isn't entirely accurate... It loads as well, but in terms of
5525 ; scheduling the following insn it is better to consider it as a store
5526 (set_attr "type" "store2")]
5531 ;; Compare & branch insns
5532 ;; The range calcualations are based as follows:
5533 ;; For forward branches, the address calculation returns the address of
5534 ;; the next instruction. This is 2 beyond the branch instruction.
5535 ;; For backward branches, the address calculation returns the address of
5536 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5537 ;; instruction for the shortest sequence, and 4 before the branch instruction
5538 ;; if we have to jump around an unconditional branch.
5539 ;; To the basic branch range the PC offset must be added (this is +4).
5540 ;; So for forward branches we have
5541 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5542 ;; And for backward branches we have
5543 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5545 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5546 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5548 (define_insn "cbranchsi4"
5551 (match_operator 0 "arm_comparison_operator"
5552 [(match_operand:SI 1 "register_operand" "l,r")
5553 (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5554 (label_ref (match_operand 3 "" ""))
5558 output_asm_insn (\"cmp\\t%1, %2\", operands);
5559 switch (get_attr_length (insn))
5561 case 4: return \"b%d0\\t%l3\";
5562 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5563 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5566 [(set (attr "far_jump")
5568 (eq_attr "length" "8")
5569 (const_string "yes")
5570 (const_string "no")))
5571 (set (attr "length")
5573 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5574 (le (minus (match_dup 3) (pc)) (const_int 256)))
5577 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5578 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5583 (define_insn "*negated_cbranchsi4"
5586 (match_operator 0 "arm_comparison_operator"
5587 [(match_operand:SI 1 "register_operand" "l")
5588 (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5589 (label_ref (match_operand 3 "" ""))
5593 output_asm_insn (\"cmn\\t%1, %2\", operands);
5594 switch (get_attr_length (insn))
5596 case 4: return \"b%d0\\t%l3\";
5597 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5598 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5601 [(set (attr "far_jump")
5603 (eq_attr "length" "8")
5604 (const_string "yes")
5605 (const_string "no")))
5606 (set (attr "length")
5608 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5609 (le (minus (match_dup 3) (pc)) (const_int 256)))
5612 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5613 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5619 ;; Comparison and test insns
5621 (define_expand "cmpsi"
5622 [(match_operand:SI 0 "s_register_operand" "")
5623 (match_operand:SI 1 "arm_add_operand" "")]
5626 arm_compare_op0 = operands[0];
5627 arm_compare_op1 = operands[1];
5632 (define_expand "cmpsf"
5633 [(match_operand:SF 0 "s_register_operand" "")
5634 (match_operand:SF 1 "fpu_rhs_operand" "")]
5635 "TARGET_ARM && TARGET_HARD_FLOAT"
5637 arm_compare_op0 = operands[0];
5638 arm_compare_op1 = operands[1];
5643 (define_expand "cmpdf"
5644 [(match_operand:DF 0 "s_register_operand" "")
5645 (match_operand:DF 1 "fpu_rhs_operand" "")]
5646 "TARGET_ARM && TARGET_HARD_FLOAT"
5648 arm_compare_op0 = operands[0];
5649 arm_compare_op1 = operands[1];
5654 (define_expand "cmpxf"
5655 [(match_operand:XF 0 "s_register_operand" "")
5656 (match_operand:XF 1 "fpu_rhs_operand" "")]
5657 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5659 arm_compare_op0 = operands[0];
5660 arm_compare_op1 = operands[1];
5665 (define_insn "*arm_cmpsi_insn"
5666 [(set (reg:CC CC_REGNUM)
5667 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5668 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
5673 [(set_attr "conds" "set")]
5676 (define_insn "*cmpsi_shiftsi"
5677 [(set (reg:CC CC_REGNUM)
5678 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5679 (match_operator:SI 3 "shift_operator"
5680 [(match_operand:SI 1 "s_register_operand" "r")
5681 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
5684 [(set_attr "conds" "set")
5685 (set_attr "shift" "1")
5689 (define_insn "*cmpsi_shiftsi_swp"
5690 [(set (reg:CC_SWP CC_REGNUM)
5691 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5692 [(match_operand:SI 1 "s_register_operand" "r")
5693 (match_operand:SI 2 "reg_or_int_operand" "rM")])
5694 (match_operand:SI 0 "s_register_operand" "r")))]
5697 [(set_attr "conds" "set")
5698 (set_attr "shift" "1")
5702 (define_insn "*cmpsi_neg_shiftsi"
5703 [(set (reg:CC CC_REGNUM)
5704 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5705 (neg:SI (match_operator:SI 3 "shift_operator"
5706 [(match_operand:SI 1 "s_register_operand" "r")
5707 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5710 [(set_attr "conds" "set")
5711 (set_attr "shift" "1")
5715 (define_insn "*cmpsf_insn"
5716 [(set (reg:CCFP CC_REGNUM)
5717 (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
5718 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5719 "TARGET_ARM && TARGET_HARD_FLOAT"
5723 [(set_attr "conds" "set")
5724 (set_attr "type" "f_2_r")]
5727 (define_insn "*cmpdf_insn"
5728 [(set (reg:CCFP CC_REGNUM)
5729 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
5730 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5731 "TARGET_ARM && TARGET_HARD_FLOAT"
5735 [(set_attr "conds" "set")
5736 (set_attr "type" "f_2_r")]
5739 (define_insn "*cmpesfdf_df"
5740 [(set (reg:CCFP CC_REGNUM)
5741 (compare:CCFP (float_extend:DF
5742 (match_operand:SF 0 "s_register_operand" "f,f"))
5743 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5744 "TARGET_ARM && TARGET_HARD_FLOAT"
5748 [(set_attr "conds" "set")
5749 (set_attr "type" "f_2_r")]
5752 (define_insn "*cmpdf_esfdf"
5753 [(set (reg:CCFP CC_REGNUM)
5754 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5756 (match_operand:SF 1 "s_register_operand" "f"))))]
5757 "TARGET_ARM && TARGET_HARD_FLOAT"
5759 [(set_attr "conds" "set")
5760 (set_attr "type" "f_2_r")]
5763 (define_insn "*cmpxf_insn"
5764 [(set (reg:CCFP CC_REGNUM)
5765 (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
5766 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5767 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5771 [(set_attr "conds" "set")
5772 (set_attr "type" "f_2_r")]
5775 (define_insn "*cmpsf_trap"
5776 [(set (reg:CCFPE CC_REGNUM)
5777 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
5778 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5779 "TARGET_ARM && TARGET_HARD_FLOAT"
5783 [(set_attr "conds" "set")
5784 (set_attr "type" "f_2_r")]
5787 (define_insn "*cmpdf_trap"
5788 [(set (reg:CCFPE CC_REGNUM)
5789 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
5790 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5791 "TARGET_ARM && TARGET_HARD_FLOAT"
5795 [(set_attr "conds" "set")
5796 (set_attr "type" "f_2_r")]
5799 (define_insn "*cmp_esfdf_df_trap"
5800 [(set (reg:CCFPE CC_REGNUM)
5801 (compare:CCFPE (float_extend:DF
5802 (match_operand:SF 0 "s_register_operand" "f,f"))
5803 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5804 "TARGET_ARM && TARGET_HARD_FLOAT"
5808 [(set_attr "conds" "set")
5809 (set_attr "type" "f_2_r")]
5812 (define_insn "*cmp_df_esfdf_trap"
5813 [(set (reg:CCFPE CC_REGNUM)
5814 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
5816 (match_operand:SF 1 "s_register_operand" "f"))))]
5817 "TARGET_ARM && TARGET_HARD_FLOAT"
5819 [(set_attr "conds" "set")
5820 (set_attr "type" "f_2_r")]
5823 (define_insn "*cmpxf_trap"
5824 [(set (reg:CCFPE CC_REGNUM)
5825 (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
5826 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5827 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5831 [(set_attr "conds" "set")
5832 (set_attr "type" "f_2_r")]
5835 ; This insn allows redundant compares to be removed by cse, nothing should
5836 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5837 ; is deleted later on. The match_dup will match the mode here, so that
5838 ; mode changes of the condition codes aren't lost by this even though we don't
5839 ; specify what they are.
5841 (define_insn "*deleted_compare"
5842 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5844 "\\t%@ deleted compare"
5845 [(set_attr "conds" "set")
5846 (set_attr "length" "0")]
5850 ;; Conditional branch insns
5852 (define_expand "beq"
5854 (if_then_else (eq (match_dup 1) (const_int 0))
5855 (label_ref (match_operand 0 "" ""))
5858 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5861 (define_expand "bne"
5863 (if_then_else (ne (match_dup 1) (const_int 0))
5864 (label_ref (match_operand 0 "" ""))
5867 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5870 (define_expand "bgt"
5872 (if_then_else (gt (match_dup 1) (const_int 0))
5873 (label_ref (match_operand 0 "" ""))
5876 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5879 (define_expand "ble"
5881 (if_then_else (le (match_dup 1) (const_int 0))
5882 (label_ref (match_operand 0 "" ""))
5885 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5888 (define_expand "bge"
5890 (if_then_else (ge (match_dup 1) (const_int 0))
5891 (label_ref (match_operand 0 "" ""))
5894 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5897 (define_expand "blt"
5899 (if_then_else (lt (match_dup 1) (const_int 0))
5900 (label_ref (match_operand 0 "" ""))
5903 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5906 (define_expand "bgtu"
5908 (if_then_else (gtu (match_dup 1) (const_int 0))
5909 (label_ref (match_operand 0 "" ""))
5912 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5915 (define_expand "bleu"
5917 (if_then_else (leu (match_dup 1) (const_int 0))
5918 (label_ref (match_operand 0 "" ""))
5921 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5924 (define_expand "bgeu"
5926 (if_then_else (geu (match_dup 1) (const_int 0))
5927 (label_ref (match_operand 0 "" ""))
5930 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5933 (define_expand "bltu"
5935 (if_then_else (ltu (match_dup 1) (const_int 0))
5936 (label_ref (match_operand 0 "" ""))
5939 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5942 (define_expand "bunordered"
5944 (if_then_else (unordered (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 (UNORDERED, arm_compare_op0,
5952 (define_expand "bordered"
5954 (if_then_else (ordered (match_dup 1) (const_int 0))
5955 (label_ref (match_operand 0 "" ""))
5957 "TARGET_ARM && TARGET_HARD_FLOAT"
5958 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5962 (define_expand "bungt"
5964 (if_then_else (ungt (match_dup 1) (const_int 0))
5965 (label_ref (match_operand 0 "" ""))
5967 "TARGET_ARM && TARGET_HARD_FLOAT"
5968 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5971 (define_expand "bunlt"
5973 (if_then_else (unlt (match_dup 1) (const_int 0))
5974 (label_ref (match_operand 0 "" ""))
5976 "TARGET_ARM && TARGET_HARD_FLOAT"
5977 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5980 (define_expand "bunge"
5982 (if_then_else (unge (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 (UNGE, arm_compare_op0, arm_compare_op1);"
5989 (define_expand "bunle"
5991 (if_then_else (unle (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 (UNLE, arm_compare_op0, arm_compare_op1);"
5998 ;; The following two patterns need two branch instructions, since there is
5999 ;; no single instruction that will handle all cases.
6000 (define_expand "buneq"
6002 (if_then_else (uneq (match_dup 1) (const_int 0))
6003 (label_ref (match_operand 0 "" ""))
6005 "TARGET_ARM && TARGET_HARD_FLOAT"
6006 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6009 (define_expand "bltgt"
6011 (if_then_else (ltgt (match_dup 1) (const_int 0))
6012 (label_ref (match_operand 0 "" ""))
6014 "TARGET_ARM && TARGET_HARD_FLOAT"
6015 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6019 ;; Patterns to match conditional branch insns.
6022 ; Special pattern to match UNEQ.
6023 (define_insn "*arm_buneq"
6025 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6026 (label_ref (match_operand 0 "" ""))
6028 "TARGET_ARM && TARGET_HARD_FLOAT"
6030 if (arm_ccfsm_state != 0)
6033 return \"bvs\\t%l0\;beq\\t%l0\";
6035 [(set_attr "conds" "jump_clob")
6036 (set_attr "length" "8")]
6039 ; Special pattern to match LTGT.
6040 (define_insn "*arm_bltgt"
6042 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6043 (label_ref (match_operand 0 "" ""))
6045 "TARGET_ARM && TARGET_HARD_FLOAT"
6047 if (arm_ccfsm_state != 0)
6050 return \"bmi\\t%l0\;bgt\\t%l0\";
6052 [(set_attr "conds" "jump_clob")
6053 (set_attr "length" "8")]
6056 (define_insn "*arm_cond_branch"
6058 (if_then_else (match_operator 1 "arm_comparison_operator"
6059 [(match_operand 2 "cc_register" "") (const_int 0)])
6060 (label_ref (match_operand 0 "" ""))
6064 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6066 arm_ccfsm_state += 2;
6069 return \"b%d1\\t%l0\";
6071 [(set_attr "conds" "use")]
6074 ; Special pattern to match reversed UNEQ.
6075 (define_insn "*arm_buneq_reversed"
6077 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6079 (label_ref (match_operand 0 "" ""))))]
6080 "TARGET_ARM && TARGET_HARD_FLOAT"
6082 if (arm_ccfsm_state != 0)
6085 return \"bmi\\t%l0\;bgt\\t%l0\";
6087 [(set_attr "conds" "jump_clob")
6088 (set_attr "length" "8")]
6091 ; Special pattern to match reversed LTGT.
6092 (define_insn "*arm_bltgt_reversed"
6094 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6096 (label_ref (match_operand 0 "" ""))))]
6097 "TARGET_ARM && TARGET_HARD_FLOAT"
6099 if (arm_ccfsm_state != 0)
6102 return \"bvs\\t%l0\;beq\\t%l0\";
6104 [(set_attr "conds" "jump_clob")
6105 (set_attr "length" "8")]
6108 (define_insn "*arm_cond_branch_reversed"
6110 (if_then_else (match_operator 1 "arm_comparison_operator"
6111 [(match_operand 2 "cc_register" "") (const_int 0)])
6113 (label_ref (match_operand 0 "" ""))))]
6116 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6118 arm_ccfsm_state += 2;
6121 return \"b%D1\\t%l0\";
6123 [(set_attr "conds" "use")]
6130 (define_expand "seq"
6131 [(set (match_operand:SI 0 "s_register_operand" "=r")
6132 (eq:SI (match_dup 1) (const_int 0)))]
6134 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6137 (define_expand "sne"
6138 [(set (match_operand:SI 0 "s_register_operand" "=r")
6139 (ne:SI (match_dup 1) (const_int 0)))]
6141 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6144 (define_expand "sgt"
6145 [(set (match_operand:SI 0 "s_register_operand" "=r")
6146 (gt:SI (match_dup 1) (const_int 0)))]
6148 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6151 (define_expand "sle"
6152 [(set (match_operand:SI 0 "s_register_operand" "=r")
6153 (le:SI (match_dup 1) (const_int 0)))]
6155 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6158 (define_expand "sge"
6159 [(set (match_operand:SI 0 "s_register_operand" "=r")
6160 (ge:SI (match_dup 1) (const_int 0)))]
6162 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6165 (define_expand "slt"
6166 [(set (match_operand:SI 0 "s_register_operand" "=r")
6167 (lt:SI (match_dup 1) (const_int 0)))]
6169 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6172 (define_expand "sgtu"
6173 [(set (match_operand:SI 0 "s_register_operand" "=r")
6174 (gtu:SI (match_dup 1) (const_int 0)))]
6176 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6179 (define_expand "sleu"
6180 [(set (match_operand:SI 0 "s_register_operand" "=r")
6181 (leu:SI (match_dup 1) (const_int 0)))]
6183 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6186 (define_expand "sgeu"
6187 [(set (match_operand:SI 0 "s_register_operand" "=r")
6188 (geu:SI (match_dup 1) (const_int 0)))]
6190 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6193 (define_expand "sltu"
6194 [(set (match_operand:SI 0 "s_register_operand" "=r")
6195 (ltu:SI (match_dup 1) (const_int 0)))]
6197 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6200 (define_expand "sunordered"
6201 [(set (match_operand:SI 0 "s_register_operand" "=r")
6202 (unordered:SI (match_dup 1) (const_int 0)))]
6203 "TARGET_ARM && TARGET_HARD_FLOAT"
6204 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6208 (define_expand "sordered"
6209 [(set (match_operand:SI 0 "s_register_operand" "=r")
6210 (ordered:SI (match_dup 1) (const_int 0)))]
6211 "TARGET_ARM && TARGET_HARD_FLOAT"
6212 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6216 (define_expand "sungt"
6217 [(set (match_operand:SI 0 "s_register_operand" "=r")
6218 (ungt:SI (match_dup 1) (const_int 0)))]
6219 "TARGET_ARM && TARGET_HARD_FLOAT"
6220 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6224 (define_expand "sunge"
6225 [(set (match_operand:SI 0 "s_register_operand" "=r")
6226 (unge:SI (match_dup 1) (const_int 0)))]
6227 "TARGET_ARM && TARGET_HARD_FLOAT"
6228 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6232 (define_expand "sunlt"
6233 [(set (match_operand:SI 0 "s_register_operand" "=r")
6234 (unlt:SI (match_dup 1) (const_int 0)))]
6235 "TARGET_ARM && TARGET_HARD_FLOAT"
6236 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6240 (define_expand "sunle"
6241 [(set (match_operand:SI 0 "s_register_operand" "=r")
6242 (unle:SI (match_dup 1) (const_int 0)))]
6243 "TARGET_ARM && TARGET_HARD_FLOAT"
6244 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6248 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6249 ;;; simple ARM instructions.
6251 ; (define_expand "suneq"
6252 ; [(set (match_operand:SI 0 "s_register_operand" "=r")
6253 ; (uneq:SI (match_dup 1) (const_int 0)))]
6254 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6258 ; (define_expand "sltgt"
6259 ; [(set (match_operand:SI 0 "s_register_operand" "=r")
6260 ; (ltgt:SI (match_dup 1) (const_int 0)))]
6261 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6265 (define_insn "*mov_scc"
6266 [(set (match_operand:SI 0 "s_register_operand" "=r")
6267 (match_operator:SI 1 "arm_comparison_operator"
6268 [(match_operand 2 "cc_register" "") (const_int 0)]))]
6270 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6271 [(set_attr "conds" "use")
6272 (set_attr "length" "8")]
6275 (define_insn "*mov_negscc"
6276 [(set (match_operand:SI 0 "s_register_operand" "=r")
6277 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
6278 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6280 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6281 [(set_attr "conds" "use")
6282 (set_attr "length" "8")]
6285 (define_insn "*mov_notscc"
6286 [(set (match_operand:SI 0 "s_register_operand" "=r")
6287 (not:SI (match_operator:SI 1 "arm_comparison_operator"
6288 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6290 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6291 [(set_attr "conds" "use")
6292 (set_attr "length" "8")]
6296 ;; Conditional move insns
6298 (define_expand "movsicc"
6299 [(set (match_operand:SI 0 "s_register_operand" "")
6300 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6301 (match_operand:SI 2 "arm_not_operand" "")
6302 (match_operand:SI 3 "arm_not_operand" "")))]
6306 enum rtx_code code = GET_CODE (operands[1]);
6309 if (code == UNEQ || code == LTGT)
6312 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6313 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6317 (define_expand "movsfcc"
6318 [(set (match_operand:SF 0 "s_register_operand" "")
6319 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6320 (match_operand:SF 2 "s_register_operand" "")
6321 (match_operand:SF 3 "nonmemory_operand" "")))]
6325 enum rtx_code code = GET_CODE (operands[1]);
6328 if (code == UNEQ || code == LTGT)
6331 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
6332 Otherwise, ensure it is a valid FP add operand */
6333 if ((!TARGET_HARD_FLOAT)
6334 || (!fpu_add_operand (operands[3], SFmode)))
6335 operands[3] = force_reg (SFmode, operands[3]);
6337 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6338 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6342 (define_expand "movdfcc"
6343 [(set (match_operand:DF 0 "s_register_operand" "")
6344 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6345 (match_operand:DF 2 "s_register_operand" "")
6346 (match_operand:DF 3 "fpu_add_operand" "")))]
6347 "TARGET_ARM && TARGET_HARD_FLOAT"
6350 enum rtx_code code = GET_CODE (operands[1]);
6353 if (code == UNEQ || code == LTGT)
6356 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6357 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6361 (define_insn "*movsicc_insn"
6362 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6364 (match_operator 3 "arm_comparison_operator"
6365 [(match_operand 4 "cc_register" "") (const_int 0)])
6366 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6367 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6374 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6375 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6376 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6377 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6378 [(set_attr "length" "4,4,4,4,8,8,8,8")
6379 (set_attr "conds" "use")]
6382 (define_insn "*movsfcc_hard_insn"
6383 [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6385 (match_operator 3 "arm_comparison_operator"
6386 [(match_operand 4 "cc_register" "") (const_int 0)])
6387 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6388 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6389 "TARGET_ARM && TARGET_HARD_FLOAT"
6395 mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
6396 mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
6397 mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
6398 mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
6399 [(set_attr "length" "4,4,4,4,8,8,8,8")
6400 (set_attr "type" "ffarith")
6401 (set_attr "conds" "use")]
6404 (define_insn "*movsfcc_soft_insn"
6405 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6406 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
6407 [(match_operand 4 "cc_register" "") (const_int 0)])
6408 (match_operand:SF 1 "s_register_operand" "0,r")
6409 (match_operand:SF 2 "s_register_operand" "r,0")))]
6410 "TARGET_ARM && TARGET_SOFT_FLOAT"
6414 [(set_attr "conds" "use")]
6417 (define_insn "*movdfcc_insn"
6418 [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6420 (match_operator 3 "arm_comparison_operator"
6421 [(match_operand 4 "cc_register" "") (const_int 0)])
6422 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6423 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6424 "TARGET_ARM && TARGET_HARD_FLOAT"
6430 mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
6431 mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
6432 mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
6433 mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
6434 [(set_attr "length" "4,4,4,4,8,8,8,8")
6435 (set_attr "type" "ffarith")
6436 (set_attr "conds" "use")]
6440 ;; Jump and linkage insns
6442 (define_expand "jump"
6444 (label_ref (match_operand 0 "" "")))]
6449 (define_insn "*arm_jump"
6451 (label_ref (match_operand 0 "" "")))]
6455 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6457 arm_ccfsm_state += 2;
6460 return \"b%?\\t%l0\";
6463 [(set_attr "predicable" "yes")]
6466 (define_insn "*thumb_jump"
6468 (label_ref (match_operand 0 "" "")))]
6471 if (get_attr_length (insn) == 2)
6473 return \"bl\\t%l0\\t%@ far jump\";
6475 [(set (attr "far_jump")
6477 (eq_attr "length" "4")
6478 (const_string "yes")
6479 (const_string "no")))
6480 (set (attr "length")
6482 (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6483 (le (minus (match_dup 0) (pc)) (const_int 2044)))
6488 (define_expand "call"
6489 [(parallel [(call (match_operand 0 "memory_operand" "")
6490 (match_operand 1 "general_operand" ""))
6491 (use (match_operand 2 "" ""))
6492 (clobber (reg:SI LR_REGNUM))])]
6498 /* In an untyped call, we can get NULL for operand 2. */
6499 if (operands[2] == NULL_RTX)
6500 operands[2] = const0_rtx;
6502 /* This is to decide if we should generate indirect calls by loading the
6503 32 bit address of the callee into a register before performing the
6504 branch and link. operand[2] encodes the long_call/short_call
6505 attribute of the function being called. This attribute is set whenever
6506 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6507 is used, and the short_call attribute can also be set if function is
6508 declared as static or if it has already been defined in the current
6509 compilation unit. See arm.c and arm.h for info about this. The third
6510 parameter to arm_is_longcall_p is used to tell it which pattern
6512 callee = XEXP (operands[0], 0);
6514 if (GET_CODE (callee) != REG
6515 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6516 XEXP (operands[0], 0) = force_reg (Pmode, callee);
6520 (define_insn "*call_reg"
6521 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
6522 (match_operand 1 "" ""))
6523 (use (match_operand 2 "" ""))
6524 (clobber (reg:SI LR_REGNUM))]
6527 return output_call (operands);
6529 ;; length is worst case, normally it is only two
6530 [(set_attr "length" "12")
6531 (set_attr "type" "call")]
6534 (define_insn "*call_mem"
6535 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
6536 (match_operand 1 "" ""))
6537 (use (match_operand 2 "" ""))
6538 (clobber (reg:SI LR_REGNUM))]
6541 return output_call_mem (operands);
6543 [(set_attr "length" "12")
6544 (set_attr "type" "call")]
6547 (define_insn "*call_indirect"
6548 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6549 (match_operand 1 "" ""))
6550 (use (match_operand 2 "" ""))
6551 (clobber (reg:SI LR_REGNUM))]
6555 if (TARGET_CALLER_INTERWORKING)
6556 return \"bl\\t%__interwork_call_via_%0\";
6558 return \"bl\\t%__call_via_%0\";
6560 [(set_attr "type" "call")]
6563 (define_insn "*call_value_indirect"
6564 [(set (match_operand 0 "" "=l")
6565 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6566 (match_operand 2 "" "")))
6567 (use (match_operand 3 "" ""))
6568 (clobber (reg:SI LR_REGNUM))]
6572 if (TARGET_CALLER_INTERWORKING)
6573 return \"bl\\t%__interwork_call_via_%1\";
6575 return \"bl\\t%__call_via_%1\";
6577 [(set_attr "type" "call")]
6580 (define_expand "call_value"
6581 [(parallel [(set (match_operand 0 "" "")
6582 (call (match_operand 1 "memory_operand" "")
6583 (match_operand 2 "general_operand" "")))
6584 (use (match_operand 3 "" ""))
6585 (clobber (reg:SI LR_REGNUM))])]
6589 rtx callee = XEXP (operands[1], 0);
6591 /* In an untyped call, we can get NULL for operand 2. */
6592 if (operands[3] == 0)
6593 operands[3] = const0_rtx;
6595 /* See the comment in define_expand \"call\". */
6596 if (GET_CODE (callee) != REG
6597 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6598 XEXP (operands[1], 0) = force_reg (Pmode, callee);
6602 (define_insn "*call_value_reg"
6603 [(set (match_operand 0 "" "=r,f")
6604 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r"))
6605 (match_operand 2 "" "")))
6606 (use (match_operand 3 "" ""))
6607 (clobber (reg:SI LR_REGNUM))]
6610 return output_call (&operands[1]);
6612 [(set_attr "length" "12")
6613 (set_attr "type" "call")]
6616 (define_insn "*call_value_mem"
6617 [(set (match_operand 0 "" "=r,f")
6618 (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m"))
6619 (match_operand 2 "" "")))
6620 (use (match_operand 3 "" ""))
6621 (clobber (reg:SI LR_REGNUM))]
6622 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6624 return output_call_mem (&operands[1]);
6626 [(set_attr "length" "12")
6627 (set_attr "type" "call")]
6630 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6631 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6633 (define_insn "*call_symbol"
6634 [(call (mem:SI (match_operand:SI 0 "" "X"))
6635 (match_operand 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)"
6643 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6645 [(set_attr "type" "call")]
6648 (define_insn "*call_value_symbol"
6649 [(set (match_operand 0 "s_register_operand" "=r,f")
6650 (call (mem:SI (match_operand:SI 1 "" "X,X"))
6651 (match_operand:SI 2 "" "")))
6652 (use (match_operand 3 "" ""))
6653 (clobber (reg:SI LR_REGNUM))]
6655 && (GET_CODE (operands[1]) == SYMBOL_REF)
6656 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6659 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6661 [(set_attr "type" "call")]
6664 (define_insn "*call_insn"
6665 [(call (mem:SI (match_operand:SI 0 "" "X"))
6666 (match_operand:SI 1 "" ""))
6667 (use (match_operand 2 "" ""))
6668 (clobber (reg:SI LR_REGNUM))]
6670 && GET_CODE (operands[0]) == SYMBOL_REF
6671 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6673 [(set_attr "length" "4")
6674 (set_attr "type" "call")]
6677 (define_insn "*call_value_insn"
6678 [(set (match_operand 0 "register_operand" "=l")
6679 (call (mem:SI (match_operand 1 "" "X"))
6680 (match_operand 2 "" "")))
6681 (use (match_operand 3 "" ""))
6682 (clobber (reg:SI LR_REGNUM))]
6684 && GET_CODE (operands[1]) == SYMBOL_REF
6685 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6687 [(set_attr "length" "4")
6688 (set_attr "type" "call")]
6691 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6692 (define_expand "sibcall"
6693 [(parallel [(call (match_operand 0 "memory_operand" "")
6694 (match_operand 1 "general_operand" ""))
6696 (use (match_operand 2 "" ""))])]
6700 if (operands[2] == NULL_RTX)
6701 operands[2] = const0_rtx;
6705 (define_expand "sibcall_value"
6706 [(parallel [(set (match_operand 0 "register_operand" "")
6707 (call (match_operand 1 "memory_operand" "")
6708 (match_operand 2 "general_operand" "")))
6710 (use (match_operand 3 "" ""))])]
6714 if (operands[3] == NULL_RTX)
6715 operands[3] = const0_rtx;
6719 (define_insn "*sibcall_insn"
6720 [(call (mem:SI (match_operand:SI 0 "" "X"))
6721 (match_operand 1 "" ""))
6723 (use (match_operand 2 "" ""))]
6724 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6726 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6728 [(set_attr "type" "call")]
6731 (define_insn "*sibcall_value_insn"
6732 [(set (match_operand 0 "s_register_operand" "=r,f")
6733 (call (mem:SI (match_operand:SI 1 "" "X,X"))
6734 (match_operand 2 "" "")))
6736 (use (match_operand 3 "" ""))]
6737 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6739 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6741 [(set_attr "type" "call")]
6744 ;; Often the return insn will be the same as loading from memory, so set attr
6745 (define_insn "return"
6747 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6750 if (arm_ccfsm_state == 2)
6752 arm_ccfsm_state += 2;
6755 return output_return_instruction (const_true_rtx, TRUE, FALSE);
6757 [(set_attr "type" "load")
6758 (set_attr "predicable" "yes")]
6761 (define_insn "*cond_return"
6763 (if_then_else (match_operator 0 "arm_comparison_operator"
6764 [(match_operand 1 "cc_register" "") (const_int 0)])
6767 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6770 if (arm_ccfsm_state == 2)
6772 arm_ccfsm_state += 2;
6775 return output_return_instruction (operands[0], TRUE, FALSE);
6777 [(set_attr "conds" "use")
6778 (set_attr "type" "load")]
6781 (define_insn "*cond_return_inverted"
6783 (if_then_else (match_operator 0 "arm_comparison_operator"
6784 [(match_operand 1 "cc_register" "") (const_int 0)])
6787 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6790 if (arm_ccfsm_state == 2)
6792 arm_ccfsm_state += 2;
6795 return output_return_instruction (operands[0], TRUE, TRUE);
6797 [(set_attr "conds" "use")
6798 (set_attr "type" "load")]
6801 ;; Generate a sequence of instructions to determine if the processor is
6802 ;; in 26-bit or 32-bit mode, and return the appropriate return address
6805 (define_expand "return_addr_mask"
6807 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6809 (set (match_operand:SI 0 "s_register_operand" "")
6810 (if_then_else:SI (eq (match_dup 1) (const_int 0))
6812 (const_int 67108860)))] ; 0x03fffffc
6815 operands[1] = gen_rtx_REG (CC_NOOVmode, 24);
6818 (define_insn "*check_arch2"
6819 [(set (match_operand:CC_NOOV 0 "cc_register" "")
6820 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6823 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
6824 [(set_attr "length" "8")
6825 (set_attr "conds" "set")]
6828 ;; Call subroutine returning any type.
6830 (define_expand "untyped_call"
6831 [(parallel [(call (match_operand 0 "" "")
6833 (match_operand 1 "" "")
6834 (match_operand 2 "" "")])]
6840 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6842 for (i = 0; i < XVECLEN (operands[2], 0); i++)
6844 rtx set = XVECEXP (operands[2], 0, i);
6846 emit_move_insn (SET_DEST (set), SET_SRC (set));
6849 /* The optimizer does not know that the call sets the function value
6850 registers we stored in the result block. We avoid problems by
6851 claiming that all hard registers are used and clobbered at this
6853 emit_insn (gen_blockage ());
6859 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6860 ;; all of memory. This blocks insns from being moved across this point.
6862 (define_insn "blockage"
6863 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6866 [(set_attr "length" "0")
6867 (set_attr "type" "block")]
6870 (define_expand "casesi"
6871 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6872 (match_operand:SI 1 "const_int_operand" "") ; lower bound
6873 (match_operand:SI 2 "const_int_operand" "") ; total range
6874 (match_operand:SI 3 "" "") ; table label
6875 (match_operand:SI 4 "" "")] ; Out of range label
6880 if (operands[1] != const0_rtx)
6882 reg = gen_reg_rtx (SImode);
6884 emit_insn (gen_addsi3 (reg, operands[0],
6885 GEN_INT (-INTVAL (operands[1]))));
6889 if (!const_ok_for_arm (INTVAL (operands[2])))
6890 operands[2] = force_reg (SImode, operands[2]);
6892 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6898 ;; The USE in this pattern is needed to tell flow analysis that this is
6899 ;; a CASESI insn. It has no other purpose.
6900 (define_insn "casesi_internal"
6901 [(parallel [(set (pc)
6903 (leu (match_operand:SI 0 "s_register_operand" "r")
6904 (match_operand:SI 1 "arm_rhs_operand" "rI"))
6905 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6906 (label_ref (match_operand 2 "" ""))))
6907 (label_ref (match_operand 3 "" ""))))
6908 (clobber (reg:CC CC_REGNUM))
6909 (use (label_ref (match_dup 2)))])]
6913 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6914 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6916 [(set_attr "conds" "clob")
6917 (set_attr "length" "12")]
6920 (define_expand "indirect_jump"
6922 (match_operand:SI 0 "s_register_operand" ""))]
6927 (define_insn "*arm_indirect_jump"
6929 (match_operand:SI 0 "s_register_operand" "r"))]
6931 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6932 [(set_attr "predicable" "yes")]
6935 ;; Although not supported by the define_expand above,
6936 ;; cse/combine may generate this form.
6937 (define_insn "*load_indirect_jump"
6939 (match_operand:SI 0 "memory_operand" "m"))]
6941 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6942 [(set_attr "type" "load")
6943 (set_attr "pool_range" "4096")
6944 (set_attr "neg_pool_range" "4084")
6945 (set_attr "predicable" "yes")]
6948 (define_insn "*thumb_indirect_jump"
6950 (match_operand:SI 0 "register_operand" "l*r"))]
6953 [(set_attr "conds" "clob")
6954 (set_attr "length" "2")]
6965 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6966 return \"mov\\tr8, r8\";
6968 [(set (attr "length")
6969 (if_then_else (eq_attr "is_thumb" "yes")
6975 ;; Patterns to allow combination of arithmetic, cond code and shifts
6977 (define_insn "*arith_shiftsi"
6978 [(set (match_operand:SI 0 "s_register_operand" "=r")
6979 (match_operator:SI 1 "shiftable_operator"
6980 [(match_operator:SI 3 "shift_operator"
6981 [(match_operand:SI 4 "s_register_operand" "r")
6982 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6983 (match_operand:SI 2 "s_register_operand" "r")]))]
6985 "%i1%?\\t%0, %2, %4%S3"
6986 [(set_attr "predicable" "yes")
6987 (set_attr "shift" "4")
6991 (define_insn "*arith_shiftsi_compare0"
6992 [(set (reg:CC_NOOV CC_REGNUM)
6993 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6994 [(match_operator:SI 3 "shift_operator"
6995 [(match_operand:SI 4 "s_register_operand" "r")
6996 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6997 (match_operand:SI 2 "s_register_operand" "r")])
6999 (set (match_operand:SI 0 "s_register_operand" "=r")
7000 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7003 "%i1%?s\\t%0, %2, %4%S3"
7004 [(set_attr "conds" "set")
7005 (set_attr "shift" "4")
7009 (define_insn "*arith_shiftsi_compare0_scratch"
7010 [(set (reg:CC_NOOV CC_REGNUM)
7011 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7012 [(match_operator:SI 3 "shift_operator"
7013 [(match_operand:SI 4 "s_register_operand" "r")
7014 (match_operand:SI 5 "reg_or_int_operand" "rI")])
7015 (match_operand:SI 2 "s_register_operand" "r")])
7017 (clobber (match_scratch:SI 0 "=r"))]
7019 "%i1%?s\\t%0, %2, %4%S3"
7020 [(set_attr "conds" "set")
7021 (set_attr "shift" "4")
7025 (define_insn "*sub_shiftsi"
7026 [(set (match_operand:SI 0 "s_register_operand" "=r")
7027 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7028 (match_operator:SI 2 "shift_operator"
7029 [(match_operand:SI 3 "s_register_operand" "r")
7030 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7032 "sub%?\\t%0, %1, %3%S2"
7033 [(set_attr "predicable" "yes")
7034 (set_attr "shift" "3")
7038 (define_insn "*sub_shiftsi_compare0"
7039 [(set (reg:CC_NOOV CC_REGNUM)
7041 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7042 (match_operator:SI 2 "shift_operator"
7043 [(match_operand:SI 3 "s_register_operand" "r")
7044 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7046 (set (match_operand:SI 0 "s_register_operand" "=r")
7047 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7050 "sub%?s\\t%0, %1, %3%S2"
7051 [(set_attr "conds" "set")
7052 (set_attr "shift" "3")
7056 (define_insn "*sub_shiftsi_compare0_scratch"
7057 [(set (reg:CC_NOOV CC_REGNUM)
7059 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7060 (match_operator:SI 2 "shift_operator"
7061 [(match_operand:SI 3 "s_register_operand" "r")
7062 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7064 (clobber (match_scratch:SI 0 "=r"))]
7066 "sub%?s\\t%0, %1, %3%S2"
7067 [(set_attr "conds" "set")
7068 (set_attr "shift" "3")
7074 (define_insn "*and_scc"
7075 [(set (match_operand:SI 0 "s_register_operand" "=r")
7076 (and:SI (match_operator:SI 1 "arm_comparison_operator"
7077 [(match_operand 3 "cc_register" "") (const_int 0)])
7078 (match_operand:SI 2 "s_register_operand" "r")))]
7080 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7081 [(set_attr "conds" "use")
7082 (set_attr "length" "8")]
7085 (define_insn "*ior_scc"
7086 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7087 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
7088 [(match_operand 3 "cc_register" "") (const_int 0)])
7089 (match_operand:SI 1 "s_register_operand" "0,?r")))]
7093 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7094 [(set_attr "conds" "use")
7095 (set_attr "length" "4,8")]
7098 (define_insn "*compare_scc"
7099 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7100 (match_operator:SI 1 "arm_comparison_operator"
7101 [(match_operand:SI 2 "s_register_operand" "r,r")
7102 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7103 (clobber (reg:CC CC_REGNUM))]
7106 if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
7107 return \"mov\\t%0, %2, lsr #31\";
7109 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
7110 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7112 if (GET_CODE (operands[1]) == NE)
7114 if (which_alternative == 1)
7115 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7116 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7118 if (which_alternative == 1)
7119 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7121 output_asm_insn (\"cmp\\t%2, %3\", operands);
7122 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7124 [(set_attr "conds" "clob")
7125 (set_attr "length" "12")]
7128 (define_insn "*cond_move"
7129 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7130 (if_then_else:SI (match_operator 3 "equality_operator"
7131 [(match_operator 4 "arm_comparison_operator"
7132 [(match_operand 5 "cc_register" "") (const_int 0)])
7134 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7135 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7138 if (GET_CODE (operands[3]) == NE)
7140 if (which_alternative != 1)
7141 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7142 if (which_alternative != 0)
7143 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7146 if (which_alternative != 0)
7147 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7148 if (which_alternative != 1)
7149 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7152 [(set_attr "conds" "use")
7153 (set_attr "length" "4,4,8")]
7156 (define_insn "*cond_arith"
7157 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7158 (match_operator:SI 5 "shiftable_operator"
7159 [(match_operator:SI 4 "arm_comparison_operator"
7160 [(match_operand:SI 2 "s_register_operand" "r,r")
7161 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7162 (match_operand:SI 1 "s_register_operand" "0,?r")]))
7163 (clobber (reg:CC CC_REGNUM))]
7166 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7167 return \"%i5\\t%0, %1, %2, lsr #31\";
7169 output_asm_insn (\"cmp\\t%2, %3\", operands);
7170 if (GET_CODE (operands[5]) == AND)
7171 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7172 else if (GET_CODE (operands[5]) == MINUS)
7173 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7174 else if (which_alternative != 0)
7175 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7176 return \"%i5%d4\\t%0, %1, #1\";
7178 [(set_attr "conds" "clob")
7179 (set_attr "length" "12")]
7182 (define_insn "*cond_sub"
7183 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7184 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7185 (match_operator:SI 4 "arm_comparison_operator"
7186 [(match_operand:SI 2 "s_register_operand" "r,r")
7187 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7188 (clobber (reg:CC CC_REGNUM))]
7191 output_asm_insn (\"cmp\\t%2, %3\", operands);
7192 if (which_alternative != 0)
7193 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7194 return \"sub%d4\\t%0, %1, #1\";
7196 [(set_attr "conds" "clob")
7197 (set_attr "length" "8,12")]
7200 (define_insn "*cmp_ite0"
7201 [(set (match_operand 6 "dominant_cc_register" "")
7204 (match_operator 4 "arm_comparison_operator"
7205 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7206 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7207 (match_operator:SI 5 "arm_comparison_operator"
7208 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7209 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7215 static const char * const opcodes[4][2] =
7217 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7218 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7219 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7220 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7221 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7222 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7223 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7224 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7227 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7229 return opcodes[which_alternative][swap];
7231 [(set_attr "conds" "set")
7232 (set_attr "length" "8")]
7235 (define_insn "*cmp_ite1"
7236 [(set (match_operand 6 "dominant_cc_register" "")
7239 (match_operator 4 "arm_comparison_operator"
7240 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7241 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7242 (match_operator:SI 5 "arm_comparison_operator"
7243 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7244 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7250 static const char * const opcodes[4][2] =
7252 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7253 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7254 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7255 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7256 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7257 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7258 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7259 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7262 comparison_dominates_p (GET_CODE (operands[5]),
7263 reverse_condition (GET_CODE (operands[4])));
7265 return opcodes[which_alternative][swap];
7267 [(set_attr "conds" "set")
7268 (set_attr "length" "8")]
7271 (define_insn "*cmp_and"
7272 [(set (match_operand 6 "dominant_cc_register" "")
7275 (match_operator 4 "arm_comparison_operator"
7276 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7277 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7278 (match_operator:SI 5 "arm_comparison_operator"
7279 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7280 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7285 static const char *const opcodes[4][2] =
7287 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7288 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7289 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7290 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7291 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7292 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7293 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7294 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7297 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7299 return opcodes[which_alternative][swap];
7301 [(set_attr "conds" "set")
7302 (set_attr "predicable" "no")
7303 (set_attr "length" "8")]
7306 (define_insn "*cmp_ior"
7307 [(set (match_operand 6 "dominant_cc_register" "")
7310 (match_operator 4 "arm_comparison_operator"
7311 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7312 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7313 (match_operator:SI 5 "arm_comparison_operator"
7314 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7315 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7320 static const char *const opcodes[4][2] =
7322 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7323 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7324 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7325 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7326 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7327 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7328 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7329 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7332 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7334 return opcodes[which_alternative][swap];
7337 [(set_attr "conds" "set")
7338 (set_attr "length" "8")]
7341 (define_insn "*negscc"
7342 [(set (match_operand:SI 0 "s_register_operand" "=r")
7343 (neg:SI (match_operator 3 "arm_comparison_operator"
7344 [(match_operand:SI 1 "s_register_operand" "r")
7345 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7346 (clobber (reg:CC CC_REGNUM))]
7349 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7350 return \"mov\\t%0, %1, asr #31\";
7352 if (GET_CODE (operands[3]) == NE)
7353 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7355 if (GET_CODE (operands[3]) == GT)
7356 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7358 output_asm_insn (\"cmp\\t%1, %2\", operands);
7359 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7360 return \"mvn%d3\\t%0, #0\";
7362 [(set_attr "conds" "clob")
7363 (set_attr "length" "12")]
7366 (define_insn "movcond"
7367 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7369 (match_operator 5 "arm_comparison_operator"
7370 [(match_operand:SI 3 "s_register_operand" "r,r,r")
7371 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7372 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7373 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
7374 (clobber (reg:CC CC_REGNUM))]
7377 if (GET_CODE (operands[5]) == LT
7378 && (operands[4] == const0_rtx))
7380 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7382 if (operands[2] == const0_rtx)
7383 return \"and\\t%0, %1, %3, asr #31\";
7384 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
7386 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7388 if (operands[1] == const0_rtx)
7389 return \"bic\\t%0, %2, %3, asr #31\";
7390 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
7392 /* The only case that falls through to here is when both ops 1 & 2
7396 if (GET_CODE (operands[5]) == GE
7397 && (operands[4] == const0_rtx))
7399 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7401 if (operands[2] == const0_rtx)
7402 return \"bic\\t%0, %1, %3, asr #31\";
7403 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7405 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7407 if (operands[1] == const0_rtx)
7408 return \"and\\t%0, %2, %3, asr #31\";
7409 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7411 /* The only case that falls through to here is when both ops 1 & 2
7414 if (GET_CODE (operands[4]) == CONST_INT
7415 && !const_ok_for_arm (INTVAL (operands[4])))
7416 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7418 output_asm_insn (\"cmp\\t%3, %4\", operands);
7419 if (which_alternative != 0)
7420 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7421 if (which_alternative != 1)
7422 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7425 [(set_attr "conds" "clob")
7426 (set_attr "length" "8,8,12")]
7429 (define_insn "*ifcompare_plus_move"
7430 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7431 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7432 [(match_operand:SI 4 "s_register_operand" "r,r")
7433 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7435 (match_operand:SI 2 "s_register_operand" "r,r")
7436 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7437 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7438 (clobber (reg:CC CC_REGNUM))]
7441 [(set_attr "conds" "clob")
7442 (set_attr "length" "8,12")]
7445 (define_insn "*if_plus_move"
7446 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7448 (match_operator 4 "arm_comparison_operator"
7449 [(match_operand 5 "cc_register" "") (const_int 0)])
7451 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7452 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7453 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7457 sub%d4\\t%0, %2, #%n3
7458 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7459 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7460 [(set_attr "conds" "use")
7461 (set_attr "length" "4,4,8,8")
7462 (set_attr "type" "*,*,*,*")]
7465 (define_insn "*ifcompare_move_plus"
7466 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7467 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7468 [(match_operand:SI 4 "s_register_operand" "r,r")
7469 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7470 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7472 (match_operand:SI 2 "s_register_operand" "r,r")
7473 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7474 (clobber (reg:CC CC_REGNUM))]
7477 [(set_attr "conds" "clob")
7478 (set_attr "length" "8,12")]
7481 (define_insn "*if_move_plus"
7482 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7484 (match_operator 4 "arm_comparison_operator"
7485 [(match_operand 5 "cc_register" "") (const_int 0)])
7486 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7488 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7489 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7493 sub%D4\\t%0, %2, #%n3
7494 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7495 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7496 [(set_attr "conds" "use")
7497 (set_attr "length" "4,4,8,8")
7498 (set_attr "type" "*,*,*,*")]
7501 (define_insn "*ifcompare_arith_arith"
7502 [(set (match_operand:SI 0 "s_register_operand" "=r")
7503 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7504 [(match_operand:SI 5 "s_register_operand" "r")
7505 (match_operand:SI 6 "arm_add_operand" "rIL")])
7506 (match_operator:SI 8 "shiftable_operator"
7507 [(match_operand:SI 1 "s_register_operand" "r")
7508 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7509 (match_operator:SI 7 "shiftable_operator"
7510 [(match_operand:SI 3 "s_register_operand" "r")
7511 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7512 (clobber (reg:CC CC_REGNUM))]
7515 [(set_attr "conds" "clob")
7516 (set_attr "length" "12")]
7519 (define_insn "*if_arith_arith"
7520 [(set (match_operand:SI 0 "s_register_operand" "=r")
7521 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7522 [(match_operand 8 "cc_register" "") (const_int 0)])
7523 (match_operator:SI 6 "shiftable_operator"
7524 [(match_operand:SI 1 "s_register_operand" "r")
7525 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7526 (match_operator:SI 7 "shiftable_operator"
7527 [(match_operand:SI 3 "s_register_operand" "r")
7528 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7530 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7531 [(set_attr "conds" "use")
7532 (set_attr "length" "8")]
7535 (define_insn "*ifcompare_arith_move"
7536 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7537 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7538 [(match_operand:SI 2 "s_register_operand" "r,r")
7539 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7540 (match_operator:SI 7 "shiftable_operator"
7541 [(match_operand:SI 4 "s_register_operand" "r,r")
7542 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7543 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7544 (clobber (reg:CC CC_REGNUM))]
7547 /* If we have an operation where (op x 0) is the identity operation and
7548 the conditional operator is LT or GE and we are comparing against zero and
7549 everything is in registers then we can do this in two instructions */
7550 if (operands[3] == const0_rtx
7551 && GET_CODE (operands[7]) != AND
7552 && GET_CODE (operands[5]) == REG
7553 && GET_CODE (operands[1]) == REG
7554 && REGNO (operands[1]) == REGNO (operands[4])
7555 && REGNO (operands[4]) != REGNO (operands[0]))
7557 if (GET_CODE (operands[6]) == LT)
7558 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7559 else if (GET_CODE (operands[6]) == GE)
7560 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7562 if (GET_CODE (operands[3]) == CONST_INT
7563 && !const_ok_for_arm (INTVAL (operands[3])))
7564 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7566 output_asm_insn (\"cmp\\t%2, %3\", operands);
7567 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7568 if (which_alternative != 0)
7569 return \"mov%D6\\t%0, %1\";
7572 [(set_attr "conds" "clob")
7573 (set_attr "length" "8,12")]
7576 (define_insn "*if_arith_move"
7577 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7578 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7579 [(match_operand 6 "cc_register" "") (const_int 0)])
7580 (match_operator:SI 5 "shiftable_operator"
7581 [(match_operand:SI 2 "s_register_operand" "r,r")
7582 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7583 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7587 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7588 [(set_attr "conds" "use")
7589 (set_attr "length" "4,8")
7590 (set_attr "type" "*,*")]
7593 (define_insn "*ifcompare_move_arith"
7594 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7595 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7596 [(match_operand:SI 4 "s_register_operand" "r,r")
7597 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7598 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7599 (match_operator:SI 7 "shiftable_operator"
7600 [(match_operand:SI 2 "s_register_operand" "r,r")
7601 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7602 (clobber (reg:CC CC_REGNUM))]
7605 /* If we have an operation where (op x 0) is the identity operation and
7606 the conditional operator is LT or GE and we are comparing against zero and
7607 everything is in registers then we can do this in two instructions */
7608 if (operands[5] == const0_rtx
7609 && GET_CODE (operands[7]) != AND
7610 && GET_CODE (operands[3]) == REG
7611 && GET_CODE (operands[1]) == REG
7612 && REGNO (operands[1]) == REGNO (operands[2])
7613 && REGNO (operands[2]) != REGNO (operands[0]))
7615 if (GET_CODE (operands[6]) == GE)
7616 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7617 else if (GET_CODE (operands[6]) == LT)
7618 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7621 if (GET_CODE (operands[5]) == CONST_INT
7622 && !const_ok_for_arm (INTVAL (operands[5])))
7623 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7625 output_asm_insn (\"cmp\\t%4, %5\", operands);
7627 if (which_alternative != 0)
7628 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7629 return \"%I7%D6\\t%0, %2, %3\";
7631 [(set_attr "conds" "clob")
7632 (set_attr "length" "8,12")]
7635 (define_insn "*if_move_arith"
7636 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7638 (match_operator 4 "arm_comparison_operator"
7639 [(match_operand 6 "cc_register" "") (const_int 0)])
7640 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7641 (match_operator:SI 5 "shiftable_operator"
7642 [(match_operand:SI 2 "s_register_operand" "r,r")
7643 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7647 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7648 [(set_attr "conds" "use")
7649 (set_attr "length" "4,8")
7650 (set_attr "type" "*,*")]
7653 (define_insn "*ifcompare_move_not"
7654 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7656 (match_operator 5 "arm_comparison_operator"
7657 [(match_operand:SI 3 "s_register_operand" "r,r")
7658 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7659 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7661 (match_operand:SI 2 "s_register_operand" "r,r"))))
7662 (clobber (reg:CC CC_REGNUM))]
7665 [(set_attr "conds" "clob")
7666 (set_attr "length" "8,12")]
7669 (define_insn "*if_move_not"
7670 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7672 (match_operator 4 "arm_comparison_operator"
7673 [(match_operand 3 "cc_register" "") (const_int 0)])
7674 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7675 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7679 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7680 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7681 [(set_attr "conds" "use")
7682 (set_attr "length" "4,8,8")]
7685 (define_insn "*ifcompare_not_move"
7686 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7688 (match_operator 5 "arm_comparison_operator"
7689 [(match_operand:SI 3 "s_register_operand" "r,r")
7690 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7692 (match_operand:SI 2 "s_register_operand" "r,r"))
7693 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7694 (clobber (reg:CC CC_REGNUM))]
7697 [(set_attr "conds" "clob")
7698 (set_attr "length" "8,12")]
7701 (define_insn "*if_not_move"
7702 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7704 (match_operator 4 "arm_comparison_operator"
7705 [(match_operand 3 "cc_register" "") (const_int 0)])
7706 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7707 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7711 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7712 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7713 [(set_attr "conds" "use")
7714 (set_attr "length" "4,8,8")]
7717 (define_insn "*ifcompare_shift_move"
7718 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7720 (match_operator 6 "arm_comparison_operator"
7721 [(match_operand:SI 4 "s_register_operand" "r,r")
7722 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7723 (match_operator:SI 7 "shift_operator"
7724 [(match_operand:SI 2 "s_register_operand" "r,r")
7725 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7726 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7727 (clobber (reg:CC CC_REGNUM))]
7730 [(set_attr "conds" "clob")
7731 (set_attr "length" "8,12")]
7734 (define_insn "*if_shift_move"
7735 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7737 (match_operator 5 "arm_comparison_operator"
7738 [(match_operand 6 "cc_register" "") (const_int 0)])
7739 (match_operator:SI 4 "shift_operator"
7740 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7741 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7742 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7746 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7747 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7748 [(set_attr "conds" "use")
7749 (set_attr "shift" "2")
7750 (set_attr "length" "4,8,8")]
7753 (define_insn "*ifcompare_move_shift"
7754 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7756 (match_operator 6 "arm_comparison_operator"
7757 [(match_operand:SI 4 "s_register_operand" "r,r")
7758 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7759 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7760 (match_operator:SI 7 "shift_operator"
7761 [(match_operand:SI 2 "s_register_operand" "r,r")
7762 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7763 (clobber (reg:CC CC_REGNUM))]
7766 [(set_attr "conds" "clob")
7767 (set_attr "length" "8,12")]
7770 (define_insn "*if_move_shift"
7771 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7773 (match_operator 5 "arm_comparison_operator"
7774 [(match_operand 6 "cc_register" "") (const_int 0)])
7775 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7776 (match_operator:SI 4 "shift_operator"
7777 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7778 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7782 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7783 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7784 [(set_attr "conds" "use")
7785 (set_attr "shift" "2")
7786 (set_attr "length" "4,8,8")]
7789 (define_insn "*ifcompare_shift_shift"
7790 [(set (match_operand:SI 0 "s_register_operand" "=r")
7792 (match_operator 7 "arm_comparison_operator"
7793 [(match_operand:SI 5 "s_register_operand" "r")
7794 (match_operand:SI 6 "arm_add_operand" "rIL")])
7795 (match_operator:SI 8 "shift_operator"
7796 [(match_operand:SI 1 "s_register_operand" "r")
7797 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7798 (match_operator:SI 9 "shift_operator"
7799 [(match_operand:SI 3 "s_register_operand" "r")
7800 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7801 (clobber (reg:CC CC_REGNUM))]
7804 [(set_attr "conds" "clob")
7805 (set_attr "length" "12")]
7808 (define_insn "*if_shift_shift"
7809 [(set (match_operand:SI 0 "s_register_operand" "=r")
7811 (match_operator 5 "arm_comparison_operator"
7812 [(match_operand 8 "cc_register" "") (const_int 0)])
7813 (match_operator:SI 6 "shift_operator"
7814 [(match_operand:SI 1 "s_register_operand" "r")
7815 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7816 (match_operator:SI 7 "shift_operator"
7817 [(match_operand:SI 3 "s_register_operand" "r")
7818 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7820 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7821 [(set_attr "conds" "use")
7822 (set_attr "shift" "1")
7823 (set_attr "length" "8")]
7826 (define_insn "*ifcompare_not_arith"
7827 [(set (match_operand:SI 0 "s_register_operand" "=r")
7829 (match_operator 6 "arm_comparison_operator"
7830 [(match_operand:SI 4 "s_register_operand" "r")
7831 (match_operand:SI 5 "arm_add_operand" "rIL")])
7832 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7833 (match_operator:SI 7 "shiftable_operator"
7834 [(match_operand:SI 2 "s_register_operand" "r")
7835 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7836 (clobber (reg:CC CC_REGNUM))]
7839 [(set_attr "conds" "clob")
7840 (set_attr "length" "12")]
7843 (define_insn "*if_not_arith"
7844 [(set (match_operand:SI 0 "s_register_operand" "=r")
7846 (match_operator 5 "arm_comparison_operator"
7847 [(match_operand 4 "cc_register" "") (const_int 0)])
7848 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7849 (match_operator:SI 6 "shiftable_operator"
7850 [(match_operand:SI 2 "s_register_operand" "r")
7851 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7853 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7854 [(set_attr "conds" "use")
7855 (set_attr "length" "8")]
7858 (define_insn "*ifcompare_arith_not"
7859 [(set (match_operand:SI 0 "s_register_operand" "=r")
7861 (match_operator 6 "arm_comparison_operator"
7862 [(match_operand:SI 4 "s_register_operand" "r")
7863 (match_operand:SI 5 "arm_add_operand" "rIL")])
7864 (match_operator:SI 7 "shiftable_operator"
7865 [(match_operand:SI 2 "s_register_operand" "r")
7866 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7867 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7868 (clobber (reg:CC CC_REGNUM))]
7871 [(set_attr "conds" "clob")
7872 (set_attr "length" "12")]
7875 (define_insn "*if_arith_not"
7876 [(set (match_operand:SI 0 "s_register_operand" "=r")
7878 (match_operator 5 "arm_comparison_operator"
7879 [(match_operand 4 "cc_register" "") (const_int 0)])
7880 (match_operator:SI 6 "shiftable_operator"
7881 [(match_operand:SI 2 "s_register_operand" "r")
7882 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7883 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7885 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7886 [(set_attr "conds" "use")
7887 (set_attr "length" "8")]
7890 (define_insn "*ifcompare_neg_move"
7891 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7893 (match_operator 5 "arm_comparison_operator"
7894 [(match_operand:SI 3 "s_register_operand" "r,r")
7895 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7896 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7897 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7898 (clobber (reg:CC CC_REGNUM))]
7901 [(set_attr "conds" "clob")
7902 (set_attr "length" "8,12")]
7905 (define_insn "*if_neg_move"
7906 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7908 (match_operator 4 "arm_comparison_operator"
7909 [(match_operand 3 "cc_register" "") (const_int 0)])
7910 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7911 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7915 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7916 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
7917 [(set_attr "conds" "use")
7918 (set_attr "length" "4,8,8")]
7921 (define_insn "*ifcompare_move_neg"
7922 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7924 (match_operator 5 "arm_comparison_operator"
7925 [(match_operand:SI 3 "s_register_operand" "r,r")
7926 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7927 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7928 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
7929 (clobber (reg:CC CC_REGNUM))]
7932 [(set_attr "conds" "clob")
7933 (set_attr "length" "8,12")]
7936 (define_insn "*if_move_neg"
7937 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7939 (match_operator 4 "arm_comparison_operator"
7940 [(match_operand 3 "cc_register" "") (const_int 0)])
7941 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7942 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7946 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
7947 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
7948 [(set_attr "conds" "use")
7949 (set_attr "length" "4,8,8")]
7952 (define_insn "*arith_adjacentmem"
7953 [(set (match_operand:SI 0 "s_register_operand" "=r")
7954 (match_operator:SI 1 "shiftable_operator"
7955 [(match_operand:SI 2 "memory_operand" "m")
7956 (match_operand:SI 3 "memory_operand" "m")]))
7957 (clobber (match_scratch:SI 4 "=r"))]
7958 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
7963 int val1 = 0, val2 = 0;
7965 if (REGNO (operands[0]) > REGNO (operands[4]))
7967 ldm[1] = operands[4];
7968 ldm[2] = operands[0];
7972 ldm[1] = operands[0];
7973 ldm[2] = operands[4];
7975 if (GET_CODE (XEXP (operands[2], 0)) != REG)
7976 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
7977 if (GET_CODE (XEXP (operands[3], 0)) != REG)
7978 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
7979 arith[0] = operands[0];
7980 arith[3] = operands[1];
7994 ldm[0] = ops[0] = operands[4];
7995 ops[1] = XEXP (XEXP (operands[2], 0), 0);
7996 ops[2] = XEXP (XEXP (operands[2], 0), 1);
7997 output_add_immediate (ops);
7999 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8001 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8005 ldm[0] = XEXP (operands[3], 0);
8007 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8009 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8013 ldm[0] = XEXP (operands[2], 0);
8015 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8017 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8019 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
8022 [(set_attr "length" "12")
8023 (set_attr "predicable" "yes")
8024 (set_attr "type" "load")]
8027 ;; the arm can support extended pre-inc instructions
8029 ;; In all these cases, we use operands 0 and 1 for the register being
8030 ;; incremented because those are the operands that local-alloc will
8031 ;; tie and these are the pair most likely to be tieable (and the ones
8032 ;; that will benefit the most).
8034 ;; We reject the frame pointer if it occurs anywhere in these patterns since
8035 ;; elimination will cause too many headaches.
8037 (define_insn "*strqi_preinc"
8038 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8039 (match_operand:SI 2 "index_operand" "rJ")))
8040 (match_operand:QI 3 "s_register_operand" "r"))
8041 (set (match_operand:SI 0 "s_register_operand" "=r")
8042 (plus:SI (match_dup 1) (match_dup 2)))]
8044 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8045 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8046 && (GET_CODE (operands[2]) != REG
8047 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8048 "str%?b\\t%3, [%0, %2]!"
8049 [(set_attr "type" "store1")
8050 (set_attr "predicable" "yes")]
8053 (define_insn "*strqi_predec"
8054 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8055 (match_operand:SI 2 "s_register_operand" "r")))
8056 (match_operand:QI 3 "s_register_operand" "r"))
8057 (set (match_operand:SI 0 "s_register_operand" "=r")
8058 (minus:SI (match_dup 1) (match_dup 2)))]
8060 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8061 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8062 && (GET_CODE (operands[2]) != REG
8063 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8064 "str%?b\\t%3, [%0, -%2]!"
8065 [(set_attr "type" "store1")
8066 (set_attr "predicable" "yes")]
8069 (define_insn "*loadqi_preinc"
8070 [(set (match_operand:QI 3 "s_register_operand" "=r")
8071 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8072 (match_operand:SI 2 "index_operand" "rJ"))))
8073 (set (match_operand:SI 0 "s_register_operand" "=r")
8074 (plus:SI (match_dup 1) (match_dup 2)))]
8076 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8077 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8078 && (GET_CODE (operands[2]) != REG
8079 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8080 "ldr%?b\\t%3, [%0, %2]!"
8081 [(set_attr "type" "load")
8082 (set_attr "predicable" "yes")]
8085 (define_insn "*loadqi_predec"
8086 [(set (match_operand:QI 3 "s_register_operand" "=r")
8087 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8088 (match_operand:SI 2 "s_register_operand" "r"))))
8089 (set (match_operand:SI 0 "s_register_operand" "=r")
8090 (minus:SI (match_dup 1) (match_dup 2)))]
8092 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8093 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8094 && (GET_CODE (operands[2]) != REG
8095 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8096 "ldr%?b\\t%3, [%0, -%2]!"
8097 [(set_attr "type" "load")
8098 (set_attr "predicable" "yes")]
8101 (define_insn "*loadqisi_preinc"
8102 [(set (match_operand:SI 3 "s_register_operand" "=r")
8104 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8105 (match_operand:SI 2 "index_operand" "rJ")))))
8106 (set (match_operand:SI 0 "s_register_operand" "=r")
8107 (plus:SI (match_dup 1) (match_dup 2)))]
8109 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8110 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8111 && (GET_CODE (operands[2]) != REG
8112 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8113 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8114 [(set_attr "type" "load")
8115 (set_attr "predicable" "yes")]
8118 (define_insn "*loadqisi_predec"
8119 [(set (match_operand:SI 3 "s_register_operand" "=r")
8121 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8122 (match_operand:SI 2 "s_register_operand" "r")))))
8123 (set (match_operand:SI 0 "s_register_operand" "=r")
8124 (minus:SI (match_dup 1) (match_dup 2)))]
8126 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8127 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8128 && (GET_CODE (operands[2]) != REG
8129 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8130 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8131 [(set_attr "type" "load")
8132 (set_attr "predicable" "yes")]
8135 (define_insn "*strsi_preinc"
8136 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8137 (match_operand:SI 2 "index_operand" "rJ")))
8138 (match_operand:SI 3 "s_register_operand" "r"))
8139 (set (match_operand:SI 0 "s_register_operand" "=r")
8140 (plus:SI (match_dup 1) (match_dup 2)))]
8142 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8143 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8144 && (GET_CODE (operands[2]) != REG
8145 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8146 "str%?\\t%3, [%0, %2]!"
8147 [(set_attr "type" "store1")
8148 (set_attr "predicable" "yes")]
8151 (define_insn "*strsi_predec"
8152 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8153 (match_operand:SI 2 "s_register_operand" "r")))
8154 (match_operand:SI 3 "s_register_operand" "r"))
8155 (set (match_operand:SI 0 "s_register_operand" "=r")
8156 (minus:SI (match_dup 1) (match_dup 2)))]
8158 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8159 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8160 && (GET_CODE (operands[2]) != REG
8161 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8162 "str%?\\t%3, [%0, -%2]!"
8163 [(set_attr "type" "store1")
8164 (set_attr "predicable" "yes")]
8167 (define_insn "*loadsi_preinc"
8168 [(set (match_operand:SI 3 "s_register_operand" "=r")
8169 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8170 (match_operand:SI 2 "index_operand" "rJ"))))
8171 (set (match_operand:SI 0 "s_register_operand" "=r")
8172 (plus:SI (match_dup 1) (match_dup 2)))]
8174 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8175 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8176 && (GET_CODE (operands[2]) != REG
8177 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8178 "ldr%?\\t%3, [%0, %2]!"
8179 [(set_attr "type" "load")
8180 (set_attr "predicable" "yes")]
8183 (define_insn "*loadsi_predec"
8184 [(set (match_operand:SI 3 "s_register_operand" "=r")
8185 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8186 (match_operand:SI 2 "s_register_operand" "r"))))
8187 (set (match_operand:SI 0 "s_register_operand" "=r")
8188 (minus:SI (match_dup 1) (match_dup 2)))]
8190 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8191 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8192 && (GET_CODE (operands[2]) != REG
8193 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8194 "ldr%?\\t%3, [%0, -%2]!"
8195 [(set_attr "type" "load")
8196 (set_attr "predicable" "yes")]
8199 (define_insn "*loadhi_preinc"
8200 [(set (match_operand:HI 3 "s_register_operand" "=r")
8201 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8202 (match_operand:SI 2 "index_operand" "rJ"))))
8203 (set (match_operand:SI 0 "s_register_operand" "=r")
8204 (plus:SI (match_dup 1) (match_dup 2)))]
8206 && !BYTES_BIG_ENDIAN
8207 && !TARGET_MMU_TRAPS
8209 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8210 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8211 && (GET_CODE (operands[2]) != REG
8212 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8213 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8214 [(set_attr "type" "load")
8215 (set_attr "predicable" "yes")]
8218 (define_insn "*loadhi_predec"
8219 [(set (match_operand:HI 3 "s_register_operand" "=r")
8220 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8221 (match_operand:SI 2 "s_register_operand" "r"))))
8222 (set (match_operand:SI 0 "s_register_operand" "=r")
8223 (minus:SI (match_dup 1) (match_dup 2)))]
8225 && !BYTES_BIG_ENDIAN
8226 && !TARGET_MMU_TRAPS
8228 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8229 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8230 && (GET_CODE (operands[2]) != REG
8231 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8232 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8233 [(set_attr "type" "load")
8234 (set_attr "predicable" "yes")]
8237 (define_insn "*strqi_shiftpreinc"
8238 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8239 [(match_operand:SI 3 "s_register_operand" "r")
8240 (match_operand:SI 4 "const_shift_operand" "n")])
8241 (match_operand:SI 1 "s_register_operand" "0")))
8242 (match_operand:QI 5 "s_register_operand" "r"))
8243 (set (match_operand:SI 0 "s_register_operand" "=r")
8244 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8247 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8248 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8249 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8250 "str%?b\\t%5, [%0, %3%S2]!"
8251 [(set_attr "type" "store1")
8252 (set_attr "predicable" "yes")]
8255 (define_insn "*strqi_shiftpredec"
8256 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8257 (match_operator:SI 2 "shift_operator"
8258 [(match_operand:SI 3 "s_register_operand" "r")
8259 (match_operand:SI 4 "const_shift_operand" "n")])))
8260 (match_operand:QI 5 "s_register_operand" "r"))
8261 (set (match_operand:SI 0 "s_register_operand" "=r")
8262 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8265 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8266 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8267 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8268 "str%?b\\t%5, [%0, -%3%S2]!"
8269 [(set_attr "type" "store1")
8270 (set_attr "predicable" "yes")]
8273 (define_insn "*loadqi_shiftpreinc"
8274 [(set (match_operand:QI 5 "s_register_operand" "=r")
8275 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8276 [(match_operand:SI 3 "s_register_operand" "r")
8277 (match_operand:SI 4 "const_shift_operand" "n")])
8278 (match_operand:SI 1 "s_register_operand" "0"))))
8279 (set (match_operand:SI 0 "s_register_operand" "=r")
8280 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8283 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8284 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8285 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8286 "ldr%?b\\t%5, [%0, %3%S2]!"
8287 [(set_attr "type" "load")
8288 (set_attr "predicable" "yes")]
8291 (define_insn "*loadqi_shiftpredec"
8292 [(set (match_operand:QI 5 "s_register_operand" "=r")
8293 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8294 (match_operator:SI 2 "shift_operator"
8295 [(match_operand:SI 3 "s_register_operand" "r")
8296 (match_operand:SI 4 "const_shift_operand" "n")]))))
8297 (set (match_operand:SI 0 "s_register_operand" "=r")
8298 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8301 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8302 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8303 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8304 "ldr%?b\\t%5, [%0, -%3%S2]!"
8305 [(set_attr "type" "load")
8306 (set_attr "predicable" "yes")]
8309 (define_insn "*strsi_shiftpreinc"
8310 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8311 [(match_operand:SI 3 "s_register_operand" "r")
8312 (match_operand:SI 4 "const_shift_operand" "n")])
8313 (match_operand:SI 1 "s_register_operand" "0")))
8314 (match_operand:SI 5 "s_register_operand" "r"))
8315 (set (match_operand:SI 0 "s_register_operand" "=r")
8316 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8319 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8320 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8321 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8322 "str%?\\t%5, [%0, %3%S2]!"
8323 [(set_attr "type" "store1")
8324 (set_attr "predicable" "yes")]
8327 (define_insn "*strsi_shiftpredec"
8328 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8329 (match_operator:SI 2 "shift_operator"
8330 [(match_operand:SI 3 "s_register_operand" "r")
8331 (match_operand:SI 4 "const_shift_operand" "n")])))
8332 (match_operand:SI 5 "s_register_operand" "r"))
8333 (set (match_operand:SI 0 "s_register_operand" "=r")
8334 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8337 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8338 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8339 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8340 "str%?\\t%5, [%0, -%3%S2]!"
8341 [(set_attr "type" "store1")
8342 (set_attr "predicable" "yes")]
8345 (define_insn "*loadsi_shiftpreinc"
8346 [(set (match_operand:SI 5 "s_register_operand" "=r")
8347 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8348 [(match_operand:SI 3 "s_register_operand" "r")
8349 (match_operand:SI 4 "const_shift_operand" "n")])
8350 (match_operand:SI 1 "s_register_operand" "0"))))
8351 (set (match_operand:SI 0 "s_register_operand" "=r")
8352 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8355 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8356 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8357 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8358 "ldr%?\\t%5, [%0, %3%S2]!"
8359 [(set_attr "type" "load")
8360 (set_attr "predicable" "yes")]
8363 (define_insn "*loadsi_shiftpredec"
8364 [(set (match_operand:SI 5 "s_register_operand" "=r")
8365 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8366 (match_operator:SI 2 "shift_operator"
8367 [(match_operand:SI 3 "s_register_operand" "r")
8368 (match_operand:SI 4 "const_shift_operand" "n")]))))
8369 (set (match_operand:SI 0 "s_register_operand" "=r")
8370 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8373 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8374 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8375 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8376 "ldr%?\\t%5, [%0, -%3%S2]!"
8377 [(set_attr "type" "load")
8378 (set_attr "predicable" "yes")])
8380 (define_insn "*loadhi_shiftpreinc"
8381 [(set (match_operand:HI 5 "s_register_operand" "=r")
8382 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8383 [(match_operand:SI 3 "s_register_operand" "r")
8384 (match_operand:SI 4 "const_shift_operand" "n")])
8385 (match_operand:SI 1 "s_register_operand" "0"))))
8386 (set (match_operand:SI 0 "s_register_operand" "=r")
8387 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8390 && !BYTES_BIG_ENDIAN
8391 && !TARGET_MMU_TRAPS
8393 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8394 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8395 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8396 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8397 [(set_attr "type" "load")
8398 (set_attr "predicable" "yes")]
8401 (define_insn "*loadhi_shiftpredec"
8402 [(set (match_operand:HI 5 "s_register_operand" "=r")
8403 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8404 (match_operator:SI 2 "shift_operator"
8405 [(match_operand:SI 3 "s_register_operand" "r")
8406 (match_operand:SI 4 "const_shift_operand" "n")]))))
8407 (set (match_operand:SI 0 "s_register_operand" "=r")
8408 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8411 && !BYTES_BIG_ENDIAN
8412 && !TARGET_MMU_TRAPS
8414 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8415 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8416 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8417 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8418 [(set_attr "type" "load")
8419 (set_attr "predicable" "yes")]
8422 ; It can also support extended post-inc expressions, but combine doesn't
8424 ; It doesn't seem worth adding peepholes for anything but the most common
8425 ; cases since, unlike combine, the increment must immediately follow the load
8426 ; for this pattern to match.
8427 ; We must watch to see that the source/destination register isn't also the
8428 ; same as the base address register, and that if the index is a register,
8429 ; that it is not the same as the base address register. In such cases the
8430 ; instruction that we would generate would have UNPREDICTABLE behaviour so
8434 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8435 (match_operand:QI 2 "s_register_operand" "r"))
8437 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8439 && (REGNO (operands[2]) != REGNO (operands[0]))
8440 && (GET_CODE (operands[1]) != REG
8441 || (REGNO (operands[1]) != REGNO (operands[0])))"
8442 "str%?b\\t%2, [%0], %1"
8446 [(set (match_operand:QI 0 "s_register_operand" "=r")
8447 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8449 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8451 && REGNO (operands[0]) != REGNO(operands[1])
8452 && (GET_CODE (operands[2]) != REG
8453 || REGNO(operands[0]) != REGNO (operands[2]))"
8454 "ldr%?b\\t%0, [%1], %2"
8458 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8459 (match_operand:SI 2 "s_register_operand" "r"))
8461 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8463 && (REGNO (operands[2]) != REGNO (operands[0]))
8464 && (GET_CODE (operands[1]) != REG
8465 || (REGNO (operands[1]) != REGNO (operands[0])))"
8466 "str%?\\t%2, [%0], %1"
8470 [(set (match_operand:HI 0 "s_register_operand" "=r")
8471 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8473 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8475 && !BYTES_BIG_ENDIAN
8476 && !TARGET_MMU_TRAPS
8478 && REGNO (operands[0]) != REGNO(operands[1])
8479 && (GET_CODE (operands[2]) != REG
8480 || REGNO(operands[0]) != REGNO (operands[2]))"
8481 "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8485 [(set (match_operand:SI 0 "s_register_operand" "=r")
8486 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8488 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8490 && REGNO (operands[0]) != REGNO(operands[1])
8491 && (GET_CODE (operands[2]) != REG
8492 || REGNO(operands[0]) != REGNO (operands[2]))"
8493 "ldr%?\\t%0, [%1], %2"
8497 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8498 (match_operand:SI 1 "index_operand" "rJ")))
8499 (match_operand:QI 2 "s_register_operand" "r"))
8500 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8502 && (REGNO (operands[2]) != REGNO (operands[0]))
8503 && (GET_CODE (operands[1]) != REG
8504 || (REGNO (operands[1]) != REGNO (operands[0])))"
8505 "str%?b\\t%2, [%0, %1]!"
8509 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8510 [(match_operand:SI 0 "s_register_operand" "r")
8511 (match_operand:SI 1 "const_int_operand" "n")])
8512 (match_operand:SI 2 "s_register_operand" "+r")))
8513 (match_operand:QI 3 "s_register_operand" "r"))
8514 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8517 && (REGNO (operands[3]) != REGNO (operands[2]))
8518 && (REGNO (operands[0]) != REGNO (operands[2]))"
8519 "str%?b\\t%3, [%2, %0%S4]!"
8522 ; This pattern is never tried by combine, so do it as a peephole
8525 [(set (match_operand:SI 0 "s_register_operand" "")
8526 (match_operand:SI 1 "s_register_operand" ""))
8527 (set (reg:CC CC_REGNUM)
8528 (compare:CC (match_dup 1) (const_int 0)))]
8531 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8532 (set (match_dup 0) (match_dup 1))])]
8536 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8537 ; reversed, check that the memory references aren't volatile.
8540 [(set (match_operand:SI 0 "s_register_operand" "=r")
8541 (match_operand:SI 4 "memory_operand" "m"))
8542 (set (match_operand:SI 1 "s_register_operand" "=r")
8543 (match_operand:SI 5 "memory_operand" "m"))
8544 (set (match_operand:SI 2 "s_register_operand" "=r")
8545 (match_operand:SI 6 "memory_operand" "m"))
8546 (set (match_operand:SI 3 "s_register_operand" "=r")
8547 (match_operand:SI 7 "memory_operand" "m"))]
8548 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8550 return emit_ldm_seq (operands, 4);
8555 [(set (match_operand:SI 0 "s_register_operand" "=r")
8556 (match_operand:SI 3 "memory_operand" "m"))
8557 (set (match_operand:SI 1 "s_register_operand" "=r")
8558 (match_operand:SI 4 "memory_operand" "m"))
8559 (set (match_operand:SI 2 "s_register_operand" "=r")
8560 (match_operand:SI 5 "memory_operand" "m"))]
8561 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8563 return emit_ldm_seq (operands, 3);
8568 [(set (match_operand:SI 0 "s_register_operand" "=r")
8569 (match_operand:SI 2 "memory_operand" "m"))
8570 (set (match_operand:SI 1 "s_register_operand" "=r")
8571 (match_operand:SI 3 "memory_operand" "m"))]
8572 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8574 return emit_ldm_seq (operands, 2);
8579 [(set (match_operand:SI 4 "memory_operand" "=m")
8580 (match_operand:SI 0 "s_register_operand" "r"))
8581 (set (match_operand:SI 5 "memory_operand" "=m")
8582 (match_operand:SI 1 "s_register_operand" "r"))
8583 (set (match_operand:SI 6 "memory_operand" "=m")
8584 (match_operand:SI 2 "s_register_operand" "r"))
8585 (set (match_operand:SI 7 "memory_operand" "=m")
8586 (match_operand:SI 3 "s_register_operand" "r"))]
8587 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8589 return emit_stm_seq (operands, 4);
8594 [(set (match_operand:SI 3 "memory_operand" "=m")
8595 (match_operand:SI 0 "s_register_operand" "r"))
8596 (set (match_operand:SI 4 "memory_operand" "=m")
8597 (match_operand:SI 1 "s_register_operand" "r"))
8598 (set (match_operand:SI 5 "memory_operand" "=m")
8599 (match_operand:SI 2 "s_register_operand" "r"))]
8600 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8602 return emit_stm_seq (operands, 3);
8607 [(set (match_operand:SI 2 "memory_operand" "=m")
8608 (match_operand:SI 0 "s_register_operand" "r"))
8609 (set (match_operand:SI 3 "memory_operand" "=m")
8610 (match_operand:SI 1 "s_register_operand" "r"))]
8611 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8613 return emit_stm_seq (operands, 2);
8618 [(set (match_operand:SI 0 "s_register_operand" "")
8619 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8621 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8622 [(match_operand:SI 3 "s_register_operand" "")
8623 (match_operand:SI 4 "arm_rhs_operand" "")]))))
8624 (clobber (match_operand:SI 5 "s_register_operand" ""))]
8626 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8627 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8632 ;; This split can be used because CC_Z mode implies that the following
8633 ;; branch will be an equality, or an unsigned inequality, so the sign
8634 ;; extension is not needed.
8637 [(set (reg:CC_Z CC_REGNUM)
8639 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8641 (match_operand 1 "const_int_operand" "")))
8642 (clobber (match_scratch:SI 2 ""))]
8644 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8645 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8646 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8647 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8649 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8653 (define_expand "prologue"
8654 [(clobber (const_int 0))]
8657 arm_expand_prologue ();
8659 thumb_expand_prologue ();
8664 (define_expand "epilogue"
8665 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8669 thumb_expand_epilogue ();
8670 else if (USE_RETURN_INSN (FALSE))
8672 emit_jump_insn (gen_return ());
8675 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8677 gen_rtx_RETURN (VOIDmode)),
8683 (define_insn "sibcall_epilogue"
8684 [(unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)]
8687 if (USE_RETURN_INSN (FALSE))
8688 return output_return_instruction (const_true_rtx, FALSE, FALSE);
8689 return arm_output_epilogue (FALSE);
8691 ;; Length is absolute worst case
8692 [(set_attr "length" "44")
8693 (set_attr "type" "block")]
8696 (define_insn "*epilogue_insns"
8697 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8701 return arm_output_epilogue (TRUE);
8702 else /* TARGET_THUMB */
8703 return thumb_unexpanded_epilogue ();
8705 ; Length is absolute worst case
8706 [(set_attr "length" "44")
8707 (set_attr "type" "block")]
8710 (define_expand "eh_epilogue"
8711 [(use (match_operand:SI 0 "register_operand" "r"))
8712 (use (match_operand:SI 1 "register_operand" "r"))
8713 (use (match_operand:SI 2 "register_operand" "r"))]
8717 cfun->machine->eh_epilogue_sp_ofs = operands[1];
8718 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8720 rtx ra = gen_rtx_REG (Pmode, 2);
8722 emit_move_insn (ra, operands[2]);
8725 /* This is a hack -- we may have crystalized the function type too
8727 cfun->machine->func_type = 0;
8731 ;; This split is only used during output to reduce the number of patterns
8732 ;; that need assembler instructions adding to them. We allowed the setting
8733 ;; of the conditions to be implicit during rtl generation so that
8734 ;; the conditional compare patterns would work. However this conflicts to
8735 ;; some extent with the conditional data operations, so we have to split them
8739 [(set (match_operand:SI 0 "s_register_operand" "")
8740 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8741 [(match_operand 2 "" "") (match_operand 3 "" "")])
8743 (match_operand 4 "" "")))
8744 (clobber (reg:CC CC_REGNUM))]
8745 "TARGET_ARM && reload_completed"
8746 [(set (match_dup 5) (match_dup 6))
8747 (cond_exec (match_dup 7)
8748 (set (match_dup 0) (match_dup 4)))]
8751 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8752 operands[2], operands[3]);
8753 enum rtx_code rc = GET_CODE (operands[1]);
8755 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8756 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8757 if (mode == CCFPmode || mode == CCFPEmode)
8758 rc = reverse_condition_maybe_unordered (rc);
8760 rc = reverse_condition (rc);
8762 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8767 [(set (match_operand:SI 0 "s_register_operand" "")
8768 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8769 [(match_operand 2 "" "") (match_operand 3 "" "")])
8770 (match_operand 4 "" "")
8772 (clobber (reg:CC CC_REGNUM))]
8773 "TARGET_ARM && reload_completed"
8774 [(set (match_dup 5) (match_dup 6))
8775 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8776 (set (match_dup 0) (match_dup 4)))]
8779 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8780 operands[2], operands[3]);
8782 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8783 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8788 [(set (match_operand:SI 0 "s_register_operand" "")
8789 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8790 [(match_operand 2 "" "") (match_operand 3 "" "")])
8791 (match_operand 4 "" "")
8792 (match_operand 5 "" "")))
8793 (clobber (reg:CC CC_REGNUM))]
8794 "TARGET_ARM && reload_completed"
8795 [(set (match_dup 6) (match_dup 7))
8796 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8797 (set (match_dup 0) (match_dup 4)))
8798 (cond_exec (match_dup 8)
8799 (set (match_dup 0) (match_dup 5)))]
8802 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8803 operands[2], operands[3]);
8804 enum rtx_code rc = GET_CODE (operands[1]);
8806 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8807 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8808 if (mode == CCFPmode || mode == CCFPEmode)
8809 rc = reverse_condition_maybe_unordered (rc);
8811 rc = reverse_condition (rc);
8813 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8818 [(set (match_operand:SI 0 "s_register_operand" "")
8819 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8820 [(match_operand:SI 2 "s_register_operand" "")
8821 (match_operand:SI 3 "arm_add_operand" "")])
8822 (match_operand:SI 4 "arm_rhs_operand" "")
8824 (match_operand:SI 5 "s_register_operand" ""))))
8825 (clobber (reg:CC CC_REGNUM))]
8826 "TARGET_ARM && reload_completed"
8827 [(set (match_dup 6) (match_dup 7))
8828 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8829 (set (match_dup 0) (match_dup 4)))
8830 (cond_exec (match_dup 8)
8831 (set (match_dup 0) (not:SI (match_dup 5))))]
8834 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8835 operands[2], operands[3]);
8836 enum rtx_code rc = GET_CODE (operands[1]);
8838 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8839 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8840 if (mode == CCFPmode || mode == CCFPEmode)
8841 rc = reverse_condition_maybe_unordered (rc);
8843 rc = reverse_condition (rc);
8845 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8849 (define_insn "*cond_move_not"
8850 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8851 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8852 [(match_operand 3 "cc_register" "") (const_int 0)])
8853 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8855 (match_operand:SI 2 "s_register_operand" "r,r"))))]
8859 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8860 [(set_attr "conds" "use")
8861 (set_attr "length" "4,8")]
8864 ;; The next two patterns occur when an AND operation is followed by a
8865 ;; scc insn sequence
8867 (define_insn "*sign_extract_onebit"
8868 [(set (match_operand:SI 0 "s_register_operand" "=r")
8869 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8871 (match_operand:SI 2 "const_int_operand" "n")))]
8874 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8875 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8876 return \"mvnne\\t%0, #0\";
8878 [(set_attr "conds" "clob")
8879 (set_attr "length" "8")]
8882 (define_insn "*not_signextract_onebit"
8883 [(set (match_operand:SI 0 "s_register_operand" "=r")
8885 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8887 (match_operand:SI 2 "const_int_operand" "n"))))]
8890 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8891 output_asm_insn (\"tst\\t%1, %2\", operands);
8892 output_asm_insn (\"mvneq\\t%0, #0\", operands);
8893 return \"movne\\t%0, #0\";
8895 [(set_attr "conds" "clob")
8896 (set_attr "length" "12")]
8899 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
8900 ;; expressions. For simplicity, the first register is also in the unspec
8902 (define_insn "*push_multi"
8903 [(match_parallel 2 "multi_register_push"
8904 [(set (match_operand:BLK 0 "memory_operand" "=m")
8905 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8906 UNSPEC_PUSH_MULT))])]
8910 int num_saves = XVECLEN (operands[2], 0);
8912 /* For the StrongARM at least it is faster to
8913 use STR to store only a single register. */
8915 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8921 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
8923 for (i = 1; i < num_saves; i++)
8925 strcat (pattern, \", %|\");
8927 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
8930 strcat (pattern, \"}\");
8931 output_asm_insn (pattern, operands);
8936 [(set_attr "type" "store4")]
8939 (define_insn "stack_tie"
8940 [(set (mem:BLK (scratch))
8941 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
8942 (match_operand:SI 1 "s_register_operand" "r")]
8946 [(set_attr "length" "0")]
8949 ;; Similarly for the floating point registers
8950 (define_insn "*push_fp_multi"
8951 [(match_parallel 2 "multi_register_push"
8952 [(set (match_operand:BLK 0 "memory_operand" "=m")
8953 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
8954 UNSPEC_PUSH_MULT))])]
8960 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
8961 output_asm_insn (pattern, operands);
8964 [(set_attr "type" "f_store")]
8967 ;; Special patterns for dealing with the constant pool
8969 (define_insn "align_4"
8970 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
8973 assemble_align (32);
8978 (define_insn "consttable_end"
8979 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
8982 making_const_table = FALSE;
8987 (define_insn "consttable_1"
8988 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
8991 making_const_table = TRUE;
8992 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
8996 [(set_attr "length" "4")]
8999 (define_insn "consttable_2"
9000 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9003 making_const_table = TRUE;
9004 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9008 [(set_attr "length" "4")]
9011 (define_insn "consttable_4"
9012 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9016 making_const_table = TRUE;
9017 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9022 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9023 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9027 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9032 [(set_attr "length" "4")]
9035 (define_insn "consttable_8"
9036 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9040 making_const_table = TRUE;
9041 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9046 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9047 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9051 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9056 [(set_attr "length" "8")]
9059 ;; Miscellaneous Thumb patterns
9061 (define_expand "tablejump"
9062 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9063 (use (label_ref (match_operand 1 "" "")))])]
9068 /* Hopefully, CSE will eliminate this copy. */
9069 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
9070 rtx reg2 = gen_reg_rtx (SImode);
9072 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
9078 (define_insn "*thumb_tablejump"
9079 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9080 (use (label_ref (match_operand 1 "" "")))]
9083 [(set_attr "length" "2")]
9089 [(set (match_operand:SI 0 "s_register_operand" "=r")
9090 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")]
9092 "TARGET_ARM && arm_arch5"
9095 (define_expand "ffssi2"
9096 [(set (match_operand:SI 0 "s_register_operand" "")
9097 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9098 "TARGET_ARM && arm_arch5"
9103 t1 = gen_reg_rtx (SImode);
9104 t2 = gen_reg_rtx (SImode);
9105 t3 = gen_reg_rtx (SImode);
9107 emit_insn (gen_negsi2 (t1, operands[1]));
9108 emit_insn (gen_andsi3 (t2, operands[1], t1));
9109 emit_insn (gen_clz (t3, t2));
9110 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
9115 ;; V5E instructions.
9117 (define_insn "prefetch"
9118 [(prefetch (match_operand:SI 0 "address_operand" "p")
9119 (match_operand:SI 1 "" "")
9120 (match_operand:SI 2 "" ""))]
9121 "TARGET_ARM && arm_arch5e"
9124 ;; General predication pattern
9127 [(match_operator 0 "arm_comparison_operator"
9128 [(match_operand 1 "cc_register" "")
9134 (define_insn "prologue_use"
9135 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
9137 "%@ %0 needed for prologue"