1 ;;- Machine description for ARM for GNU compiler
2 ;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;; 2001, 2002 Free Software Foundation, Inc.
4 ;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;; and Martin Simmons (@harleqn.co.uk).
6 ;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
8 ;; This file is part of GNU CC.
10 ;; GNU CC is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; GNU CC is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU CC; see the file COPYING. If not, write to
22 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
27 ;; There are patterns in this file to support XFmode arithmetic.
28 ;; Unfortunately RISC iX doesn't work well with these so they are disabled.
31 ;;---------------------------------------------------------------------------
36 [(IP_REGNUM 12) ; Scratch register
37 (SP_REGNUM 13) ; Stack pointer
38 (LR_REGNUM 14) ; Return address register
39 (PC_REGNUM 15) ; Program counter
40 (CC_REGNUM 24) ; Condition code pseudo register
46 ;; Note: sin and cos are no-longer used.
49 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
50 ; operand 0 is the result,
51 ; operand 1 the parameter.
52 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
53 ; operand 0 is the result,
54 ; operand 1 the parameter.
55 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
56 ; operand 0 is the first register,
57 ; subsequent registers are in parallel (use ...)
59 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
60 ; usage, that is, we will add the pic_register
61 ; value to it before trying to dereference it.
62 (UNSPEC_PRLG_STK 4) ; A special barrier that prevents frame accesses
63 ; being scheduled before the stack adjustment insn.
64 (UNSPEC_CLZ 5) ; `clz' instruction, count leading zeros (SImode):
65 ; operand 0 is the result,
66 ; operand 1 is the parameter.
67 (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
68 ; this unspec is used to prevent the deletion of
69 ; instructions setting registers for EH handling
70 ; and stack frame generation. Operand 0 is the
75 ;; UNSPEC_VOLATILE Usage:
78 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
80 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
81 ; instruction epilogue sequence that isn't expanded
82 ; into normal RTL. Used for both normal and sibcall
84 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
85 ; for inlined constants.
86 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
88 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
90 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
92 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
94 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
99 ;;---------------------------------------------------------------------------
102 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
103 ; generating ARM code. This is used to control the length of some insn
104 ; patterns that share the same RTL in both ARM and Thumb code.
105 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
107 ; PROG_MODE attribute is used to determine whether condition codes are
108 ; clobbered by a call insn: they are if in prog32 mode. This is controlled
109 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
110 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
112 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
113 ; scheduling decisions for the load unit and the multiplier.
114 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
116 ;; Operand number of an input operand that is shifted. Zero if the
117 ;; given instruction does not shift one of its input operands.
118 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_is_xscale")))
119 (define_attr "shift" "" (const_int 0))
121 ; Floating Point Unit. If we only have floating point emulation, then there
122 ; is no point in scheduling the floating point insns. (Well, for best
123 ; performance we should try and group them together).
124 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
126 ; LENGTH of an instruction (in bytes)
127 (define_attr "length" "" (const_int 4))
129 ; POOL_RANGE is how far away from a constant pool entry that this insn
130 ; can be placed. If the distance is zero, then this insn will never
131 ; reference the pool.
132 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
133 ; before its address.
134 (define_attr "pool_range" "" (const_int 0))
135 (define_attr "neg_pool_range" "" (const_int 0))
137 ; An assembler sequence may clobber the condition codes without us knowing.
138 (define_asm_attributes
139 [(set_attr "conds" "clob")])
141 ; TYPE attribute is used to detect floating point instructions which, if
142 ; running on a co-processor can run in parallel with other, basic instructions
143 ; If write-buffer scheduling is enabled then it can also be used in the
144 ; scheduling of writes.
146 ; Classification of each insn
147 ; normal any data instruction that doesn't hit memory or fp regs
148 ; mult a multiply instruction
149 ; block blockage insn, this blocks all functional units
150 ; float a floating point arithmetic operation (subject to expansion)
151 ; fdivx XFmode floating point division
152 ; fdivd DFmode floating point division
153 ; fdivs SFmode floating point division
154 ; fmul Floating point multiply
155 ; ffmul Fast floating point multiply
156 ; farith Floating point arithmetic (4 cycle)
157 ; ffarith Fast floating point arithmetic (2 cycle)
158 ; float_em a floating point arithmetic operation that is normally emulated
159 ; even on a machine with an fpa.
160 ; f_load a floating point load from memory
161 ; f_store a floating point store to memory
162 ; f_mem_r a transfer of a floating point register to a real reg via mem
163 ; r_mem_f the reverse of f_mem_r
164 ; f_2_r fast transfer float to arm (no memory needed)
165 ; r_2_f fast transfer arm to float
166 ; call a subroutine call
167 ; load any load from memory
168 ; store1 store 1 word to memory from arm registers
169 ; store2 store 2 words
170 ; store3 store 3 words
171 ; store4 store 4 words
174 "normal,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,call,load,store1,store2,store3,store4"
175 (const_string "normal"))
177 ; Load scheduling, set from the arm_ld_sched variable
178 ; initialised by arm_override_options()
179 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
181 ; condition codes: this one is used by final_prescan_insn to speed up
182 ; conditionalizing instructions. It saves having to scan the rtl to see if
183 ; it uses or alters the condition codes.
185 ; USE means that the condition codes are used by the insn in the process of
186 ; outputting code, this means (at present) that we can't use the insn in
189 ; SET means that the purpose of the insn is to set the condition codes in a
190 ; well defined manner.
192 ; CLOB means that the condition codes are altered in an undefined manner, if
193 ; they are altered at all
195 ; JUMP_CLOB is used when the condition cannot be represented by a single
196 ; instruction (UNEQ and LTGT). These cannot be predicated.
198 ; NOCOND means that the condition codes are neither altered nor affect the
199 ; output of this insn
201 (define_attr "conds" "use,set,clob,jump_clob,nocond"
202 (if_then_else (eq_attr "type" "call")
203 (if_then_else (eq_attr "prog_mode" "prog32")
204 (const_string "clob") (const_string "nocond"))
205 (const_string "nocond")))
207 ; Predicable means that the insn can be conditionally executed based on
208 ; an automatically added predicate (additional patterns are generated by
209 ; gen...). We default to 'no' because no Thumb patterns match this rule
210 ; and not all ARM patterns do.
211 (define_attr "predicable" "no,yes" (const_string "no"))
213 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
214 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
215 ; suffer blockages enough to warrent modelling this (and it can adversely
216 ; affect the schedule).
217 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
219 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
220 ; to stall the processor. Used with model_wbuf above.
221 (define_attr "write_conflict" "no,yes"
222 (if_then_else (eq_attr "type"
223 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
225 (const_string "no")))
227 ; Classify the insns into those that take one cycle and those that take more
228 ; than one on the main cpu execution unit.
229 (define_attr "core_cycles" "single,multi"
230 (if_then_else (eq_attr "type"
231 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
232 (const_string "single")
233 (const_string "multi")))
235 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
236 ;; distant label. Only applicable to Thumb code.
237 (define_attr "far_jump" "yes,no" (const_string "no"))
239 ;; (define_function_unit {name} {num-units} {n-users} {test}
240 ;; {ready-delay} {issue-delay} [{conflict-list}])
242 ;;--------------------------------------------------------------------
243 ;; Floating point unit (FPA)
244 ;;--------------------------------------------------------------------
245 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
246 (eq_attr "type" "fdivx")) 71 69)
248 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
249 (eq_attr "type" "fdivd")) 59 57)
251 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
252 (eq_attr "type" "fdivs")) 31 29)
254 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
255 (eq_attr "type" "fmul")) 9 7)
257 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
258 (eq_attr "type" "ffmul")) 6 4)
260 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
261 (eq_attr "type" "farith")) 4 2)
263 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
264 (eq_attr "type" "ffarith")) 2 2)
266 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
267 (eq_attr "type" "r_2_f")) 5 3)
269 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
270 (eq_attr "type" "f_2_r")) 1 2)
272 ; The fpa10 doesn't really have a memory read unit, but it can start to
273 ; speculatively execute the instruction in the pipeline, provided the data
274 ; is already loaded, so pretend reads have a delay of 2 (and that the
275 ; pipeline is infinite).
277 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
278 (eq_attr "type" "f_load")) 3 1)
280 ;;--------------------------------------------------------------------
282 ;;--------------------------------------------------------------------
283 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
285 ; The write buffer on some of the arm6 processors is hard to model exactly.
286 ; There is room in the buffer for up to two addresses and up to eight words
287 ; of memory, but the two needn't be split evenly. When writing the two
288 ; addresses are fully pipelined. However, a read from memory that is not
289 ; currently in the cache will block until the writes have completed.
290 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
291 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
292 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
293 ; cycle to add as well.
295 (define_function_unit "write_buf" 1 2
296 (and (eq_attr "model_wbuf" "yes")
297 (eq_attr "type" "store1,r_mem_f")) 5 3)
298 (define_function_unit "write_buf" 1 2
299 (and (eq_attr "model_wbuf" "yes")
300 (eq_attr "type" "store2")) 7 4)
301 (define_function_unit "write_buf" 1 2
302 (and (eq_attr "model_wbuf" "yes")
303 (eq_attr "type" "store3")) 9 5)
304 (define_function_unit "write_buf" 1 2
305 (and (eq_attr "model_wbuf" "yes")
306 (eq_attr "type" "store4")) 11 6)
308 ;;--------------------------------------------------------------------
309 ;; Write blockage unit
310 ;;--------------------------------------------------------------------
311 ; The write_blockage unit models (partially), the fact that reads will stall
312 ; until the write buffer empties.
313 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
314 ; so we don't model them here
315 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
316 (eq_attr "type" "store1")) 5 5
317 [(eq_attr "write_conflict" "yes")])
318 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
319 (eq_attr "type" "store2")) 7 7
320 [(eq_attr "write_conflict" "yes")])
321 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
322 (eq_attr "type" "store3")) 9 9
323 [(eq_attr "write_conflict" "yes")])
324 (define_function_unit "write_blockage" 1 0
325 (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
326 [(eq_attr "write_conflict" "yes")])
327 (define_function_unit "write_blockage" 1 0
328 (and (eq_attr "model_wbuf" "yes")
329 (eq_attr "write_conflict" "yes")) 1 1)
331 ;;--------------------------------------------------------------------
333 ;;--------------------------------------------------------------------
334 ; Everything must spend at least one cycle in the core unit
335 (define_function_unit "core" 1 0 (eq_attr "core_cycles" "single") 1 1)
337 (define_function_unit "core" 1 0
338 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
340 (define_function_unit "core" 1 0
341 (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
343 ;; We do not need to conditionalize the define_function_unit immediately
344 ;; above. This one will be ignored for anything other than xscale
345 ;; compiles and for xscale compiles it provides a larger delay
346 ;; and the scheduler will DTRT.
347 ;; FIXME: this test needs to be revamped to not depend on this feature
350 (define_function_unit "core" 1 0
351 (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
352 (eq_attr "is_xscale" "yes"))
355 (define_function_unit "core" 1 0
356 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
358 (define_function_unit "core" 1 0
359 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
361 (define_function_unit "core" 1 0
362 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
364 (define_function_unit "core" 1 0
365 (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
367 (define_function_unit "core" 1 0
368 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
370 (define_function_unit "core" 1 0
371 (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
373 (define_function_unit "core" 1 0
374 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
375 (eq_attr "type" "mult")) 4 4)
377 (define_function_unit "core" 1 0
378 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
379 (eq_attr "type" "mult")) 3 2)
381 (define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
383 (define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
385 (define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
387 (define_function_unit "core" 1 0
388 (and (eq_attr "core_cycles" "multi")
389 (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
391 ;;---------------------------------------------------------------------------
396 ;; Note: For DImode insns, there is normally no reason why operands should
397 ;; not be in the same register, what we don't want is for something being
398 ;; written to partially overlap something that is an input.
400 (define_expand "adddi3"
402 [(set (match_operand:DI 0 "s_register_operand" "")
403 (plus:DI (match_operand:DI 1 "s_register_operand" "")
404 (match_operand:DI 2 "s_register_operand" "")))
405 (clobber (reg:CC CC_REGNUM))])]
410 if (GET_CODE (operands[1]) != REG)
411 operands[1] = force_reg (SImode, operands[1]);
412 if (GET_CODE (operands[2]) != REG)
413 operands[2] = force_reg (SImode, operands[2]);
418 (define_insn "*thumb_adddi3"
419 [(set (match_operand:DI 0 "register_operand" "=l")
420 (plus:DI (match_operand:DI 1 "register_operand" "%0")
421 (match_operand:DI 2 "register_operand" "l")))
422 (clobber (reg:CC CC_REGNUM))
425 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
426 [(set_attr "length" "4")]
429 (define_insn_and_split "*arm_adddi3"
430 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
431 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
432 (match_operand:DI 2 "s_register_operand" "r, 0")))
433 (clobber (reg:CC CC_REGNUM))]
436 "TARGET_ARM && reload_completed"
437 [(parallel [(set (reg:CC_C CC_REGNUM)
438 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
440 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
441 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
442 (plus:SI (match_dup 4) (match_dup 5))))]
445 operands[3] = gen_highpart (SImode, operands[0]);
446 operands[0] = gen_lowpart (SImode, operands[0]);
447 operands[4] = gen_highpart (SImode, operands[1]);
448 operands[1] = gen_lowpart (SImode, operands[1]);
449 operands[5] = gen_highpart (SImode, operands[2]);
450 operands[2] = gen_lowpart (SImode, operands[2]);
452 [(set_attr "conds" "clob")
453 (set_attr "length" "8")]
456 (define_insn_and_split "*adddi_sesidi_di"
457 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
458 (plus:DI (sign_extend:DI
459 (match_operand:SI 2 "s_register_operand" "r,r"))
460 (match_operand:DI 1 "s_register_operand" "r,0")))
461 (clobber (reg:CC CC_REGNUM))]
464 "TARGET_ARM && reload_completed"
465 [(parallel [(set (reg:CC_C CC_REGNUM)
466 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
468 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
469 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
470 (plus:SI (ashiftrt:SI (match_dup 2)
475 operands[3] = gen_highpart (SImode, operands[0]);
476 operands[0] = gen_lowpart (SImode, operands[0]);
477 operands[4] = gen_highpart (SImode, operands[1]);
478 operands[1] = gen_lowpart (SImode, operands[1]);
479 operands[2] = gen_lowpart (SImode, operands[2]);
481 [(set_attr "conds" "clob")
482 (set_attr "length" "8")]
485 (define_insn_and_split "*adddi_zesidi_di"
486 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
487 (plus:DI (zero_extend:DI
488 (match_operand:SI 2 "s_register_operand" "r,r"))
489 (match_operand:DI 1 "s_register_operand" "r,0")))
490 (clobber (reg:CC CC_REGNUM))]
493 "TARGET_ARM && reload_completed"
494 [(parallel [(set (reg:CC_C CC_REGNUM)
495 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
497 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
498 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
499 (plus:SI (match_dup 4) (const_int 0))))]
502 operands[3] = gen_highpart (SImode, operands[0]);
503 operands[0] = gen_lowpart (SImode, operands[0]);
504 operands[4] = gen_highpart (SImode, operands[1]);
505 operands[1] = gen_lowpart (SImode, operands[1]);
506 operands[2] = gen_lowpart (SImode, operands[2]);
508 [(set_attr "conds" "clob")
509 (set_attr "length" "8")]
512 (define_expand "addsi3"
513 [(set (match_operand:SI 0 "s_register_operand" "")
514 (plus:SI (match_operand:SI 1 "s_register_operand" "")
515 (match_operand:SI 2 "reg_or_int_operand" "")))]
518 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
520 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
522 (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
528 ; If there is a scratch available, this will be faster than synthesising the
531 [(match_scratch:SI 3 "r")
532 (set (match_operand:SI 0 "s_register_operand" "")
533 (plus:SI (match_operand:SI 1 "s_register_operand" "")
534 (match_operand:SI 2 "const_int_operand" "")))]
536 !(const_ok_for_arm (INTVAL (operands[2]))
537 || const_ok_for_arm (-INTVAL (operands[2])))
538 && const_ok_for_arm (~INTVAL (operands[2]))"
539 [(set (match_dup 3) (match_dup 2))
540 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
544 (define_insn_and_split "*arm_addsi3"
545 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
546 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
547 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
554 GET_CODE (operands[2]) == CONST_INT
555 && !(const_ok_for_arm (INTVAL (operands[2]))
556 || const_ok_for_arm (-INTVAL (operands[2])))"
557 [(clobber (const_int 0))]
559 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
563 [(set_attr "length" "4,4,16")
564 (set_attr "predicable" "yes")]
567 ;; Register group 'k' is a single register group containing only the stack
568 ;; register. Trying to reload it will always fail catastrophically,
569 ;; so never allow those alternatives to match if reloading is needed.
571 (define_insn "*thumb_addsi3"
572 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
573 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
574 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
577 static const char * const asms[] =
579 \"add\\t%0, %0, %2\",
580 \"sub\\t%0, %0, #%n2\",
581 \"add\\t%0, %1, %2\",
582 \"add\\t%0, %0, %2\",
583 \"add\\t%0, %0, %2\",
584 \"add\\t%0, %1, %2\",
587 if ((which_alternative == 2 || which_alternative == 6)
588 && GET_CODE (operands[2]) == CONST_INT
589 && INTVAL (operands[2]) < 0)
590 return \"sub\\t%0, %1, #%n2\";
591 return asms[which_alternative];
593 [(set_attr "length" "2")]
596 ;; Reloading and elimination of the frame pointer can
597 ;; sometimes cause this optimization to be missed.
599 [(set (match_operand:SI 0 "register_operand" "=l")
600 (match_operand:SI 1 "const_int_operand" "M"))
602 (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "k")))]
604 && REGNO (operands[2]) == STACK_POINTER_REGNUM
605 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
606 && (INTVAL (operands[1]) & 3) == 0"
607 [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
611 (define_insn "*addsi3_compare0"
612 [(set (reg:CC_NOOV CC_REGNUM)
614 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
615 (match_operand:SI 2 "arm_add_operand" "rI,L"))
617 (set (match_operand:SI 0 "s_register_operand" "=r,r")
618 (plus:SI (match_dup 1) (match_dup 2)))]
622 sub%?s\\t%0, %1, #%n2"
623 [(set_attr "conds" "set")]
626 (define_insn "*addsi3_compare0_scratch"
627 [(set (reg:CC_NOOV CC_REGNUM)
629 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
630 (match_operand:SI 1 "arm_add_operand" "rI,L"))
636 [(set_attr "conds" "set")]
639 ;; These patterns are the same ones as the two regular addsi3_compare0
640 ;; patterns, except we write them slightly different - the combiner
641 ;; tends to generate them this way.
642 (define_insn "*addsi3_compare0_for_combiner"
643 [(set (reg:CC CC_REGNUM)
645 (match_operand:SI 1 "s_register_operand" "r,r")
646 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
647 (set (match_operand:SI 0 "s_register_operand" "=r,r")
648 (plus:SI (match_dup 1) (match_dup 2)))]
652 sub%?s\\t%0, %1, #%n2"
653 [(set_attr "conds" "set")]
656 (define_insn "*addsi3_compare0_scratch_for_combiner"
657 [(set (reg:CC CC_REGNUM)
659 (match_operand:SI 0 "s_register_operand" "r,r")
660 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
665 [(set_attr "conds" "set")]
668 ;; The next four insns work because they compare the result with one of
669 ;; the operands, and we know that the use of the condition code is
670 ;; either GEU or LTU, so we can use the carry flag from the addition
671 ;; instead of doing the compare a second time.
672 (define_insn "*addsi3_compare_op1"
673 [(set (reg:CC_C CC_REGNUM)
675 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
676 (match_operand:SI 2 "arm_add_operand" "rI,L"))
678 (set (match_operand:SI 0 "s_register_operand" "=r,r")
679 (plus:SI (match_dup 1) (match_dup 2)))]
683 sub%?s\\t%0, %1, #%n2"
684 [(set_attr "conds" "set")]
687 (define_insn "*addsi3_compare_op2"
688 [(set (reg:CC_C CC_REGNUM)
690 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
691 (match_operand:SI 2 "arm_add_operand" "rI,L"))
693 (set (match_operand:SI 0 "s_register_operand" "=r,r")
694 (plus:SI (match_dup 1) (match_dup 2)))]
698 sub%?s\\t%0, %1, #%n2"
699 [(set_attr "conds" "set")]
702 (define_insn "*compare_addsi2_op0"
703 [(set (reg:CC_C CC_REGNUM)
705 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
706 (match_operand:SI 1 "arm_add_operand" "rI,L"))
712 [(set_attr "conds" "set")]
715 (define_insn "*compare_addsi2_op1"
716 [(set (reg:CC_C CC_REGNUM)
718 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
719 (match_operand:SI 1 "arm_add_operand" "rI,L"))
725 [(set_attr "conds" "set")]
728 (define_insn "*addsi3_carryin"
729 [(set (match_operand:SI 0 "s_register_operand" "=r")
730 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
731 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
732 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
735 [(set_attr "conds" "use")]
738 (define_insn "*addsi3_carryin_shift"
739 [(set (match_operand:SI 0 "s_register_operand" "")
740 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
742 (match_operator:SI 2 "shift_operator"
743 [(match_operand:SI 3 "s_register_operand" "")
744 (match_operand:SI 4 "reg_or_int_operand" "")])
745 (match_operand:SI 1 "s_register_operand" ""))))]
747 "adc%?\\t%0, %1, %3%S2"
748 [(set_attr "conds" "use")]
751 (define_insn "*addsi3_carryin_alt1"
752 [(set (match_operand:SI 0 "s_register_operand" "=r")
753 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
754 (match_operand:SI 2 "arm_rhs_operand" "rI"))
755 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
758 [(set_attr "conds" "use")]
761 (define_insn "*addsi3_carryin_alt2"
762 [(set (match_operand:SI 0 "s_register_operand" "=r")
763 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
764 (match_operand:SI 1 "s_register_operand" "r"))
765 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
768 [(set_attr "conds" "use")]
771 (define_insn "*addsi3_carryin_alt3"
772 [(set (match_operand:SI 0 "s_register_operand" "=r")
773 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
774 (match_operand:SI 2 "arm_rhs_operand" "rI"))
775 (match_operand:SI 1 "s_register_operand" "r")))]
778 [(set_attr "conds" "use")]
781 (define_insn "incscc"
782 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
783 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
784 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
785 (match_operand:SI 1 "s_register_operand" "0,?r")))]
789 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
790 [(set_attr "conds" "use")
791 (set_attr "length" "4,8")]
794 (define_insn "addsf3"
795 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
796 (plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
797 (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
798 "TARGET_ARM && TARGET_HARD_FLOAT"
801 suf%?s\\t%0, %1, #%N2"
802 [(set_attr "type" "farith")
803 (set_attr "predicable" "yes")]
806 (define_insn "adddf3"
807 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
808 (plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
809 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
810 "TARGET_ARM && TARGET_HARD_FLOAT"
813 suf%?d\\t%0, %1, #%N2"
814 [(set_attr "type" "farith")
815 (set_attr "predicable" "yes")]
818 (define_insn "*adddf_esfdf_df"
819 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
820 (plus:DF (float_extend:DF
821 (match_operand:SF 1 "s_register_operand" "f,f"))
822 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
823 "TARGET_ARM && TARGET_HARD_FLOAT"
826 suf%?d\\t%0, %1, #%N2"
827 [(set_attr "type" "farith")
828 (set_attr "predicable" "yes")]
831 (define_insn "*adddf_df_esfdf"
832 [(set (match_operand:DF 0 "s_register_operand" "=f")
833 (plus:DF (match_operand:DF 1 "s_register_operand" "f")
835 (match_operand:SF 2 "s_register_operand" "f"))))]
836 "TARGET_ARM && TARGET_HARD_FLOAT"
837 "adf%?d\\t%0, %1, %2"
838 [(set_attr "type" "farith")
839 (set_attr "predicable" "yes")]
842 (define_insn "*adddf_esfdf_esfdf"
843 [(set (match_operand:DF 0 "s_register_operand" "=f")
844 (plus:DF (float_extend:DF
845 (match_operand:SF 1 "s_register_operand" "f"))
847 (match_operand:SF 2 "s_register_operand" "f"))))]
848 "TARGET_ARM && TARGET_HARD_FLOAT"
849 "adf%?d\\t%0, %1, %2"
850 [(set_attr "type" "farith")
851 (set_attr "predicable" "yes")]
854 (define_insn "addxf3"
855 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
856 (plus:XF (match_operand:XF 1 "s_register_operand" "f,f")
857 (match_operand:XF 2 "fpu_add_operand" "fG,H")))]
858 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
861 suf%?e\\t%0, %1, #%N2"
862 [(set_attr "type" "farith")
863 (set_attr "predicable" "yes")]
866 (define_expand "subdi3"
868 [(set (match_operand:DI 0 "s_register_operand" "")
869 (minus:DI (match_operand:DI 1 "s_register_operand" "")
870 (match_operand:DI 2 "s_register_operand" "")))
871 (clobber (reg:CC CC_REGNUM))])]
876 if (GET_CODE (operands[1]) != REG)
877 operands[1] = force_reg (SImode, operands[1]);
878 if (GET_CODE (operands[2]) != REG)
879 operands[2] = force_reg (SImode, operands[2]);
884 (define_insn "*arm_subdi3"
885 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
886 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
887 (match_operand:DI 2 "s_register_operand" "r,0,0")))
888 (clobber (reg:CC CC_REGNUM))]
890 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
891 [(set_attr "conds" "clob")
892 (set_attr "length" "8")]
895 (define_insn "*thumb_subdi3"
896 [(set (match_operand:DI 0 "register_operand" "=l")
897 (minus:DI (match_operand:DI 1 "register_operand" "0")
898 (match_operand:DI 2 "register_operand" "l")))
899 (clobber (reg:CC CC_REGNUM))]
901 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
902 [(set_attr "length" "4")]
905 (define_insn "*subdi_di_zesidi"
906 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
907 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
909 (match_operand:SI 2 "s_register_operand" "r,r"))))
910 (clobber (reg:CC CC_REGNUM))]
912 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
913 [(set_attr "conds" "clob")
914 (set_attr "length" "8")]
917 (define_insn "*subdi_di_sesidi"
918 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
919 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
921 (match_operand:SI 2 "s_register_operand" "r,r"))))
922 (clobber (reg:CC CC_REGNUM))]
924 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
925 [(set_attr "conds" "clob")
926 (set_attr "length" "8")]
929 (define_insn "*subdi_zesidi_di"
930 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
931 (minus:DI (zero_extend:DI
932 (match_operand:SI 2 "s_register_operand" "r,r"))
933 (match_operand:DI 1 "s_register_operand" "?r,0")))
934 (clobber (reg:CC CC_REGNUM))]
936 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
937 [(set_attr "conds" "clob")
938 (set_attr "length" "8")]
941 (define_insn "*subdi_sesidi_di"
942 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
943 (minus:DI (sign_extend:DI
944 (match_operand:SI 2 "s_register_operand" "r,r"))
945 (match_operand:DI 1 "s_register_operand" "?r,0")))
946 (clobber (reg:CC CC_REGNUM))]
948 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
949 [(set_attr "conds" "clob")
950 (set_attr "length" "8")]
953 (define_insn "*subdi_zesidi_zesidi"
954 [(set (match_operand:DI 0 "s_register_operand" "=r")
955 (minus:DI (zero_extend:DI
956 (match_operand:SI 1 "s_register_operand" "r"))
958 (match_operand:SI 2 "s_register_operand" "r"))))
959 (clobber (reg:CC CC_REGNUM))]
961 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
962 [(set_attr "conds" "clob")
963 (set_attr "length" "8")]
966 (define_expand "subsi3"
967 [(set (match_operand:SI 0 "s_register_operand" "")
968 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
969 (match_operand:SI 2 "s_register_operand" "")))]
972 if (GET_CODE (operands[1]) == CONST_INT)
976 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
979 : preserve_subexpressions_p ()));
982 else /* TARGET_THUMB */
983 operands[1] = force_reg (SImode, operands[1]);
988 (define_insn "*thumb_subsi3_insn"
989 [(set (match_operand:SI 0 "register_operand" "=l")
990 (minus:SI (match_operand:SI 1 "register_operand" "l")
991 (match_operand:SI 2 "register_operand" "l")))]
994 [(set_attr "length" "2")]
997 (define_insn_and_split "*arm_subsi3_insn"
998 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
999 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
1000 (match_operand:SI 2 "s_register_operand" "r,r")))]
1006 && GET_CODE (operands[1]) == CONST_INT
1007 && !const_ok_for_arm (INTVAL (operands[1]))"
1008 [(clobber (const_int 0))]
1010 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1014 [(set_attr "length" "4,16")
1015 (set_attr "predicable" "yes")]
1019 [(match_scratch:SI 3 "r")
1020 (set (match_operand:SI 0 "s_register_operand" "")
1021 (minus:SI (match_operand:SI 1 "const_int_operand" "")
1022 (match_operand:SI 2 "s_register_operand" "")))]
1024 && !const_ok_for_arm (INTVAL (operands[1]))
1025 && const_ok_for_arm (~INTVAL (operands[1]))"
1026 [(set (match_dup 3) (match_dup 1))
1027 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1031 (define_insn "*subsi3_compare0"
1032 [(set (reg:CC_NOOV CC_REGNUM)
1034 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1035 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1037 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1038 (minus:SI (match_dup 1) (match_dup 2)))]
1042 rsb%?s\\t%0, %2, %1"
1043 [(set_attr "conds" "set")]
1046 (define_insn "decscc"
1047 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1048 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1049 (match_operator:SI 2 "arm_comparison_operator"
1050 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1054 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1055 [(set_attr "conds" "use")
1056 (set_attr "length" "*,8")]
1059 (define_insn "subsf3"
1060 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1061 (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1062 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1063 "TARGET_ARM && TARGET_HARD_FLOAT"
1066 rsf%?s\\t%0, %2, %1"
1067 [(set_attr "type" "farith")]
1070 (define_insn "subdf3"
1071 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1072 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1073 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1074 "TARGET_ARM && TARGET_HARD_FLOAT"
1077 rsf%?d\\t%0, %2, %1"
1078 [(set_attr "type" "farith")
1079 (set_attr "predicable" "yes")]
1082 (define_insn "*subdf_esfdf_df"
1083 [(set (match_operand:DF 0 "s_register_operand" "=f")
1084 (minus:DF (float_extend:DF
1085 (match_operand:SF 1 "s_register_operand" "f"))
1086 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1087 "TARGET_ARM && TARGET_HARD_FLOAT"
1088 "suf%?d\\t%0, %1, %2"
1089 [(set_attr "type" "farith")
1090 (set_attr "predicable" "yes")]
1093 (define_insn "*subdf_df_esfdf"
1094 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1095 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1097 (match_operand:SF 2 "s_register_operand" "f,f"))))]
1098 "TARGET_ARM && TARGET_HARD_FLOAT"
1101 rsf%?d\\t%0, %2, %1"
1102 [(set_attr "type" "farith")
1103 (set_attr "predicable" "yes")]
1106 (define_insn "*subdf_esfdf_esfdf"
1107 [(set (match_operand:DF 0 "s_register_operand" "=f")
1108 (minus:DF (float_extend:DF
1109 (match_operand:SF 1 "s_register_operand" "f"))
1111 (match_operand:SF 2 "s_register_operand" "f"))))]
1112 "TARGET_ARM && TARGET_HARD_FLOAT"
1113 "suf%?d\\t%0, %1, %2"
1114 [(set_attr "type" "farith")
1115 (set_attr "predicable" "yes")]
1118 (define_insn "subxf3"
1119 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1120 (minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1121 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1122 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1125 rsf%?e\\t%0, %2, %1"
1126 [(set_attr "type" "farith")
1127 (set_attr "predicable" "yes")]
1130 ;; Multiplication insns
1132 (define_expand "mulsi3"
1133 [(set (match_operand:SI 0 "s_register_operand" "")
1134 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1135 (match_operand:SI 1 "s_register_operand" "")))]
1140 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1141 (define_insn "*arm_mulsi3"
1142 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1143 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1144 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1146 "mul%?\\t%0, %2, %1"
1147 [(set_attr "type" "mult")
1148 (set_attr "predicable" "yes")]
1151 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1152 ; 1 and 2; are the same, because reload will make operand 0 match
1153 ; operand 1 without realizing that this conflicts with operand 2. We fix
1154 ; this by adding another alternative to match this case, and then `reload'
1155 ; it ourselves. This alternative must come first.
1156 (define_insn "*thumb_mulsi3"
1157 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1158 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1159 (match_operand:SI 2 "register_operand" "l,l,l")))]
1162 if (which_alternative < 2)
1163 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1165 return \"mul\\t%0, %0, %2\";
1167 [(set_attr "length" "4,4,2")
1168 (set_attr "type" "mult")]
1171 (define_insn "*mulsi3_compare0"
1172 [(set (reg:CC_NOOV CC_REGNUM)
1173 (compare:CC_NOOV (mult:SI
1174 (match_operand:SI 2 "s_register_operand" "r,r")
1175 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1177 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1178 (mult:SI (match_dup 2) (match_dup 1)))]
1179 "TARGET_ARM && !arm_is_xscale"
1180 "mul%?s\\t%0, %2, %1"
1181 [(set_attr "conds" "set")
1182 (set_attr "type" "mult")]
1185 (define_insn "*mulsi_compare0_scratch"
1186 [(set (reg:CC_NOOV CC_REGNUM)
1187 (compare:CC_NOOV (mult:SI
1188 (match_operand:SI 2 "s_register_operand" "r,r")
1189 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1191 (clobber (match_scratch:SI 0 "=&r,&r"))]
1192 "TARGET_ARM && !arm_is_xscale"
1193 "mul%?s\\t%0, %2, %1"
1194 [(set_attr "conds" "set")
1195 (set_attr "type" "mult")]
1198 ;; Unnamed templates to match MLA instruction.
1200 (define_insn "*mulsi3addsi"
1201 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1203 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1204 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1205 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1207 "mla%?\\t%0, %2, %1, %3"
1208 [(set_attr "type" "mult")
1209 (set_attr "predicable" "yes")]
1212 (define_insn "*mulsi3addsi_compare0"
1213 [(set (reg:CC_NOOV CC_REGNUM)
1216 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1217 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1218 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1220 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1221 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1223 "TARGET_ARM && !arm_is_xscale"
1224 "mla%?s\\t%0, %2, %1, %3"
1225 [(set_attr "conds" "set")
1226 (set_attr "type" "mult")]
1229 (define_insn "*mulsi3addsi_compare0_scratch"
1230 [(set (reg:CC_NOOV CC_REGNUM)
1233 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1234 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1235 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1237 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1238 "TARGET_ARM && !arm_is_xscale"
1239 "mla%?s\\t%0, %2, %1, %3"
1240 [(set_attr "conds" "set")
1241 (set_attr "type" "mult")]
1244 ;; Unnamed template to match long long multiply-accumlate (smlal)
1246 (define_insn "*mulsidi3adddi"
1247 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1250 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1251 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1252 (match_operand:DI 1 "s_register_operand" "0")))]
1253 "TARGET_ARM && arm_fast_multiply"
1254 "smlal%?\\t%Q0, %R0, %3, %2"
1255 [(set_attr "type" "mult")
1256 (set_attr "predicable" "yes")]
1259 (define_insn "mulsidi3"
1260 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1262 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1263 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1264 "TARGET_ARM && arm_fast_multiply"
1265 "smull%?\\t%Q0, %R0, %1, %2"
1266 [(set_attr "type" "mult")
1267 (set_attr "predicable" "yes")]
1270 (define_insn "umulsidi3"
1271 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1273 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1274 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1275 "TARGET_ARM && arm_fast_multiply"
1276 "umull%?\\t%Q0, %R0, %1, %2"
1277 [(set_attr "type" "mult")
1278 (set_attr "predicable" "yes")]
1281 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1283 (define_insn "*umulsidi3adddi"
1284 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1287 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1288 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1289 (match_operand:DI 1 "s_register_operand" "0")))]
1290 "TARGET_ARM && arm_fast_multiply"
1291 "umlal%?\\t%Q0, %R0, %3, %2"
1292 [(set_attr "type" "mult")
1293 (set_attr "predicable" "yes")]
1296 (define_insn "smulsi3_highpart"
1297 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1301 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1302 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1304 (clobber (match_scratch:SI 3 "=&r,&r"))]
1305 "TARGET_ARM && arm_fast_multiply"
1306 "smull%?\\t%3, %0, %2, %1"
1307 [(set_attr "type" "mult")
1308 (set_attr "predicable" "yes")]
1311 (define_insn "umulsi3_highpart"
1312 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1316 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1317 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1319 (clobber (match_scratch:SI 3 "=&r,&r"))]
1320 "TARGET_ARM && arm_fast_multiply"
1321 "umull%?\\t%3, %0, %2, %1"
1322 [(set_attr "type" "mult")
1323 (set_attr "predicable" "yes")]
1326 (define_insn "mulhisi3"
1327 [(set (match_operand:SI 0 "s_register_operand" "=r")
1328 (mult:SI (sign_extend:SI
1329 (match_operand:HI 1 "s_register_operand" "%r"))
1331 (match_operand:HI 2 "s_register_operand" "r"))))]
1332 "TARGET_ARM && arm_is_xscale"
1333 "smulbb%?\\t%0, %1, %2"
1334 [(set_attr "type" "mult")]
1337 (define_insn "*mulhisi3addsi"
1338 [(set (match_operand:SI 0 "s_register_operand" "=r")
1339 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1340 (mult:SI (sign_extend:SI
1341 (match_operand:HI 2 "s_register_operand" "%r"))
1343 (match_operand:HI 3 "s_register_operand" "r")))))]
1344 "TARGET_ARM && arm_is_xscale"
1345 "smlabb%?\\t%0, %2, %3, %1"
1346 [(set_attr "type" "mult")]
1349 (define_insn "*mulhidi3adddi"
1350 [(set (match_operand:DI 0 "s_register_operand" "=r")
1352 (match_operand:DI 1 "s_register_operand" "0")
1353 (mult:DI (sign_extend:DI
1354 (match_operand:HI 2 "s_register_operand" "%r"))
1356 (match_operand:HI 3 "s_register_operand" "r")))))]
1357 "TARGET_ARM && arm_is_xscale"
1358 "smlalbb%?\\t%Q0, %R0, %2, %3"
1359 [(set_attr "type" "mult")])
1361 (define_insn "mulsf3"
1362 [(set (match_operand:SF 0 "s_register_operand" "=f")
1363 (mult:SF (match_operand:SF 1 "s_register_operand" "f")
1364 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1365 "TARGET_ARM && TARGET_HARD_FLOAT"
1366 "fml%?s\\t%0, %1, %2"
1367 [(set_attr "type" "ffmul")
1368 (set_attr "predicable" "yes")]
1371 (define_insn "muldf3"
1372 [(set (match_operand:DF 0 "s_register_operand" "=f")
1373 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1374 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1375 "TARGET_ARM && TARGET_HARD_FLOAT"
1376 "muf%?d\\t%0, %1, %2"
1377 [(set_attr "type" "fmul")
1378 (set_attr "predicable" "yes")]
1381 (define_insn "*muldf_esfdf_df"
1382 [(set (match_operand:DF 0 "s_register_operand" "=f")
1383 (mult:DF (float_extend:DF
1384 (match_operand:SF 1 "s_register_operand" "f"))
1385 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1386 "TARGET_ARM && TARGET_HARD_FLOAT"
1387 "muf%?d\\t%0, %1, %2"
1388 [(set_attr "type" "fmul")
1389 (set_attr "predicable" "yes")]
1392 (define_insn "*muldf_df_esfdf"
1393 [(set (match_operand:DF 0 "s_register_operand" "=f")
1394 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1396 (match_operand:SF 2 "s_register_operand" "f"))))]
1397 "TARGET_ARM && TARGET_HARD_FLOAT"
1398 "muf%?d\\t%0, %1, %2"
1399 [(set_attr "type" "fmul")
1400 (set_attr "predicable" "yes")]
1403 (define_insn "*muldf_esfdf_esfdf"
1404 [(set (match_operand:DF 0 "s_register_operand" "=f")
1406 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f"))
1407 (float_extend:DF (match_operand:SF 2 "s_register_operand" "f"))))]
1408 "TARGET_ARM && TARGET_HARD_FLOAT"
1409 "muf%?d\\t%0, %1, %2"
1410 [(set_attr "type" "fmul")
1411 (set_attr "predicable" "yes")]
1414 (define_insn "mulxf3"
1415 [(set (match_operand:XF 0 "s_register_operand" "=f")
1416 (mult:XF (match_operand:XF 1 "s_register_operand" "f")
1417 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1418 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1419 "muf%?e\\t%0, %1, %2"
1420 [(set_attr "type" "fmul")
1421 (set_attr "predicable" "yes")]
1426 (define_insn "divsf3"
1427 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1428 (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1429 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1430 "TARGET_ARM && TARGET_HARD_FLOAT"
1433 frd%?s\\t%0, %2, %1"
1434 [(set_attr "type" "fdivs")
1435 (set_attr "predicable" "yes")]
1438 (define_insn "divdf3"
1439 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1440 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1441 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1442 "TARGET_ARM && TARGET_HARD_FLOAT"
1445 rdf%?d\\t%0, %2, %1"
1446 [(set_attr "type" "fdivd")
1447 (set_attr "predicable" "yes")]
1450 (define_insn "*divdf_esfdf_df"
1451 [(set (match_operand:DF 0 "s_register_operand" "=f")
1452 (div:DF (float_extend:DF
1453 (match_operand:SF 1 "s_register_operand" "f"))
1454 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1455 "TARGET_ARM && TARGET_HARD_FLOAT"
1456 "dvf%?d\\t%0, %1, %2"
1457 [(set_attr "type" "fdivd")
1458 (set_attr "predicable" "yes")]
1461 (define_insn "*divdf_df_esfdf"
1462 [(set (match_operand:DF 0 "s_register_operand" "=f")
1463 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1465 (match_operand:SF 2 "s_register_operand" "f"))))]
1466 "TARGET_ARM && TARGET_HARD_FLOAT"
1467 "rdf%?d\\t%0, %2, %1"
1468 [(set_attr "type" "fdivd")
1469 (set_attr "predicable" "yes")]
1472 (define_insn "*divdf_esfdf_esfdf"
1473 [(set (match_operand:DF 0 "s_register_operand" "=f")
1474 (div:DF (float_extend:DF
1475 (match_operand:SF 1 "s_register_operand" "f"))
1477 (match_operand:SF 2 "s_register_operand" "f"))))]
1478 "TARGET_ARM && TARGET_HARD_FLOAT"
1479 "dvf%?d\\t%0, %1, %2"
1480 [(set_attr "type" "fdivd")
1481 (set_attr "predicable" "yes")]
1484 (define_insn "divxf3"
1485 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1486 (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1487 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1488 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1491 rdf%?e\\t%0, %2, %1"
1492 [(set_attr "type" "fdivx")
1493 (set_attr "predicable" "yes")]
1498 (define_insn "modsf3"
1499 [(set (match_operand:SF 0 "s_register_operand" "=f")
1500 (mod:SF (match_operand:SF 1 "s_register_operand" "f")
1501 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1502 "TARGET_ARM && TARGET_HARD_FLOAT"
1503 "rmf%?s\\t%0, %1, %2"
1504 [(set_attr "type" "fdivs")
1505 (set_attr "predicable" "yes")]
1508 (define_insn "moddf3"
1509 [(set (match_operand:DF 0 "s_register_operand" "=f")
1510 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1511 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1512 "TARGET_ARM && TARGET_HARD_FLOAT"
1513 "rmf%?d\\t%0, %1, %2"
1514 [(set_attr "type" "fdivd")
1515 (set_attr "predicable" "yes")]
1518 (define_insn "*moddf_esfdf_df"
1519 [(set (match_operand:DF 0 "s_register_operand" "=f")
1520 (mod:DF (float_extend:DF
1521 (match_operand:SF 1 "s_register_operand" "f"))
1522 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1523 "TARGET_ARM && TARGET_HARD_FLOAT"
1524 "rmf%?d\\t%0, %1, %2"
1525 [(set_attr "type" "fdivd")
1526 (set_attr "predicable" "yes")]
1529 (define_insn "*moddf_df_esfdf"
1530 [(set (match_operand:DF 0 "s_register_operand" "=f")
1531 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1533 (match_operand:SF 2 "s_register_operand" "f"))))]
1534 "TARGET_ARM && TARGET_HARD_FLOAT"
1535 "rmf%?d\\t%0, %1, %2"
1536 [(set_attr "type" "fdivd")
1537 (set_attr "predicable" "yes")]
1540 (define_insn "*moddf_esfdf_esfdf"
1541 [(set (match_operand:DF 0 "s_register_operand" "=f")
1542 (mod:DF (float_extend:DF
1543 (match_operand:SF 1 "s_register_operand" "f"))
1545 (match_operand:SF 2 "s_register_operand" "f"))))]
1546 "TARGET_ARM && TARGET_HARD_FLOAT"
1547 "rmf%?d\\t%0, %1, %2"
1548 [(set_attr "type" "fdivd")
1549 (set_attr "predicable" "yes")]
1552 (define_insn "modxf3"
1553 [(set (match_operand:XF 0 "s_register_operand" "=f")
1554 (mod:XF (match_operand:XF 1 "s_register_operand" "f")
1555 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1556 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1557 "rmf%?e\\t%0, %1, %2"
1558 [(set_attr "type" "fdivx")
1559 (set_attr "predicable" "yes")]
1562 ;; Boolean and,ior,xor insns
1564 ;; Split up double word logical operations
1566 ;; Split up simple DImode logical operations. Simply perform the logical
1567 ;; operation on the upper and lower halves of the registers.
1569 [(set (match_operand:DI 0 "s_register_operand" "")
1570 (match_operator:DI 6 "logical_binary_operator"
1571 [(match_operand:DI 1 "s_register_operand" "")
1572 (match_operand:DI 2 "s_register_operand" "")]))]
1573 "TARGET_ARM && reload_completed"
1574 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1575 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1578 operands[3] = gen_highpart (SImode, operands[0]);
1579 operands[0] = gen_lowpart (SImode, operands[0]);
1580 operands[4] = gen_highpart (SImode, operands[1]);
1581 operands[1] = gen_lowpart (SImode, operands[1]);
1582 operands[5] = gen_highpart (SImode, operands[2]);
1583 operands[2] = gen_lowpart (SImode, operands[2]);
1588 [(set (match_operand:DI 0 "s_register_operand" "")
1589 (match_operator:DI 6 "logical_binary_operator"
1590 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1591 (match_operand:DI 1 "s_register_operand" "")]))]
1592 "TARGET_ARM && reload_completed"
1593 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1594 (set (match_dup 3) (match_op_dup:SI 6
1595 [(ashiftrt:SI (match_dup 2) (const_int 31))
1599 operands[3] = gen_highpart (SImode, operands[0]);
1600 operands[0] = gen_lowpart (SImode, operands[0]);
1601 operands[4] = gen_highpart (SImode, operands[1]);
1602 operands[1] = gen_lowpart (SImode, operands[1]);
1603 operands[5] = gen_highpart (SImode, operands[2]);
1604 operands[2] = gen_lowpart (SImode, operands[2]);
1608 ;; The zero extend of operand 2 means we can just copy the high part of
1609 ;; operand1 into operand0.
1611 [(set (match_operand:DI 0 "s_register_operand" "")
1613 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1614 (match_operand:DI 1 "s_register_operand" "")))]
1615 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1616 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1617 (set (match_dup 3) (match_dup 4))]
1620 operands[4] = gen_highpart (SImode, operands[1]);
1621 operands[3] = gen_highpart (SImode, operands[0]);
1622 operands[0] = gen_lowpart (SImode, operands[0]);
1623 operands[1] = gen_lowpart (SImode, operands[1]);
1627 ;; The zero extend of operand 2 means we can just copy the high part of
1628 ;; operand1 into operand0.
1630 [(set (match_operand:DI 0 "s_register_operand" "")
1632 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1633 (match_operand:DI 1 "s_register_operand" "")))]
1634 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1635 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1636 (set (match_dup 3) (match_dup 4))]
1639 operands[4] = gen_highpart (SImode, operands[1]);
1640 operands[3] = gen_highpart (SImode, operands[0]);
1641 operands[0] = gen_lowpart (SImode, operands[0]);
1642 operands[1] = gen_lowpart (SImode, operands[1]);
1646 (define_insn "anddi3"
1647 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1648 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1649 (match_operand:DI 2 "s_register_operand" "r,r")))]
1652 [(set_attr "length" "8")]
1655 (define_insn_and_split "*anddi_zesidi_di"
1656 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1657 (and:DI (zero_extend:DI
1658 (match_operand:SI 2 "s_register_operand" "r,r"))
1659 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1662 "TARGET_ARM && reload_completed"
1663 ; The zero extend of operand 2 clears the high word of the output
1665 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1666 (set (match_dup 3) (const_int 0))]
1669 operands[3] = gen_highpart (SImode, operands[0]);
1670 operands[0] = gen_lowpart (SImode, operands[0]);
1671 operands[1] = gen_lowpart (SImode, operands[1]);
1673 [(set_attr "length" "8")]
1676 (define_insn "*anddi_sesdi_di"
1677 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1678 (and:DI (sign_extend:DI
1679 (match_operand:SI 2 "s_register_operand" "r,r"))
1680 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1683 [(set_attr "length" "8")]
1686 (define_expand "andsi3"
1687 [(set (match_operand:SI 0 "s_register_operand" "")
1688 (and:SI (match_operand:SI 1 "s_register_operand" "")
1689 (match_operand:SI 2 "reg_or_int_operand" "")))]
1694 if (GET_CODE (operands[2]) == CONST_INT)
1696 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1699 ? 0 : preserve_subexpressions_p ()));
1703 else /* TARGET_THUMB */
1705 if (GET_CODE (operands[2]) != CONST_INT)
1706 operands[2] = force_reg (SImode, operands[2]);
1711 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1713 operands[2] = force_reg (SImode,
1714 GEN_INT (~INTVAL (operands[2])));
1716 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1721 for (i = 9; i <= 31; i++)
1723 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1725 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1729 else if ((((HOST_WIDE_INT) 1) << i) - 1
1730 == ~INTVAL (operands[2]))
1732 rtx shift = GEN_INT (i);
1733 rtx reg = gen_reg_rtx (SImode);
1735 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1736 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1742 operands[2] = force_reg (SImode, operands[2]);
1748 (define_insn_and_split "*arm_andsi3_insn"
1749 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1750 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1751 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1755 bic%?\\t%0, %1, #%B2
1758 && GET_CODE (operands[2]) == CONST_INT
1759 && !(const_ok_for_arm (INTVAL (operands[2]))
1760 || const_ok_for_arm (~INTVAL (operands[2])))"
1761 [(clobber (const_int 0))]
1763 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1767 [(set_attr "length" "4,4,16")
1768 (set_attr "predicable" "yes")]
1771 (define_insn "*thumb_andsi3_insn"
1772 [(set (match_operand:SI 0 "register_operand" "=l")
1773 (and:SI (match_operand:SI 1 "register_operand" "%0")
1774 (match_operand:SI 2 "register_operand" "l")))]
1777 [(set_attr "length" "2")]
1780 (define_insn "*andsi3_compare0"
1781 [(set (reg:CC_NOOV CC_REGNUM)
1783 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1784 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1786 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1787 (and:SI (match_dup 1) (match_dup 2)))]
1791 bic%?s\\t%0, %1, #%B2"
1792 [(set_attr "conds" "set")]
1795 (define_insn "*andsi3_compare0_scratch"
1796 [(set (reg:CC_NOOV CC_REGNUM)
1798 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1799 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1801 (clobber (match_scratch:SI 2 "=X,r"))]
1805 bic%?s\\t%2, %0, #%B1"
1806 [(set_attr "conds" "set")]
1809 (define_insn "*zeroextractsi_compare0_scratch"
1810 [(set (reg:CC_NOOV CC_REGNUM)
1811 (compare:CC_NOOV (zero_extract:SI
1812 (match_operand:SI 0 "s_register_operand" "r")
1813 (match_operand 1 "const_int_operand" "n")
1814 (match_operand 2 "const_int_operand" "n"))
1817 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1818 && INTVAL (operands[1]) > 0
1819 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1820 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1822 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1823 << INTVAL (operands[2]));
1824 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1827 [(set_attr "conds" "set")]
1830 (define_insn "*ne_zeroextractsi"
1831 [(set (match_operand:SI 0 "s_register_operand" "=r")
1832 (ne:SI (zero_extract:SI
1833 (match_operand:SI 1 "s_register_operand" "r")
1834 (match_operand:SI 2 "const_int_operand" "n")
1835 (match_operand:SI 3 "const_int_operand" "n"))
1838 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1839 && INTVAL (operands[2]) > 0
1840 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1841 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1843 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1844 << INTVAL (operands[3]));
1845 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1846 return \"movne\\t%0, #1\";
1848 [(set_attr "conds" "clob")
1849 (set_attr "length" "8")]
1852 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1853 ;;; represented by the bitfield, then this will produce incorrect results.
1854 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1855 ;;; which have a real bitfield insert instruction, the truncation happens
1856 ;;; in the bitfield insert instruction itself. Since arm does not have a
1857 ;;; bitfield insert instruction, we would have to emit code here to truncate
1858 ;;; the value before we insert. This loses some of the advantage of having
1859 ;;; this insv pattern, so this pattern needs to be reevalutated.
1861 (define_expand "insv"
1862 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1863 (match_operand:SI 1 "general_operand" "")
1864 (match_operand:SI 2 "general_operand" ""))
1865 (match_operand:SI 3 "nonmemory_operand" ""))]
1869 int start_bit = INTVAL (operands[2]);
1870 int width = INTVAL (operands[1]);
1871 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1872 rtx target, subtarget;
1874 target = operands[0];
1875 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1876 subreg as the final target. */
1877 if (GET_CODE (target) == SUBREG)
1879 subtarget = gen_reg_rtx (SImode);
1880 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1881 < GET_MODE_SIZE (SImode))
1882 target = SUBREG_REG (target);
1887 if (GET_CODE (operands[3]) == CONST_INT)
1889 /* Since we are inserting a known constant, we may be able to
1890 reduce the number of bits that we have to clear so that
1891 the mask becomes simple. */
1892 /* ??? This code does not check to see if the new mask is actually
1893 simpler. It may not be. */
1894 rtx op1 = gen_reg_rtx (SImode);
1895 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1896 start of this pattern. */
1897 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1898 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1900 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1901 emit_insn (gen_iorsi3 (subtarget, op1,
1902 GEN_INT (op3_value << start_bit)));
1904 else if (start_bit == 0
1905 && !(const_ok_for_arm (mask)
1906 || const_ok_for_arm (~mask)))
1908 /* A Trick, since we are setting the bottom bits in the word,
1909 we can shift operand[3] up, operand[0] down, OR them together
1910 and rotate the result back again. This takes 3 insns, and
1911 the third might be mergable into another op. */
1912 /* The shift up copes with the possibility that operand[3] is
1913 wider than the bitfield. */
1914 rtx op0 = gen_reg_rtx (SImode);
1915 rtx op1 = gen_reg_rtx (SImode);
1917 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1918 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1919 emit_insn (gen_iorsi3 (op1, op1, op0));
1920 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1922 else if ((width + start_bit == 32)
1923 && !(const_ok_for_arm (mask)
1924 || const_ok_for_arm (~mask)))
1926 /* Similar trick, but slightly less efficient. */
1928 rtx op0 = gen_reg_rtx (SImode);
1929 rtx op1 = gen_reg_rtx (SImode);
1931 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1932 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1933 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1934 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1938 rtx op0 = GEN_INT (mask);
1939 rtx op1 = gen_reg_rtx (SImode);
1940 rtx op2 = gen_reg_rtx (SImode);
1942 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1944 rtx tmp = gen_reg_rtx (SImode);
1946 emit_insn (gen_movsi (tmp, op0));
1950 /* Mask out any bits in operand[3] that are not needed. */
1951 emit_insn (gen_andsi3 (op1, operands[3], op0));
1953 if (GET_CODE (op0) == CONST_INT
1954 && (const_ok_for_arm (mask << start_bit)
1955 || const_ok_for_arm (~(mask << start_bit))))
1957 op0 = GEN_INT (~(mask << start_bit));
1958 emit_insn (gen_andsi3 (op2, operands[0], op0));
1962 if (GET_CODE (op0) == CONST_INT)
1964 rtx tmp = gen_reg_rtx (SImode);
1966 emit_insn (gen_movsi (tmp, op0));
1971 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1973 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1977 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1979 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1982 if (subtarget != target)
1984 /* If TARGET is still a SUBREG, then it must be wider than a word,
1985 so we must be careful only to set the subword we were asked to. */
1986 if (GET_CODE (target) == SUBREG)
1987 emit_move_insn (target, subtarget);
1989 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1996 ; constants for op 2 will never be given to these patterns.
1997 (define_insn_and_split "*anddi_notdi_di"
1998 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1999 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2000 (match_operand:DI 2 "s_register_operand" "0,r")))]
2003 "TARGET_ARM && reload_completed"
2004 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2005 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2008 operands[3] = gen_highpart (SImode, operands[0]);
2009 operands[0] = gen_lowpart (SImode, operands[0]);
2010 operands[4] = gen_highpart (SImode, operands[1]);
2011 operands[1] = gen_lowpart (SImode, operands[1]);
2012 operands[5] = gen_highpart (SImode, operands[2]);
2013 operands[2] = gen_lowpart (SImode, operands[2]);
2015 [(set_attr "length" "8")
2016 (set_attr "predicable" "yes")]
2019 (define_insn_and_split "*anddi_notzesidi_di"
2020 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2021 (and:DI (not:DI (zero_extend:DI
2022 (match_operand:SI 2 "s_register_operand" "r,r")))
2023 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2026 bic%?\\t%Q0, %Q1, %2
2028 ; (not (zero_extend ...)) allows us to just copy the high word from
2029 ; operand1 to operand0.
2032 && operands[0] != operands[1]"
2033 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2034 (set (match_dup 3) (match_dup 4))]
2037 operands[3] = gen_highpart (SImode, operands[0]);
2038 operands[0] = gen_lowpart (SImode, operands[0]);
2039 operands[4] = gen_highpart (SImode, operands[1]);
2040 operands[1] = gen_lowpart (SImode, operands[1]);
2042 [(set_attr "length" "4,8")
2043 (set_attr "predicable" "yes")]
2046 (define_insn_and_split "*anddi_notsesidi_di"
2047 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2048 (and:DI (not:DI (sign_extend:DI
2049 (match_operand:SI 2 "s_register_operand" "r,r")))
2050 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2053 "TARGET_ARM && reload_completed"
2054 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2055 (set (match_dup 3) (and:SI (not:SI
2056 (ashiftrt:SI (match_dup 2) (const_int 31)))
2060 operands[3] = gen_highpart (SImode, operands[0]);
2061 operands[0] = gen_lowpart (SImode, operands[0]);
2062 operands[4] = gen_highpart (SImode, operands[1]);
2063 operands[1] = gen_lowpart (SImode, operands[1]);
2065 [(set_attr "length" "8")
2066 (set_attr "predicable" "yes")]
2069 (define_insn "andsi_notsi_si"
2070 [(set (match_operand:SI 0 "s_register_operand" "=r")
2071 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2072 (match_operand:SI 1 "s_register_operand" "r")))]
2074 "bic%?\\t%0, %1, %2"
2075 [(set_attr "predicable" "yes")]
2078 (define_insn "bicsi3"
2079 [(set (match_operand:SI 0 "register_operand" "=l")
2080 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2081 (match_operand:SI 2 "register_operand" "0")))]
2084 [(set_attr "length" "2")]
2087 (define_insn "andsi_not_shiftsi_si"
2088 [(set (match_operand:SI 0 "s_register_operand" "=r")
2089 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2090 [(match_operand:SI 2 "s_register_operand" "r")
2091 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2092 (match_operand:SI 1 "s_register_operand" "r")))]
2094 "bic%?\\t%0, %1, %2%S4"
2095 [(set_attr "predicable" "yes")
2096 (set_attr "shift" "2")
2100 (define_insn "*andsi_notsi_si_compare0"
2101 [(set (reg:CC_NOOV CC_REGNUM)
2103 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2104 (match_operand:SI 1 "s_register_operand" "r"))
2106 (set (match_operand:SI 0 "s_register_operand" "=r")
2107 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2109 "bic%?s\\t%0, %1, %2"
2110 [(set_attr "conds" "set")]
2113 (define_insn "*andsi_notsi_si_compare0_scratch"
2114 [(set (reg:CC_NOOV CC_REGNUM)
2116 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2117 (match_operand:SI 1 "s_register_operand" "r"))
2119 (clobber (match_scratch:SI 0 "=r"))]
2121 "bic%?s\\t%0, %1, %2"
2122 [(set_attr "conds" "set")]
2125 (define_insn "iordi3"
2126 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2127 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2128 (match_operand:DI 2 "s_register_operand" "r,r")))]
2131 [(set_attr "length" "8")
2132 (set_attr "predicable" "yes")]
2135 (define_insn "*iordi_zesidi_di"
2136 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2137 (ior:DI (zero_extend:DI
2138 (match_operand:SI 2 "s_register_operand" "r,r"))
2139 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2142 orr%?\\t%Q0, %Q1, %2
2144 [(set_attr "length" "4,8")
2145 (set_attr "predicable" "yes")]
2148 (define_insn "*iordi_sesidi_di"
2149 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2150 (ior:DI (sign_extend:DI
2151 (match_operand:SI 2 "s_register_operand" "r,r"))
2152 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2155 [(set_attr "length" "8")
2156 (set_attr "predicable" "yes")]
2159 (define_expand "iorsi3"
2160 [(set (match_operand:SI 0 "s_register_operand" "")
2161 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2162 (match_operand:SI 2 "reg_or_int_operand" "")))]
2165 if (GET_CODE (operands[2]) == CONST_INT)
2169 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2172 ? 0 : preserve_subexpressions_p ()));
2175 else /* TARGET_THUMB */
2176 operands [2] = force_reg (SImode, operands [2]);
2181 (define_insn_and_split "*arm_iorsi3"
2182 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2183 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2184 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2190 && GET_CODE (operands[2]) == CONST_INT
2191 && !const_ok_for_arm (INTVAL (operands[2]))"
2192 [(clobber (const_int 0))]
2194 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2198 [(set_attr "length" "4,16")
2199 (set_attr "predicable" "yes")]
2202 (define_insn "*thumb_iorsi3"
2203 [(set (match_operand:SI 0 "register_operand" "=l")
2204 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2205 (match_operand:SI 2 "register_operand" "l")))]
2208 [(set_attr "length" "2")]
2212 [(match_scratch:SI 3 "r")
2213 (set (match_operand:SI 0 "s_register_operand" "")
2214 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2215 (match_operand:SI 2 "const_int_operand" "")))]
2217 && !const_ok_for_arm (INTVAL (operands[2]))
2218 && const_ok_for_arm (~INTVAL (operands[2]))"
2219 [(set (match_dup 3) (match_dup 2))
2220 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2224 (define_insn "*iorsi3_compare0"
2225 [(set (reg:CC_NOOV CC_REGNUM)
2226 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2227 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2229 (set (match_operand:SI 0 "s_register_operand" "=r")
2230 (ior:SI (match_dup 1) (match_dup 2)))]
2232 "orr%?s\\t%0, %1, %2"
2233 [(set_attr "conds" "set")]
2236 (define_insn "*iorsi3_compare0_scratch"
2237 [(set (reg:CC_NOOV CC_REGNUM)
2238 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2239 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2241 (clobber (match_scratch:SI 0 "=r"))]
2243 "orr%?s\\t%0, %1, %2"
2244 [(set_attr "conds" "set")]
2247 (define_insn "xordi3"
2248 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2249 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2250 (match_operand:DI 2 "s_register_operand" "r,r")))]
2253 [(set_attr "length" "8")
2254 (set_attr "predicable" "yes")]
2257 (define_insn "*xordi_zesidi_di"
2258 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2259 (xor:DI (zero_extend:DI
2260 (match_operand:SI 2 "s_register_operand" "r,r"))
2261 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2264 eor%?\\t%Q0, %Q1, %2
2266 [(set_attr "length" "4,8")
2267 (set_attr "predicable" "yes")]
2270 (define_insn "*xordi_sesidi_di"
2271 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2272 (xor:DI (sign_extend:DI
2273 (match_operand:SI 2 "s_register_operand" "r,r"))
2274 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2277 [(set_attr "length" "8")
2278 (set_attr "predicable" "yes")]
2281 (define_expand "xorsi3"
2282 [(set (match_operand:SI 0 "s_register_operand" "")
2283 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2284 (match_operand:SI 2 "arm_rhs_operand" "")))]
2287 if (GET_CODE (operands[2]) == CONST_INT)
2288 operands[2] = force_reg (SImode, operands[2]);
2292 (define_insn "*arm_xorsi3"
2293 [(set (match_operand:SI 0 "s_register_operand" "=r")
2294 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2295 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2297 "eor%?\\t%0, %1, %2"
2298 [(set_attr "predicable" "yes")]
2301 (define_insn "*thumb_xorsi3"
2302 [(set (match_operand:SI 0 "register_operand" "=l")
2303 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2304 (match_operand:SI 2 "register_operand" "l")))]
2307 [(set_attr "length" "2")]
2310 (define_insn "*xorsi3_compare0"
2311 [(set (reg:CC_NOOV CC_REGNUM)
2312 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2313 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2315 (set (match_operand:SI 0 "s_register_operand" "=r")
2316 (xor:SI (match_dup 1) (match_dup 2)))]
2318 "eor%?s\\t%0, %1, %2"
2319 [(set_attr "conds" "set")]
2322 (define_insn "*xorsi3_compare0_scratch"
2323 [(set (reg:CC_NOOV CC_REGNUM)
2324 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2325 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2329 [(set_attr "conds" "set")]
2332 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2333 ; (NOT D) we can sometimes merge the final NOT into one of the following
2337 [(set (match_operand:SI 0 "s_register_operand" "=r")
2338 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2339 (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
2340 (match_operand:SI 3 "arm_rhs_operand" "rI")))
2341 (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
2343 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2344 (not:SI (match_dup 3))))
2345 (set (match_dup 0) (not:SI (match_dup 4)))]
2349 (define_insn "*andsi_iorsi3_notsi"
2350 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2351 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2352 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2353 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2355 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2356 [(set_attr "length" "8")
2357 (set_attr "predicable" "yes")]
2362 ;; Minimum and maximum insns
2364 (define_insn "smaxsi3"
2365 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2366 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2367 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2368 (clobber (reg:CC CC_REGNUM))]
2371 cmp\\t%1, %2\;movlt\\t%0, %2
2372 cmp\\t%1, %2\;movge\\t%0, %1
2373 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2374 [(set_attr "conds" "clob")
2375 (set_attr "length" "8,8,12")]
2378 (define_insn "sminsi3"
2379 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2380 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2381 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2382 (clobber (reg:CC CC_REGNUM))]
2385 cmp\\t%1, %2\;movge\\t%0, %2
2386 cmp\\t%1, %2\;movlt\\t%0, %1
2387 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2388 [(set_attr "conds" "clob")
2389 (set_attr "length" "8,8,12")]
2392 (define_insn "umaxsi3"
2393 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2394 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2395 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2396 (clobber (reg:CC CC_REGNUM))]
2399 cmp\\t%1, %2\;movcc\\t%0, %2
2400 cmp\\t%1, %2\;movcs\\t%0, %1
2401 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2402 [(set_attr "conds" "clob")
2403 (set_attr "length" "8,8,12")]
2406 (define_insn "uminsi3"
2407 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2408 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2409 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2410 (clobber (reg:CC CC_REGNUM))]
2413 cmp\\t%1, %2\;movcs\\t%0, %2
2414 cmp\\t%1, %2\;movcc\\t%0, %1
2415 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2416 [(set_attr "conds" "clob")
2417 (set_attr "length" "8,8,12")]
2420 (define_insn "*store_minmaxsi"
2421 [(set (match_operand:SI 0 "memory_operand" "=m")
2422 (match_operator:SI 3 "minmax_operator"
2423 [(match_operand:SI 1 "s_register_operand" "r")
2424 (match_operand:SI 2 "s_register_operand" "r")]))
2425 (clobber (reg:CC CC_REGNUM))]
2428 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2430 output_asm_insn (\"cmp\\t%1, %2\", operands);
2431 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2432 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2435 [(set_attr "conds" "clob")
2436 (set_attr "length" "12")
2437 (set_attr "type" "store1")]
2440 ; Reject the frame pointer in operand[1], since reloading this after
2441 ; it has been eliminated can cause carnage.
2442 (define_insn "*minmax_arithsi"
2443 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2444 (match_operator:SI 4 "shiftable_operator"
2445 [(match_operator:SI 5 "minmax_operator"
2446 [(match_operand:SI 2 "s_register_operand" "r,r")
2447 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2448 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2449 (clobber (reg:CC CC_REGNUM))]
2451 && (GET_CODE (operands[1]) != REG
2452 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2453 && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2456 enum rtx_code code = GET_CODE (operands[4]);
2458 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2460 output_asm_insn (\"cmp\\t%2, %3\", operands);
2461 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2462 if (which_alternative != 0 || operands[3] != const0_rtx
2463 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2464 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2467 [(set_attr "conds" "clob")
2468 (set_attr "length" "12")]
2472 ;; Shift and rotation insns
2474 (define_expand "ashlsi3"
2475 [(set (match_operand:SI 0 "s_register_operand" "")
2476 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2477 (match_operand:SI 2 "arm_rhs_operand" "")))]
2480 if (GET_CODE (operands[2]) == CONST_INT
2481 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2483 emit_insn (gen_movsi (operands[0], const0_rtx));
2489 (define_insn "*thumb_ashlsi3"
2490 [(set (match_operand:SI 0 "register_operand" "=l,l")
2491 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2492 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2495 [(set_attr "length" "2")]
2498 (define_expand "ashrsi3"
2499 [(set (match_operand:SI 0 "s_register_operand" "")
2500 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2501 (match_operand:SI 2 "arm_rhs_operand" "")))]
2504 if (GET_CODE (operands[2]) == CONST_INT
2505 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2506 operands[2] = GEN_INT (31);
2510 (define_insn "*thumb_ashrsi3"
2511 [(set (match_operand:SI 0 "register_operand" "=l,l")
2512 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2513 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2516 [(set_attr "length" "2")]
2519 (define_expand "lshrsi3"
2520 [(set (match_operand:SI 0 "s_register_operand" "")
2521 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2522 (match_operand:SI 2 "arm_rhs_operand" "")))]
2525 if (GET_CODE (operands[2]) == CONST_INT
2526 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2528 emit_insn (gen_movsi (operands[0], const0_rtx));
2534 (define_insn "*thumb_lshrsi3"
2535 [(set (match_operand:SI 0 "register_operand" "=l,l")
2536 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2537 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2540 [(set_attr "length" "2")]
2543 (define_expand "rotlsi3"
2544 [(set (match_operand:SI 0 "s_register_operand" "")
2545 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2546 (match_operand:SI 2 "reg_or_int_operand" "")))]
2549 if (GET_CODE (operands[2]) == CONST_INT)
2550 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2553 rtx reg = gen_reg_rtx (SImode);
2554 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2560 (define_expand "rotrsi3"
2561 [(set (match_operand:SI 0 "s_register_operand" "")
2562 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2563 (match_operand:SI 2 "arm_rhs_operand" "")))]
2568 if (GET_CODE (operands[2]) == CONST_INT
2569 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2570 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2572 else /* TARGET_THUMB */
2574 if (GET_CODE (operands [2]) == CONST_INT)
2575 operands [2] = force_reg (SImode, operands[2]);
2580 (define_insn "*thumb_rotrsi3"
2581 [(set (match_operand:SI 0 "register_operand" "=l")
2582 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2583 (match_operand:SI 2 "register_operand" "l")))]
2586 [(set_attr "length" "2")]
2589 (define_insn "*arm_shiftsi3"
2590 [(set (match_operand:SI 0 "s_register_operand" "=r")
2591 (match_operator:SI 3 "shift_operator"
2592 [(match_operand:SI 1 "s_register_operand" "r")
2593 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2596 [(set_attr "predicable" "yes")
2597 (set_attr "shift" "1")
2601 (define_insn "*shiftsi3_compare0"
2602 [(set (reg:CC_NOOV CC_REGNUM)
2603 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2604 [(match_operand:SI 1 "s_register_operand" "r")
2605 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2607 (set (match_operand:SI 0 "s_register_operand" "=r")
2608 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2610 "mov%?s\\t%0, %1%S3"
2611 [(set_attr "conds" "set")
2612 (set_attr "shift" "1")
2616 (define_insn "*shiftsi3_compare0_scratch"
2617 [(set (reg:CC_NOOV CC_REGNUM)
2618 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2619 [(match_operand:SI 1 "s_register_operand" "r")
2620 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2622 (clobber (match_scratch:SI 0 "=r"))]
2624 "mov%?s\\t%0, %1%S3"
2625 [(set_attr "conds" "set")
2626 (set_attr "shift" "1")
2630 (define_insn "*notsi_shiftsi"
2631 [(set (match_operand:SI 0 "s_register_operand" "=r")
2632 (not:SI (match_operator:SI 3 "shift_operator"
2633 [(match_operand:SI 1 "s_register_operand" "r")
2634 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2637 [(set_attr "predicable" "yes")
2638 (set_attr "shift" "1")
2642 (define_insn "*notsi_shiftsi_compare0"
2643 [(set (reg:CC_NOOV CC_REGNUM)
2644 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2645 [(match_operand:SI 1 "s_register_operand" "r")
2646 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2648 (set (match_operand:SI 0 "s_register_operand" "=r")
2649 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2651 "mvn%?s\\t%0, %1%S3"
2652 [(set_attr "conds" "set")
2653 (set_attr "shift" "1")
2657 (define_insn "*not_shiftsi_compare0_scratch"
2658 [(set (reg:CC_NOOV CC_REGNUM)
2659 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2660 [(match_operand:SI 1 "s_register_operand" "r")
2661 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2663 (clobber (match_scratch:SI 0 "=r"))]
2665 "mvn%?s\\t%0, %1%S3"
2666 [(set_attr "conds" "set")
2667 (set_attr "shift" "1")
2671 ;; We don't really have extzv, but defining this using shifts helps
2672 ;; to reduce register pressure later on.
2674 (define_expand "extzv"
2676 (ashift:SI (match_operand:SI 1 "register_operand" "")
2677 (match_operand:SI 2 "const_int_operand" "")))
2678 (set (match_operand:SI 0 "register_operand" "")
2679 (lshiftrt:SI (match_dup 4)
2680 (match_operand:SI 3 "const_int_operand" "")))]
2684 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2685 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2687 operands[3] = GEN_INT (rshift);
2691 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2695 operands[2] = GEN_INT (lshift);
2696 operands[4] = gen_reg_rtx (SImode);
2701 ;; Unary arithmetic insns
2703 (define_expand "negdi2"
2705 [(set (match_operand:DI 0 "s_register_operand" "")
2706 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2707 (clobber (reg:CC CC_REGNUM))])]
2712 if (GET_CODE (operands[1]) != REG)
2713 operands[1] = force_reg (SImode, operands[1]);
2718 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2719 ;; The second alternative is to allow the common case of a *full* overlap.
2720 (define_insn "*arm_negdi2"
2721 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2722 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2723 (clobber (reg:CC CC_REGNUM))]
2725 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2726 [(set_attr "conds" "clob")
2727 (set_attr "length" "8")]
2730 (define_insn "*thumb_negdi2"
2731 [(set (match_operand:DI 0 "register_operand" "=&l")
2732 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2733 (clobber (reg:CC CC_REGNUM))]
2735 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2736 [(set_attr "length" "6")]
2739 (define_expand "negsi2"
2740 [(set (match_operand:SI 0 "s_register_operand" "")
2741 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2746 (define_insn "*arm_negsi2"
2747 [(set (match_operand:SI 0 "s_register_operand" "=r")
2748 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2750 "rsb%?\\t%0, %1, #0"
2751 [(set_attr "predicable" "yes")]
2754 (define_insn "*thumb_negsi2"
2755 [(set (match_operand:SI 0 "register_operand" "=l")
2756 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2759 [(set_attr "length" "2")]
2762 (define_insn "negsf2"
2763 [(set (match_operand:SF 0 "s_register_operand" "=f")
2764 (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
2765 "TARGET_ARM && TARGET_HARD_FLOAT"
2767 [(set_attr "type" "ffarith")
2768 (set_attr "predicable" "yes")]
2771 (define_insn "negdf2"
2772 [(set (match_operand:DF 0 "s_register_operand" "=f")
2773 (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
2774 "TARGET_ARM && TARGET_HARD_FLOAT"
2776 [(set_attr "type" "ffarith")
2777 (set_attr "predicable" "yes")]
2780 (define_insn "*negdf_esfdf"
2781 [(set (match_operand:DF 0 "s_register_operand" "=f")
2782 (neg:DF (float_extend:DF
2783 (match_operand:SF 1 "s_register_operand" "f"))))]
2784 "TARGET_ARM && TARGET_HARD_FLOAT"
2786 [(set_attr "type" "ffarith")
2787 (set_attr "predicable" "yes")]
2790 (define_insn "negxf2"
2791 [(set (match_operand:XF 0 "s_register_operand" "=f")
2792 (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
2793 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2795 [(set_attr "type" "ffarith")
2796 (set_attr "predicable" "yes")]
2799 ;; abssi2 doesn't really clobber the condition codes if a different register
2800 ;; is being set. To keep things simple, assume during rtl manipulations that
2801 ;; it does, but tell the final scan operator the truth. Similarly for
2804 (define_insn "abssi2"
2805 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2806 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2807 (clobber (reg:CC CC_REGNUM))]
2810 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2811 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2812 [(set_attr "conds" "clob,*")
2813 (set_attr "shift" "1")
2814 ;; predicable can't be set based on the variant, so left as no
2815 (set_attr "length" "8")]
2818 (define_insn "*neg_abssi2"
2819 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2820 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2821 (clobber (reg:CC CC_REGNUM))]
2824 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2825 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2826 [(set_attr "conds" "clob,*")
2827 (set_attr "shift" "1")
2828 ;; predicable can't be set based on the variant, so left as no
2829 (set_attr "length" "8")]
2832 (define_insn "abssf2"
2833 [(set (match_operand:SF 0 "s_register_operand" "=f")
2834 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
2835 "TARGET_ARM && TARGET_HARD_FLOAT"
2837 [(set_attr "type" "ffarith")
2838 (set_attr "predicable" "yes")]
2841 (define_insn "absdf2"
2842 [(set (match_operand:DF 0 "s_register_operand" "=f")
2843 (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
2844 "TARGET_ARM && TARGET_HARD_FLOAT"
2846 [(set_attr "type" "ffarith")
2847 (set_attr "predicable" "yes")]
2850 (define_insn "*absdf_esfdf"
2851 [(set (match_operand:DF 0 "s_register_operand" "=f")
2852 (abs:DF (float_extend:DF
2853 (match_operand:SF 1 "s_register_operand" "f"))))]
2854 "TARGET_ARM && TARGET_HARD_FLOAT"
2856 [(set_attr "type" "ffarith")
2857 (set_attr "predicable" "yes")]
2860 (define_insn "absxf2"
2861 [(set (match_operand:XF 0 "s_register_operand" "=f")
2862 (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
2863 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2865 [(set_attr "type" "ffarith")
2866 (set_attr "predicable" "yes")]
2869 (define_insn "sqrtsf2"
2870 [(set (match_operand:SF 0 "s_register_operand" "=f")
2871 (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
2872 "TARGET_ARM && TARGET_HARD_FLOAT"
2874 [(set_attr "type" "float_em")
2875 (set_attr "predicable" "yes")]
2878 (define_insn "sqrtdf2"
2879 [(set (match_operand:DF 0 "s_register_operand" "=f")
2880 (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
2881 "TARGET_ARM && TARGET_HARD_FLOAT"
2883 [(set_attr "type" "float_em")
2884 (set_attr "predicable" "yes")]
2887 (define_insn "*sqrtdf_esfdf"
2888 [(set (match_operand:DF 0 "s_register_operand" "=f")
2889 (sqrt:DF (float_extend:DF
2890 (match_operand:SF 1 "s_register_operand" "f"))))]
2891 "TARGET_ARM && TARGET_HARD_FLOAT"
2893 [(set_attr "type" "float_em")
2894 (set_attr "predicable" "yes")]
2897 (define_insn "sqrtxf2"
2898 [(set (match_operand:XF 0 "s_register_operand" "=f")
2899 (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
2900 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2902 [(set_attr "type" "float_em")
2903 (set_attr "predicable" "yes")]
2906 ;; SIN COS TAN and family are always emulated, so it's probably better
2907 ;; to always call a library function.
2908 ;(define_insn "sinsf2"
2909 ; [(set (match_operand:SF 0 "s_register_operand" "=f")
2910 ; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
2912 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2914 ;[(set_attr "type" "float_em")])
2916 ;(define_insn "sindf2"
2917 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2918 ; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
2920 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2922 ;[(set_attr "type" "float_em")])
2924 ;(define_insn "*sindf_esfdf"
2925 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2926 ; (unspec:DF [(float_extend:DF
2927 ; (match_operand:SF 1 "s_register_operand" "f"))]
2929 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2931 ;[(set_attr "type" "float_em")])
2933 ;(define_insn "sinxf2"
2934 ; [(set (match_operand:XF 0 "s_register_operand" "=f")
2935 ; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
2937 ; "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2939 ;[(set_attr "type" "float_em")])
2941 ;(define_insn "cossf2"
2942 ; [(set (match_operand:SF 0 "s_register_operand" "=f")
2943 ; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
2945 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2947 ;[(set_attr "type" "float_em")])
2949 ;(define_insn "cosdf2"
2950 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2951 ; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
2953 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2955 ;[(set_attr "type" "float_em")])
2957 ;(define_insn "*cosdf_esfdf"
2958 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2959 ; (unspec:DF [(float_extend:DF
2960 ; (match_operand:SF 1 "s_register_operand" "f"))]
2962 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2964 ;[(set_attr "type" "float_em")])
2966 ;(define_insn "cosxf2"
2967 ; [(set (match_operand:XF 0 "s_register_operand" "=f")
2968 ; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
2970 ; "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2972 ;[(set_attr "type" "float_em")])
2974 (define_insn_and_split "one_cmpldi2"
2975 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2976 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2979 "TARGET_ARM && reload_completed"
2980 [(set (match_dup 0) (not:SI (match_dup 1)))
2981 (set (match_dup 2) (not:SI (match_dup 3)))]
2984 operands[2] = gen_highpart (SImode, operands[0]);
2985 operands[0] = gen_lowpart (SImode, operands[0]);
2986 operands[3] = gen_highpart (SImode, operands[1]);
2987 operands[1] = gen_lowpart (SImode, operands[1]);
2989 [(set_attr "length" "8")
2990 (set_attr "predicable" "yes")]
2993 (define_expand "one_cmplsi2"
2994 [(set (match_operand:SI 0 "s_register_operand" "")
2995 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3000 (define_insn "*arm_one_cmplsi2"
3001 [(set (match_operand:SI 0 "s_register_operand" "=r")
3002 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
3005 [(set_attr "predicable" "yes")]
3008 (define_insn "*thumb_one_cmplsi2"
3009 [(set (match_operand:SI 0 "register_operand" "=l")
3010 (not:SI (match_operand:SI 1 "register_operand" "l")))]
3013 [(set_attr "length" "2")]
3016 (define_insn "*notsi_compare0"
3017 [(set (reg:CC_NOOV CC_REGNUM)
3018 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3020 (set (match_operand:SI 0 "s_register_operand" "=r")
3021 (not:SI (match_dup 1)))]
3024 [(set_attr "conds" "set")]
3027 (define_insn "*notsi_compare0_scratch"
3028 [(set (reg:CC_NOOV CC_REGNUM)
3029 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3031 (clobber (match_scratch:SI 0 "=r"))]
3034 [(set_attr "conds" "set")]
3037 ;; Fixed <--> Floating conversion insns
3039 (define_insn "floatsisf2"
3040 [(set (match_operand:SF 0 "s_register_operand" "=f")
3041 (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
3042 "TARGET_ARM && TARGET_HARD_FLOAT"
3044 [(set_attr "type" "r_2_f")
3045 (set_attr "predicable" "yes")]
3048 (define_insn "floatsidf2"
3049 [(set (match_operand:DF 0 "s_register_operand" "=f")
3050 (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
3051 "TARGET_ARM && TARGET_HARD_FLOAT"
3053 [(set_attr "type" "r_2_f")
3054 (set_attr "predicable" "yes")]
3057 (define_insn "floatsixf2"
3058 [(set (match_operand:XF 0 "s_register_operand" "=f")
3059 (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
3060 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3062 [(set_attr "type" "r_2_f")
3063 (set_attr "predicable" "yes")]
3066 (define_insn "fix_truncsfsi2"
3067 [(set (match_operand:SI 0 "s_register_operand" "=r")
3068 (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
3069 "TARGET_ARM && TARGET_HARD_FLOAT"
3071 [(set_attr "type" "f_2_r")
3072 (set_attr "predicable" "yes")]
3075 (define_insn "fix_truncdfsi2"
3076 [(set (match_operand:SI 0 "s_register_operand" "=r")
3077 (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
3078 "TARGET_ARM && TARGET_HARD_FLOAT"
3080 [(set_attr "type" "f_2_r")
3081 (set_attr "predicable" "yes")]
3084 (define_insn "fix_truncxfsi2"
3085 [(set (match_operand:SI 0 "s_register_operand" "=r")
3086 (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
3087 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3089 [(set_attr "type" "f_2_r")
3090 (set_attr "predicable" "yes")]
3095 (define_insn "truncdfsf2"
3096 [(set (match_operand:SF 0 "s_register_operand" "=f")
3098 (match_operand:DF 1 "s_register_operand" "f")))]
3099 "TARGET_ARM && TARGET_HARD_FLOAT"
3101 [(set_attr "type" "ffarith")
3102 (set_attr "predicable" "yes")]
3105 (define_insn "truncxfsf2"
3106 [(set (match_operand:SF 0 "s_register_operand" "=f")
3108 (match_operand:XF 1 "s_register_operand" "f")))]
3109 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3111 [(set_attr "type" "ffarith")
3112 (set_attr "predicable" "yes")]
3115 (define_insn "truncxfdf2"
3116 [(set (match_operand:DF 0 "s_register_operand" "=f")
3118 (match_operand:XF 1 "s_register_operand" "f")))]
3119 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3121 [(set_attr "type" "ffarith")
3122 (set_attr "predicable" "yes")]
3125 ;; Zero and sign extension instructions.
3127 (define_insn "zero_extendsidi2"
3128 [(set (match_operand:DI 0 "s_register_operand" "=r")
3129 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3132 if (REGNO (operands[1])
3133 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3134 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3135 return \"mov%?\\t%R0, #0\";
3137 [(set_attr "length" "8")
3138 (set_attr "predicable" "yes")]
3141 (define_insn "zero_extendqidi2"
3142 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
3143 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3146 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3147 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3148 [(set_attr "length" "8")
3149 (set_attr "predicable" "yes")
3150 (set_attr "type" "*,load")
3151 (set_attr "pool_range" "*,4092")
3152 (set_attr "neg_pool_range" "*,4084")]
3155 (define_insn "extendsidi2"
3156 [(set (match_operand:DI 0 "s_register_operand" "=r")
3157 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3160 if (REGNO (operands[1])
3161 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3162 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3163 return \"mov%?\\t%R0, %Q0, asr #31\";
3165 [(set_attr "length" "8")
3166 (set_attr "shift" "1")
3167 (set_attr "predicable" "yes")]
3170 (define_expand "zero_extendhisi2"
3172 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3174 (set (match_operand:SI 0 "s_register_operand" "")
3175 (lshiftrt:SI (match_dup 2) (const_int 16)))]
3181 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3183 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3184 here because the insn below will generate an LDRH instruction
3185 rather than an LDR instruction, so we cannot get an unaligned
3187 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3188 gen_rtx_ZERO_EXTEND (SImode,
3192 if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3194 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3197 if (!s_register_operand (operands[1], HImode))
3198 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3199 operands[1] = gen_lowpart (SImode, operands[1]);
3200 operands[2] = gen_reg_rtx (SImode);
3202 else /* TARGET_THUMB */
3204 if (GET_CODE (operands[1]) == MEM)
3208 tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3209 tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3216 if (!s_register_operand (operands[1], HImode))
3217 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3218 operands[1] = gen_lowpart (SImode, operands[1]);
3219 operands[2] = gen_reg_rtx (SImode);
3221 ops[0] = operands[2];
3222 ops[1] = operands[1];
3223 ops[2] = GEN_INT (16);
3225 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3226 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3228 ops[0] = operands[0];
3229 ops[1] = operands[2];
3230 ops[2] = GEN_INT (16);
3232 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3233 gen_rtx_LSHIFTRT (SImode, ops[1],
3241 (define_insn "*thumb_zero_extendhisi2"
3242 [(set (match_operand:SI 0 "register_operand" "=l")
3243 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3246 rtx mem = XEXP (operands[1], 0);
3248 if (GET_CODE (mem) == CONST)
3249 mem = XEXP (mem, 0);
3251 if (GET_CODE (mem) == LABEL_REF)
3252 return \"ldr\\t%0, %1\";
3254 if (GET_CODE (mem) == PLUS)
3256 rtx a = XEXP (mem, 0);
3257 rtx b = XEXP (mem, 1);
3259 /* This can happen due to bugs in reload. */
3260 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3263 ops[0] = operands[0];
3266 output_asm_insn (\"mov %0, %1\", ops);
3268 XEXP (mem, 0) = operands[0];
3271 else if ( GET_CODE (a) == LABEL_REF
3272 && GET_CODE (b) == CONST_INT)
3273 return \"ldr\\t%0, %1\";
3276 return \"ldrh\\t%0, %1\";
3278 [(set_attr "length" "4")
3279 (set_attr "type" "load")
3280 (set_attr "pool_range" "60")]
3283 (define_insn "*arm_zero_extendhisi2"
3284 [(set (match_operand:SI 0 "s_register_operand" "=r")
3285 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3286 "TARGET_ARM && arm_arch4"
3288 [(set_attr "type" "load")
3289 (set_attr "predicable" "yes")
3290 (set_attr "pool_range" "256")
3291 (set_attr "neg_pool_range" "244")]
3295 [(set (match_operand:SI 0 "s_register_operand" "")
3296 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3297 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3298 "TARGET_ARM && (!arm_arch4)"
3299 [(set (match_dup 2) (match_dup 1))
3300 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3302 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3308 [(set (match_operand:SI 0 "s_register_operand" "")
3309 (match_operator:SI 3 "shiftable_operator"
3310 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3311 (match_operand:SI 4 "s_register_operand" "")]))
3312 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3313 "TARGET_ARM && (!arm_arch4)"
3314 [(set (match_dup 2) (match_dup 1))
3317 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3319 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3324 (define_expand "zero_extendqisi2"
3325 [(set (match_operand:SI 0 "s_register_operand" "")
3326 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3329 if (GET_CODE (operands[1]) != MEM)
3333 emit_insn (gen_andsi3 (operands[0],
3334 gen_lowpart (SImode, operands[1]),
3337 else /* TARGET_THUMB */
3339 rtx temp = gen_reg_rtx (SImode);
3342 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3343 operands[1] = gen_lowpart (SImode, operands[1]);
3346 ops[1] = operands[1];
3347 ops[2] = GEN_INT (24);
3349 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3350 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3352 ops[0] = operands[0];
3354 ops[2] = GEN_INT (24);
3356 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3357 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3364 (define_insn "*thumb_zero_extendqisi2"
3365 [(set (match_operand:SI 0 "register_operand" "=l")
3366 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3369 [(set_attr "length" "2")
3370 (set_attr "type" "load")
3371 (set_attr "pool_range" "32")]
3374 (define_insn "*arm_zero_extendqisi2"
3375 [(set (match_operand:SI 0 "s_register_operand" "=r")
3376 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3378 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3379 [(set_attr "type" "load")
3380 (set_attr "predicable" "yes")
3381 (set_attr "pool_range" "4096")
3382 (set_attr "neg_pool_range" "4084")]
3386 [(set (match_operand:SI 0 "s_register_operand" "")
3387 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3388 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3389 "TARGET_ARM && (GET_CODE (operands[1]) != MEM)"
3390 [(set (match_dup 2) (match_dup 1))
3391 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3395 (define_insn "*compareqi_eq0"
3396 [(set (reg:CC_Z CC_REGNUM)
3397 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3401 [(set_attr "conds" "set")]
3404 (define_expand "extendhisi2"
3406 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3408 (set (match_operand:SI 0 "s_register_operand" "")
3409 (ashiftrt:SI (match_dup 2)
3414 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3416 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3417 here because the insn below will generate an LDRH instruction
3418 rather than an LDR instruction, so we cannot get an unaligned
3420 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3421 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3425 if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3427 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3430 if (!s_register_operand (operands[1], HImode))
3431 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3432 operands[1] = gen_lowpart (SImode, operands[1]);
3433 operands[2] = gen_reg_rtx (SImode);
3439 ops[0] = operands[2];
3440 ops[1] = operands[1];
3441 ops[2] = GEN_INT (16);
3443 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3444 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3446 ops[0] = operands[0];
3447 ops[1] = operands[2];
3448 ops[2] = GEN_INT (16);
3450 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3451 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3458 (define_insn "*thumb_extendhisi2_insn"
3459 [(set (match_operand:SI 0 "register_operand" "=l")
3460 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3461 (clobber (match_scratch:SI 2 "=&l"))]
3466 rtx mem = XEXP (operands[1], 0);
3468 /* This code used to try to use 'V', and fix the address only if it was
3469 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3470 range of QImode offsets, and offsettable_address_p does a QImode
3473 if (GET_CODE (mem) == CONST)
3474 mem = XEXP (mem, 0);
3476 if (GET_CODE (mem) == LABEL_REF)
3477 return \"ldr\\t%0, %1\";
3479 if (GET_CODE (mem) == PLUS)
3481 rtx a = XEXP (mem, 0);
3482 rtx b = XEXP (mem, 1);
3484 if (GET_CODE (a) == LABEL_REF
3485 && GET_CODE (b) == CONST_INT)
3486 return \"ldr\\t%0, %1\";
3488 if (GET_CODE (b) == REG)
3489 return \"ldrsh\\t%0, %1\";
3497 ops[2] = const0_rtx;
3500 if (GET_CODE (ops[1]) != REG)
3506 ops[0] = operands[0];
3507 ops[3] = operands[2];
3508 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3511 [(set_attr "length" "4")
3512 (set_attr "type" "load")
3513 (set_attr "pool_range" "1020")]
3516 (define_expand "extendhisi2_mem"
3517 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3519 (zero_extend:SI (match_dup 7)))
3520 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3521 (set (match_operand:SI 0 "" "")
3522 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3527 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3529 mem1 = gen_rtx_MEM (QImode, addr);
3530 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3531 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3532 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3533 operands[0] = gen_lowpart (SImode, operands[0]);
3535 operands[2] = gen_reg_rtx (SImode);
3536 operands[3] = gen_reg_rtx (SImode);
3537 operands[6] = gen_reg_rtx (SImode);
3540 if (BYTES_BIG_ENDIAN)
3542 operands[4] = operands[2];
3543 operands[5] = operands[3];
3547 operands[4] = operands[3];
3548 operands[5] = operands[2];
3553 (define_insn "*arm_extendhisi_insn"
3554 [(set (match_operand:SI 0 "s_register_operand" "=r")
3555 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3556 "TARGET_ARM && arm_arch4"
3558 [(set_attr "type" "load")
3559 (set_attr "predicable" "yes")
3560 (set_attr "pool_range" "256")
3561 (set_attr "neg_pool_range" "244")]
3565 [(set (match_operand:SI 0 "s_register_operand" "")
3566 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3567 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3568 "TARGET_ARM && (!arm_arch4)"
3569 [(set (match_dup 2) (match_dup 1))
3570 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3572 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3578 [(set (match_operand:SI 0 "s_register_operand" "")
3579 (match_operator:SI 3 "shiftable_operator"
3580 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3581 (match_operand:SI 4 "s_register_operand" "")]))
3582 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3583 "TARGET_ARM && (!arm_arch4)"
3584 [(set (match_dup 2) (match_dup 1))
3587 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3588 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3593 (define_expand "extendqihi2"
3595 (ashift:SI (match_operand:QI 1 "general_operand" "")
3597 (set (match_operand:HI 0 "s_register_operand" "")
3598 (ashiftrt:SI (match_dup 2)
3603 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3605 emit_insn (gen_rtx_SET (VOIDmode,
3607 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3610 if (!s_register_operand (operands[1], QImode))
3611 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3612 operands[0] = gen_lowpart (SImode, operands[0]);
3613 operands[1] = gen_lowpart (SImode, operands[1]);
3614 operands[2] = gen_reg_rtx (SImode);
3618 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3619 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3620 (define_insn "*extendqihi_insn"
3621 [(set (match_operand:HI 0 "s_register_operand" "=r")
3622 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3623 "TARGET_ARM && arm_arch4"
3625 /* If the address is invalid, this will split the instruction into two. */
3626 if (bad_signed_byte_operand (operands[1], VOIDmode))
3628 return \"ldr%?sb\\t%0, %1\";
3630 [(set_attr "type" "load")
3631 (set_attr "predicable" "yes")
3632 (set_attr "length" "8")
3633 (set_attr "pool_range" "256")
3634 (set_attr "neg_pool_range" "244")]
3638 [(set (match_operand:HI 0 "s_register_operand" "")
3639 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3640 "TARGET_ARM && arm_arch4 && reload_completed"
3641 [(set (match_dup 3) (match_dup 1))
3642 (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3645 HOST_WIDE_INT offset;
3647 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3648 operands[2] = gen_rtx_MEM (QImode, operands[3]);
3649 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3650 operands[1] = XEXP (operands[1], 0);
3651 if (GET_CODE (operands[1]) == PLUS
3652 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3653 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3654 || const_ok_for_arm (-offset)))
3656 HOST_WIDE_INT low = (offset > 0
3657 ? (offset & 0xff) : -((-offset) & 0xff));
3658 XEXP (operands[2], 0) = plus_constant (operands[3], low);
3659 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3661 /* Ensure the sum is in correct canonical form */
3662 else if (GET_CODE (operands[1]) == PLUS
3663 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3664 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3665 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3666 XEXP (operands[1], 1),
3667 XEXP (operands[1], 0));
3671 (define_expand "extendqisi2"
3673 (ashift:SI (match_operand:QI 1 "general_operand" "")
3675 (set (match_operand:SI 0 "s_register_operand" "")
3676 (ashiftrt:SI (match_dup 2)
3681 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3683 emit_insn (gen_rtx_SET (VOIDmode,
3685 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3688 if (!s_register_operand (operands[1], QImode))
3689 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3690 operands[1] = gen_lowpart (SImode, operands[1]);
3691 operands[2] = gen_reg_rtx (SImode);
3697 ops[0] = operands[2];
3698 ops[1] = operands[1];
3699 ops[2] = GEN_INT (24);
3701 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3702 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3704 ops[0] = operands[0];
3705 ops[1] = operands[2];
3706 ops[2] = GEN_INT (24);
3708 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3709 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3716 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3717 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3718 (define_insn "*arm_extendqisi_insn"
3719 [(set (match_operand:SI 0 "s_register_operand" "=r")
3720 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3721 "TARGET_ARM && arm_arch4"
3723 /* If the address is invalid, this will split the instruction into two. */
3724 if (bad_signed_byte_operand (operands[1], VOIDmode))
3726 return \"ldr%?sb\\t%0, %1\";
3728 [(set_attr "type" "load")
3729 (set_attr "predicable" "yes")
3730 (set_attr "length" "8")
3731 (set_attr "pool_range" "256")
3732 (set_attr "neg_pool_range" "244")]
3736 [(set (match_operand:SI 0 "s_register_operand" "")
3737 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3738 "TARGET_ARM && arm_arch4 && reload_completed"
3739 [(set (match_dup 0) (match_dup 1))
3740 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3743 HOST_WIDE_INT offset;
3745 operands[2] = gen_rtx_MEM (QImode, operands[0]);
3746 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3747 operands[1] = XEXP (operands[1], 0);
3748 if (GET_CODE (operands[1]) == PLUS
3749 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3750 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3751 || const_ok_for_arm (-offset)))
3753 HOST_WIDE_INT low = (offset > 0
3754 ? (offset & 0xff) : -((-offset) & 0xff));
3755 XEXP (operands[2], 0) = plus_constant (operands[0], low);
3756 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3758 /* Ensure the sum is in correct canonical form */
3759 else if (GET_CODE (operands[1]) == PLUS
3760 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3761 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3762 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3763 XEXP (operands[1], 1),
3764 XEXP (operands[1], 0));
3768 (define_insn "*thumb_extendqisi2_insn"
3769 [(set (match_operand:SI 0 "register_operand" "=l,l")
3770 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3775 rtx mem = XEXP (operands[1], 0);
3777 if (GET_CODE (mem) == CONST)
3778 mem = XEXP (mem, 0);
3780 if (GET_CODE (mem) == LABEL_REF)
3781 return \"ldr\\t%0, %1\";
3783 if (GET_CODE (mem) == PLUS
3784 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3785 return \"ldr\\t%0, %1\";
3787 if (which_alternative == 0)
3788 return \"ldrsb\\t%0, %1\";
3790 ops[0] = operands[0];
3792 if (GET_CODE (mem) == PLUS)
3794 rtx a = XEXP (mem, 0);
3795 rtx b = XEXP (mem, 1);
3800 if (GET_CODE (a) == REG)
3802 if (GET_CODE (b) == REG)
3803 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3804 else if (REGNO (a) == REGNO (ops[0]))
3806 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3807 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3808 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3811 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3813 else if (GET_CODE (b) != REG)
3817 if (REGNO (b) == REGNO (ops[0]))
3819 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3820 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3821 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3824 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3827 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3829 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3830 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3831 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3836 ops[2] = const0_rtx;
3838 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3842 [(set_attr "length" "2,6")
3843 (set_attr "type" "load,load")
3844 (set_attr "pool_range" "32,32")]
3847 (define_insn "extendsfdf2"
3848 [(set (match_operand:DF 0 "s_register_operand" "=f")
3849 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
3850 "TARGET_ARM && TARGET_HARD_FLOAT"
3852 [(set_attr "type" "ffarith")
3853 (set_attr "predicable" "yes")]
3856 (define_insn "extendsfxf2"
3857 [(set (match_operand:XF 0 "s_register_operand" "=f")
3858 (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
3859 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3861 [(set_attr "type" "ffarith")
3862 (set_attr "predicable" "yes")]
3865 (define_insn "extenddfxf2"
3866 [(set (match_operand:XF 0 "s_register_operand" "=f")
3867 (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
3868 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3870 [(set_attr "type" "ffarith")
3871 (set_attr "predicable" "yes")]
3875 ;; Move insns (including loads and stores)
3877 ;; XXX Just some ideas about movti.
3878 ;; I don't think these are a good idea on the arm, there just aren't enough
3880 ;;(define_expand "loadti"
3881 ;; [(set (match_operand:TI 0 "s_register_operand" "")
3882 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
3885 ;;(define_expand "storeti"
3886 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3887 ;; (match_operand:TI 1 "s_register_operand" ""))]
3890 ;;(define_expand "movti"
3891 ;; [(set (match_operand:TI 0 "general_operand" "")
3892 ;; (match_operand:TI 1 "general_operand" ""))]
3898 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3899 ;; operands[1] = copy_to_reg (operands[1]);
3900 ;; if (GET_CODE (operands[0]) == MEM)
3901 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3902 ;; else if (GET_CODE (operands[1]) == MEM)
3903 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3907 ;; emit_insn (insn);
3911 ;; Recognise garbage generated above.
3914 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3915 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3919 ;; register mem = (which_alternative < 3);
3920 ;; register const char *template;
3922 ;; operands[mem] = XEXP (operands[mem], 0);
3923 ;; switch (which_alternative)
3925 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3926 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
3927 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
3928 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
3929 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
3930 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
3932 ;; output_asm_insn (template, operands);
3936 (define_expand "movdi"
3937 [(set (match_operand:DI 0 "general_operand" "")
3938 (match_operand:DI 1 "general_operand" ""))]
3943 if (!no_new_pseudos)
3945 if (GET_CODE (operands[0]) != REG)
3946 operands[1] = force_reg (DImode, operands[1]);
3952 (define_insn "*arm_movdi"
3953 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3954 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
3957 return (output_move_double (operands));
3959 [(set_attr "length" "8")
3960 (set_attr "type" "*,load,store2")
3961 (set_attr "pool_range" "*,1020,*")
3962 (set_attr "neg_pool_range" "*,1012,*")]
3965 ;;; ??? This should have alternatives for constants.
3966 ;;; ??? This was originally identical to the movdf_insn pattern.
3967 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3968 ;;; thumb_reorg with a memory reference.
3969 (define_insn "*thumb_movdi_insn"
3970 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3971 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
3973 && ( register_operand (operands[0], DImode)
3974 || register_operand (operands[1], DImode))"
3977 switch (which_alternative)
3981 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3982 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
3983 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
3985 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3987 operands[1] = GEN_INT (- INTVAL (operands[1]));
3988 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3990 return \"ldmia\\t%1, {%0, %H0}\";
3992 return \"stmia\\t%0, {%1, %H1}\";
3994 return thumb_load_double_from_address (operands);
3996 operands[2] = gen_rtx (MEM, SImode,
3997 plus_constant (XEXP (operands[0], 0), 4));
3998 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4001 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4002 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4003 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4006 [(set_attr "length" "4,4,6,2,2,6,4,4")
4007 (set_attr "type" "*,*,*,load,store2,load,store2,*")
4008 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4011 (define_expand "movsi"
4012 [(set (match_operand:SI 0 "general_operand" "")
4013 (match_operand:SI 1 "general_operand" ""))]
4018 /* Everything except mem = const or mem = mem can be done easily */
4019 if (GET_CODE (operands[0]) == MEM)
4020 operands[1] = force_reg (SImode, operands[1]);
4021 if (GET_CODE (operands[1]) == CONST_INT
4022 && !(const_ok_for_arm (INTVAL (operands[1]))
4023 || const_ok_for_arm (~INTVAL (operands[1]))))
4025 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4028 : preserve_subexpressions_p ()));
4032 else /* TARGET_THUMB.... */
4034 if (!no_new_pseudos)
4036 if (GET_CODE (operands[0]) != REG)
4037 operands[1] = force_reg (SImode, operands[1]);
4042 && (CONSTANT_P (operands[1])
4043 || symbol_mentioned_p (operands[1])
4044 || label_mentioned_p (operands[1])))
4045 operands[1] = legitimize_pic_address (operands[1], SImode,
4046 (no_new_pseudos ? operands[0] : 0));
4050 (define_insn "*arm_movsi_insn"
4051 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4052 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
4054 && ( register_operand (operands[0], SImode)
4055 || register_operand (operands[1], SImode))"
4061 [(set_attr "type" "*,*,load,store1")
4062 (set_attr "predicable" "yes")
4063 (set_attr "pool_range" "*,*,4096,*")
4064 (set_attr "neg_pool_range" "*,*,4084,*")]
4068 [(set (match_operand:SI 0 "s_register_operand" "")
4069 (match_operand:SI 1 "const_int_operand" ""))]
4071 && (!(const_ok_for_arm (INTVAL (operands[1]))
4072 || const_ok_for_arm (~INTVAL (operands[1]))))"
4073 [(clobber (const_int 0))]
4075 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4081 (define_insn "*thumb_movsi_insn"
4082 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4083 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
4085 && ( register_operand (operands[0], SImode)
4086 || register_operand (operands[1], SImode))"
4097 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4098 (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
4099 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4103 [(set (match_operand:SI 0 "register_operand" "")
4104 (match_operand:SI 1 "const_int_operand" ""))]
4105 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4106 [(set (match_dup 0) (match_dup 1))
4107 (set (match_dup 0) (neg:SI (match_dup 0)))]
4108 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4112 [(set (match_operand:SI 0 "register_operand" "")
4113 (match_operand:SI 1 "const_int_operand" ""))]
4114 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4115 [(set (match_dup 0) (match_dup 1))
4116 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4119 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4120 unsigned HOST_WIDE_INT mask = 0xff;
4123 for (i = 0; i < 25; i++)
4124 if ((val & (mask << i)) == val)
4130 operands[1] = GEN_INT (val >> i);
4131 operands[2] = GEN_INT (i);
4135 (define_expand "movaddr"
4136 [(set (match_operand:SI 0 "s_register_operand" "")
4137 (match_operand:DI 1 "address_operand" ""))]
4142 (define_insn "*movaddr_insn"
4143 [(set (match_operand:SI 0 "s_register_operand" "=r")
4144 (match_operand:DI 1 "address_operand" "p"))]
4147 && (GET_CODE (operands[1]) == LABEL_REF
4148 || (GET_CODE (operands[1]) == CONST
4149 && GET_CODE (XEXP (operands[1], 0)) == PLUS
4150 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
4151 && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))"
4153 [(set_attr "predicable" "yes")]
4156 ;; When generating pic, we need to load the symbol offset into a register.
4157 ;; So that the optimizer does not confuse this with a normal symbol load
4158 ;; we use an unspec. The offset will be loaded from a constant pool entry,
4159 ;; since that is the only type of relocation we can use.
4161 ;; The rather odd constraints on the following are to force reload to leave
4162 ;; the insn alone, and to force the minipool generation pass to then move
4163 ;; the GOT symbol to memory.
4165 (define_insn "pic_load_addr_arm"
4166 [(set (match_operand:SI 0 "s_register_operand" "=r")
4167 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4168 "TARGET_ARM && flag_pic"
4170 [(set_attr "type" "load")
4171 (set (attr "pool_range") (const_int 4096))
4172 (set (attr "neg_pool_range") (const_int 4084))]
4175 (define_insn "pic_load_addr_thumb"
4176 [(set (match_operand:SI 0 "s_register_operand" "=l")
4177 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4178 "TARGET_THUMB && flag_pic"
4180 [(set_attr "type" "load")
4181 (set (attr "pool_range") (const_int 1024))]
4184 ;; This variant is used for AOF assembly, since it needs to mention the
4185 ;; pic register in the rtl.
4186 (define_expand "pic_load_addr_based"
4187 [(set (match_operand:SI 0 "s_register_operand" "=r")
4188 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4189 "TARGET_ARM && flag_pic"
4190 "operands[2] = pic_offset_table_rtx;"
4193 (define_insn "*pic_load_addr_based_insn"
4194 [(set (match_operand:SI 0 "s_register_operand" "=r")
4195 (unspec:SI [(match_operand 1 "" "")
4196 (match_operand 2 "s_register_operand" "r")]
4198 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4200 #ifdef AOF_ASSEMBLER
4201 operands[1] = aof_pic_entry (operands[1]);
4203 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4206 [(set_attr "type" "load")
4207 (set (attr "pool_range")
4208 (if_then_else (eq_attr "is_thumb" "yes")
4211 (set (attr "neg_pool_range")
4212 (if_then_else (eq_attr "is_thumb" "yes")
4217 (define_insn "pic_add_dot_plus_four"
4218 [(set (match_operand:SI 0 "register_operand" "+r")
4219 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
4220 (use (label_ref (match_operand 1 "" "")))]
4221 "TARGET_THUMB && flag_pic"
4223 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4224 CODE_LABEL_NUMBER (operands[1]));
4225 return \"add\\t%0, %|pc\";
4227 [(set_attr "length" "2")]
4230 (define_insn "pic_add_dot_plus_eight"
4231 [(set (match_operand:SI 0 "register_operand" "+r")
4232 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
4233 (use (label_ref (match_operand 1 "" "")))]
4234 "TARGET_ARM && flag_pic"
4236 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4237 CODE_LABEL_NUMBER (operands[1]));
4238 return \"add%?\\t%0, %|pc, %0\";
4240 [(set_attr "predicable" "yes")]
4243 (define_expand "builtin_setjmp_receiver"
4244 [(label_ref (match_operand 0 "" ""))]
4248 arm_finalize_pic (0);
4252 ;; If copying one reg to another we can set the condition codes according to
4253 ;; its value. Such a move is common after a return from subroutine and the
4254 ;; result is being tested against zero.
4256 (define_insn "*movsi_compare0"
4257 [(set (reg:CC CC_REGNUM)
4258 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4260 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4265 sub%?s\\t%0, %1, #0"
4266 [(set_attr "conds" "set")]
4269 ;; Subroutine to store a half word from a register into memory.
4270 ;; Operand 0 is the source register (HImode)
4271 ;; Operand 1 is the destination address in a register (SImode)
4273 ;; In both this routine and the next, we must be careful not to spill
4274 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4275 ;; can generate unrecognizable rtl.
4277 (define_expand "storehi"
4278 [;; store the low byte
4279 (set (match_operand 1 "" "") (match_dup 3))
4280 ;; extract the high byte
4282 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4283 ;; store the high byte
4284 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
4288 rtx op1 = operands[1];
4289 rtx addr = XEXP (op1, 0);
4290 enum rtx_code code = GET_CODE (addr);
4292 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4294 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4296 operands[4] = adjust_address (op1, QImode, 1);
4297 operands[1] = adjust_address (operands[1], QImode, 0);
4298 operands[3] = gen_lowpart (QImode, operands[0]);
4299 operands[0] = gen_lowpart (SImode, operands[0]);
4300 operands[2] = gen_reg_rtx (SImode);
4304 (define_expand "storehi_bigend"
4305 [(set (match_dup 4) (match_dup 3))
4307 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4308 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 0))]
4312 rtx op1 = operands[1];
4313 rtx addr = XEXP (op1, 0);
4314 enum rtx_code code = GET_CODE (addr);
4316 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4318 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4320 operands[4] = adjust_address (op1, QImode, 1);
4321 operands[1] = adjust_address (operands[1], QImode, 0);
4322 operands[3] = gen_lowpart (QImode, operands[0]);
4323 operands[0] = gen_lowpart (SImode, operands[0]);
4324 operands[2] = gen_reg_rtx (SImode);
4328 ;; Subroutine to store a half word integer constant into memory.
4329 (define_expand "storeinthi"
4330 [(set (match_operand 0 "" "")
4331 (subreg:QI (match_operand 1 "" "") 0))
4332 (set (match_dup 3) (subreg:QI (match_dup 2) 0))]
4336 HOST_WIDE_INT value = INTVAL (operands[1]);
4337 rtx addr = XEXP (operands[0], 0);
4338 rtx op0 = operands[0];
4339 enum rtx_code code = GET_CODE (addr);
4341 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4343 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4345 operands[1] = gen_reg_rtx (SImode);
4346 if (BYTES_BIG_ENDIAN)
4348 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4349 if ((value & 255) == ((value >> 8) & 255))
4350 operands[2] = operands[1];
4353 operands[2] = gen_reg_rtx (SImode);
4354 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4359 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4360 if ((value & 255) == ((value >> 8) & 255))
4361 operands[2] = operands[1];
4364 operands[2] = gen_reg_rtx (SImode);
4365 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4369 operands[3] = adjust_address (op0, QImode, 1);
4370 operands[0] = adjust_address (operands[0], QImode, 0);
4374 (define_expand "storehi_single_op"
4375 [(set (match_operand:HI 0 "memory_operand" "")
4376 (match_operand:HI 1 "general_operand" ""))]
4377 "TARGET_ARM && arm_arch4"
4379 if (!s_register_operand (operands[1], HImode))
4380 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4384 (define_expand "movhi"
4385 [(set (match_operand:HI 0 "general_operand" "")
4386 (match_operand:HI 1 "general_operand" ""))]
4391 if (!no_new_pseudos)
4393 if (GET_CODE (operands[0]) == MEM)
4397 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4400 if (GET_CODE (operands[1]) == CONST_INT)
4401 emit_insn (gen_storeinthi (operands[0], operands[1]));
4404 if (GET_CODE (operands[1]) == MEM)
4405 operands[1] = force_reg (HImode, operands[1]);
4406 if (BYTES_BIG_ENDIAN)
4407 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4409 emit_insn (gen_storehi (operands[1], operands[0]));
4413 /* Sign extend a constant, and keep it in an SImode reg. */
4414 else if (GET_CODE (operands[1]) == CONST_INT)
4416 rtx reg = gen_reg_rtx (SImode);
4417 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4419 /* If the constant is already valid, leave it alone. */
4420 if (!const_ok_for_arm (val))
4422 /* If setting all the top bits will make the constant
4423 loadable in a single instruction, then set them.
4424 Otherwise, sign extend the number. */
4426 if (const_ok_for_arm (~(val | ~0xffff)))
4428 else if (val & 0x8000)
4432 emit_insn (gen_movsi (reg, GEN_INT (val)));
4433 operands[1] = gen_rtx_SUBREG (HImode, reg, 0);
4435 else if (!arm_arch4)
4437 /* Note: We do not have to worry about TARGET_MMU_TRAPS
4438 for v4 and up architectures because LDRH instructions will
4439 be used to access the HI values, and these cannot generate
4440 unaligned word access faults in the MMU. */
4441 if (GET_CODE (operands[1]) == MEM)
4443 if (TARGET_MMU_TRAPS)
4446 rtx offset = const0_rtx;
4447 rtx reg = gen_reg_rtx (SImode);
4449 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4450 || (GET_CODE (base) == PLUS
4451 && (GET_CODE (offset = XEXP (base, 1))
4453 && ((INTVAL(offset) & 1) != 1)
4454 && GET_CODE (base = XEXP (base, 0)) == REG))
4455 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4457 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4460 new = gen_rtx_MEM (SImode,
4461 plus_constant (base, new_offset));
4462 MEM_COPY_ATTRIBUTES (new, operands[1]);
4463 emit_insn (gen_movsi (reg, new));
4464 if (((INTVAL (offset) & 2) != 0)
4465 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4467 rtx reg2 = gen_reg_rtx (SImode);
4469 emit_insn (gen_lshrsi3 (reg2, reg,
4475 emit_insn (gen_movhi_bytes (reg, operands[1]));
4477 operands[1] = gen_lowpart (HImode, reg);
4479 else if (BYTES_BIG_ENDIAN)
4482 rtx offset = const0_rtx;
4484 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4485 || (GET_CODE (base) == PLUS
4486 && (GET_CODE (offset = XEXP (base, 1))
4488 && GET_CODE (base = XEXP (base, 0)) == REG))
4489 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4491 rtx reg = gen_reg_rtx (SImode);
4494 if ((INTVAL (offset) & 2) == 2)
4496 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4497 new = gen_rtx_MEM (SImode,
4498 plus_constant (base,
4500 MEM_COPY_ATTRIBUTES (new, operands[1]);
4501 emit_insn (gen_movsi (reg, new));
4505 new = gen_rtx_MEM (SImode,
4506 XEXP (operands[1], 0));
4507 MEM_COPY_ATTRIBUTES (new, operands[1]);
4508 emit_insn (gen_rotated_loadsi (reg, new));
4511 operands[1] = gen_lowpart (HImode, reg);
4515 emit_insn (gen_movhi_bigend (operands[0],
4523 /* Handle loading a large integer during reload */
4524 else if (GET_CODE (operands[1]) == CONST_INT
4525 && !const_ok_for_arm (INTVAL (operands[1]))
4526 && !const_ok_for_arm (~INTVAL (operands[1])))
4528 /* Writing a constant to memory needs a scratch, which should
4529 be handled with SECONDARY_RELOADs. */
4530 if (GET_CODE (operands[0]) != REG)
4533 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4534 emit_insn (gen_movsi (operands[0], operands[1]));
4538 else /* TARGET_THUMB */
4540 if (!no_new_pseudos)
4542 if (GET_CODE (operands[0]) != REG)
4543 operands[1] = force_reg (HImode, operands[1]);
4545 /* ??? We shouldn't really get invalid addresses here, but this can
4546 happen if we are passed a SP (never OK for HImode/QImode) or
4547 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4548 HImode/QImode) relative address. */
4549 /* ??? This should perhaps be fixed elsewhere, for instance, in
4550 fixup_stack_1, by checking for other kinds of invalid addresses,
4551 e.g. a bare reference to a virtual register. This may confuse the
4552 alpha though, which must handle this case differently. */
4553 if (GET_CODE (operands[0]) == MEM
4554 && !memory_address_p (GET_MODE (operands[0]),
4555 XEXP (operands[0], 0)))
4557 = replace_equiv_address (operands[0],
4558 copy_to_reg (XEXP (operands[0], 0)));
4560 if (GET_CODE (operands[1]) == MEM
4561 && !memory_address_p (GET_MODE (operands[1]),
4562 XEXP (operands[1], 0)))
4564 = replace_equiv_address (operands[1],
4565 copy_to_reg (XEXP (operands[1], 0)));
4567 /* Handle loading a large integer during reload */
4568 else if (GET_CODE (operands[1]) == CONST_INT
4569 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4571 /* Writing a constant to memory needs a scratch, which should
4572 be handled with SECONDARY_RELOADs. */
4573 if (GET_CODE (operands[0]) != REG)
4576 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4577 emit_insn (gen_movsi (operands[0], operands[1]));
4584 (define_insn "*thumb_movhi_insn"
4585 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4586 (match_operand:HI 1 "general_operand" "l,mn,l,*h,*r,I"))]
4588 && ( register_operand (operands[0], HImode)
4589 || register_operand (operands[1], HImode))"
4591 switch (which_alternative)
4593 case 0: return \"add %0, %1, #0\";
4594 case 2: return \"strh %1, %0\";
4595 case 3: return \"mov %0, %1\";
4596 case 4: return \"mov %0, %1\";
4597 case 5: return \"mov %0, %1\";
4600 /* The stack pointer can end up being taken as an index register.
4601 Catch this case here and deal with it. */
4602 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4603 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4604 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4607 ops[0] = operands[0];
4608 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4610 output_asm_insn (\"mov %0, %1\", ops);
4612 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4615 return \"ldrh %0, %1\";
4617 [(set_attr "length" "2,4,2,2,2,2")
4618 (set_attr "type" "*,load,store1,*,*,*")
4619 (set_attr "pool_range" "*,64,*,*,*,*")]
4623 (define_insn "rotated_loadsi"
4624 [(set (match_operand:SI 0 "s_register_operand" "=r")
4625 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4627 "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4632 ops[0] = operands[0];
4633 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4634 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4637 [(set_attr "type" "load")
4638 (set_attr "predicable" "yes")]
4641 (define_expand "movhi_bytes"
4642 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4644 (zero_extend:SI (match_dup 6)))
4645 (set (match_operand:SI 0 "" "")
4646 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4651 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4653 mem1 = gen_rtx_MEM (QImode, addr);
4654 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4655 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4656 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4657 operands[0] = gen_lowpart (SImode, operands[0]);
4659 operands[2] = gen_reg_rtx (SImode);
4660 operands[3] = gen_reg_rtx (SImode);
4663 if (BYTES_BIG_ENDIAN)
4665 operands[4] = operands[2];
4666 operands[5] = operands[3];
4670 operands[4] = operands[3];
4671 operands[5] = operands[2];
4676 (define_expand "movhi_bigend"
4678 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4681 (ashiftrt:SI (match_dup 2) (const_int 16)))
4682 (set (match_operand:HI 0 "s_register_operand" "")
4683 (subreg:HI (match_dup 3) 0))]
4686 operands[2] = gen_reg_rtx (SImode);
4687 operands[3] = gen_reg_rtx (SImode);
4691 ;; Pattern to recognise insn generated default case above
4692 (define_insn "*movhi_insn_arch4"
4693 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4694 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4697 && (GET_CODE (operands[1]) != CONST_INT
4698 || const_ok_for_arm (INTVAL (operands[1]))
4699 || const_ok_for_arm (~INTVAL (operands[1])))"
4701 mov%?\\t%0, %1\\t%@ movhi
4702 mvn%?\\t%0, #%B1\\t%@ movhi
4703 str%?h\\t%1, %0\\t%@ movhi
4704 ldr%?h\\t%0, %1\\t%@ movhi"
4705 [(set_attr "type" "*,*,store1,load")
4706 (set_attr "predicable" "yes")
4707 (set_attr "pool_range" "*,*,*,256")
4708 (set_attr "neg_pool_range" "*,*,*,244")]
4711 (define_insn "*movhi_insn_littleend"
4712 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4713 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4716 && !BYTES_BIG_ENDIAN
4717 && !TARGET_MMU_TRAPS
4718 && (GET_CODE (operands[1]) != CONST_INT
4719 || const_ok_for_arm (INTVAL (operands[1]))
4720 || const_ok_for_arm (~INTVAL (operands[1])))"
4722 mov%?\\t%0, %1\\t%@ movhi
4723 mvn%?\\t%0, #%B1\\t%@ movhi
4724 ldr%?\\t%0, %1\\t%@ movhi"
4725 [(set_attr "type" "*,*,load")
4726 (set_attr "predicable" "yes")
4727 (set_attr "pool_range" "4096")
4728 (set_attr "neg_pool_range" "4084")]
4731 (define_insn "*movhi_insn_bigend"
4732 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4733 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4737 && !TARGET_MMU_TRAPS
4738 && (GET_CODE (operands[1]) != CONST_INT
4739 || const_ok_for_arm (INTVAL (operands[1]))
4740 || const_ok_for_arm (~INTVAL (operands[1])))"
4742 mov%?\\t%0, %1\\t%@ movhi
4743 mvn%?\\t%0, #%B1\\t%@ movhi
4744 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4745 [(set_attr "type" "*,*,load")
4746 (set_attr "predicable" "yes")
4747 (set_attr "length" "4,4,8")
4748 (set_attr "pool_range" "*,*,4092")
4749 (set_attr "neg_pool_range" "*,*,4084")]
4752 (define_insn "*loadhi_si_bigend"
4753 [(set (match_operand:SI 0 "s_register_operand" "=r")
4754 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
4758 && !TARGET_MMU_TRAPS"
4759 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4760 [(set_attr "type" "load")
4761 (set_attr "predicable" "yes")
4762 (set_attr "pool_range" "4096")
4763 (set_attr "neg_pool_range" "4084")]
4766 (define_insn "*movhi_bytes"
4767 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4768 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4769 "TARGET_ARM && TARGET_MMU_TRAPS"
4771 mov%?\\t%0, %1\\t%@ movhi
4772 mvn%?\\t%0, #%B1\\t%@ movhi"
4773 [(set_attr "predicable" "yes")]
4776 (define_insn "thumb_movhi_clobber"
4777 [(set (match_operand:HI 0 "memory_operand" "=m")
4778 (match_operand:HI 1 "register_operand" "l"))
4779 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4785 ;; We use a DImode scratch because we may occasionally need an additional
4786 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4787 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4788 (define_expand "reload_outhi"
4789 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4790 (match_operand:HI 1 "s_register_operand" "r")
4791 (match_operand:DI 2 "s_register_operand" "=&l")])]
4794 arm_reload_out_hi (operands);
4796 thumb_reload_out_hi (operands);
4801 (define_expand "reload_inhi"
4802 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4803 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4804 (match_operand:DI 2 "s_register_operand" "=&r")])]
4805 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4808 arm_reload_in_hi (operands);
4810 thumb_reload_out_hi (operands);
4814 (define_expand "movqi"
4815 [(set (match_operand:QI 0 "general_operand" "")
4816 (match_operand:QI 1 "general_operand" ""))]
4821 /* Everything except mem = const or mem = mem can be done easily */
4823 if (!no_new_pseudos)
4825 if (GET_CODE (operands[1]) == CONST_INT)
4827 rtx reg = gen_reg_rtx (SImode);
4829 emit_insn (gen_movsi (reg, operands[1]));
4830 operands[1] = gen_rtx_SUBREG (QImode, reg, 0);
4832 if (GET_CODE (operands[0]) == MEM)
4833 operands[1] = force_reg (QImode, operands[1]);
4836 else /* TARGET_THUMB */
4838 if (!no_new_pseudos)
4840 if (GET_CODE (operands[0]) != REG)
4841 operands[1] = force_reg (QImode, operands[1]);
4843 /* ??? We shouldn't really get invalid addresses here, but this can
4844 happen if we are passed a SP (never OK for HImode/QImode) or
4845 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4846 HImode/QImode) relative address. */
4847 /* ??? This should perhaps be fixed elsewhere, for instance, in
4848 fixup_stack_1, by checking for other kinds of invalid addresses,
4849 e.g. a bare reference to a virtual register. This may confuse the
4850 alpha though, which must handle this case differently. */
4851 if (GET_CODE (operands[0]) == MEM
4852 && !memory_address_p (GET_MODE (operands[0]),
4853 XEXP (operands[0], 0)))
4855 = replace_equiv_address (operands[0],
4856 copy_to_reg (XEXP (operands[0], 0)));
4857 if (GET_CODE (operands[1]) == MEM
4858 && !memory_address_p (GET_MODE (operands[1]),
4859 XEXP (operands[1], 0)))
4861 = replace_equiv_address (operands[1],
4862 copy_to_reg (XEXP (operands[1], 0)));
4864 /* Handle loading a large integer during reload */
4865 else if (GET_CODE (operands[1]) == CONST_INT
4866 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4868 /* Writing a constant to memory needs a scratch, which should
4869 be handled with SECONDARY_RELOADs. */
4870 if (GET_CODE (operands[0]) != REG)
4873 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4874 emit_insn (gen_movsi (operands[0], operands[1]));
4882 (define_insn "*arm_movqi_insn"
4883 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4884 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4886 && ( register_operand (operands[0], QImode)
4887 || register_operand (operands[1], QImode))"
4893 [(set_attr "type" "*,*,load,store1")
4894 (set_attr "predicable" "yes")]
4897 (define_insn "*thumb_movqi_insn"
4898 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4899 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
4901 && ( register_operand (operands[0], QImode)
4902 || register_operand (operands[1], QImode))"
4910 [(set_attr "length" "2")
4911 (set_attr "type" "*,load,store1,*,*,*")
4912 (set_attr "pool_range" "*,32,*,*,*,*")]
4915 (define_expand "movsf"
4916 [(set (match_operand:SF 0 "general_operand" "")
4917 (match_operand:SF 1 "general_operand" ""))]
4922 if (GET_CODE (operands[0]) == MEM)
4923 operands[1] = force_reg (SFmode, operands[1]);
4925 else /* TARGET_THUMB */
4927 if (!no_new_pseudos)
4929 if (GET_CODE (operands[0]) != REG)
4930 operands[1] = force_reg (SFmode, operands[1]);
4937 [(set (match_operand:SF 0 "nonimmediate_operand" "")
4938 (match_operand:SF 1 "immediate_operand" ""))]
4940 && !TARGET_HARD_FLOAT
4942 && GET_CODE (operands[1]) == CONST_DOUBLE"
4943 [(set (match_dup 2) (match_dup 3))]
4945 operands[2] = gen_lowpart (SImode, operands[0]);
4946 operands[3] = gen_lowpart (SImode, operands[1]);
4947 if (operands[2] == 0 || operands[3] == 0)
4952 (define_insn "*arm_movsf_hard_insn"
4953 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
4954 (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
4956 && TARGET_HARD_FLOAT
4957 && (GET_CODE (operands[0]) != MEM
4958 || register_operand (operands[1], SFmode))"
4964 str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
4965 stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
4967 ldr%?\\t%0, %1\\t%@ float
4968 str%?\\t%1, %0\\t%@ float"
4969 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
4970 (set_attr "predicable" "yes")
4972 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
4973 (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
4974 (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
4977 ;; Exactly the same as above, except that all `f' cases are deleted.
4978 ;; This is necessary to prevent reload from ever trying to use a `f' reg
4979 ;; when -msoft-float.
4981 (define_insn "*arm_movsf_soft_insn"
4982 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4983 (match_operand:SF 1 "general_operand" "r,mE,r"))]
4985 && TARGET_SOFT_FLOAT
4986 && (GET_CODE (operands[0]) != MEM
4987 || register_operand (operands[1], SFmode))"
4990 ldr%?\\t%0, %1\\t%@ float
4991 str%?\\t%1, %0\\t%@ float"
4992 [(set_attr "length" "4,4,4")
4993 (set_attr "predicable" "yes")
4994 (set_attr "type" "*,load,store1")
4995 (set_attr "pool_range" "*,4096,*")
4996 (set_attr "neg_pool_range" "*,4084,*")]
4999 ;;; ??? This should have alternatives for constants.
5000 (define_insn "*thumb_movsf_insn"
5001 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5002 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
5004 && ( register_operand (operands[0], SFmode)
5005 || register_operand (operands[1], SFmode))"
5014 [(set_attr "length" "2")
5015 (set_attr "type" "*,load,store1,load,store1,*,*")
5016 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5019 (define_expand "movdf"
5020 [(set (match_operand:DF 0 "general_operand" "")
5021 (match_operand:DF 1 "general_operand" ""))]
5026 if (GET_CODE (operands[0]) == MEM)
5027 operands[1] = force_reg (DFmode, operands[1]);
5029 else /* TARGET_THUMB */
5031 if (!no_new_pseudos)
5033 if (GET_CODE (operands[0]) != REG)
5034 operands[1] = force_reg (DFmode, operands[1]);
5040 ;; Reloading a df mode value stored in integer regs to memory can require a
5042 (define_expand "reload_outdf"
5043 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5044 (match_operand:DF 1 "s_register_operand" "r")
5045 (match_operand:SI 2 "s_register_operand" "=&r")]
5049 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5052 operands[2] = XEXP (operands[0], 0);
5053 else if (code == POST_INC || code == PRE_DEC)
5055 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5056 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5057 emit_insn (gen_movdi (operands[0], operands[1]));
5060 else if (code == PRE_INC)
5062 rtx reg = XEXP (XEXP (operands[0], 0), 0);
5064 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5067 else if (code == POST_DEC)
5068 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5070 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5071 XEXP (XEXP (operands[0], 0), 1)));
5073 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5076 if (code == POST_DEC)
5077 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5083 (define_insn "*movdf_hard_insn"
5084 [(set (match_operand:DF 0 "nonimmediate_operand"
5085 "=r,Q,r,m,r, f, f,f, m,!f,!r")
5086 (match_operand:DF 1 "general_operand"
5087 "Q, r,r,r,mF,fG,H,mF,f,r, f"))]
5089 && TARGET_HARD_FLOAT
5090 && (GET_CODE (operands[0]) != MEM
5091 || register_operand (operands[1], DFmode))"
5094 switch (which_alternative)
5097 case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
5098 case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
5099 case 2: case 3: case 4: return output_move_double (operands);
5100 case 5: return \"mvf%?d\\t%0, %1\";
5101 case 6: return \"mnf%?d\\t%0, #%N1\";
5102 case 7: return \"ldf%?d\\t%0, %1\";
5103 case 8: return \"stf%?d\\t%1, %0\";
5104 case 9: return output_mov_double_fpu_from_arm (operands);
5105 case 10: return output_mov_double_arm_from_fpu (operands);
5109 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
5110 (set_attr "predicable" "yes")
5112 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
5113 (set_attr "pool_range" "*,*,*,*,252,*,*,1024,*,*,*")
5114 (set_attr "neg_pool_range" "*,*,*,*,244,*,*,1012,*,*,*")]
5117 ;; Software floating point version. This is essentially the same as movdi.
5118 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
5121 (define_insn "*movdf_soft_insn"
5122 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5123 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5124 "TARGET_ARM && TARGET_SOFT_FLOAT
5126 "* return output_move_double (operands);"
5127 [(set_attr "length" "8,8,8")
5128 (set_attr "type" "*,load,store2")
5129 (set_attr "pool_range" "252")
5130 (set_attr "neg_pool_range" "244")]
5133 ;;; ??? This should have alternatives for constants.
5134 ;;; ??? This was originally identical to the movdi_insn pattern.
5135 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5136 ;;; thumb_reorg with a memory reference.
5137 (define_insn "*thumb_movdf_insn"
5138 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5139 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
5141 && ( register_operand (operands[0], DFmode)
5142 || register_operand (operands[1], DFmode))"
5144 switch (which_alternative)
5148 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5149 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5150 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5152 return \"ldmia\\t%1, {%0, %H0}\";
5154 return \"stmia\\t%0, {%1, %H1}\";
5156 return thumb_load_double_from_address (operands);
5158 operands[2] = gen_rtx (MEM, SImode,
5159 plus_constant (XEXP (operands[0], 0), 4));
5160 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5163 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5164 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5165 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5168 [(set_attr "length" "4,2,2,6,4,4")
5169 (set_attr "type" "*,load,store2,load,store2,*")
5170 (set_attr "pool_range" "*,*,*,1020,*,*")]
5174 (define_expand "movxf"
5175 [(set (match_operand:XF 0 "general_operand" "")
5176 (match_operand:XF 1 "general_operand" ""))]
5177 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5180 ;; Even when the XFmode patterns aren't enabled, we enable this after
5181 ;; reloading so that we can push floating point registers in the prologue.
5183 (define_insn "*movxf_hard_insn"
5184 [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
5185 (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
5186 "TARGET_ARM && TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
5188 switch (which_alternative)
5191 case 0: return \"mvf%?e\\t%0, %1\";
5192 case 1: return \"mnf%?e\\t%0, #%N1\";
5193 case 2: return \"ldf%?e\\t%0, %1\";
5194 case 3: return \"stf%?e\\t%1, %0\";
5195 case 4: return output_mov_long_double_fpu_from_arm (operands);
5196 case 5: return output_mov_long_double_arm_from_fpu (operands);
5197 case 6: return output_mov_long_double_arm_from_arm (operands);
5200 [(set_attr "length" "4,4,4,4,8,8,12")
5201 (set_attr "predicable" "yes")
5202 (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
5203 (set_attr "pool_range" "*,*,1024,*,*,*,*")
5204 (set_attr "neg_pool_range" "*,*,1012,*,*,*,*")]
5208 ;; load- and store-multiple insns
5209 ;; The arm can load/store any set of registers, provided that they are in
5210 ;; ascending order; but that is beyond GCC so stick with what it knows.
5212 (define_expand "load_multiple"
5213 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5214 (match_operand:SI 1 "" ""))
5215 (use (match_operand:SI 2 "" ""))])]
5218 /* Support only fixed point registers. */
5219 if (GET_CODE (operands[2]) != CONST_INT
5220 || INTVAL (operands[2]) > 14
5221 || INTVAL (operands[2]) < 2
5222 || GET_CODE (operands[1]) != MEM
5223 || GET_CODE (operands[0]) != REG
5224 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5225 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5229 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5230 force_reg (SImode, XEXP (operands[1], 0)),
5231 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5232 MEM_IN_STRUCT_P(operands[1]),
5233 MEM_SCALAR_P (operands[1]));
5237 ;; Load multiple with write-back
5239 (define_insn "*ldmsi_postinc4"
5240 [(match_parallel 0 "load_multiple_operation"
5241 [(set (match_operand:SI 1 "s_register_operand" "=r")
5242 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5244 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5245 (mem:SI (match_dup 2)))
5246 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5247 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5248 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5249 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5250 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5251 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5252 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5253 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5254 [(set_attr "type" "load")
5255 (set_attr "predicable" "yes")]
5258 (define_insn "*ldmsi_postinc3"
5259 [(match_parallel 0 "load_multiple_operation"
5260 [(set (match_operand:SI 1 "s_register_operand" "=r")
5261 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5263 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5264 (mem:SI (match_dup 2)))
5265 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5266 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5267 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5268 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5269 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5270 "ldm%?ia\\t%1!, {%3, %4, %5}"
5271 [(set_attr "type" "load")
5272 (set_attr "predicable" "yes")]
5275 (define_insn "*ldmsi_postinc2"
5276 [(match_parallel 0 "load_multiple_operation"
5277 [(set (match_operand:SI 1 "s_register_operand" "=r")
5278 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5280 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5281 (mem:SI (match_dup 2)))
5282 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5283 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5284 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5285 "ldm%?ia\\t%1!, {%3, %4}"
5286 [(set_attr "type" "load")
5287 (set_attr "predicable" "yes")]
5290 ;; Ordinary load multiple
5292 (define_insn "*ldmsi4"
5293 [(match_parallel 0 "load_multiple_operation"
5294 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5295 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5296 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5297 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5298 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5299 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5300 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5301 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5302 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5303 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5304 [(set_attr "type" "load")
5305 (set_attr "predicable" "yes")]
5308 (define_insn "*ldmsi3"
5309 [(match_parallel 0 "load_multiple_operation"
5310 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5311 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5312 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5313 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5314 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5315 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5316 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5317 "ldm%?ia\\t%1, {%2, %3, %4}"
5318 [(set_attr "type" "load")
5319 (set_attr "predicable" "yes")]
5322 (define_insn "*ldmsi2"
5323 [(match_parallel 0 "load_multiple_operation"
5324 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5325 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5326 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5327 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5328 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5329 "ldm%?ia\\t%1, {%2, %3}"
5330 [(set_attr "type" "load")
5331 (set_attr "predicable" "yes")]
5334 (define_expand "store_multiple"
5335 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5336 (match_operand:SI 1 "" ""))
5337 (use (match_operand:SI 2 "" ""))])]
5340 /* Support only fixed point registers */
5341 if (GET_CODE (operands[2]) != CONST_INT
5342 || INTVAL (operands[2]) > 14
5343 || INTVAL (operands[2]) < 2
5344 || GET_CODE (operands[1]) != REG
5345 || GET_CODE (operands[0]) != MEM
5346 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5347 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5351 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5352 force_reg (SImode, XEXP (operands[0], 0)),
5353 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5354 MEM_IN_STRUCT_P(operands[0]),
5355 MEM_SCALAR_P (operands[0]));
5359 ;; Store multiple with write-back
5361 (define_insn "*stmsi_postinc4"
5362 [(match_parallel 0 "store_multiple_operation"
5363 [(set (match_operand:SI 1 "s_register_operand" "=r")
5364 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5366 (set (mem:SI (match_dup 2))
5367 (match_operand:SI 3 "arm_hard_register_operand" ""))
5368 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5369 (match_operand:SI 4 "arm_hard_register_operand" ""))
5370 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5371 (match_operand:SI 5 "arm_hard_register_operand" ""))
5372 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5373 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5374 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5375 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5376 [(set_attr "predicable" "yes")
5377 (set_attr "type" "store4")]
5380 (define_insn "*stmsi_postinc3"
5381 [(match_parallel 0 "store_multiple_operation"
5382 [(set (match_operand:SI 1 "s_register_operand" "=r")
5383 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5385 (set (mem:SI (match_dup 2))
5386 (match_operand:SI 3 "arm_hard_register_operand" ""))
5387 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5388 (match_operand:SI 4 "arm_hard_register_operand" ""))
5389 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5390 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5391 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5392 "stm%?ia\\t%1!, {%3, %4, %5}"
5393 [(set_attr "predicable" "yes")
5394 (set_attr "type" "store3")]
5397 (define_insn "*stmsi_postinc2"
5398 [(match_parallel 0 "store_multiple_operation"
5399 [(set (match_operand:SI 1 "s_register_operand" "=r")
5400 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5402 (set (mem:SI (match_dup 2))
5403 (match_operand:SI 3 "arm_hard_register_operand" ""))
5404 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5405 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5406 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5407 "stm%?ia\\t%1!, {%3, %4}"
5408 [(set_attr "predicable" "yes")
5409 (set_attr "type" "store2")]
5412 ;; Ordinary store multiple
5414 (define_insn "*stmsi4"
5415 [(match_parallel 0 "store_multiple_operation"
5416 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5417 (match_operand:SI 2 "arm_hard_register_operand" ""))
5418 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5419 (match_operand:SI 3 "arm_hard_register_operand" ""))
5420 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5421 (match_operand:SI 4 "arm_hard_register_operand" ""))
5422 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5423 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5424 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5425 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5426 [(set_attr "predicable" "yes")
5427 (set_attr "type" "store4")]
5430 (define_insn "*stmsi3"
5431 [(match_parallel 0 "store_multiple_operation"
5432 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5433 (match_operand:SI 2 "arm_hard_register_operand" ""))
5434 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5435 (match_operand:SI 3 "arm_hard_register_operand" ""))
5436 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5437 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5438 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5439 "stm%?ia\\t%1, {%2, %3, %4}"
5440 [(set_attr "predicable" "yes")
5441 (set_attr "type" "store3")]
5444 (define_insn "*stmsi2"
5445 [(match_parallel 0 "store_multiple_operation"
5446 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5447 (match_operand:SI 2 "arm_hard_register_operand" ""))
5448 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5449 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5450 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5451 "stm%?ia\\t%1, {%2, %3}"
5452 [(set_attr "predicable" "yes")
5453 (set_attr "type" "store2")]
5456 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5457 ;; We could let this apply for blocks of less than this, but it clobbers so
5458 ;; many registers that there is then probably a better way.
5460 (define_expand "movstrqi"
5461 [(match_operand:BLK 0 "general_operand" "")
5462 (match_operand:BLK 1 "general_operand" "")
5463 (match_operand:SI 2 "const_int_operand" "")
5464 (match_operand:SI 3 "const_int_operand" "")]
5469 if (arm_gen_movstrqi (operands))
5473 else /* TARGET_THUMB */
5475 if ( INTVAL (operands[3]) != 4
5476 || INTVAL (operands[2]) > 48)
5479 thumb_expand_movstrqi (operands);
5485 ;; Thumb block-move insns
5487 (define_insn "movmem12b"
5488 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5489 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5490 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5491 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5492 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5493 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5494 (set (match_operand:SI 0 "register_operand" "=l")
5495 (plus:SI (match_dup 2) (const_int 12)))
5496 (set (match_operand:SI 1 "register_operand" "=l")
5497 (plus:SI (match_dup 3) (const_int 12)))
5498 (clobber (match_scratch:SI 4 "=&l"))
5499 (clobber (match_scratch:SI 5 "=&l"))
5500 (clobber (match_scratch:SI 6 "=&l"))]
5502 "* return thumb_output_move_mem_multiple (3, operands);"
5503 [(set_attr "length" "4")
5504 ; This isn't entirely accurate... It loads as well, but in terms of
5505 ; scheduling the following insn it is better to consider it as a store
5506 (set_attr "type" "store3")]
5509 (define_insn "movmem8b"
5510 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5511 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5512 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5513 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5514 (set (match_operand:SI 0 "register_operand" "=l")
5515 (plus:SI (match_dup 2) (const_int 8)))
5516 (set (match_operand:SI 1 "register_operand" "=l")
5517 (plus:SI (match_dup 3) (const_int 8)))
5518 (clobber (match_scratch:SI 4 "=&l"))
5519 (clobber (match_scratch:SI 5 "=&l"))]
5521 "* return thumb_output_move_mem_multiple (2, operands);"
5522 [(set_attr "length" "4")
5523 ; This isn't entirely accurate... It loads as well, but in terms of
5524 ; scheduling the following insn it is better to consider it as a store
5525 (set_attr "type" "store2")]
5530 ;; Compare & branch insns
5531 ;; The range calcualations are based as follows:
5532 ;; For forward branches, the address calculation returns the address of
5533 ;; the next instruction. This is 2 beyond the branch instruction.
5534 ;; For backward branches, the address calculation returns the address of
5535 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5536 ;; instruction for the shortest sequence, and 4 before the branch instruction
5537 ;; if we have to jump around an unconditional branch.
5538 ;; To the basic branch range the PC offset must be added (this is +4).
5539 ;; So for forward branches we have
5540 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5541 ;; And for backward branches we have
5542 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5544 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5545 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5547 (define_insn "cbranchsi4"
5550 (match_operator 0 "arm_comparison_operator"
5551 [(match_operand:SI 1 "register_operand" "l,r")
5552 (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5553 (label_ref (match_operand 3 "" ""))
5557 output_asm_insn (\"cmp\\t%1, %2\", operands);
5558 switch (get_attr_length (insn))
5560 case 4: return \"b%d0\\t%l3\";
5561 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5562 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5565 [(set (attr "far_jump")
5567 (eq_attr "length" "8")
5568 (const_string "yes")
5569 (const_string "no")))
5570 (set (attr "length")
5572 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5573 (le (minus (match_dup 3) (pc)) (const_int 256)))
5576 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5577 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5582 (define_insn "*negated_cbranchsi4"
5585 (match_operator 0 "arm_comparison_operator"
5586 [(match_operand:SI 1 "register_operand" "l")
5587 (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5588 (label_ref (match_operand 3 "" ""))
5592 output_asm_insn (\"cmn\\t%1, %2\", operands);
5593 switch (get_attr_length (insn))
5595 case 4: return \"b%d0\\t%l3\";
5596 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5597 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5600 [(set (attr "far_jump")
5602 (eq_attr "length" "8")
5603 (const_string "yes")
5604 (const_string "no")))
5605 (set (attr "length")
5607 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5608 (le (minus (match_dup 3) (pc)) (const_int 256)))
5611 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5612 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5618 ;; Comparison and test insns
5620 (define_expand "cmpsi"
5621 [(match_operand:SI 0 "s_register_operand" "")
5622 (match_operand:SI 1 "arm_add_operand" "")]
5625 arm_compare_op0 = operands[0];
5626 arm_compare_op1 = operands[1];
5631 (define_expand "cmpsf"
5632 [(match_operand:SF 0 "s_register_operand" "")
5633 (match_operand:SF 1 "fpu_rhs_operand" "")]
5634 "TARGET_ARM && TARGET_HARD_FLOAT"
5636 arm_compare_op0 = operands[0];
5637 arm_compare_op1 = operands[1];
5642 (define_expand "cmpdf"
5643 [(match_operand:DF 0 "s_register_operand" "")
5644 (match_operand:DF 1 "fpu_rhs_operand" "")]
5645 "TARGET_ARM && TARGET_HARD_FLOAT"
5647 arm_compare_op0 = operands[0];
5648 arm_compare_op1 = operands[1];
5653 (define_expand "cmpxf"
5654 [(match_operand:XF 0 "s_register_operand" "")
5655 (match_operand:XF 1 "fpu_rhs_operand" "")]
5656 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5658 arm_compare_op0 = operands[0];
5659 arm_compare_op1 = operands[1];
5664 (define_insn "*arm_cmpsi_insn"
5665 [(set (reg:CC CC_REGNUM)
5666 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5667 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
5672 [(set_attr "conds" "set")]
5675 (define_insn "*cmpsi_shiftsi"
5676 [(set (reg:CC CC_REGNUM)
5677 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5678 (match_operator:SI 3 "shift_operator"
5679 [(match_operand:SI 1 "s_register_operand" "r")
5680 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
5683 [(set_attr "conds" "set")
5684 (set_attr "shift" "1")
5688 (define_insn "*cmpsi_shiftsi_swp"
5689 [(set (reg:CC_SWP CC_REGNUM)
5690 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5691 [(match_operand:SI 1 "s_register_operand" "r")
5692 (match_operand:SI 2 "reg_or_int_operand" "rM")])
5693 (match_operand:SI 0 "s_register_operand" "r")))]
5696 [(set_attr "conds" "set")
5697 (set_attr "shift" "1")
5701 (define_insn "*cmpsi_neg_shiftsi"
5702 [(set (reg:CC CC_REGNUM)
5703 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5704 (neg:SI (match_operator:SI 3 "shift_operator"
5705 [(match_operand:SI 1 "s_register_operand" "r")
5706 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5709 [(set_attr "conds" "set")
5710 (set_attr "shift" "1")
5714 (define_insn "*cmpsf_insn"
5715 [(set (reg:CCFP CC_REGNUM)
5716 (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
5717 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5718 "TARGET_ARM && TARGET_HARD_FLOAT"
5722 [(set_attr "conds" "set")
5723 (set_attr "type" "f_2_r")]
5726 (define_insn "*cmpdf_insn"
5727 [(set (reg:CCFP CC_REGNUM)
5728 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
5729 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5730 "TARGET_ARM && TARGET_HARD_FLOAT"
5734 [(set_attr "conds" "set")
5735 (set_attr "type" "f_2_r")]
5738 (define_insn "*cmpesfdf_df"
5739 [(set (reg:CCFP CC_REGNUM)
5740 (compare:CCFP (float_extend:DF
5741 (match_operand:SF 0 "s_register_operand" "f,f"))
5742 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5743 "TARGET_ARM && TARGET_HARD_FLOAT"
5747 [(set_attr "conds" "set")
5748 (set_attr "type" "f_2_r")]
5751 (define_insn "*cmpdf_esfdf"
5752 [(set (reg:CCFP CC_REGNUM)
5753 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5755 (match_operand:SF 1 "s_register_operand" "f"))))]
5756 "TARGET_ARM && TARGET_HARD_FLOAT"
5758 [(set_attr "conds" "set")
5759 (set_attr "type" "f_2_r")]
5762 (define_insn "*cmpxf_insn"
5763 [(set (reg:CCFP CC_REGNUM)
5764 (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
5765 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5766 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5770 [(set_attr "conds" "set")
5771 (set_attr "type" "f_2_r")]
5774 (define_insn "*cmpsf_trap"
5775 [(set (reg:CCFPE CC_REGNUM)
5776 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
5777 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5778 "TARGET_ARM && TARGET_HARD_FLOAT"
5782 [(set_attr "conds" "set")
5783 (set_attr "type" "f_2_r")]
5786 (define_insn "*cmpdf_trap"
5787 [(set (reg:CCFPE CC_REGNUM)
5788 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
5789 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5790 "TARGET_ARM && TARGET_HARD_FLOAT"
5794 [(set_attr "conds" "set")
5795 (set_attr "type" "f_2_r")]
5798 (define_insn "*cmp_esfdf_df_trap"
5799 [(set (reg:CCFPE CC_REGNUM)
5800 (compare:CCFPE (float_extend:DF
5801 (match_operand:SF 0 "s_register_operand" "f,f"))
5802 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5803 "TARGET_ARM && TARGET_HARD_FLOAT"
5807 [(set_attr "conds" "set")
5808 (set_attr "type" "f_2_r")]
5811 (define_insn "*cmp_df_esfdf_trap"
5812 [(set (reg:CCFPE CC_REGNUM)
5813 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
5815 (match_operand:SF 1 "s_register_operand" "f"))))]
5816 "TARGET_ARM && TARGET_HARD_FLOAT"
5818 [(set_attr "conds" "set")
5819 (set_attr "type" "f_2_r")]
5822 (define_insn "*cmpxf_trap"
5823 [(set (reg:CCFPE CC_REGNUM)
5824 (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
5825 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5826 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5830 [(set_attr "conds" "set")
5831 (set_attr "type" "f_2_r")]
5834 ; This insn allows redundant compares to be removed by cse, nothing should
5835 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5836 ; is deleted later on. The match_dup will match the mode here, so that
5837 ; mode changes of the condition codes aren't lost by this even though we don't
5838 ; specify what they are.
5840 (define_insn "*deleted_compare"
5841 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5843 "\\t%@ deleted compare"
5844 [(set_attr "conds" "set")
5845 (set_attr "length" "0")]
5849 ;; Conditional branch insns
5851 (define_expand "beq"
5853 (if_then_else (eq (match_dup 1) (const_int 0))
5854 (label_ref (match_operand 0 "" ""))
5857 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5860 (define_expand "bne"
5862 (if_then_else (ne (match_dup 1) (const_int 0))
5863 (label_ref (match_operand 0 "" ""))
5866 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5869 (define_expand "bgt"
5871 (if_then_else (gt (match_dup 1) (const_int 0))
5872 (label_ref (match_operand 0 "" ""))
5875 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5878 (define_expand "ble"
5880 (if_then_else (le (match_dup 1) (const_int 0))
5881 (label_ref (match_operand 0 "" ""))
5884 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5887 (define_expand "bge"
5889 (if_then_else (ge (match_dup 1) (const_int 0))
5890 (label_ref (match_operand 0 "" ""))
5893 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5896 (define_expand "blt"
5898 (if_then_else (lt (match_dup 1) (const_int 0))
5899 (label_ref (match_operand 0 "" ""))
5902 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5905 (define_expand "bgtu"
5907 (if_then_else (gtu (match_dup 1) (const_int 0))
5908 (label_ref (match_operand 0 "" ""))
5911 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5914 (define_expand "bleu"
5916 (if_then_else (leu (match_dup 1) (const_int 0))
5917 (label_ref (match_operand 0 "" ""))
5920 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5923 (define_expand "bgeu"
5925 (if_then_else (geu (match_dup 1) (const_int 0))
5926 (label_ref (match_operand 0 "" ""))
5929 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5932 (define_expand "bltu"
5934 (if_then_else (ltu (match_dup 1) (const_int 0))
5935 (label_ref (match_operand 0 "" ""))
5938 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5941 (define_expand "bunordered"
5943 (if_then_else (unordered (match_dup 1) (const_int 0))
5944 (label_ref (match_operand 0 "" ""))
5946 "TARGET_ARM && TARGET_HARD_FLOAT"
5947 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5951 (define_expand "bordered"
5953 (if_then_else (ordered (match_dup 1) (const_int 0))
5954 (label_ref (match_operand 0 "" ""))
5956 "TARGET_ARM && TARGET_HARD_FLOAT"
5957 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5961 (define_expand "bungt"
5963 (if_then_else (ungt (match_dup 1) (const_int 0))
5964 (label_ref (match_operand 0 "" ""))
5966 "TARGET_ARM && TARGET_HARD_FLOAT"
5967 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5970 (define_expand "bunlt"
5972 (if_then_else (unlt (match_dup 1) (const_int 0))
5973 (label_ref (match_operand 0 "" ""))
5975 "TARGET_ARM && TARGET_HARD_FLOAT"
5976 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5979 (define_expand "bunge"
5981 (if_then_else (unge (match_dup 1) (const_int 0))
5982 (label_ref (match_operand 0 "" ""))
5984 "TARGET_ARM && TARGET_HARD_FLOAT"
5985 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5988 (define_expand "bunle"
5990 (if_then_else (unle (match_dup 1) (const_int 0))
5991 (label_ref (match_operand 0 "" ""))
5993 "TARGET_ARM && TARGET_HARD_FLOAT"
5994 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5997 ;; The following two patterns need two branch instructions, since there is
5998 ;; no single instruction that will handle all cases.
5999 (define_expand "buneq"
6001 (if_then_else (uneq (match_dup 1) (const_int 0))
6002 (label_ref (match_operand 0 "" ""))
6004 "TARGET_ARM && TARGET_HARD_FLOAT"
6005 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6008 (define_expand "bltgt"
6010 (if_then_else (ltgt (match_dup 1) (const_int 0))
6011 (label_ref (match_operand 0 "" ""))
6013 "TARGET_ARM && TARGET_HARD_FLOAT"
6014 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6018 ;; Patterns to match conditional branch insns.
6021 ; Special pattern to match UNEQ.
6022 (define_insn "*arm_buneq"
6024 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6025 (label_ref (match_operand 0 "" ""))
6027 "TARGET_ARM && TARGET_HARD_FLOAT"
6029 if (arm_ccfsm_state != 0)
6032 return \"bvs\\t%l0;beq\\t%l0\";
6034 [(set_attr "conds" "jump_clob")
6035 (set_attr "length" "8")]
6038 ; Special pattern to match LTGT.
6039 (define_insn "*arm_bltgt"
6041 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6042 (label_ref (match_operand 0 "" ""))
6044 "TARGET_ARM && TARGET_HARD_FLOAT"
6046 if (arm_ccfsm_state != 0)
6049 return \"bmi\\t%l0;bgt\\t%l0\";
6051 [(set_attr "conds" "jump_clob")
6052 (set_attr "length" "8")]
6055 (define_insn "*arm_cond_branch"
6057 (if_then_else (match_operator 1 "arm_comparison_operator"
6058 [(match_operand 2 "cc_register" "") (const_int 0)])
6059 (label_ref (match_operand 0 "" ""))
6063 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6065 arm_ccfsm_state += 2;
6068 return \"b%d1\\t%l0\";
6070 [(set_attr "conds" "use")]
6073 ; Special pattern to match reversed UNEQ.
6074 (define_insn "*arm_buneq_reversed"
6076 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6078 (label_ref (match_operand 0 "" ""))))]
6079 "TARGET_ARM && TARGET_HARD_FLOAT"
6081 if (arm_ccfsm_state != 0)
6084 return \"bmi\\t%l0;bgt\\t%l0\";
6086 [(set_attr "conds" "jump_clob")
6087 (set_attr "length" "8")]
6090 ; Special pattern to match reversed LTGT.
6091 (define_insn "*arm_bltgt_reversed"
6093 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6095 (label_ref (match_operand 0 "" ""))))]
6096 "TARGET_ARM && TARGET_HARD_FLOAT"
6098 if (arm_ccfsm_state != 0)
6101 return \"bvs\\t%l0;beq\\t%l0\";
6103 [(set_attr "conds" "jump_clob")
6104 (set_attr "length" "8")]
6107 (define_insn "*arm_cond_branch_reversed"
6109 (if_then_else (match_operator 1 "arm_comparison_operator"
6110 [(match_operand 2 "cc_register" "") (const_int 0)])
6112 (label_ref (match_operand 0 "" ""))))]
6115 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6117 arm_ccfsm_state += 2;
6120 return \"b%D1\\t%l0\";
6122 [(set_attr "conds" "use")]
6129 (define_expand "seq"
6130 [(set (match_operand:SI 0 "s_register_operand" "=r")
6131 (eq:SI (match_dup 1) (const_int 0)))]
6133 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6136 (define_expand "sne"
6137 [(set (match_operand:SI 0 "s_register_operand" "=r")
6138 (ne:SI (match_dup 1) (const_int 0)))]
6140 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6143 (define_expand "sgt"
6144 [(set (match_operand:SI 0 "s_register_operand" "=r")
6145 (gt:SI (match_dup 1) (const_int 0)))]
6147 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6150 (define_expand "sle"
6151 [(set (match_operand:SI 0 "s_register_operand" "=r")
6152 (le:SI (match_dup 1) (const_int 0)))]
6154 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6157 (define_expand "sge"
6158 [(set (match_operand:SI 0 "s_register_operand" "=r")
6159 (ge:SI (match_dup 1) (const_int 0)))]
6161 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6164 (define_expand "slt"
6165 [(set (match_operand:SI 0 "s_register_operand" "=r")
6166 (lt:SI (match_dup 1) (const_int 0)))]
6168 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6171 (define_expand "sgtu"
6172 [(set (match_operand:SI 0 "s_register_operand" "=r")
6173 (gtu:SI (match_dup 1) (const_int 0)))]
6175 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6178 (define_expand "sleu"
6179 [(set (match_operand:SI 0 "s_register_operand" "=r")
6180 (leu:SI (match_dup 1) (const_int 0)))]
6182 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6185 (define_expand "sgeu"
6186 [(set (match_operand:SI 0 "s_register_operand" "=r")
6187 (geu:SI (match_dup 1) (const_int 0)))]
6189 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6192 (define_expand "sltu"
6193 [(set (match_operand:SI 0 "s_register_operand" "=r")
6194 (ltu:SI (match_dup 1) (const_int 0)))]
6196 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6199 (define_expand "sunordered"
6200 [(set (match_operand:SI 0 "s_register_operand" "=r")
6201 (unordered:SI (match_dup 1) (const_int 0)))]
6202 "TARGET_ARM && TARGET_HARD_FLOAT"
6203 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6207 (define_expand "sordered"
6208 [(set (match_operand:SI 0 "s_register_operand" "=r")
6209 (ordered:SI (match_dup 1) (const_int 0)))]
6210 "TARGET_ARM && TARGET_HARD_FLOAT"
6211 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6215 (define_expand "sungt"
6216 [(set (match_operand:SI 0 "s_register_operand" "=r")
6217 (ungt:SI (match_dup 1) (const_int 0)))]
6218 "TARGET_ARM && TARGET_HARD_FLOAT"
6219 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6223 (define_expand "sunge"
6224 [(set (match_operand:SI 0 "s_register_operand" "=r")
6225 (unge:SI (match_dup 1) (const_int 0)))]
6226 "TARGET_ARM && TARGET_HARD_FLOAT"
6227 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6231 (define_expand "sunlt"
6232 [(set (match_operand:SI 0 "s_register_operand" "=r")
6233 (unlt:SI (match_dup 1) (const_int 0)))]
6234 "TARGET_ARM && TARGET_HARD_FLOAT"
6235 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6239 (define_expand "sunle"
6240 [(set (match_operand:SI 0 "s_register_operand" "=r")
6241 (unle:SI (match_dup 1) (const_int 0)))]
6242 "TARGET_ARM && TARGET_HARD_FLOAT"
6243 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6247 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6248 ;;; simple ARM instructions.
6250 ; (define_expand "suneq"
6251 ; [(set (match_operand:SI 0 "s_register_operand" "=r")
6252 ; (uneq:SI (match_dup 1) (const_int 0)))]
6253 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6257 ; (define_expand "sltgt"
6258 ; [(set (match_operand:SI 0 "s_register_operand" "=r")
6259 ; (ltgt:SI (match_dup 1) (const_int 0)))]
6260 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6264 (define_insn "*mov_scc"
6265 [(set (match_operand:SI 0 "s_register_operand" "=r")
6266 (match_operator:SI 1 "arm_comparison_operator"
6267 [(match_operand 2 "cc_register" "") (const_int 0)]))]
6269 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6270 [(set_attr "conds" "use")
6271 (set_attr "length" "8")]
6274 (define_insn "*mov_negscc"
6275 [(set (match_operand:SI 0 "s_register_operand" "=r")
6276 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
6277 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6279 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6280 [(set_attr "conds" "use")
6281 (set_attr "length" "8")]
6284 (define_insn "*mov_notscc"
6285 [(set (match_operand:SI 0 "s_register_operand" "=r")
6286 (not:SI (match_operator:SI 1 "arm_comparison_operator"
6287 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6289 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6290 [(set_attr "conds" "use")
6291 (set_attr "length" "8")]
6295 ;; Conditional move insns
6297 (define_expand "movsicc"
6298 [(set (match_operand:SI 0 "s_register_operand" "")
6299 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6300 (match_operand:SI 2 "arm_not_operand" "")
6301 (match_operand:SI 3 "arm_not_operand" "")))]
6305 enum rtx_code code = GET_CODE (operands[1]);
6306 rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6308 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6312 (define_expand "movsfcc"
6313 [(set (match_operand:SF 0 "s_register_operand" "")
6314 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6315 (match_operand:SF 2 "s_register_operand" "")
6316 (match_operand:SF 3 "nonmemory_operand" "")))]
6320 enum rtx_code code = GET_CODE (operands[1]);
6323 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
6324 Otherwise, ensure it is a valid FP add operand */
6325 if ((!TARGET_HARD_FLOAT)
6326 || (!fpu_add_operand (operands[3], SFmode)))
6327 operands[3] = force_reg (SFmode, operands[3]);
6329 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6330 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6334 (define_expand "movdfcc"
6335 [(set (match_operand:DF 0 "s_register_operand" "")
6336 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6337 (match_operand:DF 2 "s_register_operand" "")
6338 (match_operand:DF 3 "fpu_add_operand" "")))]
6339 "TARGET_ARM && TARGET_HARD_FLOAT"
6342 enum rtx_code code = GET_CODE (operands[1]);
6343 rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6345 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6349 (define_insn "*movsicc_insn"
6350 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6352 (match_operator 3 "arm_comparison_operator"
6353 [(match_operand 4 "cc_register" "") (const_int 0)])
6354 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6355 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6362 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6363 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6364 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6365 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6366 [(set_attr "length" "4,4,4,4,8,8,8,8")
6367 (set_attr "conds" "use")]
6370 (define_insn "*movsfcc_hard_insn"
6371 [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6373 (match_operator 3 "arm_comparison_operator"
6374 [(match_operand 4 "cc_register" "") (const_int 0)])
6375 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6376 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6377 "TARGET_ARM && TARGET_HARD_FLOAT"
6383 mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
6384 mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
6385 mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
6386 mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
6387 [(set_attr "length" "4,4,4,4,8,8,8,8")
6388 (set_attr "type" "ffarith")
6389 (set_attr "conds" "use")]
6392 (define_insn "*movsfcc_soft_insn"
6393 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6394 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
6395 [(match_operand 4 "cc_register" "") (const_int 0)])
6396 (match_operand:SF 1 "s_register_operand" "0,r")
6397 (match_operand:SF 2 "s_register_operand" "r,0")))]
6398 "TARGET_ARM && TARGET_SOFT_FLOAT"
6402 [(set_attr "conds" "use")]
6405 (define_insn "*movdfcc_insn"
6406 [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6408 (match_operator 3 "arm_comparison_operator"
6409 [(match_operand 4 "cc_register" "") (const_int 0)])
6410 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6411 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6412 "TARGET_ARM && TARGET_HARD_FLOAT"
6418 mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
6419 mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
6420 mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
6421 mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
6422 [(set_attr "length" "4,4,4,4,8,8,8,8")
6423 (set_attr "type" "ffarith")
6424 (set_attr "conds" "use")]
6428 ;; Jump and linkage insns
6430 (define_expand "jump"
6432 (label_ref (match_operand 0 "" "")))]
6437 (define_insn "*arm_jump"
6439 (label_ref (match_operand 0 "" "")))]
6443 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6445 arm_ccfsm_state += 2;
6448 return \"b%?\\t%l0\";
6451 [(set_attr "predicable" "yes")]
6454 (define_insn "*thumb_jump"
6456 (label_ref (match_operand 0 "" "")))]
6459 if (get_attr_length (insn) == 2)
6461 return \"bl\\t%l0\\t%@ far jump\";
6463 [(set (attr "far_jump")
6465 (eq_attr "length" "4")
6466 (const_string "yes")
6467 (const_string "no")))
6468 (set (attr "length")
6470 (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6471 (le (minus (match_dup 0) (pc)) (const_int 2044)))
6476 (define_expand "call"
6477 [(parallel [(call (match_operand 0 "memory_operand" "")
6478 (match_operand 1 "general_operand" ""))
6479 (use (match_operand 2 "" ""))
6480 (clobber (reg:SI LR_REGNUM))])]
6486 /* In an untyped call, we can get NULL for operand 2. */
6487 if (operands[2] == NULL_RTX)
6488 operands[2] = const0_rtx;
6490 /* This is to decide if we should generate indirect calls by loading the
6491 32 bit address of the callee into a register before performing the
6492 branch and link. operand[2] encodes the long_call/short_call
6493 attribute of the function being called. This attribute is set whenever
6494 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6495 is used, and the short_call attribute can also be set if function is
6496 declared as static or if it has already been defined in the current
6497 compilation unit. See arm.c and arm.h for info about this. The third
6498 parameter to arm_is_longcall_p is used to tell it which pattern
6500 callee = XEXP (operands[0], 0);
6502 if (GET_CODE (callee) != REG
6503 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6504 XEXP (operands[0], 0) = force_reg (Pmode, callee);
6508 (define_insn "*call_reg"
6509 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
6510 (match_operand 1 "" ""))
6511 (use (match_operand 2 "" ""))
6512 (clobber (reg:SI LR_REGNUM))]
6515 return output_call (operands);
6517 ;; length is worst case, normally it is only two
6518 [(set_attr "length" "12")
6519 (set_attr "type" "call")]
6522 (define_insn "*call_mem"
6523 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
6524 (match_operand 1 "" ""))
6525 (use (match_operand 2 "" ""))
6526 (clobber (reg:SI LR_REGNUM))]
6529 return output_call_mem (operands);
6531 [(set_attr "length" "12")
6532 (set_attr "type" "call")]
6535 (define_insn "*call_indirect"
6536 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6537 (match_operand 1 "" ""))
6538 (use (match_operand 2 "" ""))
6539 (clobber (reg:SI LR_REGNUM))]
6543 if (TARGET_CALLER_INTERWORKING)
6544 return \"bl\\t%__interwork_call_via_%0\";
6546 return \"bl\\t%__call_via_%0\";
6548 [(set_attr "type" "call")]
6551 (define_insn "*call_value_indirect"
6552 [(set (match_operand 0 "" "=l")
6553 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6554 (match_operand 2 "" "")))
6555 (use (match_operand 3 "" ""))
6556 (clobber (reg:SI LR_REGNUM))]
6560 if (TARGET_CALLER_INTERWORKING)
6561 return \"bl\\t%__interwork_call_via_%1\";
6563 return \"bl\\t%__call_via_%1\";
6565 [(set_attr "type" "call")]
6568 (define_expand "call_value"
6569 [(parallel [(set (match_operand 0 "" "")
6570 (call (match_operand 1 "memory_operand" "")
6571 (match_operand 2 "general_operand" "")))
6572 (use (match_operand 3 "" ""))
6573 (clobber (reg:SI LR_REGNUM))])]
6577 rtx callee = XEXP (operands[1], 0);
6579 /* In an untyped call, we can get NULL for operand 2. */
6580 if (operands[3] == 0)
6581 operands[3] = const0_rtx;
6583 /* See the comment in define_expand \"call\". */
6584 if (GET_CODE (callee) != REG
6585 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6586 XEXP (operands[1], 0) = force_reg (Pmode, callee);
6590 (define_insn "*call_value_reg"
6591 [(set (match_operand 0 "" "=r,f")
6592 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r"))
6593 (match_operand 2 "" "")))
6594 (use (match_operand 3 "" ""))
6595 (clobber (reg:SI LR_REGNUM))]
6598 return output_call (&operands[1]);
6600 [(set_attr "length" "12")
6601 (set_attr "type" "call")]
6604 (define_insn "*call_value_mem"
6605 [(set (match_operand 0 "" "=r,f")
6606 (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m"))
6607 (match_operand 2 "" "")))
6608 (use (match_operand 3 "" ""))
6609 (clobber (reg:SI LR_REGNUM))]
6610 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6612 return output_call_mem (&operands[1]);
6614 [(set_attr "length" "12")
6615 (set_attr "type" "call")]
6618 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6619 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6621 (define_insn "*call_symbol"
6622 [(call (mem:SI (match_operand:SI 0 "" "X"))
6623 (match_operand 1 "" ""))
6624 (use (match_operand 2 "" ""))
6625 (clobber (reg:SI LR_REGNUM))]
6627 && (GET_CODE (operands[0]) == SYMBOL_REF)
6628 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6631 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6633 [(set_attr "type" "call")]
6636 (define_insn "*call_value_symbol"
6637 [(set (match_operand 0 "s_register_operand" "=r,f")
6638 (call (mem:SI (match_operand:SI 1 "" "X,X"))
6639 (match_operand:SI 2 "" "")))
6640 (use (match_operand 3 "" ""))
6641 (clobber (reg:SI LR_REGNUM))]
6643 && (GET_CODE (operands[1]) == SYMBOL_REF)
6644 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6647 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6649 [(set_attr "type" "call")]
6652 (define_insn "*call_insn"
6653 [(call (mem:SI (match_operand:SI 0 "" "X"))
6654 (match_operand:SI 1 "" ""))
6655 (use (match_operand 2 "" ""))
6656 (clobber (reg:SI LR_REGNUM))]
6658 && GET_CODE (operands[0]) == SYMBOL_REF
6659 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6661 [(set_attr "length" "4")
6662 (set_attr "type" "call")]
6665 (define_insn "*call_value_insn"
6666 [(set (match_operand 0 "register_operand" "=l")
6667 (call (mem:SI (match_operand 1 "" "X"))
6668 (match_operand 2 "" "")))
6669 (use (match_operand 3 "" ""))
6670 (clobber (reg:SI LR_REGNUM))]
6672 && GET_CODE (operands[1]) == SYMBOL_REF
6673 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6675 [(set_attr "length" "4")
6676 (set_attr "type" "call")]
6679 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6680 (define_expand "sibcall"
6681 [(parallel [(call (match_operand 0 "memory_operand" "")
6682 (match_operand 1 "general_operand" ""))
6683 (use (match_operand 2 "" ""))
6684 (use (reg:SI LR_REGNUM))])]
6688 if (operands[2] == NULL_RTX)
6689 operands[2] = const0_rtx;
6693 (define_expand "sibcall_value"
6694 [(parallel [(set (match_operand 0 "register_operand" "")
6695 (call (match_operand 1 "memory_operand" "")
6696 (match_operand 2 "general_operand" "")))
6697 (use (match_operand 3 "" ""))
6698 (use (reg:SI LR_REGNUM))])]
6702 if (operands[3] == NULL_RTX)
6703 operands[3] = const0_rtx;
6707 (define_insn "*sibcall_insn"
6708 [(call (mem:SI (match_operand:SI 0 "" "X"))
6709 (match_operand 1 "" ""))
6710 (use (match_operand 2 "" ""))
6711 (use (reg:SI LR_REGNUM))]
6712 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6714 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6716 [(set_attr "type" "call")]
6719 (define_insn "*sibcall_value_insn"
6720 [(set (match_operand 0 "s_register_operand" "=r,f")
6721 (call (mem:SI (match_operand:SI 1 "" "X,X"))
6722 (match_operand 2 "" "")))
6723 (use (match_operand 3 "" ""))
6724 (use (reg:SI LR_REGNUM))]
6725 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6727 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6729 [(set_attr "type" "call")]
6732 ;; Often the return insn will be the same as loading from memory, so set attr
6733 (define_insn "return"
6735 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6738 if (arm_ccfsm_state == 2)
6740 arm_ccfsm_state += 2;
6743 return output_return_instruction (NULL, TRUE, FALSE);
6745 [(set_attr "type" "load")
6746 (set_attr "predicable" "yes")]
6749 (define_insn "*cond_return"
6751 (if_then_else (match_operator 0 "arm_comparison_operator"
6752 [(match_operand 1 "cc_register" "") (const_int 0)])
6755 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6758 if (arm_ccfsm_state == 2)
6760 arm_ccfsm_state += 2;
6763 return output_return_instruction (operands[0], TRUE, FALSE);
6765 [(set_attr "conds" "use")
6766 (set_attr "type" "load")]
6769 (define_insn "*cond_return_inverted"
6771 (if_then_else (match_operator 0 "arm_comparison_operator"
6772 [(match_operand 1 "cc_register" "") (const_int 0)])
6775 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6778 if (arm_ccfsm_state == 2)
6780 arm_ccfsm_state += 2;
6783 return output_return_instruction (operands[0], TRUE, TRUE);
6785 [(set_attr "conds" "use")
6786 (set_attr "type" "load")]
6789 ;; Call subroutine returning any type.
6791 (define_expand "untyped_call"
6792 [(parallel [(call (match_operand 0 "" "")
6794 (match_operand 1 "" "")
6795 (match_operand 2 "" "")])]
6801 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6803 for (i = 0; i < XVECLEN (operands[2], 0); i++)
6805 rtx set = XVECEXP (operands[2], 0, i);
6807 emit_move_insn (SET_DEST (set), SET_SRC (set));
6810 /* The optimizer does not know that the call sets the function value
6811 registers we stored in the result block. We avoid problems by
6812 claiming that all hard registers are used and clobbered at this
6814 emit_insn (gen_blockage ());
6820 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6821 ;; all of memory. This blocks insns from being moved across this point.
6823 (define_insn "blockage"
6824 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6827 [(set_attr "length" "0")
6828 (set_attr "type" "block")]
6831 (define_expand "casesi"
6832 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6833 (match_operand:SI 1 "const_int_operand" "") ; lower bound
6834 (match_operand:SI 2 "const_int_operand" "") ; total range
6835 (match_operand:SI 3 "" "") ; table label
6836 (match_operand:SI 4 "" "")] ; Out of range label
6841 if (operands[1] != const0_rtx)
6843 reg = gen_reg_rtx (SImode);
6845 emit_insn (gen_addsi3 (reg, operands[0],
6846 GEN_INT (-INTVAL (operands[1]))));
6850 if (!const_ok_for_arm (INTVAL (operands[2])))
6851 operands[2] = force_reg (SImode, operands[2]);
6853 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6859 ;; The USE in this pattern is needed to tell flow analysis that this is
6860 ;; a CASESI insn. It has no other purpose.
6861 (define_insn "casesi_internal"
6862 [(parallel [(set (pc)
6864 (leu (match_operand:SI 0 "s_register_operand" "r")
6865 (match_operand:SI 1 "arm_rhs_operand" "rI"))
6866 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6867 (label_ref (match_operand 2 "" ""))))
6868 (label_ref (match_operand 3 "" ""))))
6869 (clobber (reg:CC CC_REGNUM))
6870 (use (label_ref (match_dup 2)))])]
6874 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6875 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6877 [(set_attr "conds" "clob")
6878 (set_attr "length" "12")]
6881 (define_expand "indirect_jump"
6883 (match_operand:SI 0 "s_register_operand" ""))]
6888 (define_insn "*arm_indirect_jump"
6890 (match_operand:SI 0 "s_register_operand" "r"))]
6892 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6893 [(set_attr "predicable" "yes")]
6896 ;; Although not supported by the define_expand above,
6897 ;; cse/combine may generate this form.
6898 (define_insn "*load_indirect_jump"
6900 (match_operand:SI 0 "memory_operand" "m"))]
6902 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6903 [(set_attr "type" "load")
6904 (set_attr "pool_range" "4096")
6905 (set_attr "neg_pool_range" "4084")
6906 (set_attr "predicable" "yes")]
6909 (define_insn "*thumb_indirect_jump"
6911 (match_operand:SI 0 "register_operand" "l*r"))]
6914 [(set_attr "conds" "clob")
6915 (set_attr "length" "2")]
6926 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6927 return \"mov\\tr8, r8\";
6929 [(set (attr "length")
6930 (if_then_else (eq_attr "is_thumb" "yes")
6936 ;; Patterns to allow combination of arithmetic, cond code and shifts
6938 (define_insn "*arith_shiftsi"
6939 [(set (match_operand:SI 0 "s_register_operand" "=r")
6940 (match_operator:SI 1 "shiftable_operator"
6941 [(match_operator:SI 3 "shift_operator"
6942 [(match_operand:SI 4 "s_register_operand" "r")
6943 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6944 (match_operand:SI 2 "s_register_operand" "r")]))]
6946 "%i1%?\\t%0, %2, %4%S3"
6947 [(set_attr "predicable" "yes")
6948 (set_attr "shift" "4")
6952 (define_insn "*arith_shiftsi_compare0"
6953 [(set (reg:CC_NOOV CC_REGNUM)
6954 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6955 [(match_operator:SI 3 "shift_operator"
6956 [(match_operand:SI 4 "s_register_operand" "r")
6957 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6958 (match_operand:SI 2 "s_register_operand" "r")])
6960 (set (match_operand:SI 0 "s_register_operand" "=r")
6961 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6964 "%i1%?s\\t%0, %2, %4%S3"
6965 [(set_attr "conds" "set")
6966 (set_attr "shift" "4")
6970 (define_insn "*arith_shiftsi_compare0_scratch"
6971 [(set (reg:CC_NOOV CC_REGNUM)
6972 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6973 [(match_operator:SI 3 "shift_operator"
6974 [(match_operand:SI 4 "s_register_operand" "r")
6975 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6976 (match_operand:SI 2 "s_register_operand" "r")])
6978 (clobber (match_scratch:SI 0 "=r"))]
6980 "%i1%?s\\t%0, %2, %4%S3"
6981 [(set_attr "conds" "set")
6982 (set_attr "shift" "4")
6986 (define_insn "*sub_shiftsi"
6987 [(set (match_operand:SI 0 "s_register_operand" "=r")
6988 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6989 (match_operator:SI 2 "shift_operator"
6990 [(match_operand:SI 3 "s_register_operand" "r")
6991 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
6993 "sub%?\\t%0, %1, %3%S2"
6994 [(set_attr "predicable" "yes")
6995 (set_attr "shift" "3")
6999 (define_insn "*sub_shiftsi_compare0"
7000 [(set (reg:CC_NOOV CC_REGNUM)
7002 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7003 (match_operator:SI 2 "shift_operator"
7004 [(match_operand:SI 3 "s_register_operand" "r")
7005 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7007 (set (match_operand:SI 0 "s_register_operand" "=r")
7008 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7011 "sub%?s\\t%0, %1, %3%S2"
7012 [(set_attr "conds" "set")
7013 (set_attr "shift" "3")
7017 (define_insn "*sub_shiftsi_compare0_scratch"
7018 [(set (reg:CC_NOOV CC_REGNUM)
7020 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7021 (match_operator:SI 2 "shift_operator"
7022 [(match_operand:SI 3 "s_register_operand" "r")
7023 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7025 (clobber (match_scratch:SI 0 "=r"))]
7027 "sub%?s\\t%0, %1, %3%S2"
7028 [(set_attr "conds" "set")
7029 (set_attr "shift" "3")
7033 ;; These variants of the above insns can occur if the first operand is the
7034 ;; frame pointer and we eliminate that. This is a kludge, but there doesn't
7035 ;; seem to be a way around it. Most of the predicates have to be null
7036 ;; because the format can be generated part way through reload, so
7037 ;; if we don't match it as soon as it becomes available, reload doesn't know
7038 ;; how to reload pseudos that haven't got hard registers; the constraints will
7039 ;; sort everything out.
7041 (define_insn "*reload_mulsi3"
7042 [(set (match_operand:SI 0 "" "=&r")
7043 (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
7044 [(match_operand:SI 3 "" "r")
7045 (match_operand:SI 4 "" "rM")])
7046 (match_operand:SI 2 "" "r"))
7047 (match_operand:SI 1 "const_int_operand" "n")))]
7048 "TARGET_ARM && reload_in_progress"
7050 output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
7051 operands[2] = operands[1];
7052 operands[1] = operands[0];
7053 return output_add_immediate (operands);
7056 ; we have no idea how long the add_immediate is, it could be up to 4.
7057 (set_attr "length" "20")]
7060 (define_insn "*reload_mulsi_compare0"
7061 [(set (reg:CC_NOOV CC_REGNUM)
7062 (compare:CC_NOOV (plus:SI
7064 (match_operator:SI 5 "shift_operator"
7065 [(match_operand:SI 3 "" "r")
7066 (match_operand:SI 4 "" "rM")])
7067 (match_operand:SI 1 "" "r"))
7068 (match_operand:SI 2 "const_int_operand" "n"))
7070 (set (match_operand:SI 0 "" "=&r")
7071 (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
7074 "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7076 output_add_immediate (operands);
7077 return \"add%?s\\t%0, %0, %3%S5\";
7079 [(set_attr "conds" "set")
7080 (set_attr "shift" "3")
7081 (set_attr "length" "20")]
7084 (define_insn "*reload_mulsi_compare0_scratch"
7085 [(set (reg:CC_NOOV CC_REGNUM)
7086 (compare:CC_NOOV (plus:SI
7088 (match_operator:SI 5 "shift_operator"
7089 [(match_operand:SI 3 "" "r")
7090 (match_operand:SI 4 "" "rM")])
7091 (match_operand:SI 1 "" "r"))
7092 (match_operand:SI 2 "const_int_operand" "n"))
7094 (clobber (match_scratch:SI 0 "=&r"))]
7095 "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7097 output_add_immediate (operands);
7098 return \"add%?s\\t%0, %0, %3%S5\";
7100 [(set_attr "conds" "set")
7101 (set_attr "shift" "3")
7102 (set_attr "length" "20")]
7105 ;; These are similar, but are needed when the mla pattern contains the
7106 ;; eliminated register as operand 3.
7108 (define_insn "*reload_muladdsi"
7109 [(set (match_operand:SI 0 "" "=&r,&r")
7110 (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
7111 (match_operand:SI 2 "" "r,r"))
7112 (match_operand:SI 3 "" "r,r"))
7113 (match_operand:SI 4 "const_int_operand" "n,n")))]
7114 "TARGET_ARM && reload_in_progress"
7116 output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
7117 operands[2] = operands[4];
7118 operands[1] = operands[0];
7119 return output_add_immediate (operands);
7121 [(set_attr "length" "20")
7122 (set_attr "type" "mult")]
7125 (define_insn "*reload_muladdsi_compare0"
7126 [(set (reg:CC_NOOV CC_REGNUM)
7127 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
7128 (match_operand:SI 3 "" "r")
7129 (match_operand:SI 4 "" "r"))
7130 (match_operand:SI 1 "" "r"))
7131 (match_operand:SI 2 "const_int_operand" "n"))
7133 (set (match_operand:SI 0 "" "=&r")
7134 (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
7136 "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7138 output_add_immediate (operands);
7139 output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
7142 [(set_attr "length" "20")
7143 (set_attr "conds" "set")
7144 (set_attr "type" "mult")]
7147 (define_insn "*reload_muladdsi_compare0_scratch"
7148 [(set (reg:CC_NOOV CC_REGNUM)
7149 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
7150 (match_operand:SI 3 "" "r")
7151 (match_operand:SI 4 "" "r"))
7152 (match_operand:SI 1 "" "r"))
7153 (match_operand:SI 2 "const_int_operand" "n"))
7155 (clobber (match_scratch:SI 0 "=&r"))]
7156 "TARGET_ARM && reload_in_progress"
7158 output_add_immediate (operands);
7159 return \"mla%?s\\t%0, %3, %4, %0\";
7161 [(set_attr "length" "20")
7162 (set_attr "conds" "set")
7163 (set_attr "type" "mult")]
7168 (define_insn "*and_scc"
7169 [(set (match_operand:SI 0 "s_register_operand" "=r")
7170 (and:SI (match_operator:SI 1 "arm_comparison_operator"
7171 [(match_operand 3 "cc_register" "") (const_int 0)])
7172 (match_operand:SI 2 "s_register_operand" "r")))]
7174 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7175 [(set_attr "conds" "use")
7176 (set_attr "length" "8")]
7179 (define_insn "*ior_scc"
7180 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7181 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
7182 [(match_operand 3 "cc_register" "") (const_int 0)])
7183 (match_operand:SI 1 "s_register_operand" "0,?r")))]
7187 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7188 [(set_attr "conds" "use")
7189 (set_attr "length" "4,8")]
7192 (define_insn "*compare_scc"
7193 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7194 (match_operator:SI 1 "arm_comparison_operator"
7195 [(match_operand:SI 2 "s_register_operand" "r,r")
7196 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7197 (clobber (reg:CC CC_REGNUM))]
7200 if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
7201 return \"mov\\t%0, %2, lsr #31\";
7203 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
7204 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7206 if (GET_CODE (operands[1]) == NE)
7208 if (which_alternative == 1)
7209 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7210 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7212 if (which_alternative == 1)
7213 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7215 output_asm_insn (\"cmp\\t%2, %3\", operands);
7216 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7218 [(set_attr "conds" "clob")
7219 (set_attr "length" "12")]
7222 (define_insn "*cond_move"
7223 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7224 (if_then_else:SI (match_operator 3 "equality_operator"
7225 [(match_operator 4 "arm_comparison_operator"
7226 [(match_operand 5 "cc_register" "") (const_int 0)])
7228 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7229 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7232 if (GET_CODE (operands[3]) == NE)
7234 if (which_alternative != 1)
7235 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7236 if (which_alternative != 0)
7237 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7240 if (which_alternative != 0)
7241 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7242 if (which_alternative != 1)
7243 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7246 [(set_attr "conds" "use")
7247 (set_attr "length" "4,4,8")]
7250 (define_insn "*cond_arith"
7251 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7252 (match_operator:SI 5 "shiftable_operator"
7253 [(match_operator:SI 4 "arm_comparison_operator"
7254 [(match_operand:SI 2 "s_register_operand" "r,r")
7255 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7256 (match_operand:SI 1 "s_register_operand" "0,?r")]))
7257 (clobber (reg:CC CC_REGNUM))]
7260 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7261 return \"%i5\\t%0, %1, %2, lsr #31\";
7263 output_asm_insn (\"cmp\\t%2, %3\", operands);
7264 if (GET_CODE (operands[5]) == AND)
7265 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7266 else if (GET_CODE (operands[5]) == MINUS)
7267 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7268 else if (which_alternative != 0)
7269 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7270 return \"%i5%d4\\t%0, %1, #1\";
7272 [(set_attr "conds" "clob")
7273 (set_attr "length" "12")]
7276 (define_insn "*cond_sub"
7277 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7278 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7279 (match_operator:SI 4 "arm_comparison_operator"
7280 [(match_operand:SI 2 "s_register_operand" "r,r")
7281 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7282 (clobber (reg:CC CC_REGNUM))]
7285 output_asm_insn (\"cmp\\t%2, %3\", operands);
7286 if (which_alternative != 0)
7287 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7288 return \"sub%d4\\t%0, %1, #1\";
7290 [(set_attr "conds" "clob")
7291 (set_attr "length" "8,12")]
7294 (define_insn "*cmp_ite0"
7295 [(set (match_operand 6 "dominant_cc_register" "")
7298 (match_operator 4 "arm_comparison_operator"
7299 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7300 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7301 (match_operator:SI 5 "arm_comparison_operator"
7302 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7303 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7309 static const char * const opcodes[4][2] =
7311 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7312 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7313 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7314 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7315 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7316 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7317 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7318 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7321 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7323 return opcodes[which_alternative][swap];
7325 [(set_attr "conds" "set")
7326 (set_attr "length" "8")]
7329 (define_insn "*cmp_ite1"
7330 [(set (match_operand 6 "dominant_cc_register" "")
7333 (match_operator 4 "arm_comparison_operator"
7334 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7335 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7336 (match_operator:SI 5 "arm_comparison_operator"
7337 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7338 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7344 static const char * const opcodes[4][2] =
7346 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7347 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7348 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7349 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7350 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7351 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7352 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7353 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7356 comparison_dominates_p (GET_CODE (operands[5]),
7357 reverse_condition (GET_CODE (operands[4])));
7359 return opcodes[which_alternative][swap];
7361 [(set_attr "conds" "set")
7362 (set_attr "length" "8")]
7365 (define_insn "*cmp_and"
7366 [(set (match_operand 6 "dominant_cc_register" "")
7369 (match_operator 4 "arm_comparison_operator"
7370 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7371 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7372 (match_operator:SI 5 "arm_comparison_operator"
7373 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7374 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7379 static const char *const opcodes[4][2] =
7381 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7382 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7383 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7384 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7385 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7386 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7387 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7388 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7391 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7393 return opcodes[which_alternative][swap];
7395 [(set_attr "conds" "set")
7396 (set_attr "predicable" "no")
7397 (set_attr "length" "8")]
7400 (define_insn "*cmp_ior"
7401 [(set (match_operand 6 "dominant_cc_register" "")
7404 (match_operator 4 "arm_comparison_operator"
7405 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7406 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7407 (match_operator:SI 5 "arm_comparison_operator"
7408 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7409 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7414 static const char *const opcodes[4][2] =
7416 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7417 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7418 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7419 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7420 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7421 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7422 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7423 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7426 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7428 return opcodes[which_alternative][swap];
7431 [(set_attr "conds" "set")
7432 (set_attr "length" "8")]
7435 (define_insn "*negscc"
7436 [(set (match_operand:SI 0 "s_register_operand" "=r")
7437 (neg:SI (match_operator 3 "arm_comparison_operator"
7438 [(match_operand:SI 1 "s_register_operand" "r")
7439 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7440 (clobber (reg:CC CC_REGNUM))]
7443 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7444 return \"mov\\t%0, %1, asr #31\";
7446 if (GET_CODE (operands[3]) == NE)
7447 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7449 if (GET_CODE (operands[3]) == GT)
7450 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7452 output_asm_insn (\"cmp\\t%1, %2\", operands);
7453 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7454 return \"mvn%d3\\t%0, #0\";
7456 [(set_attr "conds" "clob")
7457 (set_attr "length" "12")]
7460 (define_insn "movcond"
7461 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7463 (match_operator 5 "arm_comparison_operator"
7464 [(match_operand:SI 3 "s_register_operand" "r,r,r")
7465 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7466 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7467 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
7468 (clobber (reg:CC CC_REGNUM))]
7471 if (GET_CODE (operands[5]) == LT
7472 && (operands[4] == const0_rtx))
7474 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7476 if (operands[2] == const0_rtx)
7477 return \"and\\t%0, %1, %3, asr #31\";
7478 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
7480 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7482 if (operands[1] == const0_rtx)
7483 return \"bic\\t%0, %2, %3, asr #31\";
7484 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
7486 /* The only case that falls through to here is when both ops 1 & 2
7490 if (GET_CODE (operands[5]) == GE
7491 && (operands[4] == const0_rtx))
7493 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7495 if (operands[2] == const0_rtx)
7496 return \"bic\\t%0, %1, %3, asr #31\";
7497 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7499 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7501 if (operands[1] == const0_rtx)
7502 return \"and\\t%0, %2, %3, asr #31\";
7503 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7505 /* The only case that falls through to here is when both ops 1 & 2
7508 if (GET_CODE (operands[4]) == CONST_INT
7509 && !const_ok_for_arm (INTVAL (operands[4])))
7510 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7512 output_asm_insn (\"cmp\\t%3, %4\", operands);
7513 if (which_alternative != 0)
7514 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7515 if (which_alternative != 1)
7516 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7519 [(set_attr "conds" "clob")
7520 (set_attr "length" "8,8,12")]
7523 (define_insn "*ifcompare_plus_move"
7524 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7525 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7526 [(match_operand:SI 4 "s_register_operand" "r,r")
7527 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7529 (match_operand:SI 2 "s_register_operand" "r,r")
7530 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7531 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7532 (clobber (reg:CC CC_REGNUM))]
7535 [(set_attr "conds" "clob")
7536 (set_attr "length" "8,12")]
7539 (define_insn "*if_plus_move"
7540 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7542 (match_operator 4 "arm_comparison_operator"
7543 [(match_operand 5 "cc_register" "") (const_int 0)])
7545 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7546 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7547 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7551 sub%d4\\t%0, %2, #%n3
7552 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7553 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7554 [(set_attr "conds" "use")
7555 (set_attr "length" "4,4,8,8")
7556 (set_attr "type" "*,*,*,*")]
7559 (define_insn "*ifcompare_move_plus"
7560 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7561 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7562 [(match_operand:SI 4 "s_register_operand" "r,r")
7563 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7564 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7566 (match_operand:SI 2 "s_register_operand" "r,r")
7567 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7568 (clobber (reg:CC CC_REGNUM))]
7571 [(set_attr "conds" "clob")
7572 (set_attr "length" "8,12")]
7575 (define_insn "*if_move_plus"
7576 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7578 (match_operator 4 "arm_comparison_operator"
7579 [(match_operand 5 "cc_register" "") (const_int 0)])
7580 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7582 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7583 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7587 sub%D4\\t%0, %2, #%n3
7588 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7589 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7590 [(set_attr "conds" "use")
7591 (set_attr "length" "4,4,8,8")
7592 (set_attr "type" "*,*,*,*")]
7595 (define_insn "*ifcompare_arith_arith"
7596 [(set (match_operand:SI 0 "s_register_operand" "=r")
7597 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7598 [(match_operand:SI 5 "s_register_operand" "r")
7599 (match_operand:SI 6 "arm_add_operand" "rIL")])
7600 (match_operator:SI 8 "shiftable_operator"
7601 [(match_operand:SI 1 "s_register_operand" "r")
7602 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7603 (match_operator:SI 7 "shiftable_operator"
7604 [(match_operand:SI 3 "s_register_operand" "r")
7605 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7606 (clobber (reg:CC CC_REGNUM))]
7609 [(set_attr "conds" "clob")
7610 (set_attr "length" "12")]
7613 (define_insn "*if_arith_arith"
7614 [(set (match_operand:SI 0 "s_register_operand" "=r")
7615 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7616 [(match_operand 8 "cc_register" "") (const_int 0)])
7617 (match_operator:SI 6 "shiftable_operator"
7618 [(match_operand:SI 1 "s_register_operand" "r")
7619 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7620 (match_operator:SI 7 "shiftable_operator"
7621 [(match_operand:SI 3 "s_register_operand" "r")
7622 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7624 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7625 [(set_attr "conds" "use")
7626 (set_attr "length" "8")]
7629 (define_insn "*ifcompare_arith_move"
7630 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7631 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7632 [(match_operand:SI 2 "s_register_operand" "r,r")
7633 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7634 (match_operator:SI 7 "shiftable_operator"
7635 [(match_operand:SI 4 "s_register_operand" "r,r")
7636 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7637 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7638 (clobber (reg:CC CC_REGNUM))]
7641 /* If we have an operation where (op x 0) is the identity operation and
7642 the conditional operator is LT or GE and we are comparing against zero and
7643 everything is in registers then we can do this in two instructions */
7644 if (operands[3] == const0_rtx
7645 && GET_CODE (operands[7]) != AND
7646 && GET_CODE (operands[5]) == REG
7647 && GET_CODE (operands[1]) == REG
7648 && REGNO (operands[1]) == REGNO (operands[4])
7649 && REGNO (operands[4]) != REGNO (operands[0]))
7651 if (GET_CODE (operands[6]) == LT)
7652 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7653 else if (GET_CODE (operands[6]) == GE)
7654 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7656 if (GET_CODE (operands[3]) == CONST_INT
7657 && !const_ok_for_arm (INTVAL (operands[3])))
7658 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7660 output_asm_insn (\"cmp\\t%2, %3\", operands);
7661 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7662 if (which_alternative != 0)
7663 return \"mov%D6\\t%0, %1\";
7666 [(set_attr "conds" "clob")
7667 (set_attr "length" "8,12")]
7670 (define_insn "*if_arith_move"
7671 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7672 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7673 [(match_operand 6 "cc_register" "") (const_int 0)])
7674 (match_operator:SI 5 "shiftable_operator"
7675 [(match_operand:SI 2 "s_register_operand" "r,r")
7676 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7677 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7681 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7682 [(set_attr "conds" "use")
7683 (set_attr "length" "4,8")
7684 (set_attr "type" "*,*")]
7687 (define_insn "*ifcompare_move_arith"
7688 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7689 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7690 [(match_operand:SI 4 "s_register_operand" "r,r")
7691 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7692 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7693 (match_operator:SI 7 "shiftable_operator"
7694 [(match_operand:SI 2 "s_register_operand" "r,r")
7695 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7696 (clobber (reg:CC CC_REGNUM))]
7699 /* If we have an operation where (op x 0) is the identity operation and
7700 the conditional operator is LT or GE and we are comparing against zero and
7701 everything is in registers then we can do this in two instructions */
7702 if (operands[5] == const0_rtx
7703 && GET_CODE (operands[7]) != AND
7704 && GET_CODE (operands[3]) == REG
7705 && GET_CODE (operands[1]) == REG
7706 && REGNO (operands[1]) == REGNO (operands[2])
7707 && REGNO (operands[2]) != REGNO (operands[0]))
7709 if (GET_CODE (operands[6]) == GE)
7710 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7711 else if (GET_CODE (operands[6]) == LT)
7712 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7715 if (GET_CODE (operands[5]) == CONST_INT
7716 && !const_ok_for_arm (INTVAL (operands[5])))
7717 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7719 output_asm_insn (\"cmp\\t%4, %5\", operands);
7721 if (which_alternative != 0)
7722 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7723 return \"%I7%D6\\t%0, %2, %3\";
7725 [(set_attr "conds" "clob")
7726 (set_attr "length" "8,12")]
7729 (define_insn "*if_move_arith"
7730 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7732 (match_operator 4 "arm_comparison_operator"
7733 [(match_operand 6 "cc_register" "") (const_int 0)])
7734 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7735 (match_operator:SI 5 "shiftable_operator"
7736 [(match_operand:SI 2 "s_register_operand" "r,r")
7737 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7741 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7742 [(set_attr "conds" "use")
7743 (set_attr "length" "4,8")
7744 (set_attr "type" "*,*")]
7747 (define_insn "*ifcompare_move_not"
7748 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7750 (match_operator 5 "arm_comparison_operator"
7751 [(match_operand:SI 3 "s_register_operand" "r,r")
7752 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7753 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7755 (match_operand:SI 2 "s_register_operand" "r,r"))))
7756 (clobber (reg:CC CC_REGNUM))]
7759 [(set_attr "conds" "clob")
7760 (set_attr "length" "8,12")]
7763 (define_insn "*if_move_not"
7764 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7766 (match_operator 4 "arm_comparison_operator"
7767 [(match_operand 3 "cc_register" "") (const_int 0)])
7768 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7769 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7773 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7774 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7775 [(set_attr "conds" "use")
7776 (set_attr "length" "4,8,8")]
7779 (define_insn "*ifcompare_not_move"
7780 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7782 (match_operator 5 "arm_comparison_operator"
7783 [(match_operand:SI 3 "s_register_operand" "r,r")
7784 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7786 (match_operand:SI 2 "s_register_operand" "r,r"))
7787 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7788 (clobber (reg:CC CC_REGNUM))]
7791 [(set_attr "conds" "clob")
7792 (set_attr "length" "8,12")]
7795 (define_insn "*if_not_move"
7796 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7798 (match_operator 4 "arm_comparison_operator"
7799 [(match_operand 3 "cc_register" "") (const_int 0)])
7800 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7801 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7805 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7806 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7807 [(set_attr "conds" "use")
7808 (set_attr "length" "4,8,8")]
7811 (define_insn "*ifcompare_shift_move"
7812 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7814 (match_operator 6 "arm_comparison_operator"
7815 [(match_operand:SI 4 "s_register_operand" "r,r")
7816 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7817 (match_operator:SI 7 "shift_operator"
7818 [(match_operand:SI 2 "s_register_operand" "r,r")
7819 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7820 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7821 (clobber (reg:CC CC_REGNUM))]
7824 [(set_attr "conds" "clob")
7825 (set_attr "length" "8,12")]
7828 (define_insn "*if_shift_move"
7829 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7831 (match_operator 5 "arm_comparison_operator"
7832 [(match_operand 6 "cc_register" "") (const_int 0)])
7833 (match_operator:SI 4 "shift_operator"
7834 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7835 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7836 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7840 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7841 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7842 [(set_attr "conds" "use")
7843 (set_attr "shift" "2")
7844 (set_attr "length" "4,8,8")]
7847 (define_insn "*ifcompare_move_shift"
7848 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7850 (match_operator 6 "arm_comparison_operator"
7851 [(match_operand:SI 4 "s_register_operand" "r,r")
7852 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7853 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7854 (match_operator:SI 7 "shift_operator"
7855 [(match_operand:SI 2 "s_register_operand" "r,r")
7856 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7857 (clobber (reg:CC CC_REGNUM))]
7860 [(set_attr "conds" "clob")
7861 (set_attr "length" "8,12")]
7864 (define_insn "*if_move_shift"
7865 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7867 (match_operator 5 "arm_comparison_operator"
7868 [(match_operand 6 "cc_register" "") (const_int 0)])
7869 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7870 (match_operator:SI 4 "shift_operator"
7871 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7872 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7876 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7877 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7878 [(set_attr "conds" "use")
7879 (set_attr "shift" "2")
7880 (set_attr "length" "4,8,8")]
7883 (define_insn "*ifcompare_shift_shift"
7884 [(set (match_operand:SI 0 "s_register_operand" "=r")
7886 (match_operator 7 "arm_comparison_operator"
7887 [(match_operand:SI 5 "s_register_operand" "r")
7888 (match_operand:SI 6 "arm_add_operand" "rIL")])
7889 (match_operator:SI 8 "shift_operator"
7890 [(match_operand:SI 1 "s_register_operand" "r")
7891 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7892 (match_operator:SI 9 "shift_operator"
7893 [(match_operand:SI 3 "s_register_operand" "r")
7894 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7895 (clobber (reg:CC CC_REGNUM))]
7898 [(set_attr "conds" "clob")
7899 (set_attr "length" "12")]
7902 (define_insn "*if_shift_shift"
7903 [(set (match_operand:SI 0 "s_register_operand" "=r")
7905 (match_operator 5 "arm_comparison_operator"
7906 [(match_operand 8 "cc_register" "") (const_int 0)])
7907 (match_operator:SI 6 "shift_operator"
7908 [(match_operand:SI 1 "s_register_operand" "r")
7909 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7910 (match_operator:SI 7 "shift_operator"
7911 [(match_operand:SI 3 "s_register_operand" "r")
7912 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7914 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7915 [(set_attr "conds" "use")
7916 (set_attr "shift" "1")
7917 (set_attr "length" "8")]
7920 (define_insn "*ifcompare_not_arith"
7921 [(set (match_operand:SI 0 "s_register_operand" "=r")
7923 (match_operator 6 "arm_comparison_operator"
7924 [(match_operand:SI 4 "s_register_operand" "r")
7925 (match_operand:SI 5 "arm_add_operand" "rIL")])
7926 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7927 (match_operator:SI 7 "shiftable_operator"
7928 [(match_operand:SI 2 "s_register_operand" "r")
7929 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7930 (clobber (reg:CC CC_REGNUM))]
7933 [(set_attr "conds" "clob")
7934 (set_attr "length" "12")]
7937 (define_insn "*if_not_arith"
7938 [(set (match_operand:SI 0 "s_register_operand" "=r")
7940 (match_operator 5 "arm_comparison_operator"
7941 [(match_operand 4 "cc_register" "") (const_int 0)])
7942 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7943 (match_operator:SI 6 "shiftable_operator"
7944 [(match_operand:SI 2 "s_register_operand" "r")
7945 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7947 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7948 [(set_attr "conds" "use")
7949 (set_attr "length" "8")]
7952 (define_insn "*ifcompare_arith_not"
7953 [(set (match_operand:SI 0 "s_register_operand" "=r")
7955 (match_operator 6 "arm_comparison_operator"
7956 [(match_operand:SI 4 "s_register_operand" "r")
7957 (match_operand:SI 5 "arm_add_operand" "rIL")])
7958 (match_operator:SI 7 "shiftable_operator"
7959 [(match_operand:SI 2 "s_register_operand" "r")
7960 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7961 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7962 (clobber (reg:CC CC_REGNUM))]
7965 [(set_attr "conds" "clob")
7966 (set_attr "length" "12")]
7969 (define_insn "*if_arith_not"
7970 [(set (match_operand:SI 0 "s_register_operand" "=r")
7972 (match_operator 5 "arm_comparison_operator"
7973 [(match_operand 4 "cc_register" "") (const_int 0)])
7974 (match_operator:SI 6 "shiftable_operator"
7975 [(match_operand:SI 2 "s_register_operand" "r")
7976 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7977 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7979 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7980 [(set_attr "conds" "use")
7981 (set_attr "length" "8")]
7984 (define_insn "*ifcompare_neg_move"
7985 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7987 (match_operator 5 "arm_comparison_operator"
7988 [(match_operand:SI 3 "s_register_operand" "r,r")
7989 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7990 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7991 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7992 (clobber (reg:CC CC_REGNUM))]
7995 [(set_attr "conds" "clob")
7996 (set_attr "length" "8,12")]
7999 (define_insn "*if_neg_move"
8000 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8002 (match_operator 4 "arm_comparison_operator"
8003 [(match_operand 3 "cc_register" "") (const_int 0)])
8004 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8005 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8009 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
8010 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8011 [(set_attr "conds" "use")
8012 (set_attr "length" "4,8,8")]
8015 (define_insn "*ifcompare_move_neg"
8016 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8018 (match_operator 5 "arm_comparison_operator"
8019 [(match_operand:SI 3 "s_register_operand" "r,r")
8020 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8021 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8022 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
8023 (clobber (reg:CC CC_REGNUM))]
8026 [(set_attr "conds" "clob")
8027 (set_attr "length" "8,12")]
8030 (define_insn "*if_move_neg"
8031 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8033 (match_operator 4 "arm_comparison_operator"
8034 [(match_operand 3 "cc_register" "") (const_int 0)])
8035 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8036 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8040 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
8041 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
8042 [(set_attr "conds" "use")
8043 (set_attr "length" "4,8,8")]
8046 (define_insn "*arith_adjacentmem"
8047 [(set (match_operand:SI 0 "s_register_operand" "=r")
8048 (match_operator:SI 1 "shiftable_operator"
8049 [(match_operand:SI 2 "memory_operand" "m")
8050 (match_operand:SI 3 "memory_operand" "m")]))
8051 (clobber (match_scratch:SI 4 "=r"))]
8052 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
8057 int val1 = 0, val2 = 0;
8059 if (REGNO (operands[0]) > REGNO (operands[4]))
8061 ldm[1] = operands[4];
8062 ldm[2] = operands[0];
8066 ldm[1] = operands[0];
8067 ldm[2] = operands[4];
8069 if (GET_CODE (XEXP (operands[2], 0)) != REG)
8070 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
8071 if (GET_CODE (XEXP (operands[3], 0)) != REG)
8072 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
8073 arith[0] = operands[0];
8074 arith[3] = operands[1];
8088 ldm[0] = ops[0] = operands[4];
8089 ops[1] = XEXP (XEXP (operands[2], 0), 0);
8090 ops[2] = XEXP (XEXP (operands[2], 0), 1);
8091 output_add_immediate (ops);
8093 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8095 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8099 ldm[0] = XEXP (operands[3], 0);
8101 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8103 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8107 ldm[0] = XEXP (operands[2], 0);
8109 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8111 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8113 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
8116 [(set_attr "length" "12")
8117 (set_attr "predicable" "yes")
8118 (set_attr "type" "load")]
8121 ;; the arm can support extended pre-inc instructions
8123 ;; In all these cases, we use operands 0 and 1 for the register being
8124 ;; incremented because those are the operands that local-alloc will
8125 ;; tie and these are the pair most likely to be tieable (and the ones
8126 ;; that will benefit the most).
8128 ;; We reject the frame pointer if it occurs anywhere in these patterns since
8129 ;; elimination will cause too many headaches.
8131 (define_insn "*strqi_preinc"
8132 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8133 (match_operand:SI 2 "index_operand" "rJ")))
8134 (match_operand:QI 3 "s_register_operand" "r"))
8135 (set (match_operand:SI 0 "s_register_operand" "=r")
8136 (plus:SI (match_dup 1) (match_dup 2)))]
8138 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8139 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8140 && (GET_CODE (operands[2]) != REG
8141 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8142 "str%?b\\t%3, [%0, %2]!"
8143 [(set_attr "type" "store1")
8144 (set_attr "predicable" "yes")]
8147 (define_insn "*strqi_predec"
8148 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8149 (match_operand:SI 2 "s_register_operand" "r")))
8150 (match_operand:QI 3 "s_register_operand" "r"))
8151 (set (match_operand:SI 0 "s_register_operand" "=r")
8152 (minus:SI (match_dup 1) (match_dup 2)))]
8154 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8155 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8156 && (GET_CODE (operands[2]) != REG
8157 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8158 "str%?b\\t%3, [%0, -%2]!"
8159 [(set_attr "type" "store1")
8160 (set_attr "predicable" "yes")]
8163 (define_insn "*loadqi_preinc"
8164 [(set (match_operand:QI 3 "s_register_operand" "=r")
8165 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8166 (match_operand:SI 2 "index_operand" "rJ"))))
8167 (set (match_operand:SI 0 "s_register_operand" "=r")
8168 (plus:SI (match_dup 1) (match_dup 2)))]
8170 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8171 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8172 && (GET_CODE (operands[2]) != REG
8173 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8174 "ldr%?b\\t%3, [%0, %2]!"
8175 [(set_attr "type" "load")
8176 (set_attr "predicable" "yes")]
8179 (define_insn "*loadqi_predec"
8180 [(set (match_operand:QI 3 "s_register_operand" "=r")
8181 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8182 (match_operand:SI 2 "s_register_operand" "r"))))
8183 (set (match_operand:SI 0 "s_register_operand" "=r")
8184 (minus:SI (match_dup 1) (match_dup 2)))]
8186 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8187 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8188 && (GET_CODE (operands[2]) != REG
8189 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8190 "ldr%?b\\t%3, [%0, -%2]!"
8191 [(set_attr "type" "load")
8192 (set_attr "predicable" "yes")]
8195 (define_insn "*loadqisi_preinc"
8196 [(set (match_operand:SI 3 "s_register_operand" "=r")
8198 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8199 (match_operand:SI 2 "index_operand" "rJ")))))
8200 (set (match_operand:SI 0 "s_register_operand" "=r")
8201 (plus:SI (match_dup 1) (match_dup 2)))]
8203 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8204 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8205 && (GET_CODE (operands[2]) != REG
8206 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8207 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8208 [(set_attr "type" "load")
8209 (set_attr "predicable" "yes")]
8212 (define_insn "*loadqisi_predec"
8213 [(set (match_operand:SI 3 "s_register_operand" "=r")
8215 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8216 (match_operand:SI 2 "s_register_operand" "r")))))
8217 (set (match_operand:SI 0 "s_register_operand" "=r")
8218 (minus:SI (match_dup 1) (match_dup 2)))]
8220 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8221 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8222 && (GET_CODE (operands[2]) != REG
8223 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8224 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8225 [(set_attr "type" "load")
8226 (set_attr "predicable" "yes")]
8229 (define_insn "*strsi_preinc"
8230 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8231 (match_operand:SI 2 "index_operand" "rJ")))
8232 (match_operand:SI 3 "s_register_operand" "r"))
8233 (set (match_operand:SI 0 "s_register_operand" "=r")
8234 (plus:SI (match_dup 1) (match_dup 2)))]
8236 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8237 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8238 && (GET_CODE (operands[2]) != REG
8239 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8240 "str%?\\t%3, [%0, %2]!"
8241 [(set_attr "type" "store1")
8242 (set_attr "predicable" "yes")]
8245 (define_insn "*strsi_predec"
8246 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8247 (match_operand:SI 2 "s_register_operand" "r")))
8248 (match_operand:SI 3 "s_register_operand" "r"))
8249 (set (match_operand:SI 0 "s_register_operand" "=r")
8250 (minus:SI (match_dup 1) (match_dup 2)))]
8252 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8253 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8254 && (GET_CODE (operands[2]) != REG
8255 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8256 "str%?\\t%3, [%0, -%2]!"
8257 [(set_attr "type" "store1")
8258 (set_attr "predicable" "yes")]
8261 (define_insn "*loadsi_preinc"
8262 [(set (match_operand:SI 3 "s_register_operand" "=r")
8263 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8264 (match_operand:SI 2 "index_operand" "rJ"))))
8265 (set (match_operand:SI 0 "s_register_operand" "=r")
8266 (plus:SI (match_dup 1) (match_dup 2)))]
8268 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8269 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8270 && (GET_CODE (operands[2]) != REG
8271 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8272 "ldr%?\\t%3, [%0, %2]!"
8273 [(set_attr "type" "load")
8274 (set_attr "predicable" "yes")]
8277 (define_insn "*loadsi_predec"
8278 [(set (match_operand:SI 3 "s_register_operand" "=r")
8279 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8280 (match_operand:SI 2 "s_register_operand" "r"))))
8281 (set (match_operand:SI 0 "s_register_operand" "=r")
8282 (minus:SI (match_dup 1) (match_dup 2)))]
8284 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8285 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8286 && (GET_CODE (operands[2]) != REG
8287 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8288 "ldr%?\\t%3, [%0, -%2]!"
8289 [(set_attr "type" "load")
8290 (set_attr "predicable" "yes")]
8293 (define_insn "*loadhi_preinc"
8294 [(set (match_operand:HI 3 "s_register_operand" "=r")
8295 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8296 (match_operand:SI 2 "index_operand" "rJ"))))
8297 (set (match_operand:SI 0 "s_register_operand" "=r")
8298 (plus:SI (match_dup 1) (match_dup 2)))]
8300 && !BYTES_BIG_ENDIAN
8301 && !TARGET_MMU_TRAPS
8302 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8303 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8304 && (GET_CODE (operands[2]) != REG
8305 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8306 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8307 [(set_attr "type" "load")
8308 (set_attr "predicable" "yes")]
8311 (define_insn "*loadhi_predec"
8312 [(set (match_operand:HI 3 "s_register_operand" "=r")
8313 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8314 (match_operand:SI 2 "s_register_operand" "r"))))
8315 (set (match_operand:SI 0 "s_register_operand" "=r")
8316 (minus:SI (match_dup 1) (match_dup 2)))]
8318 && !BYTES_BIG_ENDIAN
8319 && !TARGET_MMU_TRAPS
8320 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8321 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8322 && (GET_CODE (operands[2]) != REG
8323 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8324 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8325 [(set_attr "type" "load")
8326 (set_attr "predicable" "yes")]
8329 (define_insn "*strqi_shiftpreinc"
8330 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8331 [(match_operand:SI 3 "s_register_operand" "r")
8332 (match_operand:SI 4 "const_shift_operand" "n")])
8333 (match_operand:SI 1 "s_register_operand" "0")))
8334 (match_operand:QI 5 "s_register_operand" "r"))
8335 (set (match_operand:SI 0 "s_register_operand" "=r")
8336 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8339 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8340 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8341 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8342 "str%?b\\t%5, [%0, %3%S2]!"
8343 [(set_attr "type" "store1")
8344 (set_attr "predicable" "yes")]
8347 (define_insn "*strqi_shiftpredec"
8348 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8349 (match_operator:SI 2 "shift_operator"
8350 [(match_operand:SI 3 "s_register_operand" "r")
8351 (match_operand:SI 4 "const_shift_operand" "n")])))
8352 (match_operand:QI 5 "s_register_operand" "r"))
8353 (set (match_operand:SI 0 "s_register_operand" "=r")
8354 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8357 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8358 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8359 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8360 "str%?b\\t%5, [%0, -%3%S2]!"
8361 [(set_attr "type" "store1")
8362 (set_attr "predicable" "yes")]
8365 (define_insn "*loadqi_shiftpreinc"
8366 [(set (match_operand:QI 5 "s_register_operand" "=r")
8367 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8368 [(match_operand:SI 3 "s_register_operand" "r")
8369 (match_operand:SI 4 "const_shift_operand" "n")])
8370 (match_operand:SI 1 "s_register_operand" "0"))))
8371 (set (match_operand:SI 0 "s_register_operand" "=r")
8372 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8375 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8376 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8377 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8378 "ldr%?b\\t%5, [%0, %3%S2]!"
8379 [(set_attr "type" "load")
8380 (set_attr "predicable" "yes")]
8383 (define_insn "*loadqi_shiftpredec"
8384 [(set (match_operand:QI 5 "s_register_operand" "=r")
8385 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8386 (match_operator:SI 2 "shift_operator"
8387 [(match_operand:SI 3 "s_register_operand" "r")
8388 (match_operand:SI 4 "const_shift_operand" "n")]))))
8389 (set (match_operand:SI 0 "s_register_operand" "=r")
8390 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8393 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8394 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8395 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8396 "ldr%?b\\t%5, [%0, -%3%S2]!"
8397 [(set_attr "type" "load")
8398 (set_attr "predicable" "yes")]
8401 (define_insn "*strsi_shiftpreinc"
8402 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8403 [(match_operand:SI 3 "s_register_operand" "r")
8404 (match_operand:SI 4 "const_shift_operand" "n")])
8405 (match_operand:SI 1 "s_register_operand" "0")))
8406 (match_operand:SI 5 "s_register_operand" "r"))
8407 (set (match_operand:SI 0 "s_register_operand" "=r")
8408 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8411 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8412 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8413 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8414 "str%?\\t%5, [%0, %3%S2]!"
8415 [(set_attr "type" "store1")
8416 (set_attr "predicable" "yes")]
8419 (define_insn "*strsi_shiftpredec"
8420 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8421 (match_operator:SI 2 "shift_operator"
8422 [(match_operand:SI 3 "s_register_operand" "r")
8423 (match_operand:SI 4 "const_shift_operand" "n")])))
8424 (match_operand:SI 5 "s_register_operand" "r"))
8425 (set (match_operand:SI 0 "s_register_operand" "=r")
8426 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8429 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8430 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8431 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8432 "str%?\\t%5, [%0, -%3%S2]!"
8433 [(set_attr "type" "store1")
8434 (set_attr "predicable" "yes")]
8437 (define_insn "*loadsi_shiftpreinc"
8438 [(set (match_operand:SI 5 "s_register_operand" "=r")
8439 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8440 [(match_operand:SI 3 "s_register_operand" "r")
8441 (match_operand:SI 4 "const_shift_operand" "n")])
8442 (match_operand:SI 1 "s_register_operand" "0"))))
8443 (set (match_operand:SI 0 "s_register_operand" "=r")
8444 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8447 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8448 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8449 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8450 "ldr%?\\t%5, [%0, %3%S2]!"
8451 [(set_attr "type" "load")
8452 (set_attr "predicable" "yes")]
8455 (define_insn "*loadsi_shiftpredec"
8456 [(set (match_operand:SI 5 "s_register_operand" "=r")
8457 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8458 (match_operator:SI 2 "shift_operator"
8459 [(match_operand:SI 3 "s_register_operand" "r")
8460 (match_operand:SI 4 "const_shift_operand" "n")]))))
8461 (set (match_operand:SI 0 "s_register_operand" "=r")
8462 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8465 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8466 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8467 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8468 "ldr%?\\t%5, [%0, -%3%S2]!"
8469 [(set_attr "type" "load")
8470 (set_attr "predicable" "yes")])
8472 (define_insn "*loadhi_shiftpreinc"
8473 [(set (match_operand:HI 5 "s_register_operand" "=r")
8474 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8475 [(match_operand:SI 3 "s_register_operand" "r")
8476 (match_operand:SI 4 "const_shift_operand" "n")])
8477 (match_operand:SI 1 "s_register_operand" "0"))))
8478 (set (match_operand:SI 0 "s_register_operand" "=r")
8479 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8482 && !BYTES_BIG_ENDIAN
8483 && !TARGET_MMU_TRAPS
8484 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8485 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8486 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8487 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8488 [(set_attr "type" "load")
8489 (set_attr "predicable" "yes")]
8492 (define_insn "*loadhi_shiftpredec"
8493 [(set (match_operand:HI 5 "s_register_operand" "=r")
8494 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8495 (match_operator:SI 2 "shift_operator"
8496 [(match_operand:SI 3 "s_register_operand" "r")
8497 (match_operand:SI 4 "const_shift_operand" "n")]))))
8498 (set (match_operand:SI 0 "s_register_operand" "=r")
8499 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8502 && !BYTES_BIG_ENDIAN
8503 && !TARGET_MMU_TRAPS
8504 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8505 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8506 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8507 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8508 [(set_attr "type" "load")
8509 (set_attr "predicable" "yes")]
8512 ; It can also support extended post-inc expressions, but combine doesn't
8514 ; It doesn't seem worth adding peepholes for anything but the most common
8515 ; cases since, unlike combine, the increment must immediately follow the load
8516 ; for this pattern to match.
8517 ; We must watch to see that the source/destination register isn't also the
8518 ; same as the base address register, and that if the index is a register,
8519 ; that it is not the same as the base address register. In such cases the
8520 ; instruction that we would generate would have UNPREDICTABLE behaviour so
8524 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8525 (match_operand:QI 2 "s_register_operand" "r"))
8527 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8529 && (REGNO (operands[2]) != REGNO (operands[0]))
8530 && (GET_CODE (operands[1]) != REG
8531 || (REGNO (operands[1]) != REGNO (operands[0])))"
8532 "str%?b\\t%2, [%0], %1"
8536 [(set (match_operand:QI 0 "s_register_operand" "=r")
8537 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8539 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8541 && REGNO (operands[0]) != REGNO(operands[1])
8542 && (GET_CODE (operands[2]) != REG
8543 || REGNO(operands[0]) != REGNO (operands[2]))"
8544 "ldr%?b\\t%0, [%1], %2"
8548 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8549 (match_operand:SI 2 "s_register_operand" "r"))
8551 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8553 && (REGNO (operands[2]) != REGNO (operands[0]))
8554 && (GET_CODE (operands[1]) != REG
8555 || (REGNO (operands[1]) != REGNO (operands[0])))"
8556 "str%?\\t%2, [%0], %1"
8560 [(set (match_operand:HI 0 "s_register_operand" "=r")
8561 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8563 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8565 && !BYTES_BIG_ENDIAN
8566 && !TARGET_MMU_TRAPS
8567 && REGNO (operands[0]) != REGNO(operands[1])
8568 && (GET_CODE (operands[2]) != REG
8569 || REGNO(operands[0]) != REGNO (operands[2]))"
8570 "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8574 [(set (match_operand:SI 0 "s_register_operand" "=r")
8575 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8577 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8579 && REGNO (operands[0]) != REGNO(operands[1])
8580 && (GET_CODE (operands[2]) != REG
8581 || REGNO(operands[0]) != REGNO (operands[2]))"
8582 "ldr%?\\t%0, [%1], %2"
8586 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8587 (match_operand:SI 1 "index_operand" "rJ")))
8588 (match_operand:QI 2 "s_register_operand" "r"))
8589 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8591 && (REGNO (operands[2]) != REGNO (operands[0]))
8592 && (GET_CODE (operands[1]) != REG
8593 || (REGNO (operands[1]) != REGNO (operands[0])))"
8594 "str%?b\\t%2, [%0, %1]!"
8598 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8599 [(match_operand:SI 0 "s_register_operand" "r")
8600 (match_operand:SI 1 "const_int_operand" "n")])
8601 (match_operand:SI 2 "s_register_operand" "+r")))
8602 (match_operand:QI 3 "s_register_operand" "r"))
8603 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8606 && (REGNO (operands[3]) != REGNO (operands[2]))
8607 && (REGNO (operands[0]) != REGNO (operands[2]))"
8608 "str%?b\\t%3, [%2, %0%S4]!"
8611 ; This pattern is never tried by combine, so do it as a peephole
8614 [(set (match_operand:SI 0 "s_register_operand" "")
8615 (match_operand:SI 1 "s_register_operand" ""))
8616 (set (reg:CC CC_REGNUM)
8617 (compare:CC (match_dup 1) (const_int 0)))]
8620 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8621 (set (match_dup 0) (match_dup 1))])]
8625 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8626 ; reversed, check that the memory references aren't volatile.
8629 [(set (match_operand:SI 0 "s_register_operand" "=r")
8630 (match_operand:SI 4 "memory_operand" "m"))
8631 (set (match_operand:SI 1 "s_register_operand" "=r")
8632 (match_operand:SI 5 "memory_operand" "m"))
8633 (set (match_operand:SI 2 "s_register_operand" "=r")
8634 (match_operand:SI 6 "memory_operand" "m"))
8635 (set (match_operand:SI 3 "s_register_operand" "=r")
8636 (match_operand:SI 7 "memory_operand" "m"))]
8637 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8639 return emit_ldm_seq (operands, 4);
8644 [(set (match_operand:SI 0 "s_register_operand" "=r")
8645 (match_operand:SI 3 "memory_operand" "m"))
8646 (set (match_operand:SI 1 "s_register_operand" "=r")
8647 (match_operand:SI 4 "memory_operand" "m"))
8648 (set (match_operand:SI 2 "s_register_operand" "=r")
8649 (match_operand:SI 5 "memory_operand" "m"))]
8650 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8652 return emit_ldm_seq (operands, 3);
8657 [(set (match_operand:SI 0 "s_register_operand" "=r")
8658 (match_operand:SI 2 "memory_operand" "m"))
8659 (set (match_operand:SI 1 "s_register_operand" "=r")
8660 (match_operand:SI 3 "memory_operand" "m"))]
8661 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8663 return emit_ldm_seq (operands, 2);
8668 [(set (match_operand:SI 4 "memory_operand" "=m")
8669 (match_operand:SI 0 "s_register_operand" "r"))
8670 (set (match_operand:SI 5 "memory_operand" "=m")
8671 (match_operand:SI 1 "s_register_operand" "r"))
8672 (set (match_operand:SI 6 "memory_operand" "=m")
8673 (match_operand:SI 2 "s_register_operand" "r"))
8674 (set (match_operand:SI 7 "memory_operand" "=m")
8675 (match_operand:SI 3 "s_register_operand" "r"))]
8676 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8678 return emit_stm_seq (operands, 4);
8683 [(set (match_operand:SI 3 "memory_operand" "=m")
8684 (match_operand:SI 0 "s_register_operand" "r"))
8685 (set (match_operand:SI 4 "memory_operand" "=m")
8686 (match_operand:SI 1 "s_register_operand" "r"))
8687 (set (match_operand:SI 5 "memory_operand" "=m")
8688 (match_operand:SI 2 "s_register_operand" "r"))]
8689 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8691 return emit_stm_seq (operands, 3);
8696 [(set (match_operand:SI 2 "memory_operand" "=m")
8697 (match_operand:SI 0 "s_register_operand" "r"))
8698 (set (match_operand:SI 3 "memory_operand" "=m")
8699 (match_operand:SI 1 "s_register_operand" "r"))]
8700 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8702 return emit_stm_seq (operands, 2);
8707 [(set (match_operand:SI 0 "s_register_operand" "")
8708 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8710 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8711 [(match_operand:SI 3 "s_register_operand" "")
8712 (match_operand:SI 4 "arm_rhs_operand" "")]))))
8713 (clobber (match_operand:SI 5 "s_register_operand" ""))]
8715 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8716 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8721 ;; This split can be used because CC_Z mode implies that the following
8722 ;; branch will be an equality, or an unsigned inequality, so the sign
8723 ;; extension is not needed.
8726 [(set (reg:CC_Z CC_REGNUM)
8728 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8730 (match_operand 1 "const_int_operand" "")))
8731 (clobber (match_scratch:SI 2 ""))]
8733 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8734 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8735 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8736 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8738 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8742 (define_expand "prologue"
8743 [(clobber (const_int 0))]
8746 arm_expand_prologue ();
8748 thumb_expand_prologue ();
8753 (define_expand "epilogue"
8754 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8758 thumb_expand_epilogue ();
8759 else if (USE_RETURN_INSN (FALSE))
8761 emit_jump_insn (gen_return ());
8764 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8766 gen_rtx_RETURN (VOIDmode)),
8772 (define_insn "sibcall_epilogue"
8773 [(unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)]
8776 output_asm_insn (\"%@ Sibcall epilogue\", operands);
8777 if (USE_RETURN_INSN (FALSE))
8778 return output_return_instruction (NULL, FALSE, FALSE);
8779 return arm_output_epilogue (FALSE);
8781 ;; Length is absolute worst case
8782 [(set_attr "length" "44")
8783 (set_attr "type" "block")]
8786 (define_insn "*epilogue_insns"
8787 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8791 return arm_output_epilogue (TRUE);
8792 else /* TARGET_THUMB */
8793 return thumb_unexpanded_epilogue ();
8795 ; Length is absolute worst case
8796 [(set_attr "length" "44")
8797 (set_attr "type" "block")]
8800 (define_expand "eh_epilogue"
8801 [(use (match_operand:SI 0 "register_operand" "r"))
8802 (use (match_operand:SI 1 "register_operand" "r"))
8803 (use (match_operand:SI 2 "register_operand" "r"))]
8807 cfun->machine->eh_epilogue_sp_ofs = operands[1];
8808 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8810 rtx ra = gen_rtx_REG (Pmode, 2);
8812 emit_move_insn (ra, operands[2]);
8815 /* This is a hack -- we may have crystalized the function type too
8817 cfun->machine->func_type = 0;
8821 ;; This split is only used during output to reduce the number of patterns
8822 ;; that need assembler instructions adding to them. We allowed the setting
8823 ;; of the conditions to be implicit during rtl generation so that
8824 ;; the conditional compare patterns would work. However this conflicts to
8825 ;; some extent with the conditional data operations, so we have to split them
8829 [(set (match_operand:SI 0 "s_register_operand" "")
8830 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8831 [(match_operand 2 "" "") (match_operand 3 "" "")])
8833 (match_operand 4 "" "")))
8834 (clobber (reg:CC CC_REGNUM))]
8835 "TARGET_ARM && reload_completed"
8836 [(set (match_dup 5) (match_dup 6))
8837 (cond_exec (match_dup 7)
8838 (set (match_dup 0) (match_dup 4)))]
8841 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8842 operands[2], operands[3]);
8843 enum rtx_code rc = GET_CODE (operands[1]);
8845 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8846 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8847 if (mode == CCFPmode || mode == CCFPEmode)
8848 rc = reverse_condition_maybe_unordered (rc);
8850 rc = reverse_condition (rc);
8852 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8857 [(set (match_operand:SI 0 "s_register_operand" "")
8858 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8859 [(match_operand 2 "" "") (match_operand 3 "" "")])
8860 (match_operand 4 "" "")
8862 (clobber (reg:CC CC_REGNUM))]
8863 "TARGET_ARM && reload_completed"
8864 [(set (match_dup 5) (match_dup 6))
8865 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8866 (set (match_dup 0) (match_dup 4)))]
8869 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8870 operands[2], operands[3]);
8872 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8873 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8878 [(set (match_operand:SI 0 "s_register_operand" "")
8879 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8880 [(match_operand 2 "" "") (match_operand 3 "" "")])
8881 (match_operand 4 "" "")
8882 (match_operand 5 "" "")))
8883 (clobber (reg:CC CC_REGNUM))]
8884 "TARGET_ARM && reload_completed"
8885 [(set (match_dup 6) (match_dup 7))
8886 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8887 (set (match_dup 0) (match_dup 4)))
8888 (cond_exec (match_dup 8)
8889 (set (match_dup 0) (match_dup 5)))]
8892 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8893 operands[2], operands[3]);
8894 enum rtx_code rc = GET_CODE (operands[1]);
8896 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8897 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8898 if (mode == CCFPmode || mode == CCFPEmode)
8899 rc = reverse_condition_maybe_unordered (rc);
8901 rc = reverse_condition (rc);
8903 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8908 [(set (match_operand:SI 0 "s_register_operand" "")
8909 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8910 [(match_operand:SI 2 "s_register_operand" "")
8911 (match_operand:SI 3 "arm_add_operand" "")])
8912 (match_operand:SI 4 "arm_rhs_operand" "")
8914 (match_operand:SI 5 "s_register_operand" ""))))
8915 (clobber (reg:CC CC_REGNUM))]
8916 "TARGET_ARM && reload_completed"
8917 [(set (match_dup 6) (match_dup 7))
8918 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8919 (set (match_dup 0) (match_dup 4)))
8920 (cond_exec (match_dup 8)
8921 (set (match_dup 0) (not:SI (match_dup 5))))]
8924 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8925 operands[2], operands[3]);
8926 enum rtx_code rc = GET_CODE (operands[1]);
8928 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8929 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8930 if (mode == CCFPmode || mode == CCFPEmode)
8931 rc = reverse_condition_maybe_unordered (rc);
8933 rc = reverse_condition (rc);
8935 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8939 (define_insn "*cond_move_not"
8940 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8941 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8942 [(match_operand 3 "cc_register" "") (const_int 0)])
8943 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8945 (match_operand:SI 2 "s_register_operand" "r,r"))))]
8949 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8950 [(set_attr "conds" "use")
8951 (set_attr "length" "4,8")]
8954 ;; The next two patterns occur when an AND operation is followed by a
8955 ;; scc insn sequence
8957 (define_insn "*sign_extract_onebit"
8958 [(set (match_operand:SI 0 "s_register_operand" "=r")
8959 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8961 (match_operand:SI 2 "const_int_operand" "n")))]
8964 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8965 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8966 return \"mvnne\\t%0, #0\";
8968 [(set_attr "conds" "clob")
8969 (set_attr "length" "8")]
8972 (define_insn "*not_signextract_onebit"
8973 [(set (match_operand:SI 0 "s_register_operand" "=r")
8975 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8977 (match_operand:SI 2 "const_int_operand" "n"))))]
8980 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8981 output_asm_insn (\"tst\\t%1, %2\", operands);
8982 output_asm_insn (\"mvneq\\t%0, #0\", operands);
8983 return \"movne\\t%0, #0\";
8985 [(set_attr "conds" "clob")
8986 (set_attr "length" "12")]
8989 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
8990 ;; expressions. For simplicity, the first register is also in the unspec
8992 (define_insn "*push_multi"
8993 [(match_parallel 2 "multi_register_push"
8994 [(set (match_operand:BLK 0 "memory_operand" "=m")
8995 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8996 UNSPEC_PUSH_MULT))])]
9000 int num_saves = XVECLEN (operands[2], 0);
9002 /* For the StrongARM at least it is faster to
9003 use STR to store only a single register. */
9005 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9011 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9013 for (i = 1; i < num_saves; i++)
9015 strcat (pattern, \", %|\");
9017 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9020 strcat (pattern, \"}\");
9021 output_asm_insn (pattern, operands);
9026 [(set_attr "type" "store4")]
9029 ;; Similarly for the floating point registers
9030 (define_insn "*push_fp_multi"
9031 [(match_parallel 2 "multi_register_push"
9032 [(set (match_operand:BLK 0 "memory_operand" "=m")
9033 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9034 UNSPEC_PUSH_MULT))])]
9040 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9041 output_asm_insn (pattern, operands);
9044 [(set_attr "type" "f_store")]
9047 ;; Special patterns for dealing with the constant pool
9049 (define_insn "align_4"
9050 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9053 assemble_align (32);
9058 (define_insn "consttable_end"
9059 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9062 making_const_table = FALSE;
9067 (define_insn "consttable_1"
9068 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9071 making_const_table = TRUE;
9072 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9076 [(set_attr "length" "4")]
9079 (define_insn "consttable_2"
9080 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9083 making_const_table = TRUE;
9084 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9088 [(set_attr "length" "4")]
9091 (define_insn "consttable_4"
9092 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9096 making_const_table = TRUE;
9097 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9101 union real_extract u;
9102 memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
9103 assemble_real (u.d, GET_MODE (operands[0]), BITS_PER_WORD);
9107 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9112 [(set_attr "length" "4")]
9115 (define_insn "consttable_8"
9116 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9120 making_const_table = TRUE;
9121 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9125 union real_extract u;
9126 memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
9127 assemble_real (u.d, GET_MODE (operands[0]), BITS_PER_WORD);
9131 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9136 [(set_attr "length" "8")]
9139 ;; Miscellaneous Thumb patterns
9141 (define_insn "tablejump"
9142 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9143 (use (label_ref (match_operand 1 "" "")))]
9146 [(set_attr "length" "2")]
9152 [(set (match_operand:SI 0 "s_register_operand" "=r")
9153 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")]
9155 "TARGET_ARM && arm_arch5"
9158 (define_expand "ffssi2"
9159 [(set (match_operand:SI 0 "s_register_operand" "")
9160 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9161 "TARGET_ARM && arm_arch5"
9166 t1 = gen_reg_rtx (SImode);
9167 t2 = gen_reg_rtx (SImode);
9168 t3 = gen_reg_rtx (SImode);
9170 emit_insn (gen_negsi2 (t1, operands[1]));
9171 emit_insn (gen_andsi3 (t2, operands[1], t1));
9172 emit_insn (gen_clz (t3, t2));
9173 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
9178 ;; V5E instructions.
9180 (define_insn "prefetch"
9181 [(prefetch (match_operand:SI 0 "address_operand" "p")
9182 (match_operand:SI 1 "" "")
9183 (match_operand:SI 2 "" ""))]
9184 "TARGET_ARM && arm_arch5e"
9187 ;; General predication pattern
9190 [(match_operator 0 "arm_comparison_operator"
9191 [(match_operand 1 "cc_register" "")
9197 (define_insn "prologue_use"
9198 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
9200 "%@ %0 needed for prologue"