1 ;;- Machine description for ARM for GNU compiler
2 ;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;; 2001, 2002, 2003 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 GCC.
10 ;; GCC is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 2, or (at your
13 ;; option) any later version.
15 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
18 ;; License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; 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.
28 ;;---------------------------------------------------------------------------
33 [(IP_REGNUM 12) ; Scratch register
34 (SP_REGNUM 13) ; Stack pointer
35 (LR_REGNUM 14) ; Return address register
36 (PC_REGNUM 15) ; Program counter
37 (CC_REGNUM 24) ; Condition code pseudo register
43 ;; Note: sin and cos are no-longer used.
46 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
47 ; operand 0 is the result,
48 ; operand 1 the parameter.
49 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
50 ; operand 0 is the result,
51 ; operand 1 the parameter.
52 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
53 ; operand 0 is the first register,
54 ; subsequent registers are in parallel (use ...)
56 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
57 ; usage, that is, we will add the pic_register
58 ; value to it before trying to dereference it.
59 (UNSPEC_PRLG_STK 4) ; A special barrier that prevents frame accesses
60 ; being scheduled before the stack adjustment insn.
61 (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
62 ; this unspec is used to prevent the deletion of
63 ; instructions setting registers for EH handling
64 ; and stack frame generation. Operand 0 is the
66 (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
70 ;; UNSPEC_VOLATILE Usage:
73 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
75 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
76 ; instruction epilogue sequence that isn't expanded
77 ; into normal RTL. Used for both normal and sibcall
79 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
80 ; for inlined constants.
81 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
83 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
85 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
87 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
89 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
94 ;;---------------------------------------------------------------------------
97 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
98 ; generating ARM code. This is used to control the length of some insn
99 ; patterns that share the same RTL in both ARM and Thumb code.
100 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
102 ; PROG_MODE attribute is used to determine whether condition codes are
103 ; clobbered by a call insn: they are if in prog32 mode. This is controlled
104 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
105 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
107 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
108 ; scheduling decisions for the load unit and the multiplier.
109 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
111 ;; Operand number of an input operand that is shifted. Zero if the
112 ;; given instruction does not shift one of its input operands.
113 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_is_xscale")))
114 (define_attr "shift" "" (const_int 0))
116 ; Floating Point Unit. If we only have floating point emulation, then there
117 ; is no point in scheduling the floating point insns. (Well, for best
118 ; performance we should try and group them together).
119 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
121 ; LENGTH of an instruction (in bytes)
122 (define_attr "length" "" (const_int 4))
124 ; POOL_RANGE is how far away from a constant pool entry that this insn
125 ; can be placed. If the distance is zero, then this insn will never
126 ; reference the pool.
127 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
128 ; before its address.
129 (define_attr "pool_range" "" (const_int 0))
130 (define_attr "neg_pool_range" "" (const_int 0))
132 ; An assembler sequence may clobber the condition codes without us knowing.
133 ; If such an insn references the pool, then we have no way of knowing how,
134 ; so use the most conservative value for pool_range.
135 (define_asm_attributes
136 [(set_attr "conds" "clob")
137 (set_attr "length" "4")
138 (set_attr "pool_range" "250")])
140 ; TYPE attribute is used to detect floating point instructions which, if
141 ; running on a co-processor can run in parallel with other, basic instructions
142 ; If write-buffer scheduling is enabled then it can also be used in the
143 ; scheduling of writes.
145 ; Classification of each insn
146 ; normal any data instruction that doesn't hit memory or fp regs
147 ; mult a multiply instruction
148 ; block blockage insn, this blocks all functional units
149 ; float a floating point arithmetic operation (subject to expansion)
150 ; fdivd DFmode floating point division
151 ; fdivs SFmode floating point division
152 ; fmul Floating point multiply
153 ; ffmul Fast floating point multiply
154 ; farith Floating point arithmetic (4 cycle)
155 ; ffarith Fast floating point arithmetic (2 cycle)
156 ; float_em a floating point arithmetic operation that is normally emulated
157 ; even on a machine with an fpa.
158 ; f_load a floating point load from memory
159 ; f_store a floating point store to memory
160 ; f_mem_r a transfer of a floating point register to a real reg via mem
161 ; r_mem_f the reverse of f_mem_r
162 ; f_2_r fast transfer float to arm (no memory needed)
163 ; r_2_f fast transfer arm to float
164 ; call a subroutine call
165 ; load any load from memory
166 ; store1 store 1 word to memory from arm registers
167 ; store2 store 2 words
168 ; store3 store 3 words
169 ; store4 store 4 words
172 "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"
173 (const_string "normal"))
175 ; Load scheduling, set from the arm_ld_sched variable
176 ; initialized by arm_override_options()
177 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
179 ; condition codes: this one is used by final_prescan_insn to speed up
180 ; conditionalizing instructions. It saves having to scan the rtl to see if
181 ; it uses or alters the condition codes.
183 ; USE means that the condition codes are used by the insn in the process of
184 ; outputting code, this means (at present) that we can't use the insn in
187 ; SET means that the purpose of the insn is to set the condition codes in a
188 ; well defined manner.
190 ; CLOB means that the condition codes are altered in an undefined manner, if
191 ; they are altered at all
193 ; JUMP_CLOB is used when the condition cannot be represented by a single
194 ; instruction (UNEQ and LTGT). These cannot be predicated.
196 ; NOCOND means that the condition codes are neither altered nor affect the
197 ; output of this insn
199 (define_attr "conds" "use,set,clob,jump_clob,nocond"
200 (if_then_else (eq_attr "type" "call")
201 (if_then_else (eq_attr "prog_mode" "prog32")
202 (const_string "clob") (const_string "nocond"))
203 (const_string "nocond")))
205 ; Predicable means that the insn can be conditionally executed based on
206 ; an automatically added predicate (additional patterns are generated by
207 ; gen...). We default to 'no' because no Thumb patterns match this rule
208 ; and not all ARM patterns do.
209 (define_attr "predicable" "no,yes" (const_string "no"))
211 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
212 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
213 ; suffer blockages enough to warrent modelling this (and it can adversely
214 ; affect the schedule).
215 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
217 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
218 ; to stall the processor. Used with model_wbuf above.
219 (define_attr "write_conflict" "no,yes"
220 (if_then_else (eq_attr "type"
221 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
223 (const_string "no")))
225 ; Classify the insns into those that take one cycle and those that take more
226 ; than one on the main cpu execution unit.
227 (define_attr "core_cycles" "single,multi"
228 (if_then_else (eq_attr "type"
229 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
230 (const_string "single")
231 (const_string "multi")))
233 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
234 ;; distant label. Only applicable to Thumb code.
235 (define_attr "far_jump" "yes,no" (const_string "no"))
237 ;; (define_function_unit {name} {num-units} {n-users} {test}
238 ;; {ready-delay} {issue-delay} [{conflict-list}])
240 ;;--------------------------------------------------------------------
241 ;; Floating point unit (FPA)
242 ;;--------------------------------------------------------------------
243 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
244 (eq_attr "type" "fdivx")) 71 69)
246 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
247 (eq_attr "type" "fdivd")) 59 57)
249 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
250 (eq_attr "type" "fdivs")) 31 29)
252 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
253 (eq_attr "type" "fmul")) 9 7)
255 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
256 (eq_attr "type" "ffmul")) 6 4)
258 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
259 (eq_attr "type" "farith")) 4 2)
261 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
262 (eq_attr "type" "ffarith")) 2 2)
264 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
265 (eq_attr "type" "r_2_f")) 5 3)
267 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
268 (eq_attr "type" "f_2_r")) 1 2)
270 ; The fpa10 doesn't really have a memory read unit, but it can start to
271 ; speculatively execute the instruction in the pipeline, provided the data
272 ; is already loaded, so pretend reads have a delay of 2 (and that the
273 ; pipeline is infinite).
275 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
276 (eq_attr "type" "f_load")) 3 1)
278 ;;--------------------------------------------------------------------
280 ;;--------------------------------------------------------------------
281 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
283 ; The write buffer on some of the arm6 processors is hard to model exactly.
284 ; There is room in the buffer for up to two addresses and up to eight words
285 ; of memory, but the two needn't be split evenly. When writing the two
286 ; addresses are fully pipelined. However, a read from memory that is not
287 ; currently in the cache will block until the writes have completed.
288 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
289 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
290 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
291 ; cycle to add as well.
293 (define_function_unit "write_buf" 1 2
294 (and (eq_attr "model_wbuf" "yes")
295 (eq_attr "type" "store1,r_mem_f")) 5 3)
296 (define_function_unit "write_buf" 1 2
297 (and (eq_attr "model_wbuf" "yes")
298 (eq_attr "type" "store2")) 7 4)
299 (define_function_unit "write_buf" 1 2
300 (and (eq_attr "model_wbuf" "yes")
301 (eq_attr "type" "store3")) 9 5)
302 (define_function_unit "write_buf" 1 2
303 (and (eq_attr "model_wbuf" "yes")
304 (eq_attr "type" "store4")) 11 6)
306 ;;--------------------------------------------------------------------
307 ;; Write blockage unit
308 ;;--------------------------------------------------------------------
309 ; The write_blockage unit models (partially), the fact that reads will stall
310 ; until the write buffer empties.
311 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
312 ; so we don't model them here
313 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
314 (eq_attr "type" "store1")) 5 5
315 [(eq_attr "write_conflict" "yes")])
316 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
317 (eq_attr "type" "store2")) 7 7
318 [(eq_attr "write_conflict" "yes")])
319 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
320 (eq_attr "type" "store3")) 9 9
321 [(eq_attr "write_conflict" "yes")])
322 (define_function_unit "write_blockage" 1 0
323 (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
324 [(eq_attr "write_conflict" "yes")])
325 (define_function_unit "write_blockage" 1 0
326 (and (eq_attr "model_wbuf" "yes")
327 (eq_attr "write_conflict" "yes")) 1 1)
329 ;;--------------------------------------------------------------------
331 ;;--------------------------------------------------------------------
332 ; Everything must spend at least one cycle in the core unit
333 (define_function_unit "core" 1 0 (eq_attr "core_cycles" "single") 1 1)
335 (define_function_unit "core" 1 0
336 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
338 (define_function_unit "core" 1 0
339 (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
341 ;; We do not need to conditionalize the define_function_unit immediately
342 ;; above. This one will be ignored for anything other than xscale
343 ;; compiles and for xscale compiles it provides a larger delay
344 ;; and the scheduler will DTRT.
345 ;; FIXME: this test needs to be revamped to not depend on this feature
348 (define_function_unit "core" 1 0
349 (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
350 (eq_attr "is_xscale" "yes"))
353 (define_function_unit "core" 1 0
354 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
356 (define_function_unit "core" 1 0
357 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
359 (define_function_unit "core" 1 0
360 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
362 (define_function_unit "core" 1 0
363 (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
365 (define_function_unit "core" 1 0
366 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
368 (define_function_unit "core" 1 0
369 (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
371 (define_function_unit "core" 1 0
372 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
373 (eq_attr "type" "mult")) 4 4)
375 (define_function_unit "core" 1 0
376 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
377 (eq_attr "type" "mult")) 3 2)
379 (define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
381 (define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
383 (define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
385 (define_function_unit "core" 1 0
386 (and (eq_attr "core_cycles" "multi")
387 (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
389 (include "cirrus.md")
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.
399 ;; Cirrus 64bit additions should not be split because we have a native
400 ;; 64bit addition instructions.
402 (define_expand "adddi3"
404 [(set (match_operand:DI 0 "s_register_operand" "")
405 (plus:DI (match_operand:DI 1 "s_register_operand" "")
406 (match_operand:DI 2 "s_register_operand" "")))
407 (clobber (reg:CC CC_REGNUM))])]
412 if (!cirrus_fp_register (operands[0], DImode))
413 operands[0] = force_reg (DImode, operands[0]);
414 if (!cirrus_fp_register (operands[1], DImode))
415 operands[1] = force_reg (DImode, operands[1]);
416 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
422 if (GET_CODE (operands[1]) != REG)
423 operands[1] = force_reg (SImode, operands[1]);
424 if (GET_CODE (operands[2]) != REG)
425 operands[2] = force_reg (SImode, operands[2]);
430 (define_insn "*thumb_adddi3"
431 [(set (match_operand:DI 0 "register_operand" "=l")
432 (plus:DI (match_operand:DI 1 "register_operand" "%0")
433 (match_operand:DI 2 "register_operand" "l")))
434 (clobber (reg:CC CC_REGNUM))
437 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
438 [(set_attr "length" "4")]
441 (define_insn_and_split "*arm_adddi3"
442 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
443 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
444 (match_operand:DI 2 "s_register_operand" "r, 0")))
445 (clobber (reg:CC CC_REGNUM))]
446 "TARGET_ARM && !TARGET_CIRRUS"
448 "TARGET_ARM && reload_completed"
449 [(parallel [(set (reg:CC_C CC_REGNUM)
450 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
452 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
453 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
454 (plus:SI (match_dup 4) (match_dup 5))))]
457 operands[3] = gen_highpart (SImode, operands[0]);
458 operands[0] = gen_lowpart (SImode, operands[0]);
459 operands[4] = gen_highpart (SImode, operands[1]);
460 operands[1] = gen_lowpart (SImode, operands[1]);
461 operands[5] = gen_highpart (SImode, operands[2]);
462 operands[2] = gen_lowpart (SImode, operands[2]);
464 [(set_attr "conds" "clob")
465 (set_attr "length" "8")]
468 (define_insn_and_split "*adddi_sesidi_di"
469 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
470 (plus:DI (sign_extend:DI
471 (match_operand:SI 2 "s_register_operand" "r,r"))
472 (match_operand:DI 1 "s_register_operand" "r,0")))
473 (clobber (reg:CC CC_REGNUM))]
474 "TARGET_ARM && !TARGET_CIRRUS"
476 "TARGET_ARM && reload_completed"
477 [(parallel [(set (reg:CC_C CC_REGNUM)
478 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
480 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
481 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
482 (plus:SI (ashiftrt:SI (match_dup 2)
487 operands[3] = gen_highpart (SImode, operands[0]);
488 operands[0] = gen_lowpart (SImode, operands[0]);
489 operands[4] = gen_highpart (SImode, operands[1]);
490 operands[1] = gen_lowpart (SImode, operands[1]);
491 operands[2] = gen_lowpart (SImode, operands[2]);
493 [(set_attr "conds" "clob")
494 (set_attr "length" "8")]
497 (define_insn_and_split "*adddi_zesidi_di"
498 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
499 (plus:DI (zero_extend:DI
500 (match_operand:SI 2 "s_register_operand" "r,r"))
501 (match_operand:DI 1 "s_register_operand" "r,0")))
502 (clobber (reg:CC CC_REGNUM))]
503 "TARGET_ARM && !TARGET_CIRRUS"
505 "TARGET_ARM && reload_completed"
506 [(parallel [(set (reg:CC_C CC_REGNUM)
507 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
509 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
510 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
511 (plus:SI (match_dup 4) (const_int 0))))]
514 operands[3] = gen_highpart (SImode, operands[0]);
515 operands[0] = gen_lowpart (SImode, operands[0]);
516 operands[4] = gen_highpart (SImode, operands[1]);
517 operands[1] = gen_lowpart (SImode, operands[1]);
518 operands[2] = gen_lowpart (SImode, operands[2]);
520 [(set_attr "conds" "clob")
521 (set_attr "length" "8")]
524 (define_expand "addsi3"
525 [(set (match_operand:SI 0 "s_register_operand" "")
526 (plus:SI (match_operand:SI 1 "s_register_operand" "")
527 (match_operand:SI 2 "reg_or_int_operand" "")))]
530 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
532 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
534 (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
540 ; If there is a scratch available, this will be faster than synthesising the
543 [(match_scratch:SI 3 "r")
544 (set (match_operand:SI 0 "s_register_operand" "")
545 (plus:SI (match_operand:SI 1 "s_register_operand" "")
546 (match_operand:SI 2 "const_int_operand" "")))]
548 !(const_ok_for_arm (INTVAL (operands[2]))
549 || const_ok_for_arm (-INTVAL (operands[2])))
550 && const_ok_for_arm (~INTVAL (operands[2]))"
551 [(set (match_dup 3) (match_dup 2))
552 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
556 (define_insn_and_split "*arm_addsi3"
557 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
558 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
559 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
566 GET_CODE (operands[2]) == CONST_INT
567 && !(const_ok_for_arm (INTVAL (operands[2]))
568 || const_ok_for_arm (-INTVAL (operands[2])))"
569 [(clobber (const_int 0))]
571 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
575 [(set_attr "length" "4,4,16")
576 (set_attr "predicable" "yes")]
579 ;; Register group 'k' is a single register group containing only the stack
580 ;; register. Trying to reload it will always fail catastrophically,
581 ;; so never allow those alternatives to match if reloading is needed.
583 (define_insn "*thumb_addsi3"
584 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
585 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
586 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
589 static const char * const asms[] =
591 \"add\\t%0, %0, %2\",
592 \"sub\\t%0, %0, #%n2\",
593 \"add\\t%0, %1, %2\",
594 \"add\\t%0, %0, %2\",
595 \"add\\t%0, %0, %2\",
596 \"add\\t%0, %1, %2\",
599 if ((which_alternative == 2 || which_alternative == 6)
600 && GET_CODE (operands[2]) == CONST_INT
601 && INTVAL (operands[2]) < 0)
602 return \"sub\\t%0, %1, #%n2\";
603 return asms[which_alternative];
605 [(set_attr "length" "2")]
608 ;; Reloading and elimination of the frame pointer can
609 ;; sometimes cause this optimization to be missed.
611 [(set (match_operand:SI 0 "register_operand" "")
612 (match_operand:SI 1 "const_int_operand" ""))
614 (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
616 && REGNO (operands[2]) == STACK_POINTER_REGNUM
617 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
618 && (INTVAL (operands[1]) & 3) == 0"
619 [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
623 (define_insn "*addsi3_compare0"
624 [(set (reg:CC_NOOV CC_REGNUM)
626 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
627 (match_operand:SI 2 "arm_add_operand" "rI,L"))
629 (set (match_operand:SI 0 "s_register_operand" "=r,r")
630 (plus:SI (match_dup 1) (match_dup 2)))]
634 sub%?s\\t%0, %1, #%n2"
635 [(set_attr "conds" "set")]
638 (define_insn "*addsi3_compare0_scratch"
639 [(set (reg:CC_NOOV CC_REGNUM)
641 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
642 (match_operand:SI 1 "arm_add_operand" "rI,L"))
648 [(set_attr "conds" "set")]
651 ;; These patterns are the same ones as the two regular addsi3_compare0
652 ;; patterns, except we write them slightly different - the combiner
653 ;; tends to generate them this way.
654 (define_insn "*addsi3_compare0_for_combiner"
655 [(set (reg:CC CC_REGNUM)
657 (match_operand:SI 1 "s_register_operand" "r,r")
658 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
659 (set (match_operand:SI 0 "s_register_operand" "=r,r")
660 (plus:SI (match_dup 1) (match_dup 2)))]
664 sub%?s\\t%0, %1, #%n2"
665 [(set_attr "conds" "set")]
668 (define_insn "*addsi3_compare0_scratch_for_combiner"
669 [(set (reg:CC CC_REGNUM)
671 (match_operand:SI 0 "s_register_operand" "r,r")
672 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
677 [(set_attr "conds" "set")]
680 ;; The next four insns work because they compare the result with one of
681 ;; the operands, and we know that the use of the condition code is
682 ;; either GEU or LTU, so we can use the carry flag from the addition
683 ;; instead of doing the compare a second time.
684 (define_insn "*addsi3_compare_op1"
685 [(set (reg:CC_C CC_REGNUM)
687 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
688 (match_operand:SI 2 "arm_add_operand" "rI,L"))
690 (set (match_operand:SI 0 "s_register_operand" "=r,r")
691 (plus:SI (match_dup 1) (match_dup 2)))]
695 sub%?s\\t%0, %1, #%n2"
696 [(set_attr "conds" "set")]
699 (define_insn "*addsi3_compare_op2"
700 [(set (reg:CC_C CC_REGNUM)
702 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
703 (match_operand:SI 2 "arm_add_operand" "rI,L"))
705 (set (match_operand:SI 0 "s_register_operand" "=r,r")
706 (plus:SI (match_dup 1) (match_dup 2)))]
710 sub%?s\\t%0, %1, #%n2"
711 [(set_attr "conds" "set")]
714 (define_insn "*compare_addsi2_op0"
715 [(set (reg:CC_C CC_REGNUM)
717 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
718 (match_operand:SI 1 "arm_add_operand" "rI,L"))
724 [(set_attr "conds" "set")]
727 (define_insn "*compare_addsi2_op1"
728 [(set (reg:CC_C CC_REGNUM)
730 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
731 (match_operand:SI 1 "arm_add_operand" "rI,L"))
737 [(set_attr "conds" "set")]
740 (define_insn "*addsi3_carryin"
741 [(set (match_operand:SI 0 "s_register_operand" "=r")
742 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
743 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
744 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
747 [(set_attr "conds" "use")]
750 (define_insn "*addsi3_carryin_shift"
751 [(set (match_operand:SI 0 "s_register_operand" "")
752 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
754 (match_operator:SI 2 "shift_operator"
755 [(match_operand:SI 3 "s_register_operand" "")
756 (match_operand:SI 4 "reg_or_int_operand" "")])
757 (match_operand:SI 1 "s_register_operand" ""))))]
759 "adc%?\\t%0, %1, %3%S2"
760 [(set_attr "conds" "use")]
763 (define_insn "*addsi3_carryin_alt1"
764 [(set (match_operand:SI 0 "s_register_operand" "=r")
765 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
766 (match_operand:SI 2 "arm_rhs_operand" "rI"))
767 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
770 [(set_attr "conds" "use")]
773 (define_insn "*addsi3_carryin_alt2"
774 [(set (match_operand:SI 0 "s_register_operand" "=r")
775 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
776 (match_operand:SI 1 "s_register_operand" "r"))
777 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
780 [(set_attr "conds" "use")]
783 (define_insn "*addsi3_carryin_alt3"
784 [(set (match_operand:SI 0 "s_register_operand" "=r")
785 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
786 (match_operand:SI 2 "arm_rhs_operand" "rI"))
787 (match_operand:SI 1 "s_register_operand" "r")))]
790 [(set_attr "conds" "use")]
793 (define_insn "incscc"
794 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
795 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
796 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
797 (match_operand:SI 1 "s_register_operand" "0,?r")))]
801 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
802 [(set_attr "conds" "use")
803 (set_attr "length" "4,8")]
806 (define_insn "*arm_addsf3"
807 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
808 (plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
809 (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
810 "TARGET_ARM && TARGET_HARD_FLOAT"
813 suf%?s\\t%0, %1, #%N2"
814 [(set_attr "type" "farith")
815 (set_attr "predicable" "yes")]
818 (define_insn "*arm_adddf3"
819 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
820 (plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
821 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
822 "TARGET_ARM && TARGET_HARD_FLOAT"
825 suf%?d\\t%0, %1, #%N2"
826 [(set_attr "type" "farith")
827 (set_attr "predicable" "yes")]
830 (define_insn "*adddf_esfdf_df"
831 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
832 (plus:DF (float_extend:DF
833 (match_operand:SF 1 "s_register_operand" "f,f"))
834 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
835 "TARGET_ARM && TARGET_HARD_FLOAT"
838 suf%?d\\t%0, %1, #%N2"
839 [(set_attr "type" "farith")
840 (set_attr "predicable" "yes")]
843 (define_insn "*adddf_df_esfdf"
844 [(set (match_operand:DF 0 "s_register_operand" "=f")
845 (plus:DF (match_operand:DF 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 "*adddf_esfdf_esfdf"
855 [(set (match_operand:DF 0 "s_register_operand" "=f")
856 (plus:DF (float_extend:DF
857 (match_operand:SF 1 "s_register_operand" "f"))
859 (match_operand:SF 2 "s_register_operand" "f"))))]
860 "TARGET_ARM && TARGET_HARD_FLOAT"
861 "adf%?d\\t%0, %1, %2"
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 && cirrus_fp_register (operands[0], DImode)
877 && cirrus_fp_register (operands[1], DImode))
879 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
885 if (GET_CODE (operands[1]) != REG)
886 operands[1] = force_reg (SImode, operands[1]);
887 if (GET_CODE (operands[2]) != REG)
888 operands[2] = force_reg (SImode, operands[2]);
893 (define_insn "*arm_subdi3"
894 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
895 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
896 (match_operand:DI 2 "s_register_operand" "r,0,0")))
897 (clobber (reg:CC CC_REGNUM))]
899 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
900 [(set_attr "conds" "clob")
901 (set_attr "length" "8")]
904 (define_insn "*thumb_subdi3"
905 [(set (match_operand:DI 0 "register_operand" "=l")
906 (minus:DI (match_operand:DI 1 "register_operand" "0")
907 (match_operand:DI 2 "register_operand" "l")))
908 (clobber (reg:CC CC_REGNUM))]
910 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
911 [(set_attr "length" "4")]
914 (define_insn "*subdi_di_zesidi"
915 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
916 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
918 (match_operand:SI 2 "s_register_operand" "r,r"))))
919 (clobber (reg:CC CC_REGNUM))]
921 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
922 [(set_attr "conds" "clob")
923 (set_attr "length" "8")]
926 (define_insn "*subdi_di_sesidi"
927 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
928 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
930 (match_operand:SI 2 "s_register_operand" "r,r"))))
931 (clobber (reg:CC CC_REGNUM))]
933 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
934 [(set_attr "conds" "clob")
935 (set_attr "length" "8")]
938 (define_insn "*subdi_zesidi_di"
939 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
940 (minus:DI (zero_extend:DI
941 (match_operand:SI 2 "s_register_operand" "r,r"))
942 (match_operand:DI 1 "s_register_operand" "?r,0")))
943 (clobber (reg:CC CC_REGNUM))]
945 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
946 [(set_attr "conds" "clob")
947 (set_attr "length" "8")]
950 (define_insn "*subdi_sesidi_di"
951 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
952 (minus:DI (sign_extend:DI
953 (match_operand:SI 2 "s_register_operand" "r,r"))
954 (match_operand:DI 1 "s_register_operand" "?r,0")))
955 (clobber (reg:CC CC_REGNUM))]
957 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
958 [(set_attr "conds" "clob")
959 (set_attr "length" "8")]
962 (define_insn "*subdi_zesidi_zesidi"
963 [(set (match_operand:DI 0 "s_register_operand" "=r")
964 (minus:DI (zero_extend:DI
965 (match_operand:SI 1 "s_register_operand" "r"))
967 (match_operand:SI 2 "s_register_operand" "r"))))
968 (clobber (reg:CC CC_REGNUM))]
970 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
971 [(set_attr "conds" "clob")
972 (set_attr "length" "8")]
975 (define_expand "subsi3"
976 [(set (match_operand:SI 0 "s_register_operand" "")
977 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
978 (match_operand:SI 2 "s_register_operand" "")))]
981 if (GET_CODE (operands[1]) == CONST_INT)
985 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
988 : preserve_subexpressions_p ()));
991 else /* TARGET_THUMB */
992 operands[1] = force_reg (SImode, operands[1]);
997 (define_insn "*thumb_subsi3_insn"
998 [(set (match_operand:SI 0 "register_operand" "=l")
999 (minus:SI (match_operand:SI 1 "register_operand" "l")
1000 (match_operand:SI 2 "register_operand" "l")))]
1003 [(set_attr "length" "2")]
1006 (define_insn_and_split "*arm_subsi3_insn"
1007 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1008 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
1009 (match_operand:SI 2 "s_register_operand" "r,r")))]
1015 && GET_CODE (operands[1]) == CONST_INT
1016 && !const_ok_for_arm (INTVAL (operands[1]))"
1017 [(clobber (const_int 0))]
1019 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1023 [(set_attr "length" "4,16")
1024 (set_attr "predicable" "yes")]
1028 [(match_scratch:SI 3 "r")
1029 (set (match_operand:SI 0 "s_register_operand" "")
1030 (minus:SI (match_operand:SI 1 "const_int_operand" "")
1031 (match_operand:SI 2 "s_register_operand" "")))]
1033 && !const_ok_for_arm (INTVAL (operands[1]))
1034 && const_ok_for_arm (~INTVAL (operands[1]))"
1035 [(set (match_dup 3) (match_dup 1))
1036 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1040 (define_insn "*subsi3_compare0"
1041 [(set (reg:CC_NOOV CC_REGNUM)
1043 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1044 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1046 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1047 (minus:SI (match_dup 1) (match_dup 2)))]
1051 rsb%?s\\t%0, %2, %1"
1052 [(set_attr "conds" "set")]
1055 (define_insn "decscc"
1056 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1057 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1058 (match_operator:SI 2 "arm_comparison_operator"
1059 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1063 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1064 [(set_attr "conds" "use")
1065 (set_attr "length" "*,8")]
1068 (define_insn "*arm_subsf3"
1069 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1070 (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1071 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1072 "TARGET_ARM && TARGET_HARD_FLOAT"
1075 rsf%?s\\t%0, %2, %1"
1076 [(set_attr "type" "farith")]
1079 (define_insn "*arm_subdf3"
1080 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1081 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1082 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1083 "TARGET_ARM && TARGET_HARD_FLOAT"
1086 rsf%?d\\t%0, %2, %1"
1087 [(set_attr "type" "farith")
1088 (set_attr "predicable" "yes")]
1091 (define_insn "*subdf_esfdf_df"
1092 [(set (match_operand:DF 0 "s_register_operand" "=f")
1093 (minus:DF (float_extend:DF
1094 (match_operand:SF 1 "s_register_operand" "f"))
1095 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1096 "TARGET_ARM && TARGET_HARD_FLOAT"
1097 "suf%?d\\t%0, %1, %2"
1098 [(set_attr "type" "farith")
1099 (set_attr "predicable" "yes")]
1102 (define_insn "*subdf_df_esfdf"
1103 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1104 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1106 (match_operand:SF 2 "s_register_operand" "f,f"))))]
1107 "TARGET_ARM && TARGET_HARD_FLOAT"
1110 rsf%?d\\t%0, %2, %1"
1111 [(set_attr "type" "farith")
1112 (set_attr "predicable" "yes")]
1115 (define_insn "*subdf_esfdf_esfdf"
1116 [(set (match_operand:DF 0 "s_register_operand" "=f")
1117 (minus:DF (float_extend:DF
1118 (match_operand:SF 1 "s_register_operand" "f"))
1120 (match_operand:SF 2 "s_register_operand" "f"))))]
1121 "TARGET_ARM && TARGET_HARD_FLOAT"
1122 "suf%?d\\t%0, %1, %2"
1123 [(set_attr "type" "farith")
1124 (set_attr "predicable" "yes")]
1127 ;; Multiplication insns
1129 (define_expand "mulsi3"
1130 [(set (match_operand:SI 0 "s_register_operand" "")
1131 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1132 (match_operand:SI 1 "s_register_operand" "")))]
1137 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1138 (define_insn "*arm_mulsi3"
1139 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1140 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1141 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1143 "mul%?\\t%0, %2, %1"
1144 [(set_attr "type" "mult")
1145 (set_attr "predicable" "yes")]
1148 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1149 ; 1 and 2; are the same, because reload will make operand 0 match
1150 ; operand 1 without realizing that this conflicts with operand 2. We fix
1151 ; this by adding another alternative to match this case, and then `reload'
1152 ; it ourselves. This alternative must come first.
1153 (define_insn "*thumb_mulsi3"
1154 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1155 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1156 (match_operand:SI 2 "register_operand" "l,l,l")))]
1159 if (which_alternative < 2)
1160 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1162 return \"mul\\t%0, %0, %2\";
1164 [(set_attr "length" "4,4,2")
1165 (set_attr "type" "mult")]
1168 (define_insn "*mulsi3_compare0"
1169 [(set (reg:CC_NOOV CC_REGNUM)
1170 (compare:CC_NOOV (mult:SI
1171 (match_operand:SI 2 "s_register_operand" "r,r")
1172 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1174 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1175 (mult:SI (match_dup 2) (match_dup 1)))]
1176 "TARGET_ARM && !arm_is_xscale"
1177 "mul%?s\\t%0, %2, %1"
1178 [(set_attr "conds" "set")
1179 (set_attr "type" "mult")]
1182 (define_insn "*mulsi_compare0_scratch"
1183 [(set (reg:CC_NOOV CC_REGNUM)
1184 (compare:CC_NOOV (mult:SI
1185 (match_operand:SI 2 "s_register_operand" "r,r")
1186 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1188 (clobber (match_scratch:SI 0 "=&r,&r"))]
1189 "TARGET_ARM && !arm_is_xscale"
1190 "mul%?s\\t%0, %2, %1"
1191 [(set_attr "conds" "set")
1192 (set_attr "type" "mult")]
1195 ;; Unnamed templates to match MLA instruction.
1197 (define_insn "*mulsi3addsi"
1198 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1200 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1201 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1202 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1204 "mla%?\\t%0, %2, %1, %3"
1205 [(set_attr "type" "mult")
1206 (set_attr "predicable" "yes")]
1209 (define_insn "*mulsi3addsi_compare0"
1210 [(set (reg:CC_NOOV CC_REGNUM)
1213 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1214 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1215 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1217 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1218 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1220 "TARGET_ARM && !arm_is_xscale"
1221 "mla%?s\\t%0, %2, %1, %3"
1222 [(set_attr "conds" "set")
1223 (set_attr "type" "mult")]
1226 (define_insn "*mulsi3addsi_compare0_scratch"
1227 [(set (reg:CC_NOOV CC_REGNUM)
1230 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1231 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1232 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1234 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1235 "TARGET_ARM && !arm_is_xscale"
1236 "mla%?s\\t%0, %2, %1, %3"
1237 [(set_attr "conds" "set")
1238 (set_attr "type" "mult")]
1241 ;; Unnamed template to match long long multiply-accumlate (smlal)
1243 (define_insn "*mulsidi3adddi"
1244 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1247 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1248 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1249 (match_operand:DI 1 "s_register_operand" "0")))]
1250 "TARGET_ARM && arm_fast_multiply"
1251 "smlal%?\\t%Q0, %R0, %3, %2"
1252 [(set_attr "type" "mult")
1253 (set_attr "predicable" "yes")]
1256 (define_insn "mulsidi3"
1257 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1259 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1260 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1261 "TARGET_ARM && arm_fast_multiply"
1262 "smull%?\\t%Q0, %R0, %1, %2"
1263 [(set_attr "type" "mult")
1264 (set_attr "predicable" "yes")]
1267 (define_insn "umulsidi3"
1268 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1270 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1271 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1272 "TARGET_ARM && arm_fast_multiply"
1273 "umull%?\\t%Q0, %R0, %1, %2"
1274 [(set_attr "type" "mult")
1275 (set_attr "predicable" "yes")]
1278 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1280 (define_insn "*umulsidi3adddi"
1281 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1284 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1285 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1286 (match_operand:DI 1 "s_register_operand" "0")))]
1287 "TARGET_ARM && arm_fast_multiply"
1288 "umlal%?\\t%Q0, %R0, %3, %2"
1289 [(set_attr "type" "mult")
1290 (set_attr "predicable" "yes")]
1293 (define_insn "smulsi3_highpart"
1294 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1298 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1299 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1301 (clobber (match_scratch:SI 3 "=&r,&r"))]
1302 "TARGET_ARM && arm_fast_multiply"
1303 "smull%?\\t%3, %0, %2, %1"
1304 [(set_attr "type" "mult")
1305 (set_attr "predicable" "yes")]
1308 (define_insn "umulsi3_highpart"
1309 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1313 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1314 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1316 (clobber (match_scratch:SI 3 "=&r,&r"))]
1317 "TARGET_ARM && arm_fast_multiply"
1318 "umull%?\\t%3, %0, %2, %1"
1319 [(set_attr "type" "mult")
1320 (set_attr "predicable" "yes")]
1323 (define_insn "mulhisi3"
1324 [(set (match_operand:SI 0 "s_register_operand" "=r")
1325 (mult:SI (sign_extend:SI
1326 (match_operand:HI 1 "s_register_operand" "%r"))
1328 (match_operand:HI 2 "s_register_operand" "r"))))]
1329 "TARGET_ARM && arm_is_xscale"
1330 "smulbb%?\\t%0, %1, %2"
1331 [(set_attr "type" "mult")]
1334 (define_insn "*mulhisi3addsi"
1335 [(set (match_operand:SI 0 "s_register_operand" "=r")
1336 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1337 (mult:SI (sign_extend:SI
1338 (match_operand:HI 2 "s_register_operand" "%r"))
1340 (match_operand:HI 3 "s_register_operand" "r")))))]
1341 "TARGET_ARM && arm_is_xscale"
1342 "smlabb%?\\t%0, %2, %3, %1"
1343 [(set_attr "type" "mult")]
1346 (define_insn "*mulhidi3adddi"
1347 [(set (match_operand:DI 0 "s_register_operand" "=r")
1349 (match_operand:DI 1 "s_register_operand" "0")
1350 (mult:DI (sign_extend:DI
1351 (match_operand:HI 2 "s_register_operand" "%r"))
1353 (match_operand:HI 3 "s_register_operand" "r")))))]
1354 "TARGET_ARM && arm_is_xscale"
1355 "smlalbb%?\\t%Q0, %R0, %2, %3"
1356 [(set_attr "type" "mult")])
1358 (define_insn "*arm_mulsf3"
1359 [(set (match_operand:SF 0 "s_register_operand" "=f")
1360 (mult:SF (match_operand:SF 1 "s_register_operand" "f")
1361 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1362 "TARGET_ARM && TARGET_HARD_FLOAT"
1363 "fml%?s\\t%0, %1, %2"
1364 [(set_attr "type" "ffmul")
1365 (set_attr "predicable" "yes")]
1368 (define_insn "*arm_muldf3"
1369 [(set (match_operand:DF 0 "s_register_operand" "=f")
1370 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1371 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1372 "TARGET_ARM && TARGET_HARD_FLOAT"
1373 "muf%?d\\t%0, %1, %2"
1374 [(set_attr "type" "fmul")
1375 (set_attr "predicable" "yes")]
1378 (define_insn "*muldf_esfdf_df"
1379 [(set (match_operand:DF 0 "s_register_operand" "=f")
1380 (mult:DF (float_extend:DF
1381 (match_operand:SF 1 "s_register_operand" "f"))
1382 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1383 "TARGET_ARM && TARGET_HARD_FLOAT"
1384 "muf%?d\\t%0, %1, %2"
1385 [(set_attr "type" "fmul")
1386 (set_attr "predicable" "yes")]
1389 (define_insn "*muldf_df_esfdf"
1390 [(set (match_operand:DF 0 "s_register_operand" "=f")
1391 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1393 (match_operand:SF 2 "s_register_operand" "f"))))]
1394 "TARGET_ARM && TARGET_HARD_FLOAT"
1395 "muf%?d\\t%0, %1, %2"
1396 [(set_attr "type" "fmul")
1397 (set_attr "predicable" "yes")]
1400 (define_insn "*muldf_esfdf_esfdf"
1401 [(set (match_operand:DF 0 "s_register_operand" "=f")
1403 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f"))
1404 (float_extend:DF (match_operand:SF 2 "s_register_operand" "f"))))]
1405 "TARGET_ARM && TARGET_HARD_FLOAT"
1406 "muf%?d\\t%0, %1, %2"
1407 [(set_attr "type" "fmul")
1408 (set_attr "predicable" "yes")]
1413 (define_insn "divsf3"
1414 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1415 (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1416 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1417 "TARGET_ARM && TARGET_HARD_FLOAT"
1420 frd%?s\\t%0, %2, %1"
1421 [(set_attr "type" "fdivs")
1422 (set_attr "predicable" "yes")]
1425 (define_insn "divdf3"
1426 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1427 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1428 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1429 "TARGET_ARM && TARGET_HARD_FLOAT"
1432 rdf%?d\\t%0, %2, %1"
1433 [(set_attr "type" "fdivd")
1434 (set_attr "predicable" "yes")]
1437 (define_insn "*divdf_esfdf_df"
1438 [(set (match_operand:DF 0 "s_register_operand" "=f")
1439 (div:DF (float_extend:DF
1440 (match_operand:SF 1 "s_register_operand" "f"))
1441 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1442 "TARGET_ARM && TARGET_HARD_FLOAT"
1443 "dvf%?d\\t%0, %1, %2"
1444 [(set_attr "type" "fdivd")
1445 (set_attr "predicable" "yes")]
1448 (define_insn "*divdf_df_esfdf"
1449 [(set (match_operand:DF 0 "s_register_operand" "=f")
1450 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1452 (match_operand:SF 2 "s_register_operand" "f"))))]
1453 "TARGET_ARM && TARGET_HARD_FLOAT"
1454 "rdf%?d\\t%0, %2, %1"
1455 [(set_attr "type" "fdivd")
1456 (set_attr "predicable" "yes")]
1459 (define_insn "*divdf_esfdf_esfdf"
1460 [(set (match_operand:DF 0 "s_register_operand" "=f")
1461 (div:DF (float_extend:DF
1462 (match_operand:SF 1 "s_register_operand" "f"))
1464 (match_operand:SF 2 "s_register_operand" "f"))))]
1465 "TARGET_ARM && TARGET_HARD_FLOAT"
1466 "dvf%?d\\t%0, %1, %2"
1467 [(set_attr "type" "fdivd")
1468 (set_attr "predicable" "yes")]
1473 (define_insn "modsf3"
1474 [(set (match_operand:SF 0 "s_register_operand" "=f")
1475 (mod:SF (match_operand:SF 1 "s_register_operand" "f")
1476 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1477 "TARGET_ARM && TARGET_HARD_FLOAT"
1478 "rmf%?s\\t%0, %1, %2"
1479 [(set_attr "type" "fdivs")
1480 (set_attr "predicable" "yes")]
1483 (define_insn "moddf3"
1484 [(set (match_operand:DF 0 "s_register_operand" "=f")
1485 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1486 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1487 "TARGET_ARM && TARGET_HARD_FLOAT"
1488 "rmf%?d\\t%0, %1, %2"
1489 [(set_attr "type" "fdivd")
1490 (set_attr "predicable" "yes")]
1493 (define_insn "*moddf_esfdf_df"
1494 [(set (match_operand:DF 0 "s_register_operand" "=f")
1495 (mod:DF (float_extend:DF
1496 (match_operand:SF 1 "s_register_operand" "f"))
1497 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1498 "TARGET_ARM && TARGET_HARD_FLOAT"
1499 "rmf%?d\\t%0, %1, %2"
1500 [(set_attr "type" "fdivd")
1501 (set_attr "predicable" "yes")]
1504 (define_insn "*moddf_df_esfdf"
1505 [(set (match_operand:DF 0 "s_register_operand" "=f")
1506 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1508 (match_operand:SF 2 "s_register_operand" "f"))))]
1509 "TARGET_ARM && TARGET_HARD_FLOAT"
1510 "rmf%?d\\t%0, %1, %2"
1511 [(set_attr "type" "fdivd")
1512 (set_attr "predicable" "yes")]
1515 (define_insn "*moddf_esfdf_esfdf"
1516 [(set (match_operand:DF 0 "s_register_operand" "=f")
1517 (mod:DF (float_extend:DF
1518 (match_operand:SF 1 "s_register_operand" "f"))
1520 (match_operand:SF 2 "s_register_operand" "f"))))]
1521 "TARGET_ARM && TARGET_HARD_FLOAT"
1522 "rmf%?d\\t%0, %1, %2"
1523 [(set_attr "type" "fdivd")
1524 (set_attr "predicable" "yes")]
1527 ;; Boolean and,ior,xor insns
1529 ;; Split up double word logical operations
1531 ;; Split up simple DImode logical operations. Simply perform the logical
1532 ;; operation on the upper and lower halves of the registers.
1534 [(set (match_operand:DI 0 "s_register_operand" "")
1535 (match_operator:DI 6 "logical_binary_operator"
1536 [(match_operand:DI 1 "s_register_operand" "")
1537 (match_operand:DI 2 "s_register_operand" "")]))]
1538 "TARGET_ARM && reload_completed"
1539 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1540 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1543 operands[3] = gen_highpart (SImode, operands[0]);
1544 operands[0] = gen_lowpart (SImode, operands[0]);
1545 operands[4] = gen_highpart (SImode, operands[1]);
1546 operands[1] = gen_lowpart (SImode, operands[1]);
1547 operands[5] = gen_highpart (SImode, operands[2]);
1548 operands[2] = gen_lowpart (SImode, operands[2]);
1553 [(set (match_operand:DI 0 "s_register_operand" "")
1554 (match_operator:DI 6 "logical_binary_operator"
1555 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1556 (match_operand:DI 1 "s_register_operand" "")]))]
1557 "TARGET_ARM && reload_completed"
1558 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1559 (set (match_dup 3) (match_op_dup:SI 6
1560 [(ashiftrt:SI (match_dup 2) (const_int 31))
1564 operands[3] = gen_highpart (SImode, operands[0]);
1565 operands[0] = gen_lowpart (SImode, operands[0]);
1566 operands[4] = gen_highpart (SImode, operands[1]);
1567 operands[1] = gen_lowpart (SImode, operands[1]);
1568 operands[5] = gen_highpart (SImode, operands[2]);
1569 operands[2] = gen_lowpart (SImode, operands[2]);
1573 ;; The zero extend of operand 2 means we can just copy the high part of
1574 ;; operand1 into operand0.
1576 [(set (match_operand:DI 0 "s_register_operand" "")
1578 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1579 (match_operand:DI 1 "s_register_operand" "")))]
1580 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1581 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1582 (set (match_dup 3) (match_dup 4))]
1585 operands[4] = gen_highpart (SImode, operands[1]);
1586 operands[3] = gen_highpart (SImode, operands[0]);
1587 operands[0] = gen_lowpart (SImode, operands[0]);
1588 operands[1] = gen_lowpart (SImode, operands[1]);
1592 ;; The zero extend of operand 2 means we can just copy the high part of
1593 ;; operand1 into operand0.
1595 [(set (match_operand:DI 0 "s_register_operand" "")
1597 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1598 (match_operand:DI 1 "s_register_operand" "")))]
1599 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1600 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1601 (set (match_dup 3) (match_dup 4))]
1604 operands[4] = gen_highpart (SImode, operands[1]);
1605 operands[3] = gen_highpart (SImode, operands[0]);
1606 operands[0] = gen_lowpart (SImode, operands[0]);
1607 operands[1] = gen_lowpart (SImode, operands[1]);
1611 (define_insn "anddi3"
1612 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1613 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1614 (match_operand:DI 2 "s_register_operand" "r,r")))]
1617 [(set_attr "length" "8")]
1620 (define_insn_and_split "*anddi_zesidi_di"
1621 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1622 (and:DI (zero_extend:DI
1623 (match_operand:SI 2 "s_register_operand" "r,r"))
1624 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1627 "TARGET_ARM && reload_completed"
1628 ; The zero extend of operand 2 clears the high word of the output
1630 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1631 (set (match_dup 3) (const_int 0))]
1634 operands[3] = gen_highpart (SImode, operands[0]);
1635 operands[0] = gen_lowpart (SImode, operands[0]);
1636 operands[1] = gen_lowpart (SImode, operands[1]);
1638 [(set_attr "length" "8")]
1641 (define_insn "*anddi_sesdi_di"
1642 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1643 (and:DI (sign_extend:DI
1644 (match_operand:SI 2 "s_register_operand" "r,r"))
1645 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1648 [(set_attr "length" "8")]
1651 (define_expand "andsi3"
1652 [(set (match_operand:SI 0 "s_register_operand" "")
1653 (and:SI (match_operand:SI 1 "s_register_operand" "")
1654 (match_operand:SI 2 "reg_or_int_operand" "")))]
1659 if (GET_CODE (operands[2]) == CONST_INT)
1661 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1664 ? 0 : preserve_subexpressions_p ()));
1668 else /* TARGET_THUMB */
1670 if (GET_CODE (operands[2]) != CONST_INT)
1671 operands[2] = force_reg (SImode, operands[2]);
1676 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1678 operands[2] = force_reg (SImode,
1679 GEN_INT (~INTVAL (operands[2])));
1681 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1686 for (i = 9; i <= 31; i++)
1688 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1690 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1694 else if ((((HOST_WIDE_INT) 1) << i) - 1
1695 == ~INTVAL (operands[2]))
1697 rtx shift = GEN_INT (i);
1698 rtx reg = gen_reg_rtx (SImode);
1700 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1701 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1707 operands[2] = force_reg (SImode, operands[2]);
1713 (define_insn_and_split "*arm_andsi3_insn"
1714 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1715 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1716 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1720 bic%?\\t%0, %1, #%B2
1723 && GET_CODE (operands[2]) == CONST_INT
1724 && !(const_ok_for_arm (INTVAL (operands[2]))
1725 || const_ok_for_arm (~INTVAL (operands[2])))"
1726 [(clobber (const_int 0))]
1728 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1732 [(set_attr "length" "4,4,16")
1733 (set_attr "predicable" "yes")]
1736 (define_insn "*thumb_andsi3_insn"
1737 [(set (match_operand:SI 0 "register_operand" "=l")
1738 (and:SI (match_operand:SI 1 "register_operand" "%0")
1739 (match_operand:SI 2 "register_operand" "l")))]
1742 [(set_attr "length" "2")]
1745 (define_insn "*andsi3_compare0"
1746 [(set (reg:CC_NOOV CC_REGNUM)
1748 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1749 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1751 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1752 (and:SI (match_dup 1) (match_dup 2)))]
1756 bic%?s\\t%0, %1, #%B2"
1757 [(set_attr "conds" "set")]
1760 (define_insn "*andsi3_compare0_scratch"
1761 [(set (reg:CC_NOOV CC_REGNUM)
1763 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1764 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1766 (clobber (match_scratch:SI 2 "=X,r"))]
1770 bic%?s\\t%2, %0, #%B1"
1771 [(set_attr "conds" "set")]
1774 (define_insn "*zeroextractsi_compare0_scratch"
1775 [(set (reg:CC_NOOV CC_REGNUM)
1776 (compare:CC_NOOV (zero_extract:SI
1777 (match_operand:SI 0 "s_register_operand" "r")
1778 (match_operand 1 "const_int_operand" "n")
1779 (match_operand 2 "const_int_operand" "n"))
1782 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1783 && INTVAL (operands[1]) > 0
1784 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1785 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1787 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1788 << INTVAL (operands[2]));
1789 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1792 [(set_attr "conds" "set")]
1795 (define_insn "*ne_zeroextractsi"
1796 [(set (match_operand:SI 0 "s_register_operand" "=r")
1797 (ne:SI (zero_extract:SI
1798 (match_operand:SI 1 "s_register_operand" "r")
1799 (match_operand:SI 2 "const_int_operand" "n")
1800 (match_operand:SI 3 "const_int_operand" "n"))
1802 (clobber (reg:CC CC_REGNUM))]
1804 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1805 && INTVAL (operands[2]) > 0
1806 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1807 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1809 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1810 << INTVAL (operands[3]));
1811 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1812 return \"movne\\t%0, #1\";
1814 [(set_attr "conds" "clob")
1815 (set_attr "length" "8")]
1818 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1819 ;;; represented by the bitfield, then this will produce incorrect results.
1820 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1821 ;;; which have a real bit-field insert instruction, the truncation happens
1822 ;;; in the bit-field insert instruction itself. Since arm does not have a
1823 ;;; bit-field insert instruction, we would have to emit code here to truncate
1824 ;;; the value before we insert. This loses some of the advantage of having
1825 ;;; this insv pattern, so this pattern needs to be reevalutated.
1827 (define_expand "insv"
1828 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1829 (match_operand:SI 1 "general_operand" "")
1830 (match_operand:SI 2 "general_operand" ""))
1831 (match_operand:SI 3 "reg_or_int_operand" ""))]
1835 int start_bit = INTVAL (operands[2]);
1836 int width = INTVAL (operands[1]);
1837 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1838 rtx target, subtarget;
1840 target = operands[0];
1841 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1842 subreg as the final target. */
1843 if (GET_CODE (target) == SUBREG)
1845 subtarget = gen_reg_rtx (SImode);
1846 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1847 < GET_MODE_SIZE (SImode))
1848 target = SUBREG_REG (target);
1853 if (GET_CODE (operands[3]) == CONST_INT)
1855 /* Since we are inserting a known constant, we may be able to
1856 reduce the number of bits that we have to clear so that
1857 the mask becomes simple. */
1858 /* ??? This code does not check to see if the new mask is actually
1859 simpler. It may not be. */
1860 rtx op1 = gen_reg_rtx (SImode);
1861 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1862 start of this pattern. */
1863 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1864 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1866 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1867 emit_insn (gen_iorsi3 (subtarget, op1,
1868 GEN_INT (op3_value << start_bit)));
1870 else if (start_bit == 0
1871 && !(const_ok_for_arm (mask)
1872 || const_ok_for_arm (~mask)))
1874 /* A Trick, since we are setting the bottom bits in the word,
1875 we can shift operand[3] up, operand[0] down, OR them together
1876 and rotate the result back again. This takes 3 insns, and
1877 the third might be mergable into another op. */
1878 /* The shift up copes with the possibility that operand[3] is
1879 wider than the bitfield. */
1880 rtx op0 = gen_reg_rtx (SImode);
1881 rtx op1 = gen_reg_rtx (SImode);
1883 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1884 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1885 emit_insn (gen_iorsi3 (op1, op1, op0));
1886 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1888 else if ((width + start_bit == 32)
1889 && !(const_ok_for_arm (mask)
1890 || const_ok_for_arm (~mask)))
1892 /* Similar trick, but slightly less efficient. */
1894 rtx op0 = gen_reg_rtx (SImode);
1895 rtx op1 = gen_reg_rtx (SImode);
1897 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1898 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1899 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1900 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1904 rtx op0 = GEN_INT (mask);
1905 rtx op1 = gen_reg_rtx (SImode);
1906 rtx op2 = gen_reg_rtx (SImode);
1908 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1910 rtx tmp = gen_reg_rtx (SImode);
1912 emit_insn (gen_movsi (tmp, op0));
1916 /* Mask out any bits in operand[3] that are not needed. */
1917 emit_insn (gen_andsi3 (op1, operands[3], op0));
1919 if (GET_CODE (op0) == CONST_INT
1920 && (const_ok_for_arm (mask << start_bit)
1921 || const_ok_for_arm (~(mask << start_bit))))
1923 op0 = GEN_INT (~(mask << start_bit));
1924 emit_insn (gen_andsi3 (op2, operands[0], op0));
1928 if (GET_CODE (op0) == CONST_INT)
1930 rtx tmp = gen_reg_rtx (SImode);
1932 emit_insn (gen_movsi (tmp, op0));
1937 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1939 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1943 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1945 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1948 if (subtarget != target)
1950 /* If TARGET is still a SUBREG, then it must be wider than a word,
1951 so we must be careful only to set the subword we were asked to. */
1952 if (GET_CODE (target) == SUBREG)
1953 emit_move_insn (target, subtarget);
1955 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1962 ; constants for op 2 will never be given to these patterns.
1963 (define_insn_and_split "*anddi_notdi_di"
1964 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1965 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1966 (match_operand:DI 2 "s_register_operand" "0,r")))]
1969 "TARGET_ARM && reload_completed"
1970 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1971 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1974 operands[3] = gen_highpart (SImode, operands[0]);
1975 operands[0] = gen_lowpart (SImode, operands[0]);
1976 operands[4] = gen_highpart (SImode, operands[1]);
1977 operands[1] = gen_lowpart (SImode, operands[1]);
1978 operands[5] = gen_highpart (SImode, operands[2]);
1979 operands[2] = gen_lowpart (SImode, operands[2]);
1981 [(set_attr "length" "8")
1982 (set_attr "predicable" "yes")]
1985 (define_insn_and_split "*anddi_notzesidi_di"
1986 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1987 (and:DI (not:DI (zero_extend:DI
1988 (match_operand:SI 2 "s_register_operand" "r,r")))
1989 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1992 bic%?\\t%Q0, %Q1, %2
1994 ; (not (zero_extend ...)) allows us to just copy the high word from
1995 ; operand1 to operand0.
1998 && operands[0] != operands[1]"
1999 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2000 (set (match_dup 3) (match_dup 4))]
2003 operands[3] = gen_highpart (SImode, operands[0]);
2004 operands[0] = gen_lowpart (SImode, operands[0]);
2005 operands[4] = gen_highpart (SImode, operands[1]);
2006 operands[1] = gen_lowpart (SImode, operands[1]);
2008 [(set_attr "length" "4,8")
2009 (set_attr "predicable" "yes")]
2012 (define_insn_and_split "*anddi_notsesidi_di"
2013 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2014 (and:DI (not:DI (sign_extend:DI
2015 (match_operand:SI 2 "s_register_operand" "r,r")))
2016 (match_operand:DI 1 "s_register_operand" "0,r")))]
2019 "TARGET_ARM && reload_completed"
2020 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2021 (set (match_dup 3) (and:SI (not:SI
2022 (ashiftrt:SI (match_dup 2) (const_int 31)))
2026 operands[3] = gen_highpart (SImode, operands[0]);
2027 operands[0] = gen_lowpart (SImode, operands[0]);
2028 operands[4] = gen_highpart (SImode, operands[1]);
2029 operands[1] = gen_lowpart (SImode, operands[1]);
2031 [(set_attr "length" "8")
2032 (set_attr "predicable" "yes")]
2035 (define_insn "andsi_notsi_si"
2036 [(set (match_operand:SI 0 "s_register_operand" "=r")
2037 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2038 (match_operand:SI 1 "s_register_operand" "r")))]
2040 "bic%?\\t%0, %1, %2"
2041 [(set_attr "predicable" "yes")]
2044 (define_insn "bicsi3"
2045 [(set (match_operand:SI 0 "register_operand" "=l")
2046 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2047 (match_operand:SI 2 "register_operand" "0")))]
2050 [(set_attr "length" "2")]
2053 (define_insn "andsi_not_shiftsi_si"
2054 [(set (match_operand:SI 0 "s_register_operand" "=r")
2055 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2056 [(match_operand:SI 2 "s_register_operand" "r")
2057 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2058 (match_operand:SI 1 "s_register_operand" "r")))]
2060 "bic%?\\t%0, %1, %2%S4"
2061 [(set_attr "predicable" "yes")
2062 (set_attr "shift" "2")
2066 (define_insn "*andsi_notsi_si_compare0"
2067 [(set (reg:CC_NOOV CC_REGNUM)
2069 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2070 (match_operand:SI 1 "s_register_operand" "r"))
2072 (set (match_operand:SI 0 "s_register_operand" "=r")
2073 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2075 "bic%?s\\t%0, %1, %2"
2076 [(set_attr "conds" "set")]
2079 (define_insn "*andsi_notsi_si_compare0_scratch"
2080 [(set (reg:CC_NOOV CC_REGNUM)
2082 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2083 (match_operand:SI 1 "s_register_operand" "r"))
2085 (clobber (match_scratch:SI 0 "=r"))]
2087 "bic%?s\\t%0, %1, %2"
2088 [(set_attr "conds" "set")]
2091 (define_insn "iordi3"
2092 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2093 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2094 (match_operand:DI 2 "s_register_operand" "r,r")))]
2097 [(set_attr "length" "8")
2098 (set_attr "predicable" "yes")]
2101 (define_insn "*iordi_zesidi_di"
2102 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2103 (ior:DI (zero_extend:DI
2104 (match_operand:SI 2 "s_register_operand" "r,r"))
2105 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2108 orr%?\\t%Q0, %Q1, %2
2110 [(set_attr "length" "4,8")
2111 (set_attr "predicable" "yes")]
2114 (define_insn "*iordi_sesidi_di"
2115 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2116 (ior:DI (sign_extend:DI
2117 (match_operand:SI 2 "s_register_operand" "r,r"))
2118 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2121 [(set_attr "length" "8")
2122 (set_attr "predicable" "yes")]
2125 (define_expand "iorsi3"
2126 [(set (match_operand:SI 0 "s_register_operand" "")
2127 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2128 (match_operand:SI 2 "reg_or_int_operand" "")))]
2131 if (GET_CODE (operands[2]) == CONST_INT)
2135 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2138 ? 0 : preserve_subexpressions_p ()));
2141 else /* TARGET_THUMB */
2142 operands [2] = force_reg (SImode, operands [2]);
2147 (define_insn_and_split "*arm_iorsi3"
2148 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2149 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2150 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2156 && GET_CODE (operands[2]) == CONST_INT
2157 && !const_ok_for_arm (INTVAL (operands[2]))"
2158 [(clobber (const_int 0))]
2160 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2164 [(set_attr "length" "4,16")
2165 (set_attr "predicable" "yes")]
2168 (define_insn "*thumb_iorsi3"
2169 [(set (match_operand:SI 0 "register_operand" "=l")
2170 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2171 (match_operand:SI 2 "register_operand" "l")))]
2174 [(set_attr "length" "2")]
2178 [(match_scratch:SI 3 "r")
2179 (set (match_operand:SI 0 "s_register_operand" "")
2180 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2181 (match_operand:SI 2 "const_int_operand" "")))]
2183 && !const_ok_for_arm (INTVAL (operands[2]))
2184 && const_ok_for_arm (~INTVAL (operands[2]))"
2185 [(set (match_dup 3) (match_dup 2))
2186 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2190 (define_insn "*iorsi3_compare0"
2191 [(set (reg:CC_NOOV CC_REGNUM)
2192 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2193 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2195 (set (match_operand:SI 0 "s_register_operand" "=r")
2196 (ior:SI (match_dup 1) (match_dup 2)))]
2198 "orr%?s\\t%0, %1, %2"
2199 [(set_attr "conds" "set")]
2202 (define_insn "*iorsi3_compare0_scratch"
2203 [(set (reg:CC_NOOV CC_REGNUM)
2204 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2205 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2207 (clobber (match_scratch:SI 0 "=r"))]
2209 "orr%?s\\t%0, %1, %2"
2210 [(set_attr "conds" "set")]
2213 (define_insn "xordi3"
2214 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2215 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2216 (match_operand:DI 2 "s_register_operand" "r,r")))]
2219 [(set_attr "length" "8")
2220 (set_attr "predicable" "yes")]
2223 (define_insn "*xordi_zesidi_di"
2224 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2225 (xor:DI (zero_extend:DI
2226 (match_operand:SI 2 "s_register_operand" "r,r"))
2227 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2230 eor%?\\t%Q0, %Q1, %2
2232 [(set_attr "length" "4,8")
2233 (set_attr "predicable" "yes")]
2236 (define_insn "*xordi_sesidi_di"
2237 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2238 (xor:DI (sign_extend:DI
2239 (match_operand:SI 2 "s_register_operand" "r,r"))
2240 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2243 [(set_attr "length" "8")
2244 (set_attr "predicable" "yes")]
2247 (define_expand "xorsi3"
2248 [(set (match_operand:SI 0 "s_register_operand" "")
2249 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2250 (match_operand:SI 2 "arm_rhs_operand" "")))]
2253 if (GET_CODE (operands[2]) == CONST_INT)
2254 operands[2] = force_reg (SImode, operands[2]);
2258 (define_insn "*arm_xorsi3"
2259 [(set (match_operand:SI 0 "s_register_operand" "=r")
2260 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2261 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2263 "eor%?\\t%0, %1, %2"
2264 [(set_attr "predicable" "yes")]
2267 (define_insn "*thumb_xorsi3"
2268 [(set (match_operand:SI 0 "register_operand" "=l")
2269 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2270 (match_operand:SI 2 "register_operand" "l")))]
2273 [(set_attr "length" "2")]
2276 (define_insn "*xorsi3_compare0"
2277 [(set (reg:CC_NOOV CC_REGNUM)
2278 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2279 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2281 (set (match_operand:SI 0 "s_register_operand" "=r")
2282 (xor:SI (match_dup 1) (match_dup 2)))]
2284 "eor%?s\\t%0, %1, %2"
2285 [(set_attr "conds" "set")]
2288 (define_insn "*xorsi3_compare0_scratch"
2289 [(set (reg:CC_NOOV CC_REGNUM)
2290 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2291 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2295 [(set_attr "conds" "set")]
2298 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2299 ; (NOT D) we can sometimes merge the final NOT into one of the following
2303 [(set (match_operand:SI 0 "s_register_operand" "")
2304 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2305 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2306 (match_operand:SI 3 "arm_rhs_operand" "")))
2307 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2309 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2310 (not:SI (match_dup 3))))
2311 (set (match_dup 0) (not:SI (match_dup 4)))]
2315 (define_insn "*andsi_iorsi3_notsi"
2316 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2317 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2318 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2319 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2321 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2322 [(set_attr "length" "8")
2323 (set_attr "predicable" "yes")]
2328 ;; Minimum and maximum insns
2330 (define_insn "smaxsi3"
2331 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2332 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2333 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2334 (clobber (reg:CC CC_REGNUM))]
2337 cmp\\t%1, %2\;movlt\\t%0, %2
2338 cmp\\t%1, %2\;movge\\t%0, %1
2339 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2340 [(set_attr "conds" "clob")
2341 (set_attr "length" "8,8,12")]
2344 (define_insn "sminsi3"
2345 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2346 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2347 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2348 (clobber (reg:CC CC_REGNUM))]
2351 cmp\\t%1, %2\;movge\\t%0, %2
2352 cmp\\t%1, %2\;movlt\\t%0, %1
2353 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2354 [(set_attr "conds" "clob")
2355 (set_attr "length" "8,8,12")]
2358 (define_insn "umaxsi3"
2359 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2360 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2361 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2362 (clobber (reg:CC CC_REGNUM))]
2365 cmp\\t%1, %2\;movcc\\t%0, %2
2366 cmp\\t%1, %2\;movcs\\t%0, %1
2367 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2368 [(set_attr "conds" "clob")
2369 (set_attr "length" "8,8,12")]
2372 (define_insn "uminsi3"
2373 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2374 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2375 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2376 (clobber (reg:CC CC_REGNUM))]
2379 cmp\\t%1, %2\;movcs\\t%0, %2
2380 cmp\\t%1, %2\;movcc\\t%0, %1
2381 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2382 [(set_attr "conds" "clob")
2383 (set_attr "length" "8,8,12")]
2386 (define_insn "*store_minmaxsi"
2387 [(set (match_operand:SI 0 "memory_operand" "=m")
2388 (match_operator:SI 3 "minmax_operator"
2389 [(match_operand:SI 1 "s_register_operand" "r")
2390 (match_operand:SI 2 "s_register_operand" "r")]))
2391 (clobber (reg:CC CC_REGNUM))]
2394 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2396 output_asm_insn (\"cmp\\t%1, %2\", operands);
2397 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2398 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2401 [(set_attr "conds" "clob")
2402 (set_attr "length" "12")
2403 (set_attr "type" "store1")]
2406 ; Reject the frame pointer in operand[1], since reloading this after
2407 ; it has been eliminated can cause carnage.
2408 (define_insn "*minmax_arithsi"
2409 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2410 (match_operator:SI 4 "shiftable_operator"
2411 [(match_operator:SI 5 "minmax_operator"
2412 [(match_operand:SI 2 "s_register_operand" "r,r")
2413 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2414 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2415 (clobber (reg:CC CC_REGNUM))]
2417 && (GET_CODE (operands[1]) != REG
2418 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2419 && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2422 enum rtx_code code = GET_CODE (operands[4]);
2424 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2426 output_asm_insn (\"cmp\\t%2, %3\", operands);
2427 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2428 if (which_alternative != 0 || operands[3] != const0_rtx
2429 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2430 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2433 [(set_attr "conds" "clob")
2434 (set_attr "length" "12")]
2438 ;; Shift and rotation insns
2440 (define_expand "ashlsi3"
2441 [(set (match_operand:SI 0 "s_register_operand" "")
2442 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2443 (match_operand:SI 2 "arm_rhs_operand" "")))]
2446 if (GET_CODE (operands[2]) == CONST_INT
2447 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2449 emit_insn (gen_movsi (operands[0], const0_rtx));
2455 (define_insn "*thumb_ashlsi3"
2456 [(set (match_operand:SI 0 "register_operand" "=l,l")
2457 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2458 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2461 [(set_attr "length" "2")]
2464 (define_expand "ashrsi3"
2465 [(set (match_operand:SI 0 "s_register_operand" "")
2466 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2467 (match_operand:SI 2 "arm_rhs_operand" "")))]
2470 if (GET_CODE (operands[2]) == CONST_INT
2471 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2472 operands[2] = GEN_INT (31);
2476 (define_insn "*thumb_ashrsi3"
2477 [(set (match_operand:SI 0 "register_operand" "=l,l")
2478 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2479 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2482 [(set_attr "length" "2")]
2485 (define_expand "lshrsi3"
2486 [(set (match_operand:SI 0 "s_register_operand" "")
2487 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2488 (match_operand:SI 2 "arm_rhs_operand" "")))]
2491 if (GET_CODE (operands[2]) == CONST_INT
2492 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2494 emit_insn (gen_movsi (operands[0], const0_rtx));
2500 (define_insn "*thumb_lshrsi3"
2501 [(set (match_operand:SI 0 "register_operand" "=l,l")
2502 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2503 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2506 [(set_attr "length" "2")]
2509 (define_expand "rotlsi3"
2510 [(set (match_operand:SI 0 "s_register_operand" "")
2511 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2512 (match_operand:SI 2 "reg_or_int_operand" "")))]
2515 if (GET_CODE (operands[2]) == CONST_INT)
2516 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2519 rtx reg = gen_reg_rtx (SImode);
2520 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2526 (define_expand "rotrsi3"
2527 [(set (match_operand:SI 0 "s_register_operand" "")
2528 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2529 (match_operand:SI 2 "arm_rhs_operand" "")))]
2534 if (GET_CODE (operands[2]) == CONST_INT
2535 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2536 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2538 else /* TARGET_THUMB */
2540 if (GET_CODE (operands [2]) == CONST_INT)
2541 operands [2] = force_reg (SImode, operands[2]);
2546 (define_insn "*thumb_rotrsi3"
2547 [(set (match_operand:SI 0 "register_operand" "=l")
2548 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2549 (match_operand:SI 2 "register_operand" "l")))]
2552 [(set_attr "length" "2")]
2555 (define_expand "ashldi3"
2556 [(set (match_operand:DI 0 "s_register_operand" "")
2557 (ashift:DI (match_operand:DI 1 "general_operand" "")
2558 (match_operand:SI 2 "general_operand" "")))]
2559 "TARGET_ARM && (TARGET_CIRRUS)"
2561 if (! s_register_operand (operands[1], DImode))
2562 operands[1] = copy_to_mode_reg (DImode, operands[1]);
2563 if (! s_register_operand (operands[2], SImode))
2564 operands[2] = copy_to_mode_reg (SImode, operands[2]);
2568 (define_insn "*arm_shiftsi3"
2569 [(set (match_operand:SI 0 "s_register_operand" "=r")
2570 (match_operator:SI 3 "shift_operator"
2571 [(match_operand:SI 1 "s_register_operand" "r")
2572 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2575 [(set_attr "predicable" "yes")
2576 (set_attr "shift" "1")
2580 (define_insn "*shiftsi3_compare0"
2581 [(set (reg:CC_NOOV CC_REGNUM)
2582 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2583 [(match_operand:SI 1 "s_register_operand" "r")
2584 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2586 (set (match_operand:SI 0 "s_register_operand" "=r")
2587 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2589 "mov%?s\\t%0, %1%S3"
2590 [(set_attr "conds" "set")
2591 (set_attr "shift" "1")
2595 (define_insn "*shiftsi3_compare0_scratch"
2596 [(set (reg:CC_NOOV CC_REGNUM)
2597 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2598 [(match_operand:SI 1 "s_register_operand" "r")
2599 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2601 (clobber (match_scratch:SI 0 "=r"))]
2603 "mov%?s\\t%0, %1%S3"
2604 [(set_attr "conds" "set")
2605 (set_attr "shift" "1")
2609 (define_insn "*notsi_shiftsi"
2610 [(set (match_operand:SI 0 "s_register_operand" "=r")
2611 (not:SI (match_operator:SI 3 "shift_operator"
2612 [(match_operand:SI 1 "s_register_operand" "r")
2613 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2616 [(set_attr "predicable" "yes")
2617 (set_attr "shift" "1")
2621 (define_insn "*notsi_shiftsi_compare0"
2622 [(set (reg:CC_NOOV CC_REGNUM)
2623 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2624 [(match_operand:SI 1 "s_register_operand" "r")
2625 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2627 (set (match_operand:SI 0 "s_register_operand" "=r")
2628 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2630 "mvn%?s\\t%0, %1%S3"
2631 [(set_attr "conds" "set")
2632 (set_attr "shift" "1")
2636 (define_insn "*not_shiftsi_compare0_scratch"
2637 [(set (reg:CC_NOOV CC_REGNUM)
2638 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2639 [(match_operand:SI 1 "s_register_operand" "r")
2640 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2642 (clobber (match_scratch:SI 0 "=r"))]
2644 "mvn%?s\\t%0, %1%S3"
2645 [(set_attr "conds" "set")
2646 (set_attr "shift" "1")
2650 ;; We don't really have extzv, but defining this using shifts helps
2651 ;; to reduce register pressure later on.
2653 (define_expand "extzv"
2655 (ashift:SI (match_operand:SI 1 "register_operand" "")
2656 (match_operand:SI 2 "const_int_operand" "")))
2657 (set (match_operand:SI 0 "register_operand" "")
2658 (lshiftrt:SI (match_dup 4)
2659 (match_operand:SI 3 "const_int_operand" "")))]
2663 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2664 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2666 operands[3] = GEN_INT (rshift);
2670 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2674 operands[2] = GEN_INT (lshift);
2675 operands[4] = gen_reg_rtx (SImode);
2680 ;; Unary arithmetic insns
2682 (define_expand "negdi2"
2684 [(set (match_operand:DI 0 "s_register_operand" "")
2685 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2686 (clobber (reg:CC CC_REGNUM))])]
2691 if (GET_CODE (operands[1]) != REG)
2692 operands[1] = force_reg (SImode, operands[1]);
2697 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2698 ;; The second alternative is to allow the common case of a *full* overlap.
2699 (define_insn "*arm_negdi2"
2700 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2701 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2702 (clobber (reg:CC CC_REGNUM))]
2704 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2705 [(set_attr "conds" "clob")
2706 (set_attr "length" "8")]
2709 (define_insn "*thumb_negdi2"
2710 [(set (match_operand:DI 0 "register_operand" "=&l")
2711 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2712 (clobber (reg:CC CC_REGNUM))]
2714 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2715 [(set_attr "length" "6")]
2718 (define_expand "negsi2"
2719 [(set (match_operand:SI 0 "s_register_operand" "")
2720 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2725 (define_insn "*arm_negsi2"
2726 [(set (match_operand:SI 0 "s_register_operand" "=r")
2727 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2729 "rsb%?\\t%0, %1, #0"
2730 [(set_attr "predicable" "yes")]
2733 (define_insn "*thumb_negsi2"
2734 [(set (match_operand:SI 0 "register_operand" "=l")
2735 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2738 [(set_attr "length" "2")]
2741 (define_insn "*arm_negsf2"
2742 [(set (match_operand:SF 0 "s_register_operand" "=f")
2743 (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
2744 "TARGET_ARM && TARGET_HARD_FLOAT"
2746 [(set_attr "type" "ffarith")
2747 (set_attr "predicable" "yes")]
2750 (define_insn "*arm_negdf2"
2751 [(set (match_operand:DF 0 "s_register_operand" "=f")
2752 (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
2753 "TARGET_ARM && TARGET_HARD_FLOAT"
2755 [(set_attr "type" "ffarith")
2756 (set_attr "predicable" "yes")]
2759 (define_insn "*negdf_esfdf"
2760 [(set (match_operand:DF 0 "s_register_operand" "=f")
2761 (neg:DF (float_extend:DF
2762 (match_operand:SF 1 "s_register_operand" "f"))))]
2763 "TARGET_ARM && TARGET_HARD_FLOAT"
2765 [(set_attr "type" "ffarith")
2766 (set_attr "predicable" "yes")]
2769 ;; abssi2 doesn't really clobber the condition codes if a different register
2770 ;; is being set. To keep things simple, assume during rtl manipulations that
2771 ;; it does, but tell the final scan operator the truth. Similarly for
2774 (define_insn "*arm_abssi2"
2775 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2776 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2777 (clobber (reg:CC CC_REGNUM))]
2780 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2781 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2782 [(set_attr "conds" "clob,*")
2783 (set_attr "shift" "1")
2784 ;; predicable can't be set based on the variant, so left as no
2785 (set_attr "length" "8")]
2788 (define_insn "*neg_abssi2"
2789 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2790 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2791 (clobber (reg:CC CC_REGNUM))]
2794 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2795 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2796 [(set_attr "conds" "clob,*")
2797 (set_attr "shift" "1")
2798 ;; predicable can't be set based on the variant, so left as no
2799 (set_attr "length" "8")]
2802 (define_insn "*arm_abssf2"
2803 [(set (match_operand:SF 0 "s_register_operand" "=f")
2804 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
2805 "TARGET_ARM && TARGET_HARD_FLOAT"
2807 [(set_attr "type" "ffarith")
2808 (set_attr "predicable" "yes")]
2811 (define_insn "*arm_absdf2"
2812 [(set (match_operand:DF 0 "s_register_operand" "=f")
2813 (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
2814 "TARGET_ARM && TARGET_HARD_FLOAT"
2816 [(set_attr "type" "ffarith")
2817 (set_attr "predicable" "yes")]
2820 (define_insn "*absdf_esfdf"
2821 [(set (match_operand:DF 0 "s_register_operand" "=f")
2822 (abs:DF (float_extend:DF
2823 (match_operand:SF 1 "s_register_operand" "f"))))]
2824 "TARGET_ARM && TARGET_HARD_FLOAT"
2826 [(set_attr "type" "ffarith")
2827 (set_attr "predicable" "yes")]
2830 (define_insn "sqrtsf2"
2831 [(set (match_operand:SF 0 "s_register_operand" "=f")
2832 (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
2833 "TARGET_ARM && TARGET_HARD_FLOAT"
2835 [(set_attr "type" "float_em")
2836 (set_attr "predicable" "yes")]
2839 (define_insn "sqrtdf2"
2840 [(set (match_operand:DF 0 "s_register_operand" "=f")
2841 (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
2842 "TARGET_ARM && TARGET_HARD_FLOAT"
2844 [(set_attr "type" "float_em")
2845 (set_attr "predicable" "yes")]
2848 (define_insn "*sqrtdf_esfdf"
2849 [(set (match_operand:DF 0 "s_register_operand" "=f")
2850 (sqrt:DF (float_extend:DF
2851 (match_operand:SF 1 "s_register_operand" "f"))))]
2852 "TARGET_ARM && TARGET_HARD_FLOAT"
2854 [(set_attr "type" "float_em")
2855 (set_attr "predicable" "yes")]
2858 (define_insn_and_split "one_cmpldi2"
2859 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2860 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2863 "TARGET_ARM && reload_completed"
2864 [(set (match_dup 0) (not:SI (match_dup 1)))
2865 (set (match_dup 2) (not:SI (match_dup 3)))]
2868 operands[2] = gen_highpart (SImode, operands[0]);
2869 operands[0] = gen_lowpart (SImode, operands[0]);
2870 operands[3] = gen_highpart (SImode, operands[1]);
2871 operands[1] = gen_lowpart (SImode, operands[1]);
2873 [(set_attr "length" "8")
2874 (set_attr "predicable" "yes")]
2877 (define_expand "one_cmplsi2"
2878 [(set (match_operand:SI 0 "s_register_operand" "")
2879 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2884 (define_insn "*arm_one_cmplsi2"
2885 [(set (match_operand:SI 0 "s_register_operand" "=r")
2886 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
2889 [(set_attr "predicable" "yes")]
2892 (define_insn "*thumb_one_cmplsi2"
2893 [(set (match_operand:SI 0 "register_operand" "=l")
2894 (not:SI (match_operand:SI 1 "register_operand" "l")))]
2897 [(set_attr "length" "2")]
2900 (define_insn "*notsi_compare0"
2901 [(set (reg:CC_NOOV CC_REGNUM)
2902 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2904 (set (match_operand:SI 0 "s_register_operand" "=r")
2905 (not:SI (match_dup 1)))]
2908 [(set_attr "conds" "set")]
2911 (define_insn "*notsi_compare0_scratch"
2912 [(set (reg:CC_NOOV CC_REGNUM)
2913 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2915 (clobber (match_scratch:SI 0 "=r"))]
2918 [(set_attr "conds" "set")]
2921 ;; Fixed <--> Floating conversion insns
2923 (define_insn "*arm_floatsisf2"
2924 [(set (match_operand:SF 0 "s_register_operand" "=f")
2925 (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
2926 "TARGET_ARM && TARGET_HARD_FLOAT"
2928 [(set_attr "type" "r_2_f")
2929 (set_attr "predicable" "yes")]
2932 (define_insn "*arm_floatsidf2"
2933 [(set (match_operand:DF 0 "s_register_operand" "=f")
2934 (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
2935 "TARGET_ARM && TARGET_HARD_FLOAT"
2937 [(set_attr "type" "r_2_f")
2938 (set_attr "predicable" "yes")]
2941 (define_insn "*arm_fix_truncsfsi2"
2942 [(set (match_operand:SI 0 "s_register_operand" "=r")
2943 (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
2944 "TARGET_ARM && TARGET_HARD_FLOAT"
2946 [(set_attr "type" "f_2_r")
2947 (set_attr "predicable" "yes")]
2950 (define_insn "*arm_fix_truncdfsi2"
2951 [(set (match_operand:SI 0 "s_register_operand" "=r")
2952 (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
2953 "TARGET_ARM && TARGET_HARD_FLOAT"
2955 [(set_attr "type" "f_2_r")
2956 (set_attr "predicable" "yes")]
2961 (define_insn "*arm_truncdfsf2"
2962 [(set (match_operand:SF 0 "s_register_operand" "=f")
2964 (match_operand:DF 1 "s_register_operand" "f")))]
2965 "TARGET_ARM && TARGET_HARD_FLOAT"
2967 [(set_attr "type" "ffarith")
2968 (set_attr "predicable" "yes")]
2971 ;; Zero and sign extension instructions.
2973 (define_insn "zero_extendsidi2"
2974 [(set (match_operand:DI 0 "s_register_operand" "=r")
2975 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2978 if (REGNO (operands[1])
2979 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2980 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2981 return \"mov%?\\t%R0, #0\";
2983 [(set_attr "length" "8")
2984 (set_attr "predicable" "yes")]
2987 (define_insn "zero_extendqidi2"
2988 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
2989 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2992 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
2993 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
2994 [(set_attr "length" "8")
2995 (set_attr "predicable" "yes")
2996 (set_attr "type" "*,load")
2997 (set_attr "pool_range" "*,4092")
2998 (set_attr "neg_pool_range" "*,4084")]
3001 (define_insn "extendsidi2"
3002 [(set (match_operand:DI 0 "s_register_operand" "=r")
3003 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3006 if (REGNO (operands[1])
3007 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3008 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3009 return \"mov%?\\t%R0, %Q0, asr #31\";
3011 [(set_attr "length" "8")
3012 (set_attr "shift" "1")
3013 (set_attr "predicable" "yes")]
3016 (define_expand "zero_extendhisi2"
3018 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3020 (set (match_operand:SI 0 "s_register_operand" "")
3021 (lshiftrt:SI (match_dup 2) (const_int 16)))]
3027 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3029 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3030 here because the insn below will generate an LDRH instruction
3031 rather than an LDR instruction, so we cannot get an unaligned
3033 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3034 gen_rtx_ZERO_EXTEND (SImode,
3038 if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3040 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3043 if (!s_register_operand (operands[1], HImode))
3044 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3045 operands[1] = gen_lowpart (SImode, operands[1]);
3046 operands[2] = gen_reg_rtx (SImode);
3048 else /* TARGET_THUMB */
3050 if (GET_CODE (operands[1]) == MEM)
3054 tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3055 tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3062 if (!s_register_operand (operands[1], HImode))
3063 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3064 operands[1] = gen_lowpart (SImode, operands[1]);
3065 operands[2] = gen_reg_rtx (SImode);
3067 ops[0] = operands[2];
3068 ops[1] = operands[1];
3069 ops[2] = GEN_INT (16);
3071 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3072 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3074 ops[0] = operands[0];
3075 ops[1] = operands[2];
3076 ops[2] = GEN_INT (16);
3078 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3079 gen_rtx_LSHIFTRT (SImode, ops[1],
3087 (define_insn "*thumb_zero_extendhisi2"
3088 [(set (match_operand:SI 0 "register_operand" "=l")
3089 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3092 rtx mem = XEXP (operands[1], 0);
3094 if (GET_CODE (mem) == CONST)
3095 mem = XEXP (mem, 0);
3097 if (GET_CODE (mem) == LABEL_REF)
3098 return \"ldr\\t%0, %1\";
3100 if (GET_CODE (mem) == PLUS)
3102 rtx a = XEXP (mem, 0);
3103 rtx b = XEXP (mem, 1);
3105 /* This can happen due to bugs in reload. */
3106 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3109 ops[0] = operands[0];
3112 output_asm_insn (\"mov %0, %1\", ops);
3114 XEXP (mem, 0) = operands[0];
3117 else if ( GET_CODE (a) == LABEL_REF
3118 && GET_CODE (b) == CONST_INT)
3119 return \"ldr\\t%0, %1\";
3122 return \"ldrh\\t%0, %1\";
3124 [(set_attr "length" "4")
3125 (set_attr "type" "load")
3126 (set_attr "pool_range" "60")]
3129 (define_insn "*arm_zero_extendhisi2"
3130 [(set (match_operand:SI 0 "s_register_operand" "=r")
3131 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3132 "TARGET_ARM && arm_arch4"
3134 [(set_attr "type" "load")
3135 (set_attr "predicable" "yes")
3136 (set_attr "pool_range" "256")
3137 (set_attr "neg_pool_range" "244")]
3141 [(set (match_operand:SI 0 "s_register_operand" "")
3142 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3143 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3144 "TARGET_ARM && (!arm_arch4)"
3145 [(set (match_dup 2) (match_dup 1))
3146 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3148 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3154 [(set (match_operand:SI 0 "s_register_operand" "")
3155 (match_operator:SI 3 "shiftable_operator"
3156 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3157 (match_operand:SI 4 "s_register_operand" "")]))
3158 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3159 "TARGET_ARM && (!arm_arch4)"
3160 [(set (match_dup 2) (match_dup 1))
3163 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3165 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3170 (define_expand "zero_extendqisi2"
3171 [(set (match_operand:SI 0 "s_register_operand" "")
3172 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3175 if (GET_CODE (operands[1]) != MEM)
3179 emit_insn (gen_andsi3 (operands[0],
3180 gen_lowpart (SImode, operands[1]),
3183 else /* TARGET_THUMB */
3185 rtx temp = gen_reg_rtx (SImode);
3188 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3189 operands[1] = gen_lowpart (SImode, operands[1]);
3192 ops[1] = operands[1];
3193 ops[2] = GEN_INT (24);
3195 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3196 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3198 ops[0] = operands[0];
3200 ops[2] = GEN_INT (24);
3202 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3203 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3210 (define_insn "*thumb_zero_extendqisi2"
3211 [(set (match_operand:SI 0 "register_operand" "=l")
3212 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3215 [(set_attr "length" "2")
3216 (set_attr "type" "load")
3217 (set_attr "pool_range" "32")]
3220 (define_insn "*arm_zero_extendqisi2"
3221 [(set (match_operand:SI 0 "s_register_operand" "=r")
3222 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3224 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3225 [(set_attr "type" "load")
3226 (set_attr "predicable" "yes")
3227 (set_attr "pool_range" "4096")
3228 (set_attr "neg_pool_range" "4084")]
3232 [(set (match_operand:SI 0 "s_register_operand" "")
3233 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3234 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3235 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3236 [(set (match_dup 2) (match_dup 1))
3237 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3241 (define_insn "*compareqi_eq0"
3242 [(set (reg:CC_Z CC_REGNUM)
3243 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3247 [(set_attr "conds" "set")]
3250 (define_expand "extendhisi2"
3252 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3254 (set (match_operand:SI 0 "s_register_operand" "")
3255 (ashiftrt:SI (match_dup 2)
3260 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3262 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3263 here because the insn below will generate an LDRH instruction
3264 rather than an LDR instruction, so we cannot get an unaligned
3266 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3267 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3271 if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3273 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3276 if (!s_register_operand (operands[1], HImode))
3277 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3278 operands[1] = gen_lowpart (SImode, operands[1]);
3279 operands[2] = gen_reg_rtx (SImode);
3285 ops[0] = operands[2];
3286 ops[1] = operands[1];
3287 ops[2] = GEN_INT (16);
3289 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3290 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3292 ops[0] = operands[0];
3293 ops[1] = operands[2];
3294 ops[2] = GEN_INT (16);
3296 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3297 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3304 (define_insn "*thumb_extendhisi2_insn"
3305 [(set (match_operand:SI 0 "register_operand" "=l")
3306 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3307 (clobber (match_scratch:SI 2 "=&l"))]
3312 rtx mem = XEXP (operands[1], 0);
3314 /* This code used to try to use 'V', and fix the address only if it was
3315 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3316 range of QImode offsets, and offsettable_address_p does a QImode
3319 if (GET_CODE (mem) == CONST)
3320 mem = XEXP (mem, 0);
3322 if (GET_CODE (mem) == LABEL_REF)
3323 return \"ldr\\t%0, %1\";
3325 if (GET_CODE (mem) == PLUS)
3327 rtx a = XEXP (mem, 0);
3328 rtx b = XEXP (mem, 1);
3330 if (GET_CODE (a) == LABEL_REF
3331 && GET_CODE (b) == CONST_INT)
3332 return \"ldr\\t%0, %1\";
3334 if (GET_CODE (b) == REG)
3335 return \"ldrsh\\t%0, %1\";
3343 ops[2] = const0_rtx;
3346 if (GET_CODE (ops[1]) != REG)
3352 ops[0] = operands[0];
3353 ops[3] = operands[2];
3354 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3357 [(set_attr "length" "4")
3358 (set_attr "type" "load")
3359 (set_attr "pool_range" "1020")]
3362 (define_expand "extendhisi2_mem"
3363 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3365 (zero_extend:SI (match_dup 7)))
3366 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3367 (set (match_operand:SI 0 "" "")
3368 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3373 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3375 mem1 = gen_rtx_MEM (QImode, addr);
3376 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3377 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3378 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3379 operands[0] = gen_lowpart (SImode, operands[0]);
3381 operands[2] = gen_reg_rtx (SImode);
3382 operands[3] = gen_reg_rtx (SImode);
3383 operands[6] = gen_reg_rtx (SImode);
3386 if (BYTES_BIG_ENDIAN)
3388 operands[4] = operands[2];
3389 operands[5] = operands[3];
3393 operands[4] = operands[3];
3394 operands[5] = operands[2];
3399 (define_insn "*arm_extendhisi_insn"
3400 [(set (match_operand:SI 0 "s_register_operand" "=r")
3401 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3402 "TARGET_ARM && arm_arch4"
3404 [(set_attr "type" "load")
3405 (set_attr "predicable" "yes")
3406 (set_attr "pool_range" "256")
3407 (set_attr "neg_pool_range" "244")]
3411 [(set (match_operand:SI 0 "s_register_operand" "")
3412 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3413 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3414 "TARGET_ARM && (!arm_arch4)"
3415 [(set (match_dup 2) (match_dup 1))
3416 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3418 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3424 [(set (match_operand:SI 0 "s_register_operand" "")
3425 (match_operator:SI 3 "shiftable_operator"
3426 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3427 (match_operand:SI 4 "s_register_operand" "")]))
3428 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3429 "TARGET_ARM && (!arm_arch4)"
3430 [(set (match_dup 2) (match_dup 1))
3433 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3434 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3439 (define_expand "extendqihi2"
3441 (ashift:SI (match_operand:QI 1 "general_operand" "")
3443 (set (match_operand:HI 0 "s_register_operand" "")
3444 (ashiftrt:SI (match_dup 2)
3449 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3451 emit_insn (gen_rtx_SET (VOIDmode,
3453 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3456 if (!s_register_operand (operands[1], QImode))
3457 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3458 operands[0] = gen_lowpart (SImode, operands[0]);
3459 operands[1] = gen_lowpart (SImode, operands[1]);
3460 operands[2] = gen_reg_rtx (SImode);
3464 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3465 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3466 (define_insn "*extendqihi_insn"
3467 [(set (match_operand:HI 0 "s_register_operand" "=r")
3468 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3469 "TARGET_ARM && arm_arch4"
3471 /* If the address is invalid, this will split the instruction into two. */
3472 if (bad_signed_byte_operand (operands[1], VOIDmode))
3474 return \"ldr%?sb\\t%0, %1\";
3476 [(set_attr "type" "load")
3477 (set_attr "predicable" "yes")
3478 (set_attr "length" "8")
3479 (set_attr "pool_range" "256")
3480 (set_attr "neg_pool_range" "244")]
3484 [(set (match_operand:HI 0 "s_register_operand" "")
3485 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3486 "TARGET_ARM && arm_arch4 && reload_completed"
3487 [(set (match_dup 3) (match_dup 1))
3488 (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3491 HOST_WIDE_INT offset;
3493 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3494 operands[2] = gen_rtx_MEM (QImode, operands[3]);
3495 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3496 operands[1] = XEXP (operands[1], 0);
3497 if (GET_CODE (operands[1]) == PLUS
3498 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3499 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3500 || const_ok_for_arm (-offset)))
3502 HOST_WIDE_INT low = (offset > 0
3503 ? (offset & 0xff) : -((-offset) & 0xff));
3504 XEXP (operands[2], 0) = plus_constant (operands[3], low);
3505 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3507 /* Ensure the sum is in correct canonical form */
3508 else if (GET_CODE (operands[1]) == PLUS
3509 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3510 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3511 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3512 XEXP (operands[1], 1),
3513 XEXP (operands[1], 0));
3517 (define_expand "extendqisi2"
3519 (ashift:SI (match_operand:QI 1 "general_operand" "")
3521 (set (match_operand:SI 0 "s_register_operand" "")
3522 (ashiftrt:SI (match_dup 2)
3527 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3529 emit_insn (gen_rtx_SET (VOIDmode,
3531 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3534 if (!s_register_operand (operands[1], QImode))
3535 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3536 operands[1] = gen_lowpart (SImode, operands[1]);
3537 operands[2] = gen_reg_rtx (SImode);
3543 ops[0] = operands[2];
3544 ops[1] = operands[1];
3545 ops[2] = GEN_INT (24);
3547 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3548 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3550 ops[0] = operands[0];
3551 ops[1] = operands[2];
3552 ops[2] = GEN_INT (24);
3554 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3555 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3562 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3563 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3564 (define_insn "*arm_extendqisi_insn"
3565 [(set (match_operand:SI 0 "s_register_operand" "=r")
3566 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3567 "TARGET_ARM && arm_arch4"
3569 /* If the address is invalid, this will split the instruction into two. */
3570 if (bad_signed_byte_operand (operands[1], VOIDmode))
3572 return \"ldr%?sb\\t%0, %1\";
3574 [(set_attr "type" "load")
3575 (set_attr "predicable" "yes")
3576 (set_attr "length" "8")
3577 (set_attr "pool_range" "256")
3578 (set_attr "neg_pool_range" "244")]
3582 [(set (match_operand:SI 0 "s_register_operand" "")
3583 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3584 "TARGET_ARM && arm_arch4 && reload_completed"
3585 [(set (match_dup 0) (match_dup 1))
3586 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3589 HOST_WIDE_INT offset;
3591 operands[2] = gen_rtx_MEM (QImode, operands[0]);
3592 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3593 operands[1] = XEXP (operands[1], 0);
3594 if (GET_CODE (operands[1]) == PLUS
3595 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3596 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3597 || const_ok_for_arm (-offset)))
3599 HOST_WIDE_INT low = (offset > 0
3600 ? (offset & 0xff) : -((-offset) & 0xff));
3601 XEXP (operands[2], 0) = plus_constant (operands[0], low);
3602 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3604 /* Ensure the sum is in correct canonical form */
3605 else if (GET_CODE (operands[1]) == PLUS
3606 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3607 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3608 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3609 XEXP (operands[1], 1),
3610 XEXP (operands[1], 0));
3614 (define_insn "*thumb_extendqisi2_insn"
3615 [(set (match_operand:SI 0 "register_operand" "=l,l")
3616 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3621 rtx mem = XEXP (operands[1], 0);
3623 if (GET_CODE (mem) == CONST)
3624 mem = XEXP (mem, 0);
3626 if (GET_CODE (mem) == LABEL_REF)
3627 return \"ldr\\t%0, %1\";
3629 if (GET_CODE (mem) == PLUS
3630 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3631 return \"ldr\\t%0, %1\";
3633 if (which_alternative == 0)
3634 return \"ldrsb\\t%0, %1\";
3636 ops[0] = operands[0];
3638 if (GET_CODE (mem) == PLUS)
3640 rtx a = XEXP (mem, 0);
3641 rtx b = XEXP (mem, 1);
3646 if (GET_CODE (a) == REG)
3648 if (GET_CODE (b) == REG)
3649 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3650 else if (REGNO (a) == REGNO (ops[0]))
3652 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3653 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3654 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3657 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3659 else if (GET_CODE (b) != REG)
3663 if (REGNO (b) == REGNO (ops[0]))
3665 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3666 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3667 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3670 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3673 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3675 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3676 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3677 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3682 ops[2] = const0_rtx;
3684 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3688 [(set_attr "length" "2,6")
3689 (set_attr "type" "load,load")
3690 (set_attr "pool_range" "32,32")]
3693 (define_insn "*arm_extendsfdf2"
3694 [(set (match_operand:DF 0 "s_register_operand" "=f")
3695 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
3696 "TARGET_ARM && TARGET_HARD_FLOAT"
3698 [(set_attr "type" "ffarith")
3699 (set_attr "predicable" "yes")]
3702 ;; Move insns (including loads and stores)
3704 ;; XXX Just some ideas about movti.
3705 ;; I don't think these are a good idea on the arm, there just aren't enough
3707 ;;(define_expand "loadti"
3708 ;; [(set (match_operand:TI 0 "s_register_operand" "")
3709 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
3712 ;;(define_expand "storeti"
3713 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3714 ;; (match_operand:TI 1 "s_register_operand" ""))]
3717 ;;(define_expand "movti"
3718 ;; [(set (match_operand:TI 0 "general_operand" "")
3719 ;; (match_operand:TI 1 "general_operand" ""))]
3725 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3726 ;; operands[1] = copy_to_reg (operands[1]);
3727 ;; if (GET_CODE (operands[0]) == MEM)
3728 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3729 ;; else if (GET_CODE (operands[1]) == MEM)
3730 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3734 ;; emit_insn (insn);
3738 ;; Recognize garbage generated above.
3741 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3742 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3746 ;; register mem = (which_alternative < 3);
3747 ;; register const char *template;
3749 ;; operands[mem] = XEXP (operands[mem], 0);
3750 ;; switch (which_alternative)
3752 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3753 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
3754 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
3755 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
3756 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
3757 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
3759 ;; output_asm_insn (template, operands);
3763 (define_expand "movdi"
3764 [(set (match_operand:DI 0 "general_operand" "")
3765 (match_operand:DI 1 "general_operand" ""))]
3770 if (!no_new_pseudos)
3772 if (GET_CODE (operands[0]) != REG)
3773 operands[1] = force_reg (DImode, operands[1]);
3779 (define_insn "*arm_movdi"
3780 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3781 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
3782 "TARGET_ARM && !TARGET_CIRRUS"
3784 return (output_move_double (operands));
3786 [(set_attr "length" "8")
3787 (set_attr "type" "*,load,store2")
3788 (set_attr "pool_range" "*,1020,*")
3789 (set_attr "neg_pool_range" "*,1008,*")]
3792 ;;; ??? This should have alternatives for constants.
3793 ;;; ??? This was originally identical to the movdf_insn pattern.
3794 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3795 ;;; thumb_reorg with a memory reference.
3796 (define_insn "*thumb_movdi_insn"
3797 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3798 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
3801 && ( register_operand (operands[0], DImode)
3802 || register_operand (operands[1], DImode))"
3805 switch (which_alternative)
3809 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3810 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
3811 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
3813 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3815 operands[1] = GEN_INT (- INTVAL (operands[1]));
3816 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3818 return \"ldmia\\t%1, {%0, %H0}\";
3820 return \"stmia\\t%0, {%1, %H1}\";
3822 return thumb_load_double_from_address (operands);
3824 operands[2] = gen_rtx (MEM, SImode,
3825 plus_constant (XEXP (operands[0], 0), 4));
3826 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3829 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3830 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
3831 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
3834 [(set_attr "length" "4,4,6,2,2,6,4,4")
3835 (set_attr "type" "*,*,*,load,store2,load,store2,*")
3836 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
3839 (define_expand "movsi"
3840 [(set (match_operand:SI 0 "general_operand" "")
3841 (match_operand:SI 1 "general_operand" ""))]
3846 /* Everything except mem = const or mem = mem can be done easily */
3847 if (GET_CODE (operands[0]) == MEM)
3848 operands[1] = force_reg (SImode, operands[1]);
3849 if (GET_CODE (operands[1]) == CONST_INT
3850 && !(const_ok_for_arm (INTVAL (operands[1]))
3851 || const_ok_for_arm (~INTVAL (operands[1]))))
3853 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3856 : preserve_subexpressions_p ()));
3860 else /* TARGET_THUMB.... */
3862 if (!no_new_pseudos)
3864 if (GET_CODE (operands[0]) != REG)
3865 operands[1] = force_reg (SImode, operands[1]);
3870 && (CONSTANT_P (operands[1])
3871 || symbol_mentioned_p (operands[1])
3872 || label_mentioned_p (operands[1])))
3873 operands[1] = legitimize_pic_address (operands[1], SImode,
3874 (no_new_pseudos ? operands[0] : 0));
3878 (define_insn "*arm_movsi_insn"
3879 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
3880 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
3882 && ( register_operand (operands[0], SImode)
3883 || register_operand (operands[1], SImode))"
3889 [(set_attr "type" "*,*,load,store1")
3890 (set_attr "predicable" "yes")
3891 (set_attr "pool_range" "*,*,4096,*")
3892 (set_attr "neg_pool_range" "*,*,4084,*")]
3896 [(set (match_operand:SI 0 "s_register_operand" "")
3897 (match_operand:SI 1 "const_int_operand" ""))]
3899 && (!(const_ok_for_arm (INTVAL (operands[1]))
3900 || const_ok_for_arm (~INTVAL (operands[1]))))"
3901 [(clobber (const_int 0))]
3903 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3909 (define_insn "*thumb_movsi_insn"
3910 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
3911 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
3913 && ( register_operand (operands[0], SImode)
3914 || register_operand (operands[1], SImode))"
3925 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
3926 (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
3927 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
3931 [(set (match_operand:SI 0 "register_operand" "")
3932 (match_operand:SI 1 "const_int_operand" ""))]
3933 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
3934 [(set (match_dup 0) (match_dup 1))
3935 (set (match_dup 0) (neg:SI (match_dup 0)))]
3936 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
3940 [(set (match_operand:SI 0 "register_operand" "")
3941 (match_operand:SI 1 "const_int_operand" ""))]
3942 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
3943 [(set (match_dup 0) (match_dup 1))
3944 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
3947 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
3948 unsigned HOST_WIDE_INT mask = 0xff;
3951 for (i = 0; i < 25; i++)
3952 if ((val & (mask << i)) == val)
3955 /* Shouldn't happen, but we don't want to split if the shift is zero. */
3959 operands[1] = GEN_INT (val >> i);
3960 operands[2] = GEN_INT (i);
3964 ;; When generating pic, we need to load the symbol offset into a register.
3965 ;; So that the optimizer does not confuse this with a normal symbol load
3966 ;; we use an unspec. The offset will be loaded from a constant pool entry,
3967 ;; since that is the only type of relocation we can use.
3969 ;; The rather odd constraints on the following are to force reload to leave
3970 ;; the insn alone, and to force the minipool generation pass to then move
3971 ;; the GOT symbol to memory.
3973 (define_insn "pic_load_addr_arm"
3974 [(set (match_operand:SI 0 "s_register_operand" "=r")
3975 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3976 "TARGET_ARM && flag_pic"
3978 [(set_attr "type" "load")
3979 (set (attr "pool_range") (const_int 4096))
3980 (set (attr "neg_pool_range") (const_int 4084))]
3983 (define_insn "pic_load_addr_thumb"
3984 [(set (match_operand:SI 0 "s_register_operand" "=l")
3985 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3986 "TARGET_THUMB && flag_pic"
3988 [(set_attr "type" "load")
3989 (set (attr "pool_range") (const_int 1024))]
3992 ;; This variant is used for AOF assembly, since it needs to mention the
3993 ;; pic register in the rtl.
3994 (define_expand "pic_load_addr_based"
3995 [(set (match_operand:SI 0 "s_register_operand" "=r")
3996 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
3997 "TARGET_ARM && flag_pic"
3998 "operands[2] = pic_offset_table_rtx;"
4001 (define_insn "*pic_load_addr_based_insn"
4002 [(set (match_operand:SI 0 "s_register_operand" "=r")
4003 (unspec:SI [(match_operand 1 "" "")
4004 (match_operand 2 "s_register_operand" "r")]
4006 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4008 #ifdef AOF_ASSEMBLER
4009 operands[1] = aof_pic_entry (operands[1]);
4011 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4014 [(set_attr "type" "load")
4015 (set (attr "pool_range")
4016 (if_then_else (eq_attr "is_thumb" "yes")
4019 (set (attr "neg_pool_range")
4020 (if_then_else (eq_attr "is_thumb" "yes")
4025 (define_insn "pic_add_dot_plus_four"
4026 [(set (match_operand:SI 0 "register_operand" "+r")
4027 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
4028 (use (label_ref (match_operand 1 "" "")))]
4029 "TARGET_THUMB && flag_pic"
4031 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4032 CODE_LABEL_NUMBER (operands[1]));
4033 return \"add\\t%0, %|pc\";
4035 [(set_attr "length" "2")]
4038 (define_insn "pic_add_dot_plus_eight"
4039 [(set (match_operand:SI 0 "register_operand" "+r")
4040 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
4041 (use (label_ref (match_operand 1 "" "")))]
4042 "TARGET_ARM && flag_pic"
4044 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4045 CODE_LABEL_NUMBER (operands[1]));
4046 return \"add%?\\t%0, %|pc, %0\";
4048 [(set_attr "predicable" "yes")]
4051 (define_expand "builtin_setjmp_receiver"
4052 [(label_ref (match_operand 0 "" ""))]
4056 arm_finalize_pic (0);
4060 ;; If copying one reg to another we can set the condition codes according to
4061 ;; its value. Such a move is common after a return from subroutine and the
4062 ;; result is being tested against zero.
4064 (define_insn "*movsi_compare0"
4065 [(set (reg:CC CC_REGNUM)
4066 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4068 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4073 sub%?s\\t%0, %1, #0"
4074 [(set_attr "conds" "set")]
4077 ;; Subroutine to store a half word from a register into memory.
4078 ;; Operand 0 is the source register (HImode)
4079 ;; Operand 1 is the destination address in a register (SImode)
4081 ;; In both this routine and the next, we must be careful not to spill
4082 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4083 ;; can generate unrecognizable rtl.
4085 (define_expand "storehi"
4086 [;; store the low byte
4087 (set (match_operand 1 "" "") (match_dup 3))
4088 ;; extract the high byte
4090 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4091 ;; store the high byte
4092 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
4096 rtx op1 = operands[1];
4097 rtx addr = XEXP (op1, 0);
4098 enum rtx_code code = GET_CODE (addr);
4100 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4102 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4104 operands[4] = adjust_address (op1, QImode, 1);
4105 operands[1] = adjust_address (operands[1], QImode, 0);
4106 operands[3] = gen_lowpart (QImode, operands[0]);
4107 operands[0] = gen_lowpart (SImode, operands[0]);
4108 operands[2] = gen_reg_rtx (SImode);
4112 (define_expand "storehi_bigend"
4113 [(set (match_dup 4) (match_dup 3))
4115 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4116 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 3))]
4120 rtx op1 = operands[1];
4121 rtx addr = XEXP (op1, 0);
4122 enum rtx_code code = GET_CODE (addr);
4124 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4126 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4128 operands[4] = adjust_address (op1, QImode, 1);
4129 operands[1] = adjust_address (operands[1], QImode, 0);
4130 operands[3] = gen_lowpart (QImode, operands[0]);
4131 operands[0] = gen_lowpart (SImode, operands[0]);
4132 operands[2] = gen_reg_rtx (SImode);
4136 ;; Subroutine to store a half word integer constant into memory.
4137 (define_expand "storeinthi"
4138 [(set (match_operand 0 "" "")
4139 (subreg:QI (match_operand 1 "" "") 0))
4140 (set (match_dup 3) (match_dup 2))]
4144 HOST_WIDE_INT value = INTVAL (operands[1]);
4145 rtx addr = XEXP (operands[0], 0);
4146 rtx op0 = operands[0];
4147 enum rtx_code code = GET_CODE (addr);
4149 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4151 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4153 operands[1] = gen_reg_rtx (SImode);
4154 if (BYTES_BIG_ENDIAN)
4156 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4157 if ((value & 255) == ((value >> 8) & 255))
4158 operands[2] = operands[1];
4161 operands[2] = gen_reg_rtx (SImode);
4162 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4167 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4168 if ((value & 255) == ((value >> 8) & 255))
4169 operands[2] = operands[1];
4172 operands[2] = gen_reg_rtx (SImode);
4173 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4177 operands[3] = adjust_address (op0, QImode, 1);
4178 operands[0] = adjust_address (operands[0], QImode, 0);
4179 operands[2] = gen_lowpart (QImode, operands[2]);
4183 (define_expand "storehi_single_op"
4184 [(set (match_operand:HI 0 "memory_operand" "")
4185 (match_operand:HI 1 "general_operand" ""))]
4186 "TARGET_ARM && arm_arch4"
4188 if (!s_register_operand (operands[1], HImode))
4189 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4193 (define_expand "movhi"
4194 [(set (match_operand:HI 0 "general_operand" "")
4195 (match_operand:HI 1 "general_operand" ""))]
4200 if (!no_new_pseudos)
4202 if (GET_CODE (operands[0]) == MEM)
4206 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4209 if (GET_CODE (operands[1]) == CONST_INT)
4210 emit_insn (gen_storeinthi (operands[0], operands[1]));
4213 if (GET_CODE (operands[1]) == MEM)
4214 operands[1] = force_reg (HImode, operands[1]);
4215 if (BYTES_BIG_ENDIAN)
4216 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4218 emit_insn (gen_storehi (operands[1], operands[0]));
4222 /* Sign extend a constant, and keep it in an SImode reg. */
4223 else if (GET_CODE (operands[1]) == CONST_INT)
4225 rtx reg = gen_reg_rtx (SImode);
4226 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4228 /* If the constant is already valid, leave it alone. */
4229 if (!const_ok_for_arm (val))
4231 /* If setting all the top bits will make the constant
4232 loadable in a single instruction, then set them.
4233 Otherwise, sign extend the number. */
4235 if (const_ok_for_arm (~(val | ~0xffff)))
4237 else if (val & 0x8000)
4241 emit_insn (gen_movsi (reg, GEN_INT (val)));
4242 operands[1] = gen_lowpart (HImode, reg);
4244 else if (arm_arch4 && !no_new_pseudos && optimize > 0
4245 && GET_CODE (operands[1]) == MEM)
4247 rtx reg = gen_reg_rtx (SImode);
4249 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4250 operands[1] = gen_lowpart (HImode, reg);
4252 else if (!arm_arch4)
4254 /* Note: We do not have to worry about TARGET_MMU_TRAPS
4255 for v4 and up architectures because LDRH instructions will
4256 be used to access the HI values, and these cannot generate
4257 unaligned word access faults in the MMU. */
4258 if (GET_CODE (operands[1]) == MEM)
4260 if (TARGET_MMU_TRAPS)
4263 rtx offset = const0_rtx;
4264 rtx reg = gen_reg_rtx (SImode);
4266 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4267 || (GET_CODE (base) == PLUS
4268 && (GET_CODE (offset = XEXP (base, 1))
4270 && ((INTVAL(offset) & 1) != 1)
4271 && GET_CODE (base = XEXP (base, 0)) == REG))
4272 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4274 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4277 new = gen_rtx_MEM (SImode,
4278 plus_constant (base, new_offset));
4279 MEM_COPY_ATTRIBUTES (new, operands[1]);
4280 emit_insn (gen_movsi (reg, new));
4281 if (((INTVAL (offset) & 2) != 0)
4282 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4284 rtx reg2 = gen_reg_rtx (SImode);
4286 emit_insn (gen_lshrsi3 (reg2, reg,
4292 emit_insn (gen_movhi_bytes (reg, operands[1]));
4294 operands[1] = gen_lowpart (HImode, reg);
4296 else if (BYTES_BIG_ENDIAN)
4299 rtx offset = const0_rtx;
4301 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4302 || (GET_CODE (base) == PLUS
4303 && (GET_CODE (offset = XEXP (base, 1))
4305 && GET_CODE (base = XEXP (base, 0)) == REG))
4306 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4308 rtx reg = gen_reg_rtx (SImode);
4311 if ((INTVAL (offset) & 2) == 2)
4313 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4314 new = gen_rtx_MEM (SImode,
4315 plus_constant (base,
4317 MEM_COPY_ATTRIBUTES (new, operands[1]);
4318 emit_insn (gen_movsi (reg, new));
4322 new = gen_rtx_MEM (SImode,
4323 XEXP (operands[1], 0));
4324 MEM_COPY_ATTRIBUTES (new, operands[1]);
4325 emit_insn (gen_rotated_loadsi (reg, new));
4328 operands[1] = gen_lowpart (HImode, reg);
4332 emit_insn (gen_movhi_bigend (operands[0],
4340 /* Handle loading a large integer during reload */
4341 else if (GET_CODE (operands[1]) == CONST_INT
4342 && !const_ok_for_arm (INTVAL (operands[1]))
4343 && !const_ok_for_arm (~INTVAL (operands[1])))
4345 /* Writing a constant to memory needs a scratch, which should
4346 be handled with SECONDARY_RELOADs. */
4347 if (GET_CODE (operands[0]) != REG)
4350 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4351 emit_insn (gen_movsi (operands[0], operands[1]));
4355 else /* TARGET_THUMB */
4357 if (!no_new_pseudos)
4359 if (GET_CODE (operands[0]) != REG)
4360 operands[1] = force_reg (HImode, operands[1]);
4362 /* ??? We shouldn't really get invalid addresses here, but this can
4363 happen if we are passed a SP (never OK for HImode/QImode) or
4364 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4365 HImode/QImode) relative address. */
4366 /* ??? This should perhaps be fixed elsewhere, for instance, in
4367 fixup_stack_1, by checking for other kinds of invalid addresses,
4368 e.g. a bare reference to a virtual register. This may confuse the
4369 alpha though, which must handle this case differently. */
4370 if (GET_CODE (operands[0]) == MEM
4371 && !memory_address_p (GET_MODE (operands[0]),
4372 XEXP (operands[0], 0)))
4374 = replace_equiv_address (operands[0],
4375 copy_to_reg (XEXP (operands[0], 0)));
4377 if (GET_CODE (operands[1]) == MEM
4378 && !memory_address_p (GET_MODE (operands[1]),
4379 XEXP (operands[1], 0)))
4381 = replace_equiv_address (operands[1],
4382 copy_to_reg (XEXP (operands[1], 0)));
4384 /* Handle loading a large integer during reload */
4385 else if (GET_CODE (operands[1]) == CONST_INT
4386 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4388 /* Writing a constant to memory needs a scratch, which should
4389 be handled with SECONDARY_RELOADs. */
4390 if (GET_CODE (operands[0]) != REG)
4393 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4394 emit_insn (gen_movsi (operands[0], operands[1]));
4401 (define_insn "*thumb_movhi_insn"
4402 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4403 (match_operand:HI 1 "general_operand" "l,mn,l,*h,*r,I"))]
4405 && ( register_operand (operands[0], HImode)
4406 || register_operand (operands[1], HImode))"
4408 switch (which_alternative)
4410 case 0: return \"add %0, %1, #0\";
4411 case 2: return \"strh %1, %0\";
4412 case 3: return \"mov %0, %1\";
4413 case 4: return \"mov %0, %1\";
4414 case 5: return \"mov %0, %1\";
4417 /* The stack pointer can end up being taken as an index register.
4418 Catch this case here and deal with it. */
4419 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4420 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4421 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4424 ops[0] = operands[0];
4425 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4427 output_asm_insn (\"mov %0, %1\", ops);
4429 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4432 return \"ldrh %0, %1\";
4434 [(set_attr "length" "2,4,2,2,2,2")
4435 (set_attr "type" "*,load,store1,*,*,*")
4436 (set_attr "pool_range" "*,64,*,*,*,*")]
4440 (define_insn "rotated_loadsi"
4441 [(set (match_operand:SI 0 "s_register_operand" "=r")
4442 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4444 "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4449 ops[0] = operands[0];
4450 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4451 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4454 [(set_attr "type" "load")
4455 (set_attr "predicable" "yes")]
4458 (define_expand "movhi_bytes"
4459 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4461 (zero_extend:SI (match_dup 6)))
4462 (set (match_operand:SI 0 "" "")
4463 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4468 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4470 mem1 = gen_rtx_MEM (QImode, addr);
4471 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4472 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4473 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4474 operands[0] = gen_lowpart (SImode, operands[0]);
4476 operands[2] = gen_reg_rtx (SImode);
4477 operands[3] = gen_reg_rtx (SImode);
4480 if (BYTES_BIG_ENDIAN)
4482 operands[4] = operands[2];
4483 operands[5] = operands[3];
4487 operands[4] = operands[3];
4488 operands[5] = operands[2];
4493 (define_expand "movhi_bigend"
4495 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4498 (ashiftrt:SI (match_dup 2) (const_int 16)))
4499 (set (match_operand:HI 0 "s_register_operand" "")
4500 (subreg:HI (match_dup 3) 0))]
4503 operands[2] = gen_reg_rtx (SImode);
4504 operands[3] = gen_reg_rtx (SImode);
4508 ;; Pattern to recognize insn generated default case above
4509 (define_insn "*movhi_insn_arch4"
4510 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4511 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4514 && (GET_CODE (operands[1]) != CONST_INT
4515 || const_ok_for_arm (INTVAL (operands[1]))
4516 || const_ok_for_arm (~INTVAL (operands[1])))"
4518 mov%?\\t%0, %1\\t%@ movhi
4519 mvn%?\\t%0, #%B1\\t%@ movhi
4520 str%?h\\t%1, %0\\t%@ movhi
4521 ldr%?h\\t%0, %1\\t%@ movhi"
4522 [(set_attr "type" "*,*,store1,load")
4523 (set_attr "predicable" "yes")
4524 (set_attr "pool_range" "*,*,*,256")
4525 (set_attr "neg_pool_range" "*,*,*,244")]
4528 (define_insn "*movhi_insn_littleend"
4529 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4530 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4533 && !BYTES_BIG_ENDIAN
4534 && !TARGET_MMU_TRAPS
4535 && (GET_CODE (operands[1]) != CONST_INT
4536 || const_ok_for_arm (INTVAL (operands[1]))
4537 || const_ok_for_arm (~INTVAL (operands[1])))"
4539 mov%?\\t%0, %1\\t%@ movhi
4540 mvn%?\\t%0, #%B1\\t%@ movhi
4541 ldr%?\\t%0, %1\\t%@ movhi"
4542 [(set_attr "type" "*,*,load")
4543 (set_attr "predicable" "yes")
4544 (set_attr "pool_range" "4096")
4545 (set_attr "neg_pool_range" "4084")]
4548 (define_insn "*movhi_insn_bigend"
4549 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4550 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4554 && !TARGET_MMU_TRAPS
4555 && (GET_CODE (operands[1]) != CONST_INT
4556 || const_ok_for_arm (INTVAL (operands[1]))
4557 || const_ok_for_arm (~INTVAL (operands[1])))"
4559 mov%?\\t%0, %1\\t%@ movhi
4560 mvn%?\\t%0, #%B1\\t%@ movhi
4561 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4562 [(set_attr "type" "*,*,load")
4563 (set_attr "predicable" "yes")
4564 (set_attr "length" "4,4,8")
4565 (set_attr "pool_range" "*,*,4092")
4566 (set_attr "neg_pool_range" "*,*,4084")]
4569 (define_insn "*loadhi_si_bigend"
4570 [(set (match_operand:SI 0 "s_register_operand" "=r")
4571 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
4575 && !TARGET_MMU_TRAPS"
4576 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4577 [(set_attr "type" "load")
4578 (set_attr "predicable" "yes")
4579 (set_attr "pool_range" "4096")
4580 (set_attr "neg_pool_range" "4084")]
4583 (define_insn "*movhi_bytes"
4584 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4585 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4586 "TARGET_ARM && TARGET_MMU_TRAPS"
4588 mov%?\\t%0, %1\\t%@ movhi
4589 mvn%?\\t%0, #%B1\\t%@ movhi"
4590 [(set_attr "predicable" "yes")]
4593 (define_insn "thumb_movhi_clobber"
4594 [(set (match_operand:HI 0 "memory_operand" "=m")
4595 (match_operand:HI 1 "register_operand" "l"))
4596 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4602 ;; We use a DImode scratch because we may occasionally need an additional
4603 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4604 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4605 (define_expand "reload_outhi"
4606 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4607 (match_operand:HI 1 "s_register_operand" "r")
4608 (match_operand:DI 2 "s_register_operand" "=&l")])]
4611 arm_reload_out_hi (operands);
4613 thumb_reload_out_hi (operands);
4618 (define_expand "reload_inhi"
4619 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4620 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4621 (match_operand:DI 2 "s_register_operand" "=&r")])]
4622 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4625 arm_reload_in_hi (operands);
4627 thumb_reload_out_hi (operands);
4631 (define_expand "movqi"
4632 [(set (match_operand:QI 0 "general_operand" "")
4633 (match_operand:QI 1 "general_operand" ""))]
4638 /* Everything except mem = const or mem = mem can be done easily */
4640 if (!no_new_pseudos)
4642 if (GET_CODE (operands[1]) == CONST_INT)
4644 rtx reg = gen_reg_rtx (SImode);
4646 emit_insn (gen_movsi (reg, operands[1]));
4647 operands[1] = gen_lowpart (QImode, reg);
4649 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4651 rtx reg = gen_reg_rtx (SImode);
4653 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4654 operands[1] = gen_lowpart (QImode, reg);
4656 if (GET_CODE (operands[0]) == MEM)
4657 operands[1] = force_reg (QImode, operands[1]);
4660 else /* TARGET_THUMB */
4662 if (!no_new_pseudos)
4664 if (GET_CODE (operands[0]) != REG)
4665 operands[1] = force_reg (QImode, operands[1]);
4667 /* ??? We shouldn't really get invalid addresses here, but this can
4668 happen if we are passed a SP (never OK for HImode/QImode) or
4669 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4670 HImode/QImode) relative address. */
4671 /* ??? This should perhaps be fixed elsewhere, for instance, in
4672 fixup_stack_1, by checking for other kinds of invalid addresses,
4673 e.g. a bare reference to a virtual register. This may confuse the
4674 alpha though, which must handle this case differently. */
4675 if (GET_CODE (operands[0]) == MEM
4676 && !memory_address_p (GET_MODE (operands[0]),
4677 XEXP (operands[0], 0)))
4679 = replace_equiv_address (operands[0],
4680 copy_to_reg (XEXP (operands[0], 0)));
4681 if (GET_CODE (operands[1]) == MEM
4682 && !memory_address_p (GET_MODE (operands[1]),
4683 XEXP (operands[1], 0)))
4685 = replace_equiv_address (operands[1],
4686 copy_to_reg (XEXP (operands[1], 0)));
4688 /* Handle loading a large integer during reload */
4689 else if (GET_CODE (operands[1]) == CONST_INT
4690 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4692 /* Writing a constant to memory needs a scratch, which should
4693 be handled with SECONDARY_RELOADs. */
4694 if (GET_CODE (operands[0]) != REG)
4697 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4698 emit_insn (gen_movsi (operands[0], operands[1]));
4706 (define_insn "*arm_movqi_insn"
4707 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4708 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4710 && ( register_operand (operands[0], QImode)
4711 || register_operand (operands[1], QImode))"
4717 [(set_attr "type" "*,*,load,store1")
4718 (set_attr "predicable" "yes")]
4721 (define_insn "*thumb_movqi_insn"
4722 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4723 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
4725 && ( register_operand (operands[0], QImode)
4726 || register_operand (operands[1], QImode))"
4734 [(set_attr "length" "2")
4735 (set_attr "type" "*,load,store1,*,*,*")
4736 (set_attr "pool_range" "*,32,*,*,*,*")]
4739 (define_expand "movsf"
4740 [(set (match_operand:SF 0 "general_operand" "")
4741 (match_operand:SF 1 "general_operand" ""))]
4746 if (GET_CODE (operands[0]) == MEM)
4747 operands[1] = force_reg (SFmode, operands[1]);
4749 else /* TARGET_THUMB */
4751 if (!no_new_pseudos)
4753 if (GET_CODE (operands[0]) != REG)
4754 operands[1] = force_reg (SFmode, operands[1]);
4761 [(set (match_operand:SF 0 "nonimmediate_operand" "")
4762 (match_operand:SF 1 "immediate_operand" ""))]
4764 && !TARGET_HARD_FLOAT
4766 && GET_CODE (operands[1]) == CONST_DOUBLE"
4767 [(set (match_dup 2) (match_dup 3))]
4769 operands[2] = gen_lowpart (SImode, operands[0]);
4770 operands[3] = gen_lowpart (SImode, operands[1]);
4771 if (operands[2] == 0 || operands[3] == 0)
4776 (define_insn "*arm_movsf_hard_insn"
4777 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
4778 (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
4780 && TARGET_HARD_FLOAT
4781 && (GET_CODE (operands[0]) != MEM
4782 || register_operand (operands[1], SFmode))"
4788 str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
4789 stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
4791 ldr%?\\t%0, %1\\t%@ float
4792 str%?\\t%1, %0\\t%@ float"
4793 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
4794 (set_attr "predicable" "yes")
4796 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
4797 (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
4798 (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
4801 ;; Exactly the same as above, except that all `f' cases are deleted.
4802 ;; This is necessary to prevent reload from ever trying to use a `f' reg
4803 ;; when -msoft-float.
4805 (define_insn "*arm_movsf_soft_insn"
4806 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4807 (match_operand:SF 1 "general_operand" "r,mE,r"))]
4810 && TARGET_SOFT_FLOAT
4811 && (GET_CODE (operands[0]) != MEM
4812 || register_operand (operands[1], SFmode))"
4815 ldr%?\\t%0, %1\\t%@ float
4816 str%?\\t%1, %0\\t%@ float"
4817 [(set_attr "length" "4,4,4")
4818 (set_attr "predicable" "yes")
4819 (set_attr "type" "*,load,store1")
4820 (set_attr "pool_range" "*,4096,*")
4821 (set_attr "neg_pool_range" "*,4084,*")]
4824 ;;; ??? This should have alternatives for constants.
4825 (define_insn "*thumb_movsf_insn"
4826 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4827 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
4829 && ( register_operand (operands[0], SFmode)
4830 || register_operand (operands[1], SFmode))"
4839 [(set_attr "length" "2")
4840 (set_attr "type" "*,load,store1,load,store1,*,*")
4841 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
4844 (define_expand "movdf"
4845 [(set (match_operand:DF 0 "general_operand" "")
4846 (match_operand:DF 1 "general_operand" ""))]
4851 if (GET_CODE (operands[0]) == MEM)
4852 operands[1] = force_reg (DFmode, operands[1]);
4854 else /* TARGET_THUMB */
4856 if (!no_new_pseudos)
4858 if (GET_CODE (operands[0]) != REG)
4859 operands[1] = force_reg (DFmode, operands[1]);
4865 ;; Reloading a df mode value stored in integer regs to memory can require a
4867 (define_expand "reload_outdf"
4868 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
4869 (match_operand:DF 1 "s_register_operand" "r")
4870 (match_operand:SI 2 "s_register_operand" "=&r")]
4874 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
4877 operands[2] = XEXP (operands[0], 0);
4878 else if (code == POST_INC || code == PRE_DEC)
4880 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
4881 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
4882 emit_insn (gen_movdi (operands[0], operands[1]));
4885 else if (code == PRE_INC)
4887 rtx reg = XEXP (XEXP (operands[0], 0), 0);
4889 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
4892 else if (code == POST_DEC)
4893 operands[2] = XEXP (XEXP (operands[0], 0), 0);
4895 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
4896 XEXP (XEXP (operands[0], 0), 1)));
4898 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
4901 if (code == POST_DEC)
4902 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
4908 (define_insn "*movdf_hard_insn"
4909 [(set (match_operand:DF 0 "nonimmediate_operand"
4910 "=r,Q,r,m,r, f, f,f, m,!f,!r")
4911 (match_operand:DF 1 "general_operand"
4912 "Q, r,r,r,mF,fG,H,mF,f,r, f"))]
4914 && TARGET_HARD_FLOAT
4915 && (GET_CODE (operands[0]) != MEM
4916 || register_operand (operands[1], DFmode))"
4919 switch (which_alternative)
4922 case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
4923 case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
4924 case 2: case 3: case 4: return output_move_double (operands);
4925 case 5: return \"mvf%?d\\t%0, %1\";
4926 case 6: return \"mnf%?d\\t%0, #%N1\";
4927 case 7: return \"ldf%?d\\t%0, %1\";
4928 case 8: return \"stf%?d\\t%1, %0\";
4929 case 9: return output_mov_double_fpu_from_arm (operands);
4930 case 10: return output_mov_double_arm_from_fpu (operands);
4934 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
4935 (set_attr "predicable" "yes")
4937 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
4938 (set_attr "pool_range" "*,*,*,*,1020,*,*,1024,*,*,*")
4939 (set_attr "neg_pool_range" "*,*,*,*,1008,*,*,1008,*,*,*")]
4942 ;; Software floating point version. This is essentially the same as movdi.
4943 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
4946 (define_insn "*movdf_soft_insn"
4947 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
4948 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
4949 "TARGET_ARM && TARGET_SOFT_FLOAT
4952 "* return output_move_double (operands);"
4953 [(set_attr "length" "8,8,8")
4954 (set_attr "type" "*,load,store2")
4955 (set_attr "pool_range" "1020")
4956 (set_attr "neg_pool_range" "1008")]
4959 ;;; ??? This should have alternatives for constants.
4960 ;;; ??? This was originally identical to the movdi_insn pattern.
4961 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
4962 ;;; thumb_reorg with a memory reference.
4963 (define_insn "*thumb_movdf_insn"
4964 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
4965 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
4967 && ( register_operand (operands[0], DFmode)
4968 || register_operand (operands[1], DFmode))"
4970 switch (which_alternative)
4974 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4975 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4976 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4978 return \"ldmia\\t%1, {%0, %H0}\";
4980 return \"stmia\\t%0, {%1, %H1}\";
4982 return thumb_load_double_from_address (operands);
4984 operands[2] = gen_rtx (MEM, SImode,
4985 plus_constant (XEXP (operands[0], 0), 4));
4986 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4989 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4990 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4991 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4994 [(set_attr "length" "4,2,2,6,4,4")
4995 (set_attr "type" "*,load,store2,load,store2,*")
4996 (set_attr "pool_range" "*,*,*,1020,*,*")]
5000 ;; Saving and restoring the floating point registers in the prologue should
5001 ;; be done in XFmode, even though we don't support that for anything else
5002 ;; (Well, strictly it's 'internal representation', but that's effectively
5005 (define_insn "*movxf_hard_insn"
5006 [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
5007 (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
5008 "TARGET_ARM && TARGET_HARD_FLOAT && reload_completed"
5010 switch (which_alternative)
5013 case 0: return \"mvf%?e\\t%0, %1\";
5014 case 1: return \"mnf%?e\\t%0, #%N1\";
5015 case 2: return \"ldf%?e\\t%0, %1\";
5016 case 3: return \"stf%?e\\t%1, %0\";
5017 case 4: return output_mov_long_double_fpu_from_arm (operands);
5018 case 5: return output_mov_long_double_arm_from_fpu (operands);
5019 case 6: return output_mov_long_double_arm_from_arm (operands);
5022 [(set_attr "length" "4,4,4,4,8,8,12")
5023 (set_attr "predicable" "yes")
5024 (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
5025 (set_attr "pool_range" "*,*,1024,*,*,*,*")
5026 (set_attr "neg_pool_range" "*,*,1004,*,*,*,*")]
5030 ;; load- and store-multiple insns
5031 ;; The arm can load/store any set of registers, provided that they are in
5032 ;; ascending order; but that is beyond GCC so stick with what it knows.
5034 (define_expand "load_multiple"
5035 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5036 (match_operand:SI 1 "" ""))
5037 (use (match_operand:SI 2 "" ""))])]
5040 /* Support only fixed point registers. */
5041 if (GET_CODE (operands[2]) != CONST_INT
5042 || INTVAL (operands[2]) > 14
5043 || INTVAL (operands[2]) < 2
5044 || GET_CODE (operands[1]) != MEM
5045 || GET_CODE (operands[0]) != REG
5046 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5047 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5051 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5052 force_reg (SImode, XEXP (operands[1], 0)),
5053 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5054 MEM_IN_STRUCT_P(operands[1]),
5055 MEM_SCALAR_P (operands[1]));
5059 ;; Load multiple with write-back
5061 (define_insn "*ldmsi_postinc4"
5062 [(match_parallel 0 "load_multiple_operation"
5063 [(set (match_operand:SI 1 "s_register_operand" "=r")
5064 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5066 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5067 (mem:SI (match_dup 2)))
5068 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5069 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5070 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5071 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5072 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5073 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5074 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5075 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5076 [(set_attr "type" "load")
5077 (set_attr "predicable" "yes")]
5080 (define_insn "*ldmsi_postinc3"
5081 [(match_parallel 0 "load_multiple_operation"
5082 [(set (match_operand:SI 1 "s_register_operand" "=r")
5083 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5085 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5086 (mem:SI (match_dup 2)))
5087 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5088 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5089 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5090 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5091 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5092 "ldm%?ia\\t%1!, {%3, %4, %5}"
5093 [(set_attr "type" "load")
5094 (set_attr "predicable" "yes")]
5097 (define_insn "*ldmsi_postinc2"
5098 [(match_parallel 0 "load_multiple_operation"
5099 [(set (match_operand:SI 1 "s_register_operand" "=r")
5100 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5102 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5103 (mem:SI (match_dup 2)))
5104 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5105 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5106 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5107 "ldm%?ia\\t%1!, {%3, %4}"
5108 [(set_attr "type" "load")
5109 (set_attr "predicable" "yes")]
5112 ;; Ordinary load multiple
5114 (define_insn "*ldmsi4"
5115 [(match_parallel 0 "load_multiple_operation"
5116 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5117 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5118 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5119 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5120 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5121 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5122 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5123 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5124 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5125 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5126 [(set_attr "type" "load")
5127 (set_attr "predicable" "yes")]
5130 (define_insn "*ldmsi3"
5131 [(match_parallel 0 "load_multiple_operation"
5132 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5133 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5134 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5135 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5136 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5137 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5138 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5139 "ldm%?ia\\t%1, {%2, %3, %4}"
5140 [(set_attr "type" "load")
5141 (set_attr "predicable" "yes")]
5144 (define_insn "*ldmsi2"
5145 [(match_parallel 0 "load_multiple_operation"
5146 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5147 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5148 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5149 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5150 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5151 "ldm%?ia\\t%1, {%2, %3}"
5152 [(set_attr "type" "load")
5153 (set_attr "predicable" "yes")]
5156 (define_expand "store_multiple"
5157 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5158 (match_operand:SI 1 "" ""))
5159 (use (match_operand:SI 2 "" ""))])]
5162 /* Support only fixed point registers */
5163 if (GET_CODE (operands[2]) != CONST_INT
5164 || INTVAL (operands[2]) > 14
5165 || INTVAL (operands[2]) < 2
5166 || GET_CODE (operands[1]) != REG
5167 || GET_CODE (operands[0]) != MEM
5168 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5169 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5173 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5174 force_reg (SImode, XEXP (operands[0], 0)),
5175 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5176 MEM_IN_STRUCT_P(operands[0]),
5177 MEM_SCALAR_P (operands[0]));
5181 ;; Store multiple with write-back
5183 (define_insn "*stmsi_postinc4"
5184 [(match_parallel 0 "store_multiple_operation"
5185 [(set (match_operand:SI 1 "s_register_operand" "=r")
5186 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5188 (set (mem:SI (match_dup 2))
5189 (match_operand:SI 3 "arm_hard_register_operand" ""))
5190 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5191 (match_operand:SI 4 "arm_hard_register_operand" ""))
5192 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5193 (match_operand:SI 5 "arm_hard_register_operand" ""))
5194 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5195 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5196 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5197 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5198 [(set_attr "predicable" "yes")
5199 (set_attr "type" "store4")]
5202 (define_insn "*stmsi_postinc3"
5203 [(match_parallel 0 "store_multiple_operation"
5204 [(set (match_operand:SI 1 "s_register_operand" "=r")
5205 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5207 (set (mem:SI (match_dup 2))
5208 (match_operand:SI 3 "arm_hard_register_operand" ""))
5209 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5210 (match_operand:SI 4 "arm_hard_register_operand" ""))
5211 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5212 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5213 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5214 "stm%?ia\\t%1!, {%3, %4, %5}"
5215 [(set_attr "predicable" "yes")
5216 (set_attr "type" "store3")]
5219 (define_insn "*stmsi_postinc2"
5220 [(match_parallel 0 "store_multiple_operation"
5221 [(set (match_operand:SI 1 "s_register_operand" "=r")
5222 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5224 (set (mem:SI (match_dup 2))
5225 (match_operand:SI 3 "arm_hard_register_operand" ""))
5226 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5227 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5228 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5229 "stm%?ia\\t%1!, {%3, %4}"
5230 [(set_attr "predicable" "yes")
5231 (set_attr "type" "store2")]
5234 ;; Ordinary store multiple
5236 (define_insn "*stmsi4"
5237 [(match_parallel 0 "store_multiple_operation"
5238 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5239 (match_operand:SI 2 "arm_hard_register_operand" ""))
5240 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5241 (match_operand:SI 3 "arm_hard_register_operand" ""))
5242 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5243 (match_operand:SI 4 "arm_hard_register_operand" ""))
5244 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5245 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5246 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5247 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5248 [(set_attr "predicable" "yes")
5249 (set_attr "type" "store4")]
5252 (define_insn "*stmsi3"
5253 [(match_parallel 0 "store_multiple_operation"
5254 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5255 (match_operand:SI 2 "arm_hard_register_operand" ""))
5256 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5257 (match_operand:SI 3 "arm_hard_register_operand" ""))
5258 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5259 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5260 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5261 "stm%?ia\\t%1, {%2, %3, %4}"
5262 [(set_attr "predicable" "yes")
5263 (set_attr "type" "store3")]
5266 (define_insn "*stmsi2"
5267 [(match_parallel 0 "store_multiple_operation"
5268 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5269 (match_operand:SI 2 "arm_hard_register_operand" ""))
5270 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5271 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5272 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5273 "stm%?ia\\t%1, {%2, %3}"
5274 [(set_attr "predicable" "yes")
5275 (set_attr "type" "store2")]
5278 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5279 ;; We could let this apply for blocks of less than this, but it clobbers so
5280 ;; many registers that there is then probably a better way.
5282 (define_expand "movstrqi"
5283 [(match_operand:BLK 0 "general_operand" "")
5284 (match_operand:BLK 1 "general_operand" "")
5285 (match_operand:SI 2 "const_int_operand" "")
5286 (match_operand:SI 3 "const_int_operand" "")]
5291 if (arm_gen_movstrqi (operands))
5295 else /* TARGET_THUMB */
5297 if ( INTVAL (operands[3]) != 4
5298 || INTVAL (operands[2]) > 48)
5301 thumb_expand_movstrqi (operands);
5307 ;; Thumb block-move insns
5309 (define_insn "movmem12b"
5310 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5311 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5312 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5313 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5314 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5315 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5316 (set (match_operand:SI 0 "register_operand" "=l")
5317 (plus:SI (match_dup 2) (const_int 12)))
5318 (set (match_operand:SI 1 "register_operand" "=l")
5319 (plus:SI (match_dup 3) (const_int 12)))
5320 (clobber (match_scratch:SI 4 "=&l"))
5321 (clobber (match_scratch:SI 5 "=&l"))
5322 (clobber (match_scratch:SI 6 "=&l"))]
5324 "* return thumb_output_move_mem_multiple (3, operands);"
5325 [(set_attr "length" "4")
5326 ; This isn't entirely accurate... It loads as well, but in terms of
5327 ; scheduling the following insn it is better to consider it as a store
5328 (set_attr "type" "store3")]
5331 (define_insn "movmem8b"
5332 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5333 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5334 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5335 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5336 (set (match_operand:SI 0 "register_operand" "=l")
5337 (plus:SI (match_dup 2) (const_int 8)))
5338 (set (match_operand:SI 1 "register_operand" "=l")
5339 (plus:SI (match_dup 3) (const_int 8)))
5340 (clobber (match_scratch:SI 4 "=&l"))
5341 (clobber (match_scratch:SI 5 "=&l"))]
5343 "* return thumb_output_move_mem_multiple (2, operands);"
5344 [(set_attr "length" "4")
5345 ; This isn't entirely accurate... It loads as well, but in terms of
5346 ; scheduling the following insn it is better to consider it as a store
5347 (set_attr "type" "store2")]
5352 ;; Compare & branch insns
5353 ;; The range calcualations are based as follows:
5354 ;; For forward branches, the address calculation returns the address of
5355 ;; the next instruction. This is 2 beyond the branch instruction.
5356 ;; For backward branches, the address calculation returns the address of
5357 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5358 ;; instruction for the shortest sequence, and 4 before the branch instruction
5359 ;; if we have to jump around an unconditional branch.
5360 ;; To the basic branch range the PC offset must be added (this is +4).
5361 ;; So for forward branches we have
5362 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5363 ;; And for backward branches we have
5364 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5366 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5367 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5369 (define_insn "cbranchsi4"
5372 (match_operator 0 "arm_comparison_operator"
5373 [(match_operand:SI 1 "register_operand" "l,r")
5374 (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5375 (label_ref (match_operand 3 "" ""))
5379 output_asm_insn (\"cmp\\t%1, %2\", operands);
5380 switch (get_attr_length (insn))
5382 case 4: return \"b%d0\\t%l3\";
5383 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5384 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5387 [(set (attr "far_jump")
5389 (eq_attr "length" "8")
5390 (const_string "yes")
5391 (const_string "no")))
5392 (set (attr "length")
5394 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5395 (le (minus (match_dup 3) (pc)) (const_int 256)))
5398 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5399 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5404 (define_insn "*negated_cbranchsi4"
5407 (match_operator 0 "arm_comparison_operator"
5408 [(match_operand:SI 1 "register_operand" "l")
5409 (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5410 (label_ref (match_operand 3 "" ""))
5414 output_asm_insn (\"cmn\\t%1, %2\", operands);
5415 switch (get_attr_length (insn))
5417 case 4: return \"b%d0\\t%l3\";
5418 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5419 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5422 [(set (attr "far_jump")
5424 (eq_attr "length" "8")
5425 (const_string "yes")
5426 (const_string "no")))
5427 (set (attr "length")
5429 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5430 (le (minus (match_dup 3) (pc)) (const_int 256)))
5433 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5434 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5440 ;; Comparison and test insns
5442 (define_expand "cmpsi"
5443 [(match_operand:SI 0 "s_register_operand" "")
5444 (match_operand:SI 1 "arm_add_operand" "")]
5447 arm_compare_op0 = operands[0];
5448 arm_compare_op1 = operands[1];
5453 (define_expand "cmpsf"
5454 [(match_operand:SF 0 "s_register_operand" "")
5455 (match_operand:SF 1 "fpu_rhs_operand" "")]
5456 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5458 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
5459 operands[1] = force_reg (SFmode, operands[1]);
5461 arm_compare_op0 = operands[0];
5462 arm_compare_op1 = operands[1];
5467 (define_expand "cmpdf"
5468 [(match_operand:DF 0 "s_register_operand" "")
5469 (match_operand:DF 1 "fpu_rhs_operand" "")]
5470 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5472 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
5473 operands[1] = force_reg (DFmode, operands[1]);
5475 arm_compare_op0 = operands[0];
5476 arm_compare_op1 = operands[1];
5481 (define_insn "*arm_cmpsi_insn"
5482 [(set (reg:CC CC_REGNUM)
5483 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5484 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
5489 [(set_attr "conds" "set")]
5492 (define_insn "*cmpsi_shiftsi"
5493 [(set (reg:CC CC_REGNUM)
5494 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5495 (match_operator:SI 3 "shift_operator"
5496 [(match_operand:SI 1 "s_register_operand" "r")
5497 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
5500 [(set_attr "conds" "set")
5501 (set_attr "shift" "1")
5505 (define_insn "*cmpsi_shiftsi_swp"
5506 [(set (reg:CC_SWP CC_REGNUM)
5507 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5508 [(match_operand:SI 1 "s_register_operand" "r")
5509 (match_operand:SI 2 "reg_or_int_operand" "rM")])
5510 (match_operand:SI 0 "s_register_operand" "r")))]
5513 [(set_attr "conds" "set")
5514 (set_attr "shift" "1")
5518 (define_insn "*cmpsi_neg_shiftsi"
5519 [(set (reg:CC CC_REGNUM)
5520 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5521 (neg:SI (match_operator:SI 3 "shift_operator"
5522 [(match_operand:SI 1 "s_register_operand" "r")
5523 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5526 [(set_attr "conds" "set")
5527 (set_attr "shift" "1")
5531 (define_insn "*cmpsf_insn"
5532 [(set (reg:CCFP CC_REGNUM)
5533 (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
5534 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5535 "TARGET_ARM && TARGET_HARD_FLOAT"
5539 [(set_attr "conds" "set")
5540 (set_attr "type" "f_2_r")]
5543 (define_insn "*cmpdf_insn"
5544 [(set (reg:CCFP CC_REGNUM)
5545 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
5546 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5547 "TARGET_ARM && TARGET_HARD_FLOAT"
5551 [(set_attr "conds" "set")
5552 (set_attr "type" "f_2_r")]
5555 (define_insn "*cmpesfdf_df"
5556 [(set (reg:CCFP CC_REGNUM)
5557 (compare:CCFP (float_extend:DF
5558 (match_operand:SF 0 "s_register_operand" "f,f"))
5559 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5560 "TARGET_ARM && TARGET_HARD_FLOAT"
5564 [(set_attr "conds" "set")
5565 (set_attr "type" "f_2_r")]
5568 (define_insn "*cmpdf_esfdf"
5569 [(set (reg:CCFP CC_REGNUM)
5570 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5572 (match_operand:SF 1 "s_register_operand" "f"))))]
5573 "TARGET_ARM && TARGET_HARD_FLOAT"
5575 [(set_attr "conds" "set")
5576 (set_attr "type" "f_2_r")]
5579 ;; There is no CCFPE or CCFP modes in the code below so we can have
5580 ;; one pattern to match either one. Besides, we're pretty sure we
5581 ;; have either CCFPE or CCFP because we made the patterns
5582 ;; (arm_gen_compare_reg).
5584 ;; Cirrus SF compare instruction
5585 (define_insn "*cirrus_cmpsf"
5586 [(set (reg:CCFP CC_REGNUM)
5587 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
5588 (match_operand:SF 1 "cirrus_fp_register" "v")))]
5589 "TARGET_ARM && TARGET_CIRRUS"
5590 "cfcmps%?\\tr15, %V0, %V1"
5591 [(set_attr "cirrus_type" "farith")
5592 (set_attr "cirrus" "compare")]
5595 ;; Cirrus DF compare instruction
5596 (define_insn "*cirrus_cmpdf"
5597 [(set (reg:CCFP CC_REGNUM)
5598 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
5599 (match_operand:DF 1 "cirrus_fp_register" "v")))]
5600 "TARGET_ARM && TARGET_CIRRUS"
5601 "cfcmpd%?\\tr15, %V0, %V1"
5602 [(set_attr "cirrus_type" "farith")
5603 (set_attr "cirrus" "compare")]
5606 ;; Cirrus DI compare instruction
5607 (define_expand "cmpdi"
5608 [(match_operand:DI 0 "cirrus_fp_register" "")
5609 (match_operand:DI 1 "cirrus_fp_register" "")]
5610 "TARGET_ARM && TARGET_CIRRUS"
5612 arm_compare_op0 = operands[0];
5613 arm_compare_op1 = operands[1];
5617 (define_insn "*cirrus_cmpdi"
5618 [(set (reg:CC CC_REGNUM)
5619 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
5620 (match_operand:DI 1 "cirrus_fp_register" "v")))]
5621 "TARGET_ARM && TARGET_CIRRUS"
5622 "cfcmp64%?\\tr15, %V0, %V1"
5623 [(set_attr "cirrus_type" "farith")
5624 (set_attr "cirrus" "compare")]
5627 ;; Cirrus SI compare instruction
5628 (define_insn "*cirrus_cmpsi_1"
5629 [(set (reg:CC CC_REGNUM)
5630 (compare:CC (match_operand:SI 0 "cirrus_fp_register" "v")
5631 (match_operand:SI 1 "cirrus_fp_register" "v")))]
5632 "TARGET_ARM && TARGET_CIRRUS && 0"
5633 "cfcmp32%?\\tr15, %V0, %V1"
5634 [(set_attr "cirrus_type" "farith")
5635 (set_attr "cirrus" "compare")]
5638 (define_insn "*cmpsf_trap"
5639 [(set (reg:CCFPE CC_REGNUM)
5640 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
5641 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5642 "TARGET_ARM && TARGET_HARD_FLOAT"
5646 [(set_attr "conds" "set")
5647 (set_attr "type" "f_2_r")]
5650 (define_insn "*cmpdf_trap"
5651 [(set (reg:CCFPE CC_REGNUM)
5652 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
5653 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5654 "TARGET_ARM && TARGET_HARD_FLOAT"
5658 [(set_attr "conds" "set")
5659 (set_attr "type" "f_2_r")]
5662 (define_insn "*cmp_esfdf_df_trap"
5663 [(set (reg:CCFPE CC_REGNUM)
5664 (compare:CCFPE (float_extend:DF
5665 (match_operand:SF 0 "s_register_operand" "f,f"))
5666 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5667 "TARGET_ARM && TARGET_HARD_FLOAT"
5671 [(set_attr "conds" "set")
5672 (set_attr "type" "f_2_r")]
5675 (define_insn "*cmp_df_esfdf_trap"
5676 [(set (reg:CCFPE CC_REGNUM)
5677 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
5679 (match_operand:SF 1 "s_register_operand" "f"))))]
5680 "TARGET_ARM && TARGET_HARD_FLOAT"
5682 [(set_attr "conds" "set")
5683 (set_attr "type" "f_2_r")]
5686 ; This insn allows redundant compares to be removed by cse, nothing should
5687 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5688 ; is deleted later on. The match_dup will match the mode here, so that
5689 ; mode changes of the condition codes aren't lost by this even though we don't
5690 ; specify what they are.
5692 (define_insn "*deleted_compare"
5693 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5695 "\\t%@ deleted compare"
5696 [(set_attr "conds" "set")
5697 (set_attr "length" "0")]
5701 ;; Conditional branch insns
5703 (define_expand "beq"
5705 (if_then_else (eq (match_dup 1) (const_int 0))
5706 (label_ref (match_operand 0 "" ""))
5709 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5712 (define_expand "bne"
5714 (if_then_else (ne (match_dup 1) (const_int 0))
5715 (label_ref (match_operand 0 "" ""))
5718 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5721 (define_expand "bgt"
5723 (if_then_else (gt (match_dup 1) (const_int 0))
5724 (label_ref (match_operand 0 "" ""))
5727 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5730 (define_expand "ble"
5732 (if_then_else (le (match_dup 1) (const_int 0))
5733 (label_ref (match_operand 0 "" ""))
5736 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5739 (define_expand "bge"
5741 (if_then_else (ge (match_dup 1) (const_int 0))
5742 (label_ref (match_operand 0 "" ""))
5745 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5748 (define_expand "blt"
5750 (if_then_else (lt (match_dup 1) (const_int 0))
5751 (label_ref (match_operand 0 "" ""))
5754 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5757 (define_expand "bgtu"
5759 (if_then_else (gtu (match_dup 1) (const_int 0))
5760 (label_ref (match_operand 0 "" ""))
5763 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5766 (define_expand "bleu"
5768 (if_then_else (leu (match_dup 1) (const_int 0))
5769 (label_ref (match_operand 0 "" ""))
5772 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5775 (define_expand "bgeu"
5777 (if_then_else (geu (match_dup 1) (const_int 0))
5778 (label_ref (match_operand 0 "" ""))
5781 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5784 (define_expand "bltu"
5786 (if_then_else (ltu (match_dup 1) (const_int 0))
5787 (label_ref (match_operand 0 "" ""))
5790 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5793 (define_expand "bunordered"
5795 (if_then_else (unordered (match_dup 1) (const_int 0))
5796 (label_ref (match_operand 0 "" ""))
5798 "TARGET_ARM && TARGET_HARD_FLOAT"
5799 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5803 (define_expand "bordered"
5805 (if_then_else (ordered (match_dup 1) (const_int 0))
5806 (label_ref (match_operand 0 "" ""))
5808 "TARGET_ARM && TARGET_HARD_FLOAT"
5809 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5813 (define_expand "bungt"
5815 (if_then_else (ungt (match_dup 1) (const_int 0))
5816 (label_ref (match_operand 0 "" ""))
5818 "TARGET_ARM && TARGET_HARD_FLOAT"
5819 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5822 (define_expand "bunlt"
5824 (if_then_else (unlt (match_dup 1) (const_int 0))
5825 (label_ref (match_operand 0 "" ""))
5827 "TARGET_ARM && TARGET_HARD_FLOAT"
5828 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5831 (define_expand "bunge"
5833 (if_then_else (unge (match_dup 1) (const_int 0))
5834 (label_ref (match_operand 0 "" ""))
5836 "TARGET_ARM && TARGET_HARD_FLOAT"
5837 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5840 (define_expand "bunle"
5842 (if_then_else (unle (match_dup 1) (const_int 0))
5843 (label_ref (match_operand 0 "" ""))
5845 "TARGET_ARM && TARGET_HARD_FLOAT"
5846 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5849 ;; The following two patterns need two branch instructions, since there is
5850 ;; no single instruction that will handle all cases.
5851 (define_expand "buneq"
5853 (if_then_else (uneq (match_dup 1) (const_int 0))
5854 (label_ref (match_operand 0 "" ""))
5856 "TARGET_ARM && TARGET_HARD_FLOAT"
5857 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
5860 (define_expand "bltgt"
5862 (if_then_else (ltgt (match_dup 1) (const_int 0))
5863 (label_ref (match_operand 0 "" ""))
5865 "TARGET_ARM && TARGET_HARD_FLOAT"
5866 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
5870 ;; Patterns to match conditional branch insns.
5873 ; Special pattern to match UNEQ.
5874 (define_insn "*arm_buneq"
5876 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5877 (label_ref (match_operand 0 "" ""))
5879 "TARGET_ARM && TARGET_HARD_FLOAT"
5881 if (arm_ccfsm_state != 0)
5884 return \"bvs\\t%l0\;beq\\t%l0\";
5886 [(set_attr "conds" "jump_clob")
5887 (set_attr "length" "8")]
5890 ; Special pattern to match LTGT.
5891 (define_insn "*arm_bltgt"
5893 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5894 (label_ref (match_operand 0 "" ""))
5896 "TARGET_ARM && TARGET_HARD_FLOAT"
5898 if (arm_ccfsm_state != 0)
5901 return \"bmi\\t%l0\;bgt\\t%l0\";
5903 [(set_attr "conds" "jump_clob")
5904 (set_attr "length" "8")]
5907 (define_insn "*arm_cond_branch"
5909 (if_then_else (match_operator 1 "arm_comparison_operator"
5910 [(match_operand 2 "cc_register" "") (const_int 0)])
5911 (label_ref (match_operand 0 "" ""))
5915 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5917 arm_ccfsm_state += 2;
5920 return \"b%d1\\t%l0\";
5922 [(set_attr "conds" "use")]
5925 ; Special pattern to match reversed UNEQ.
5926 (define_insn "*arm_buneq_reversed"
5928 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5930 (label_ref (match_operand 0 "" ""))))]
5931 "TARGET_ARM && TARGET_HARD_FLOAT"
5933 if (arm_ccfsm_state != 0)
5936 return \"bmi\\t%l0\;bgt\\t%l0\";
5938 [(set_attr "conds" "jump_clob")
5939 (set_attr "length" "8")]
5942 ; Special pattern to match reversed LTGT.
5943 (define_insn "*arm_bltgt_reversed"
5945 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5947 (label_ref (match_operand 0 "" ""))))]
5948 "TARGET_ARM && TARGET_HARD_FLOAT"
5950 if (arm_ccfsm_state != 0)
5953 return \"bvs\\t%l0\;beq\\t%l0\";
5955 [(set_attr "conds" "jump_clob")
5956 (set_attr "length" "8")]
5959 (define_insn "*arm_cond_branch_reversed"
5961 (if_then_else (match_operator 1 "arm_comparison_operator"
5962 [(match_operand 2 "cc_register" "") (const_int 0)])
5964 (label_ref (match_operand 0 "" ""))))]
5967 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5969 arm_ccfsm_state += 2;
5972 return \"b%D1\\t%l0\";
5974 [(set_attr "conds" "use")]
5981 (define_expand "seq"
5982 [(set (match_operand:SI 0 "s_register_operand" "=r")
5983 (eq:SI (match_dup 1) (const_int 0)))]
5985 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5988 (define_expand "sne"
5989 [(set (match_operand:SI 0 "s_register_operand" "=r")
5990 (ne:SI (match_dup 1) (const_int 0)))]
5992 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5995 (define_expand "sgt"
5996 [(set (match_operand:SI 0 "s_register_operand" "=r")
5997 (gt:SI (match_dup 1) (const_int 0)))]
5999 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6002 (define_expand "sle"
6003 [(set (match_operand:SI 0 "s_register_operand" "=r")
6004 (le:SI (match_dup 1) (const_int 0)))]
6006 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6009 (define_expand "sge"
6010 [(set (match_operand:SI 0 "s_register_operand" "=r")
6011 (ge:SI (match_dup 1) (const_int 0)))]
6013 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6016 (define_expand "slt"
6017 [(set (match_operand:SI 0 "s_register_operand" "=r")
6018 (lt:SI (match_dup 1) (const_int 0)))]
6020 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6023 (define_expand "sgtu"
6024 [(set (match_operand:SI 0 "s_register_operand" "=r")
6025 (gtu:SI (match_dup 1) (const_int 0)))]
6027 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6030 (define_expand "sleu"
6031 [(set (match_operand:SI 0 "s_register_operand" "=r")
6032 (leu:SI (match_dup 1) (const_int 0)))]
6034 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6037 (define_expand "sgeu"
6038 [(set (match_operand:SI 0 "s_register_operand" "=r")
6039 (geu:SI (match_dup 1) (const_int 0)))]
6041 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6044 (define_expand "sltu"
6045 [(set (match_operand:SI 0 "s_register_operand" "=r")
6046 (ltu:SI (match_dup 1) (const_int 0)))]
6048 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6051 (define_expand "sunordered"
6052 [(set (match_operand:SI 0 "s_register_operand" "=r")
6053 (unordered:SI (match_dup 1) (const_int 0)))]
6054 "TARGET_ARM && TARGET_HARD_FLOAT"
6055 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6059 (define_expand "sordered"
6060 [(set (match_operand:SI 0 "s_register_operand" "=r")
6061 (ordered:SI (match_dup 1) (const_int 0)))]
6062 "TARGET_ARM && TARGET_HARD_FLOAT"
6063 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6067 (define_expand "sungt"
6068 [(set (match_operand:SI 0 "s_register_operand" "=r")
6069 (ungt:SI (match_dup 1) (const_int 0)))]
6070 "TARGET_ARM && TARGET_HARD_FLOAT"
6071 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6075 (define_expand "sunge"
6076 [(set (match_operand:SI 0 "s_register_operand" "=r")
6077 (unge:SI (match_dup 1) (const_int 0)))]
6078 "TARGET_ARM && TARGET_HARD_FLOAT"
6079 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6083 (define_expand "sunlt"
6084 [(set (match_operand:SI 0 "s_register_operand" "=r")
6085 (unlt:SI (match_dup 1) (const_int 0)))]
6086 "TARGET_ARM && TARGET_HARD_FLOAT"
6087 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6091 (define_expand "sunle"
6092 [(set (match_operand:SI 0 "s_register_operand" "=r")
6093 (unle:SI (match_dup 1) (const_int 0)))]
6094 "TARGET_ARM && TARGET_HARD_FLOAT"
6095 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6099 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6100 ;;; simple ARM instructions.
6102 ; (define_expand "suneq"
6103 ; [(set (match_operand:SI 0 "s_register_operand" "=r")
6104 ; (uneq:SI (match_dup 1) (const_int 0)))]
6105 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6109 ; (define_expand "sltgt"
6110 ; [(set (match_operand:SI 0 "s_register_operand" "=r")
6111 ; (ltgt:SI (match_dup 1) (const_int 0)))]
6112 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6116 (define_insn "*mov_scc"
6117 [(set (match_operand:SI 0 "s_register_operand" "=r")
6118 (match_operator:SI 1 "arm_comparison_operator"
6119 [(match_operand 2 "cc_register" "") (const_int 0)]))]
6121 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6122 [(set_attr "conds" "use")
6123 (set_attr "length" "8")]
6126 (define_insn "*mov_negscc"
6127 [(set (match_operand:SI 0 "s_register_operand" "=r")
6128 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
6129 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6131 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6132 [(set_attr "conds" "use")
6133 (set_attr "length" "8")]
6136 (define_insn "*mov_notscc"
6137 [(set (match_operand:SI 0 "s_register_operand" "=r")
6138 (not:SI (match_operator:SI 1 "arm_comparison_operator"
6139 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6141 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6142 [(set_attr "conds" "use")
6143 (set_attr "length" "8")]
6147 ;; Conditional move insns
6149 (define_expand "movsicc"
6150 [(set (match_operand:SI 0 "s_register_operand" "")
6151 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6152 (match_operand:SI 2 "arm_not_operand" "")
6153 (match_operand:SI 3 "arm_not_operand" "")))]
6157 enum rtx_code code = GET_CODE (operands[1]);
6160 if (code == UNEQ || code == LTGT)
6163 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6164 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6168 (define_expand "movsfcc"
6169 [(set (match_operand:SF 0 "s_register_operand" "")
6170 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6171 (match_operand:SF 2 "s_register_operand" "")
6172 (match_operand:SF 3 "nonmemory_operand" "")))]
6176 enum rtx_code code = GET_CODE (operands[1]);
6179 if (code == UNEQ || code == LTGT)
6182 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
6183 Otherwise, ensure it is a valid FP add operand */
6184 if ((!TARGET_HARD_FLOAT)
6185 || (!fpu_add_operand (operands[3], SFmode)))
6186 operands[3] = force_reg (SFmode, operands[3]);
6188 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6189 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6193 (define_expand "movdfcc"
6194 [(set (match_operand:DF 0 "s_register_operand" "")
6195 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6196 (match_operand:DF 2 "s_register_operand" "")
6197 (match_operand:DF 3 "fpu_add_operand" "")))]
6198 "TARGET_ARM && TARGET_HARD_FLOAT"
6201 enum rtx_code code = GET_CODE (operands[1]);
6204 if (code == UNEQ || code == LTGT)
6207 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6208 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6212 (define_insn "*movsicc_insn"
6213 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6215 (match_operator 3 "arm_comparison_operator"
6216 [(match_operand 4 "cc_register" "") (const_int 0)])
6217 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6218 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6225 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6226 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6227 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6228 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6229 [(set_attr "length" "4,4,4,4,8,8,8,8")
6230 (set_attr "conds" "use")]
6233 (define_insn "*movsfcc_hard_insn"
6234 [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6236 (match_operator 3 "arm_comparison_operator"
6237 [(match_operand 4 "cc_register" "") (const_int 0)])
6238 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6239 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6240 "TARGET_ARM && TARGET_HARD_FLOAT"
6246 mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
6247 mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
6248 mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
6249 mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
6250 [(set_attr "length" "4,4,4,4,8,8,8,8")
6251 (set_attr "type" "ffarith")
6252 (set_attr "conds" "use")]
6255 (define_insn "*movsfcc_soft_insn"
6256 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6257 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
6258 [(match_operand 4 "cc_register" "") (const_int 0)])
6259 (match_operand:SF 1 "s_register_operand" "0,r")
6260 (match_operand:SF 2 "s_register_operand" "r,0")))]
6261 "TARGET_ARM && TARGET_SOFT_FLOAT"
6265 [(set_attr "conds" "use")]
6268 (define_insn "*movdfcc_insn"
6269 [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6271 (match_operator 3 "arm_comparison_operator"
6272 [(match_operand 4 "cc_register" "") (const_int 0)])
6273 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6274 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6275 "TARGET_ARM && TARGET_HARD_FLOAT"
6281 mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
6282 mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
6283 mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
6284 mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
6285 [(set_attr "length" "4,4,4,4,8,8,8,8")
6286 (set_attr "type" "ffarith")
6287 (set_attr "conds" "use")]
6291 ;; Jump and linkage insns
6293 (define_expand "jump"
6295 (label_ref (match_operand 0 "" "")))]
6300 (define_insn "*arm_jump"
6302 (label_ref (match_operand 0 "" "")))]
6306 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6308 arm_ccfsm_state += 2;
6311 return \"b%?\\t%l0\";
6314 [(set_attr "predicable" "yes")]
6317 (define_insn "*thumb_jump"
6319 (label_ref (match_operand 0 "" "")))]
6322 if (get_attr_length (insn) == 2)
6324 return \"bl\\t%l0\\t%@ far jump\";
6326 [(set (attr "far_jump")
6328 (eq_attr "length" "4")
6329 (const_string "yes")
6330 (const_string "no")))
6331 (set (attr "length")
6333 (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6334 (le (minus (match_dup 0) (pc)) (const_int 2044)))
6339 (define_expand "call"
6340 [(parallel [(call (match_operand 0 "memory_operand" "")
6341 (match_operand 1 "general_operand" ""))
6342 (use (match_operand 2 "" ""))
6343 (clobber (reg:SI LR_REGNUM))])]
6349 /* In an untyped call, we can get NULL for operand 2. */
6350 if (operands[2] == NULL_RTX)
6351 operands[2] = const0_rtx;
6353 /* This is to decide if we should generate indirect calls by loading the
6354 32 bit address of the callee into a register before performing the
6355 branch and link. operand[2] encodes the long_call/short_call
6356 attribute of the function being called. This attribute is set whenever
6357 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6358 is used, and the short_call attribute can also be set if function is
6359 declared as static or if it has already been defined in the current
6360 compilation unit. See arm.c and arm.h for info about this. The third
6361 parameter to arm_is_longcall_p is used to tell it which pattern
6363 callee = XEXP (operands[0], 0);
6365 if (GET_CODE (callee) != REG
6366 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6367 XEXP (operands[0], 0) = force_reg (Pmode, callee);
6371 (define_insn "*call_reg"
6372 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
6373 (match_operand 1 "" ""))
6374 (use (match_operand 2 "" ""))
6375 (clobber (reg:SI LR_REGNUM))]
6378 return output_call (operands);
6380 ;; length is worst case, normally it is only two
6381 [(set_attr "length" "12")
6382 (set_attr "type" "call")]
6385 (define_insn "*call_mem"
6386 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
6387 (match_operand 1 "" ""))
6388 (use (match_operand 2 "" ""))
6389 (clobber (reg:SI LR_REGNUM))]
6392 return output_call_mem (operands);
6394 [(set_attr "length" "12")
6395 (set_attr "type" "call")]
6398 (define_insn "*call_indirect"
6399 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6400 (match_operand 1 "" ""))
6401 (use (match_operand 2 "" ""))
6402 (clobber (reg:SI LR_REGNUM))]
6406 if (TARGET_CALLER_INTERWORKING)
6407 return \"bl\\t%__interwork_call_via_%0\";
6409 return \"bl\\t%__call_via_%0\";
6411 [(set_attr "type" "call")]
6414 (define_insn "*call_value_indirect"
6415 [(set (match_operand 0 "" "=l")
6416 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6417 (match_operand 2 "" "")))
6418 (use (match_operand 3 "" ""))
6419 (clobber (reg:SI LR_REGNUM))]
6423 if (TARGET_CALLER_INTERWORKING)
6424 return \"bl\\t%__interwork_call_via_%1\";
6426 return \"bl\\t%__call_via_%1\";
6428 [(set_attr "type" "call")]
6431 (define_expand "call_value"
6432 [(parallel [(set (match_operand 0 "" "")
6433 (call (match_operand 1 "memory_operand" "")
6434 (match_operand 2 "general_operand" "")))
6435 (use (match_operand 3 "" ""))
6436 (clobber (reg:SI LR_REGNUM))])]
6440 rtx callee = XEXP (operands[1], 0);
6442 /* In an untyped call, we can get NULL for operand 2. */
6443 if (operands[3] == 0)
6444 operands[3] = const0_rtx;
6446 /* See the comment in define_expand \"call\". */
6447 if (GET_CODE (callee) != REG
6448 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6449 XEXP (operands[1], 0) = force_reg (Pmode, callee);
6453 (define_insn "*call_value_reg"
6454 [(set (match_operand 0 "" "=r,f,v")
6455 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r,r"))
6456 (match_operand 2 "" "")))
6457 (use (match_operand 3 "" ""))
6458 (clobber (reg:SI LR_REGNUM))]
6461 return output_call (&operands[1]);
6463 [(set_attr "length" "12")
6464 (set_attr "type" "call")]
6467 (define_insn "*call_value_mem"
6468 [(set (match_operand 0 "" "=r,f,v")
6469 (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m,m"))
6470 (match_operand 2 "" "")))
6471 (use (match_operand 3 "" ""))
6472 (clobber (reg:SI LR_REGNUM))]
6473 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6475 return output_call_mem (&operands[1]);
6477 [(set_attr "length" "12")
6478 (set_attr "type" "call")]
6481 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6482 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6484 (define_insn "*call_symbol"
6485 [(call (mem:SI (match_operand:SI 0 "" "X"))
6486 (match_operand 1 "" ""))
6487 (use (match_operand 2 "" ""))
6488 (clobber (reg:SI LR_REGNUM))]
6490 && (GET_CODE (operands[0]) == SYMBOL_REF)
6491 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6494 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6496 [(set_attr "type" "call")]
6499 (define_insn "*call_value_symbol"
6500 [(set (match_operand 0 "s_register_operand" "=r,f,v")
6501 (call (mem:SI (match_operand:SI 1 "" "X,X,X"))
6502 (match_operand:SI 2 "" "")))
6503 (use (match_operand 3 "" ""))
6504 (clobber (reg:SI LR_REGNUM))]
6506 && (GET_CODE (operands[1]) == SYMBOL_REF)
6507 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6510 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6512 [(set_attr "type" "call")]
6515 (define_insn "*call_insn"
6516 [(call (mem:SI (match_operand:SI 0 "" "X"))
6517 (match_operand:SI 1 "" ""))
6518 (use (match_operand 2 "" ""))
6519 (clobber (reg:SI LR_REGNUM))]
6521 && GET_CODE (operands[0]) == SYMBOL_REF
6522 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6524 [(set_attr "length" "4")
6525 (set_attr "type" "call")]
6528 (define_insn "*call_value_insn"
6529 [(set (match_operand 0 "register_operand" "=l")
6530 (call (mem:SI (match_operand 1 "" "X"))
6531 (match_operand 2 "" "")))
6532 (use (match_operand 3 "" ""))
6533 (clobber (reg:SI LR_REGNUM))]
6535 && GET_CODE (operands[1]) == SYMBOL_REF
6536 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6538 [(set_attr "length" "4")
6539 (set_attr "type" "call")]
6542 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6543 (define_expand "sibcall"
6544 [(parallel [(call (match_operand 0 "memory_operand" "")
6545 (match_operand 1 "general_operand" ""))
6547 (use (match_operand 2 "" ""))])]
6551 if (operands[2] == NULL_RTX)
6552 operands[2] = const0_rtx;
6556 (define_expand "sibcall_value"
6557 [(parallel [(set (match_operand 0 "register_operand" "")
6558 (call (match_operand 1 "memory_operand" "")
6559 (match_operand 2 "general_operand" "")))
6561 (use (match_operand 3 "" ""))])]
6565 if (operands[3] == NULL_RTX)
6566 operands[3] = const0_rtx;
6570 (define_insn "*sibcall_insn"
6571 [(call (mem:SI (match_operand:SI 0 "" "X"))
6572 (match_operand 1 "" ""))
6574 (use (match_operand 2 "" ""))]
6575 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6577 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6579 [(set_attr "type" "call")]
6582 (define_insn "*sibcall_value_insn"
6583 [(set (match_operand 0 "s_register_operand" "=r,f,v")
6584 (call (mem:SI (match_operand:SI 1 "" "X,X,X"))
6585 (match_operand 2 "" "")))
6587 (use (match_operand 3 "" ""))]
6588 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6590 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6592 [(set_attr "type" "call")]
6595 ;; Often the return insn will be the same as loading from memory, so set attr
6596 (define_insn "return"
6598 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6601 if (arm_ccfsm_state == 2)
6603 arm_ccfsm_state += 2;
6606 return output_return_instruction (const_true_rtx, TRUE, FALSE);
6608 [(set_attr "type" "load")
6609 (set_attr "predicable" "yes")]
6612 (define_insn "*cond_return"
6614 (if_then_else (match_operator 0 "arm_comparison_operator"
6615 [(match_operand 1 "cc_register" "") (const_int 0)])
6618 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6621 if (arm_ccfsm_state == 2)
6623 arm_ccfsm_state += 2;
6626 return output_return_instruction (operands[0], TRUE, FALSE);
6628 [(set_attr "conds" "use")
6629 (set_attr "type" "load")]
6632 (define_insn "*cond_return_inverted"
6634 (if_then_else (match_operator 0 "arm_comparison_operator"
6635 [(match_operand 1 "cc_register" "") (const_int 0)])
6638 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6641 if (arm_ccfsm_state == 2)
6643 arm_ccfsm_state += 2;
6646 return output_return_instruction (operands[0], TRUE, TRUE);
6648 [(set_attr "conds" "use")
6649 (set_attr "type" "load")]
6652 ;; Generate a sequence of instructions to determine if the processor is
6653 ;; in 26-bit or 32-bit mode, and return the appropriate return address
6656 (define_expand "return_addr_mask"
6658 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6660 (set (match_operand:SI 0 "s_register_operand" "")
6661 (if_then_else:SI (eq (match_dup 1) (const_int 0))
6663 (const_int 67108860)))] ; 0x03fffffc
6666 operands[1] = gen_rtx_REG (CC_NOOVmode, 24);
6669 (define_insn "*check_arch2"
6670 [(set (match_operand:CC_NOOV 0 "cc_register" "")
6671 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6674 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
6675 [(set_attr "length" "8")
6676 (set_attr "conds" "set")]
6679 ;; Call subroutine returning any type.
6681 (define_expand "untyped_call"
6682 [(parallel [(call (match_operand 0 "" "")
6684 (match_operand 1 "" "")
6685 (match_operand 2 "" "")])]
6691 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6693 for (i = 0; i < XVECLEN (operands[2], 0); i++)
6695 rtx set = XVECEXP (operands[2], 0, i);
6697 emit_move_insn (SET_DEST (set), SET_SRC (set));
6700 /* The optimizer does not know that the call sets the function value
6701 registers we stored in the result block. We avoid problems by
6702 claiming that all hard registers are used and clobbered at this
6704 emit_insn (gen_blockage ());
6710 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6711 ;; all of memory. This blocks insns from being moved across this point.
6713 (define_insn "blockage"
6714 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6717 [(set_attr "length" "0")
6718 (set_attr "type" "block")]
6721 (define_expand "casesi"
6722 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6723 (match_operand:SI 1 "const_int_operand" "") ; lower bound
6724 (match_operand:SI 2 "const_int_operand" "") ; total range
6725 (match_operand:SI 3 "" "") ; table label
6726 (match_operand:SI 4 "" "")] ; Out of range label
6731 if (operands[1] != const0_rtx)
6733 reg = gen_reg_rtx (SImode);
6735 emit_insn (gen_addsi3 (reg, operands[0],
6736 GEN_INT (-INTVAL (operands[1]))));
6740 if (!const_ok_for_arm (INTVAL (operands[2])))
6741 operands[2] = force_reg (SImode, operands[2]);
6743 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6749 ;; The USE in this pattern is needed to tell flow analysis that this is
6750 ;; a CASESI insn. It has no other purpose.
6751 (define_insn "casesi_internal"
6752 [(parallel [(set (pc)
6754 (leu (match_operand:SI 0 "s_register_operand" "r")
6755 (match_operand:SI 1 "arm_rhs_operand" "rI"))
6756 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6757 (label_ref (match_operand 2 "" ""))))
6758 (label_ref (match_operand 3 "" ""))))
6759 (clobber (reg:CC CC_REGNUM))
6760 (use (label_ref (match_dup 2)))])]
6764 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6765 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6767 [(set_attr "conds" "clob")
6768 (set_attr "length" "12")]
6771 (define_expand "indirect_jump"
6773 (match_operand:SI 0 "s_register_operand" ""))]
6778 (define_insn "*arm_indirect_jump"
6780 (match_operand:SI 0 "s_register_operand" "r"))]
6782 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6783 [(set_attr "predicable" "yes")]
6786 ;; Although not supported by the define_expand above,
6787 ;; cse/combine may generate this form.
6788 (define_insn "*load_indirect_jump"
6790 (match_operand:SI 0 "memory_operand" "m"))]
6792 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6793 [(set_attr "type" "load")
6794 (set_attr "pool_range" "4096")
6795 (set_attr "neg_pool_range" "4084")
6796 (set_attr "predicable" "yes")]
6799 (define_insn "*thumb_indirect_jump"
6801 (match_operand:SI 0 "register_operand" "l*r"))]
6804 [(set_attr "conds" "clob")
6805 (set_attr "length" "2")]
6816 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6817 return \"mov\\tr8, r8\";
6819 [(set (attr "length")
6820 (if_then_else (eq_attr "is_thumb" "yes")
6826 ;; Patterns to allow combination of arithmetic, cond code and shifts
6828 (define_insn "*arith_shiftsi"
6829 [(set (match_operand:SI 0 "s_register_operand" "=r")
6830 (match_operator:SI 1 "shiftable_operator"
6831 [(match_operator:SI 3 "shift_operator"
6832 [(match_operand:SI 4 "s_register_operand" "r")
6833 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6834 (match_operand:SI 2 "s_register_operand" "r")]))]
6836 "%i1%?\\t%0, %2, %4%S3"
6837 [(set_attr "predicable" "yes")
6838 (set_attr "shift" "4")
6842 (define_insn "*arith_shiftsi_compare0"
6843 [(set (reg:CC_NOOV CC_REGNUM)
6844 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6845 [(match_operator:SI 3 "shift_operator"
6846 [(match_operand:SI 4 "s_register_operand" "r")
6847 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6848 (match_operand:SI 2 "s_register_operand" "r")])
6850 (set (match_operand:SI 0 "s_register_operand" "=r")
6851 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6854 "%i1%?s\\t%0, %2, %4%S3"
6855 [(set_attr "conds" "set")
6856 (set_attr "shift" "4")
6860 (define_insn "*arith_shiftsi_compare0_scratch"
6861 [(set (reg:CC_NOOV CC_REGNUM)
6862 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6863 [(match_operator:SI 3 "shift_operator"
6864 [(match_operand:SI 4 "s_register_operand" "r")
6865 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6866 (match_operand:SI 2 "s_register_operand" "r")])
6868 (clobber (match_scratch:SI 0 "=r"))]
6870 "%i1%?s\\t%0, %2, %4%S3"
6871 [(set_attr "conds" "set")
6872 (set_attr "shift" "4")
6876 (define_insn "*sub_shiftsi"
6877 [(set (match_operand:SI 0 "s_register_operand" "=r")
6878 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6879 (match_operator:SI 2 "shift_operator"
6880 [(match_operand:SI 3 "s_register_operand" "r")
6881 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
6883 "sub%?\\t%0, %1, %3%S2"
6884 [(set_attr "predicable" "yes")
6885 (set_attr "shift" "3")
6889 (define_insn "*sub_shiftsi_compare0"
6890 [(set (reg:CC_NOOV CC_REGNUM)
6892 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6893 (match_operator:SI 2 "shift_operator"
6894 [(match_operand:SI 3 "s_register_operand" "r")
6895 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6897 (set (match_operand:SI 0 "s_register_operand" "=r")
6898 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6901 "sub%?s\\t%0, %1, %3%S2"
6902 [(set_attr "conds" "set")
6903 (set_attr "shift" "3")
6907 (define_insn "*sub_shiftsi_compare0_scratch"
6908 [(set (reg:CC_NOOV CC_REGNUM)
6910 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6911 (match_operator:SI 2 "shift_operator"
6912 [(match_operand:SI 3 "s_register_operand" "r")
6913 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6915 (clobber (match_scratch:SI 0 "=r"))]
6917 "sub%?s\\t%0, %1, %3%S2"
6918 [(set_attr "conds" "set")
6919 (set_attr "shift" "3")
6925 (define_insn "*and_scc"
6926 [(set (match_operand:SI 0 "s_register_operand" "=r")
6927 (and:SI (match_operator:SI 1 "arm_comparison_operator"
6928 [(match_operand 3 "cc_register" "") (const_int 0)])
6929 (match_operand:SI 2 "s_register_operand" "r")))]
6931 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
6932 [(set_attr "conds" "use")
6933 (set_attr "length" "8")]
6936 (define_insn "*ior_scc"
6937 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6938 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
6939 [(match_operand 3 "cc_register" "") (const_int 0)])
6940 (match_operand:SI 1 "s_register_operand" "0,?r")))]
6944 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
6945 [(set_attr "conds" "use")
6946 (set_attr "length" "4,8")]
6949 (define_insn "*compare_scc"
6950 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6951 (match_operator:SI 1 "arm_comparison_operator"
6952 [(match_operand:SI 2 "s_register_operand" "r,r")
6953 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
6954 (clobber (reg:CC CC_REGNUM))]
6957 if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
6958 return \"mov\\t%0, %2, lsr #31\";
6960 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
6961 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
6963 if (GET_CODE (operands[1]) == NE)
6965 if (which_alternative == 1)
6966 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
6967 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
6969 if (which_alternative == 1)
6970 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
6972 output_asm_insn (\"cmp\\t%2, %3\", operands);
6973 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
6975 [(set_attr "conds" "clob")
6976 (set_attr "length" "12")]
6979 (define_insn "*cond_move"
6980 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
6981 (if_then_else:SI (match_operator 3 "equality_operator"
6982 [(match_operator 4 "arm_comparison_operator"
6983 [(match_operand 5 "cc_register" "") (const_int 0)])
6985 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
6986 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
6989 if (GET_CODE (operands[3]) == NE)
6991 if (which_alternative != 1)
6992 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
6993 if (which_alternative != 0)
6994 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
6997 if (which_alternative != 0)
6998 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6999 if (which_alternative != 1)
7000 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7003 [(set_attr "conds" "use")
7004 (set_attr "length" "4,4,8")]
7007 (define_insn "*cond_arith"
7008 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7009 (match_operator:SI 5 "shiftable_operator"
7010 [(match_operator:SI 4 "arm_comparison_operator"
7011 [(match_operand:SI 2 "s_register_operand" "r,r")
7012 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7013 (match_operand:SI 1 "s_register_operand" "0,?r")]))
7014 (clobber (reg:CC CC_REGNUM))]
7017 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7018 return \"%i5\\t%0, %1, %2, lsr #31\";
7020 output_asm_insn (\"cmp\\t%2, %3\", operands);
7021 if (GET_CODE (operands[5]) == AND)
7022 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7023 else if (GET_CODE (operands[5]) == MINUS)
7024 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7025 else if (which_alternative != 0)
7026 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7027 return \"%i5%d4\\t%0, %1, #1\";
7029 [(set_attr "conds" "clob")
7030 (set_attr "length" "12")]
7033 (define_insn "*cond_sub"
7034 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7035 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7036 (match_operator:SI 4 "arm_comparison_operator"
7037 [(match_operand:SI 2 "s_register_operand" "r,r")
7038 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7039 (clobber (reg:CC CC_REGNUM))]
7042 output_asm_insn (\"cmp\\t%2, %3\", operands);
7043 if (which_alternative != 0)
7044 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7045 return \"sub%d4\\t%0, %1, #1\";
7047 [(set_attr "conds" "clob")
7048 (set_attr "length" "8,12")]
7051 (define_insn "*cmp_ite0"
7052 [(set (match_operand 6 "dominant_cc_register" "")
7055 (match_operator 4 "arm_comparison_operator"
7056 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7057 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7058 (match_operator:SI 5 "arm_comparison_operator"
7059 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7060 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7066 static const char * const opcodes[4][2] =
7068 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7069 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7070 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7071 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7072 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7073 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7074 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7075 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7078 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7080 return opcodes[which_alternative][swap];
7082 [(set_attr "conds" "set")
7083 (set_attr "length" "8")]
7086 (define_insn "*cmp_ite1"
7087 [(set (match_operand 6 "dominant_cc_register" "")
7090 (match_operator 4 "arm_comparison_operator"
7091 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7092 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7093 (match_operator:SI 5 "arm_comparison_operator"
7094 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7095 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7101 static const char * const opcodes[4][2] =
7103 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7104 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7105 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7106 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7107 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7108 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7109 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7110 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7113 comparison_dominates_p (GET_CODE (operands[5]),
7114 reverse_condition (GET_CODE (operands[4])));
7116 return opcodes[which_alternative][swap];
7118 [(set_attr "conds" "set")
7119 (set_attr "length" "8")]
7122 (define_insn "*cmp_and"
7123 [(set (match_operand 6 "dominant_cc_register" "")
7126 (match_operator 4 "arm_comparison_operator"
7127 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7128 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7129 (match_operator:SI 5 "arm_comparison_operator"
7130 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7131 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7136 static const char *const opcodes[4][2] =
7138 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7139 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7140 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7141 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7142 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7143 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7144 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7145 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7148 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7150 return opcodes[which_alternative][swap];
7152 [(set_attr "conds" "set")
7153 (set_attr "predicable" "no")
7154 (set_attr "length" "8")]
7157 (define_insn "*cmp_ior"
7158 [(set (match_operand 6 "dominant_cc_register" "")
7161 (match_operator 4 "arm_comparison_operator"
7162 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7163 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7164 (match_operator:SI 5 "arm_comparison_operator"
7165 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7166 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7171 static const char *const opcodes[4][2] =
7173 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7174 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7175 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7176 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7177 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7178 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7179 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7180 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7183 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7185 return opcodes[which_alternative][swap];
7188 [(set_attr "conds" "set")
7189 (set_attr "length" "8")]
7192 (define_insn "*negscc"
7193 [(set (match_operand:SI 0 "s_register_operand" "=r")
7194 (neg:SI (match_operator 3 "arm_comparison_operator"
7195 [(match_operand:SI 1 "s_register_operand" "r")
7196 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7197 (clobber (reg:CC CC_REGNUM))]
7200 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7201 return \"mov\\t%0, %1, asr #31\";
7203 if (GET_CODE (operands[3]) == NE)
7204 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7206 if (GET_CODE (operands[3]) == GT)
7207 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7209 output_asm_insn (\"cmp\\t%1, %2\", operands);
7210 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7211 return \"mvn%d3\\t%0, #0\";
7213 [(set_attr "conds" "clob")
7214 (set_attr "length" "12")]
7217 (define_insn "movcond"
7218 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7220 (match_operator 5 "arm_comparison_operator"
7221 [(match_operand:SI 3 "s_register_operand" "r,r,r")
7222 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7223 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7224 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
7225 (clobber (reg:CC CC_REGNUM))]
7228 if (GET_CODE (operands[5]) == LT
7229 && (operands[4] == const0_rtx))
7231 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7233 if (operands[2] == const0_rtx)
7234 return \"and\\t%0, %1, %3, asr #31\";
7235 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
7237 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7239 if (operands[1] == const0_rtx)
7240 return \"bic\\t%0, %2, %3, asr #31\";
7241 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
7243 /* The only case that falls through to here is when both ops 1 & 2
7247 if (GET_CODE (operands[5]) == GE
7248 && (operands[4] == const0_rtx))
7250 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7252 if (operands[2] == const0_rtx)
7253 return \"bic\\t%0, %1, %3, asr #31\";
7254 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7256 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7258 if (operands[1] == const0_rtx)
7259 return \"and\\t%0, %2, %3, asr #31\";
7260 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7262 /* The only case that falls through to here is when both ops 1 & 2
7265 if (GET_CODE (operands[4]) == CONST_INT
7266 && !const_ok_for_arm (INTVAL (operands[4])))
7267 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7269 output_asm_insn (\"cmp\\t%3, %4\", operands);
7270 if (which_alternative != 0)
7271 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7272 if (which_alternative != 1)
7273 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7276 [(set_attr "conds" "clob")
7277 (set_attr "length" "8,8,12")]
7280 (define_insn "*ifcompare_plus_move"
7281 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7282 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7283 [(match_operand:SI 4 "s_register_operand" "r,r")
7284 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7286 (match_operand:SI 2 "s_register_operand" "r,r")
7287 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7288 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7289 (clobber (reg:CC CC_REGNUM))]
7292 [(set_attr "conds" "clob")
7293 (set_attr "length" "8,12")]
7296 (define_insn "*if_plus_move"
7297 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7299 (match_operator 4 "arm_comparison_operator"
7300 [(match_operand 5 "cc_register" "") (const_int 0)])
7302 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7303 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7304 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7308 sub%d4\\t%0, %2, #%n3
7309 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7310 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7311 [(set_attr "conds" "use")
7312 (set_attr "length" "4,4,8,8")
7313 (set_attr "type" "*,*,*,*")]
7316 (define_insn "*ifcompare_move_plus"
7317 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7318 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7319 [(match_operand:SI 4 "s_register_operand" "r,r")
7320 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7321 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7323 (match_operand:SI 2 "s_register_operand" "r,r")
7324 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7325 (clobber (reg:CC CC_REGNUM))]
7328 [(set_attr "conds" "clob")
7329 (set_attr "length" "8,12")]
7332 (define_insn "*if_move_plus"
7333 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7335 (match_operator 4 "arm_comparison_operator"
7336 [(match_operand 5 "cc_register" "") (const_int 0)])
7337 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7339 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7340 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7344 sub%D4\\t%0, %2, #%n3
7345 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7346 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7347 [(set_attr "conds" "use")
7348 (set_attr "length" "4,4,8,8")
7349 (set_attr "type" "*,*,*,*")]
7352 (define_insn "*ifcompare_arith_arith"
7353 [(set (match_operand:SI 0 "s_register_operand" "=r")
7354 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7355 [(match_operand:SI 5 "s_register_operand" "r")
7356 (match_operand:SI 6 "arm_add_operand" "rIL")])
7357 (match_operator:SI 8 "shiftable_operator"
7358 [(match_operand:SI 1 "s_register_operand" "r")
7359 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7360 (match_operator:SI 7 "shiftable_operator"
7361 [(match_operand:SI 3 "s_register_operand" "r")
7362 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7363 (clobber (reg:CC CC_REGNUM))]
7366 [(set_attr "conds" "clob")
7367 (set_attr "length" "12")]
7370 (define_insn "*if_arith_arith"
7371 [(set (match_operand:SI 0 "s_register_operand" "=r")
7372 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7373 [(match_operand 8 "cc_register" "") (const_int 0)])
7374 (match_operator:SI 6 "shiftable_operator"
7375 [(match_operand:SI 1 "s_register_operand" "r")
7376 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7377 (match_operator:SI 7 "shiftable_operator"
7378 [(match_operand:SI 3 "s_register_operand" "r")
7379 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7381 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7382 [(set_attr "conds" "use")
7383 (set_attr "length" "8")]
7386 (define_insn "*ifcompare_arith_move"
7387 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7388 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7389 [(match_operand:SI 2 "s_register_operand" "r,r")
7390 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7391 (match_operator:SI 7 "shiftable_operator"
7392 [(match_operand:SI 4 "s_register_operand" "r,r")
7393 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7394 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7395 (clobber (reg:CC CC_REGNUM))]
7398 /* If we have an operation where (op x 0) is the identity operation and
7399 the conditional operator is LT or GE and we are comparing against zero and
7400 everything is in registers then we can do this in two instructions */
7401 if (operands[3] == const0_rtx
7402 && GET_CODE (operands[7]) != AND
7403 && GET_CODE (operands[5]) == REG
7404 && GET_CODE (operands[1]) == REG
7405 && REGNO (operands[1]) == REGNO (operands[4])
7406 && REGNO (operands[4]) != REGNO (operands[0]))
7408 if (GET_CODE (operands[6]) == LT)
7409 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7410 else if (GET_CODE (operands[6]) == GE)
7411 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7413 if (GET_CODE (operands[3]) == CONST_INT
7414 && !const_ok_for_arm (INTVAL (operands[3])))
7415 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7417 output_asm_insn (\"cmp\\t%2, %3\", operands);
7418 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7419 if (which_alternative != 0)
7420 return \"mov%D6\\t%0, %1\";
7423 [(set_attr "conds" "clob")
7424 (set_attr "length" "8,12")]
7427 (define_insn "*if_arith_move"
7428 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7429 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7430 [(match_operand 6 "cc_register" "") (const_int 0)])
7431 (match_operator:SI 5 "shiftable_operator"
7432 [(match_operand:SI 2 "s_register_operand" "r,r")
7433 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7434 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7438 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7439 [(set_attr "conds" "use")
7440 (set_attr "length" "4,8")
7441 (set_attr "type" "*,*")]
7444 (define_insn "*ifcompare_move_arith"
7445 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7446 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7447 [(match_operand:SI 4 "s_register_operand" "r,r")
7448 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7449 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7450 (match_operator:SI 7 "shiftable_operator"
7451 [(match_operand:SI 2 "s_register_operand" "r,r")
7452 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7453 (clobber (reg:CC CC_REGNUM))]
7456 /* If we have an operation where (op x 0) is the identity operation and
7457 the conditional operator is LT or GE and we are comparing against zero and
7458 everything is in registers then we can do this in two instructions */
7459 if (operands[5] == const0_rtx
7460 && GET_CODE (operands[7]) != AND
7461 && GET_CODE (operands[3]) == REG
7462 && GET_CODE (operands[1]) == REG
7463 && REGNO (operands[1]) == REGNO (operands[2])
7464 && REGNO (operands[2]) != REGNO (operands[0]))
7466 if (GET_CODE (operands[6]) == GE)
7467 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7468 else if (GET_CODE (operands[6]) == LT)
7469 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7472 if (GET_CODE (operands[5]) == CONST_INT
7473 && !const_ok_for_arm (INTVAL (operands[5])))
7474 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7476 output_asm_insn (\"cmp\\t%4, %5\", operands);
7478 if (which_alternative != 0)
7479 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7480 return \"%I7%D6\\t%0, %2, %3\";
7482 [(set_attr "conds" "clob")
7483 (set_attr "length" "8,12")]
7486 (define_insn "*if_move_arith"
7487 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7489 (match_operator 4 "arm_comparison_operator"
7490 [(match_operand 6 "cc_register" "") (const_int 0)])
7491 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7492 (match_operator:SI 5 "shiftable_operator"
7493 [(match_operand:SI 2 "s_register_operand" "r,r")
7494 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7498 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7499 [(set_attr "conds" "use")
7500 (set_attr "length" "4,8")
7501 (set_attr "type" "*,*")]
7504 (define_insn "*ifcompare_move_not"
7505 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7507 (match_operator 5 "arm_comparison_operator"
7508 [(match_operand:SI 3 "s_register_operand" "r,r")
7509 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7510 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7512 (match_operand:SI 2 "s_register_operand" "r,r"))))
7513 (clobber (reg:CC CC_REGNUM))]
7516 [(set_attr "conds" "clob")
7517 (set_attr "length" "8,12")]
7520 (define_insn "*if_move_not"
7521 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7523 (match_operator 4 "arm_comparison_operator"
7524 [(match_operand 3 "cc_register" "") (const_int 0)])
7525 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7526 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7530 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7531 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7532 [(set_attr "conds" "use")
7533 (set_attr "length" "4,8,8")]
7536 (define_insn "*ifcompare_not_move"
7537 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7539 (match_operator 5 "arm_comparison_operator"
7540 [(match_operand:SI 3 "s_register_operand" "r,r")
7541 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7543 (match_operand:SI 2 "s_register_operand" "r,r"))
7544 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7545 (clobber (reg:CC CC_REGNUM))]
7548 [(set_attr "conds" "clob")
7549 (set_attr "length" "8,12")]
7552 (define_insn "*if_not_move"
7553 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7555 (match_operator 4 "arm_comparison_operator"
7556 [(match_operand 3 "cc_register" "") (const_int 0)])
7557 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7558 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7562 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7563 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7564 [(set_attr "conds" "use")
7565 (set_attr "length" "4,8,8")]
7568 (define_insn "*ifcompare_shift_move"
7569 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7571 (match_operator 6 "arm_comparison_operator"
7572 [(match_operand:SI 4 "s_register_operand" "r,r")
7573 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7574 (match_operator:SI 7 "shift_operator"
7575 [(match_operand:SI 2 "s_register_operand" "r,r")
7576 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7577 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7578 (clobber (reg:CC CC_REGNUM))]
7581 [(set_attr "conds" "clob")
7582 (set_attr "length" "8,12")]
7585 (define_insn "*if_shift_move"
7586 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7588 (match_operator 5 "arm_comparison_operator"
7589 [(match_operand 6 "cc_register" "") (const_int 0)])
7590 (match_operator:SI 4 "shift_operator"
7591 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7592 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7593 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7597 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7598 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7599 [(set_attr "conds" "use")
7600 (set_attr "shift" "2")
7601 (set_attr "length" "4,8,8")]
7604 (define_insn "*ifcompare_move_shift"
7605 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7607 (match_operator 6 "arm_comparison_operator"
7608 [(match_operand:SI 4 "s_register_operand" "r,r")
7609 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7610 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7611 (match_operator:SI 7 "shift_operator"
7612 [(match_operand:SI 2 "s_register_operand" "r,r")
7613 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7614 (clobber (reg:CC CC_REGNUM))]
7617 [(set_attr "conds" "clob")
7618 (set_attr "length" "8,12")]
7621 (define_insn "*if_move_shift"
7622 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7624 (match_operator 5 "arm_comparison_operator"
7625 [(match_operand 6 "cc_register" "") (const_int 0)])
7626 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7627 (match_operator:SI 4 "shift_operator"
7628 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7629 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7633 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7634 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7635 [(set_attr "conds" "use")
7636 (set_attr "shift" "2")
7637 (set_attr "length" "4,8,8")]
7640 (define_insn "*ifcompare_shift_shift"
7641 [(set (match_operand:SI 0 "s_register_operand" "=r")
7643 (match_operator 7 "arm_comparison_operator"
7644 [(match_operand:SI 5 "s_register_operand" "r")
7645 (match_operand:SI 6 "arm_add_operand" "rIL")])
7646 (match_operator:SI 8 "shift_operator"
7647 [(match_operand:SI 1 "s_register_operand" "r")
7648 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7649 (match_operator:SI 9 "shift_operator"
7650 [(match_operand:SI 3 "s_register_operand" "r")
7651 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7652 (clobber (reg:CC CC_REGNUM))]
7655 [(set_attr "conds" "clob")
7656 (set_attr "length" "12")]
7659 (define_insn "*if_shift_shift"
7660 [(set (match_operand:SI 0 "s_register_operand" "=r")
7662 (match_operator 5 "arm_comparison_operator"
7663 [(match_operand 8 "cc_register" "") (const_int 0)])
7664 (match_operator:SI 6 "shift_operator"
7665 [(match_operand:SI 1 "s_register_operand" "r")
7666 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7667 (match_operator:SI 7 "shift_operator"
7668 [(match_operand:SI 3 "s_register_operand" "r")
7669 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7671 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7672 [(set_attr "conds" "use")
7673 (set_attr "shift" "1")
7674 (set_attr "length" "8")]
7677 (define_insn "*ifcompare_not_arith"
7678 [(set (match_operand:SI 0 "s_register_operand" "=r")
7680 (match_operator 6 "arm_comparison_operator"
7681 [(match_operand:SI 4 "s_register_operand" "r")
7682 (match_operand:SI 5 "arm_add_operand" "rIL")])
7683 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7684 (match_operator:SI 7 "shiftable_operator"
7685 [(match_operand:SI 2 "s_register_operand" "r")
7686 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7687 (clobber (reg:CC CC_REGNUM))]
7690 [(set_attr "conds" "clob")
7691 (set_attr "length" "12")]
7694 (define_insn "*if_not_arith"
7695 [(set (match_operand:SI 0 "s_register_operand" "=r")
7697 (match_operator 5 "arm_comparison_operator"
7698 [(match_operand 4 "cc_register" "") (const_int 0)])
7699 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7700 (match_operator:SI 6 "shiftable_operator"
7701 [(match_operand:SI 2 "s_register_operand" "r")
7702 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7704 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7705 [(set_attr "conds" "use")
7706 (set_attr "length" "8")]
7709 (define_insn "*ifcompare_arith_not"
7710 [(set (match_operand:SI 0 "s_register_operand" "=r")
7712 (match_operator 6 "arm_comparison_operator"
7713 [(match_operand:SI 4 "s_register_operand" "r")
7714 (match_operand:SI 5 "arm_add_operand" "rIL")])
7715 (match_operator:SI 7 "shiftable_operator"
7716 [(match_operand:SI 2 "s_register_operand" "r")
7717 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7718 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7719 (clobber (reg:CC CC_REGNUM))]
7722 [(set_attr "conds" "clob")
7723 (set_attr "length" "12")]
7726 (define_insn "*if_arith_not"
7727 [(set (match_operand:SI 0 "s_register_operand" "=r")
7729 (match_operator 5 "arm_comparison_operator"
7730 [(match_operand 4 "cc_register" "") (const_int 0)])
7731 (match_operator:SI 6 "shiftable_operator"
7732 [(match_operand:SI 2 "s_register_operand" "r")
7733 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7734 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7736 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7737 [(set_attr "conds" "use")
7738 (set_attr "length" "8")]
7741 (define_insn "*ifcompare_neg_move"
7742 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7744 (match_operator 5 "arm_comparison_operator"
7745 [(match_operand:SI 3 "s_register_operand" "r,r")
7746 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7747 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7748 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7749 (clobber (reg:CC CC_REGNUM))]
7752 [(set_attr "conds" "clob")
7753 (set_attr "length" "8,12")]
7756 (define_insn "*if_neg_move"
7757 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7759 (match_operator 4 "arm_comparison_operator"
7760 [(match_operand 3 "cc_register" "") (const_int 0)])
7761 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7762 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7766 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7767 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
7768 [(set_attr "conds" "use")
7769 (set_attr "length" "4,8,8")]
7772 (define_insn "*ifcompare_move_neg"
7773 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7775 (match_operator 5 "arm_comparison_operator"
7776 [(match_operand:SI 3 "s_register_operand" "r,r")
7777 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7778 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7779 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
7780 (clobber (reg:CC CC_REGNUM))]
7783 [(set_attr "conds" "clob")
7784 (set_attr "length" "8,12")]
7787 (define_insn "*if_move_neg"
7788 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7790 (match_operator 4 "arm_comparison_operator"
7791 [(match_operand 3 "cc_register" "") (const_int 0)])
7792 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7793 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7797 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
7798 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
7799 [(set_attr "conds" "use")
7800 (set_attr "length" "4,8,8")]
7803 (define_insn "*arith_adjacentmem"
7804 [(set (match_operand:SI 0 "s_register_operand" "=r")
7805 (match_operator:SI 1 "shiftable_operator"
7806 [(match_operand:SI 2 "memory_operand" "m")
7807 (match_operand:SI 3 "memory_operand" "m")]))
7808 (clobber (match_scratch:SI 4 "=r"))]
7809 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
7814 int val1 = 0, val2 = 0;
7816 if (REGNO (operands[0]) > REGNO (operands[4]))
7818 ldm[1] = operands[4];
7819 ldm[2] = operands[0];
7823 ldm[1] = operands[0];
7824 ldm[2] = operands[4];
7826 if (GET_CODE (XEXP (operands[2], 0)) != REG)
7827 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
7828 if (GET_CODE (XEXP (operands[3], 0)) != REG)
7829 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
7830 arith[0] = operands[0];
7831 arith[3] = operands[1];
7845 ldm[0] = ops[0] = operands[4];
7846 ops[1] = XEXP (XEXP (operands[2], 0), 0);
7847 ops[2] = XEXP (XEXP (operands[2], 0), 1);
7848 output_add_immediate (ops);
7850 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7852 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7856 ldm[0] = XEXP (operands[3], 0);
7858 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7860 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7864 ldm[0] = XEXP (operands[2], 0);
7866 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7868 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7870 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
7873 [(set_attr "length" "12")
7874 (set_attr "predicable" "yes")
7875 (set_attr "type" "load")]
7878 ;; the arm can support extended pre-inc instructions
7880 ;; In all these cases, we use operands 0 and 1 for the register being
7881 ;; incremented because those are the operands that local-alloc will
7882 ;; tie and these are the pair most likely to be tieable (and the ones
7883 ;; that will benefit the most).
7885 ;; We reject the frame pointer if it occurs anywhere in these patterns since
7886 ;; elimination will cause too many headaches.
7888 (define_insn "*strqi_preinc"
7889 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7890 (match_operand:SI 2 "index_operand" "rJ")))
7891 (match_operand:QI 3 "s_register_operand" "r"))
7892 (set (match_operand:SI 0 "s_register_operand" "=r")
7893 (plus:SI (match_dup 1) (match_dup 2)))]
7895 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7896 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7897 && (GET_CODE (operands[2]) != REG
7898 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7899 "str%?b\\t%3, [%0, %2]!"
7900 [(set_attr "type" "store1")
7901 (set_attr "predicable" "yes")]
7904 (define_insn "*strqi_predec"
7905 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7906 (match_operand:SI 2 "s_register_operand" "r")))
7907 (match_operand:QI 3 "s_register_operand" "r"))
7908 (set (match_operand:SI 0 "s_register_operand" "=r")
7909 (minus:SI (match_dup 1) (match_dup 2)))]
7911 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7912 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7913 && (GET_CODE (operands[2]) != REG
7914 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7915 "str%?b\\t%3, [%0, -%2]!"
7916 [(set_attr "type" "store1")
7917 (set_attr "predicable" "yes")]
7920 (define_insn "*loadqi_preinc"
7921 [(set (match_operand:QI 3 "s_register_operand" "=r")
7922 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7923 (match_operand:SI 2 "index_operand" "rJ"))))
7924 (set (match_operand:SI 0 "s_register_operand" "=r")
7925 (plus:SI (match_dup 1) (match_dup 2)))]
7927 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7928 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7929 && (GET_CODE (operands[2]) != REG
7930 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7931 "ldr%?b\\t%3, [%0, %2]!"
7932 [(set_attr "type" "load")
7933 (set_attr "predicable" "yes")]
7936 (define_insn "*loadqi_predec"
7937 [(set (match_operand:QI 3 "s_register_operand" "=r")
7938 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7939 (match_operand:SI 2 "s_register_operand" "r"))))
7940 (set (match_operand:SI 0 "s_register_operand" "=r")
7941 (minus:SI (match_dup 1) (match_dup 2)))]
7943 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7944 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7945 && (GET_CODE (operands[2]) != REG
7946 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7947 "ldr%?b\\t%3, [%0, -%2]!"
7948 [(set_attr "type" "load")
7949 (set_attr "predicable" "yes")]
7952 (define_insn "*loadqisi_preinc"
7953 [(set (match_operand:SI 3 "s_register_operand" "=r")
7955 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7956 (match_operand:SI 2 "index_operand" "rJ")))))
7957 (set (match_operand:SI 0 "s_register_operand" "=r")
7958 (plus:SI (match_dup 1) (match_dup 2)))]
7960 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7961 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7962 && (GET_CODE (operands[2]) != REG
7963 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7964 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
7965 [(set_attr "type" "load")
7966 (set_attr "predicable" "yes")]
7969 (define_insn "*loadqisi_predec"
7970 [(set (match_operand:SI 3 "s_register_operand" "=r")
7972 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7973 (match_operand:SI 2 "s_register_operand" "r")))))
7974 (set (match_operand:SI 0 "s_register_operand" "=r")
7975 (minus:SI (match_dup 1) (match_dup 2)))]
7977 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7978 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7979 && (GET_CODE (operands[2]) != REG
7980 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7981 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
7982 [(set_attr "type" "load")
7983 (set_attr "predicable" "yes")]
7986 (define_insn "*strsi_preinc"
7987 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7988 (match_operand:SI 2 "index_operand" "rJ")))
7989 (match_operand:SI 3 "s_register_operand" "r"))
7990 (set (match_operand:SI 0 "s_register_operand" "=r")
7991 (plus:SI (match_dup 1) (match_dup 2)))]
7993 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7994 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7995 && (GET_CODE (operands[2]) != REG
7996 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7997 "str%?\\t%3, [%0, %2]!"
7998 [(set_attr "type" "store1")
7999 (set_attr "predicable" "yes")]
8002 (define_insn "*strsi_predec"
8003 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8004 (match_operand:SI 2 "s_register_operand" "r")))
8005 (match_operand:SI 3 "s_register_operand" "r"))
8006 (set (match_operand:SI 0 "s_register_operand" "=r")
8007 (minus:SI (match_dup 1) (match_dup 2)))]
8009 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8010 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8011 && (GET_CODE (operands[2]) != REG
8012 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8013 "str%?\\t%3, [%0, -%2]!"
8014 [(set_attr "type" "store1")
8015 (set_attr "predicable" "yes")]
8018 (define_insn "*loadsi_preinc"
8019 [(set (match_operand:SI 3 "s_register_operand" "=r")
8020 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8021 (match_operand:SI 2 "index_operand" "rJ"))))
8022 (set (match_operand:SI 0 "s_register_operand" "=r")
8023 (plus:SI (match_dup 1) (match_dup 2)))]
8025 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8026 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8027 && (GET_CODE (operands[2]) != REG
8028 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8029 "ldr%?\\t%3, [%0, %2]!"
8030 [(set_attr "type" "load")
8031 (set_attr "predicable" "yes")]
8034 (define_insn "*loadsi_predec"
8035 [(set (match_operand:SI 3 "s_register_operand" "=r")
8036 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8037 (match_operand:SI 2 "s_register_operand" "r"))))
8038 (set (match_operand:SI 0 "s_register_operand" "=r")
8039 (minus:SI (match_dup 1) (match_dup 2)))]
8041 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8042 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8043 && (GET_CODE (operands[2]) != REG
8044 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8045 "ldr%?\\t%3, [%0, -%2]!"
8046 [(set_attr "type" "load")
8047 (set_attr "predicable" "yes")]
8050 (define_insn "*loadhi_preinc"
8051 [(set (match_operand:HI 3 "s_register_operand" "=r")
8052 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8053 (match_operand:SI 2 "index_operand" "rJ"))))
8054 (set (match_operand:SI 0 "s_register_operand" "=r")
8055 (plus:SI (match_dup 1) (match_dup 2)))]
8057 && !BYTES_BIG_ENDIAN
8058 && !TARGET_MMU_TRAPS
8060 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8061 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8062 && (GET_CODE (operands[2]) != REG
8063 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8064 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8065 [(set_attr "type" "load")
8066 (set_attr "predicable" "yes")]
8069 (define_insn "*loadhi_predec"
8070 [(set (match_operand:HI 3 "s_register_operand" "=r")
8071 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8072 (match_operand:SI 2 "s_register_operand" "r"))))
8073 (set (match_operand:SI 0 "s_register_operand" "=r")
8074 (minus:SI (match_dup 1) (match_dup 2)))]
8076 && !BYTES_BIG_ENDIAN
8077 && !TARGET_MMU_TRAPS
8079 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8080 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8081 && (GET_CODE (operands[2]) != REG
8082 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8083 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8084 [(set_attr "type" "load")
8085 (set_attr "predicable" "yes")]
8088 (define_insn "*strqi_shiftpreinc"
8089 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8090 [(match_operand:SI 3 "s_register_operand" "r")
8091 (match_operand:SI 4 "const_shift_operand" "n")])
8092 (match_operand:SI 1 "s_register_operand" "0")))
8093 (match_operand:QI 5 "s_register_operand" "r"))
8094 (set (match_operand:SI 0 "s_register_operand" "=r")
8095 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8098 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8099 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8100 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8101 "str%?b\\t%5, [%0, %3%S2]!"
8102 [(set_attr "type" "store1")
8103 (set_attr "predicable" "yes")]
8106 (define_insn "*strqi_shiftpredec"
8107 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8108 (match_operator:SI 2 "shift_operator"
8109 [(match_operand:SI 3 "s_register_operand" "r")
8110 (match_operand:SI 4 "const_shift_operand" "n")])))
8111 (match_operand:QI 5 "s_register_operand" "r"))
8112 (set (match_operand:SI 0 "s_register_operand" "=r")
8113 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8116 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8117 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8118 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8119 "str%?b\\t%5, [%0, -%3%S2]!"
8120 [(set_attr "type" "store1")
8121 (set_attr "predicable" "yes")]
8124 (define_insn "*loadqi_shiftpreinc"
8125 [(set (match_operand:QI 5 "s_register_operand" "=r")
8126 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8127 [(match_operand:SI 3 "s_register_operand" "r")
8128 (match_operand:SI 4 "const_shift_operand" "n")])
8129 (match_operand:SI 1 "s_register_operand" "0"))))
8130 (set (match_operand:SI 0 "s_register_operand" "=r")
8131 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8134 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8135 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8136 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8137 "ldr%?b\\t%5, [%0, %3%S2]!"
8138 [(set_attr "type" "load")
8139 (set_attr "predicable" "yes")]
8142 (define_insn "*loadqi_shiftpredec"
8143 [(set (match_operand:QI 5 "s_register_operand" "=r")
8144 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8145 (match_operator:SI 2 "shift_operator"
8146 [(match_operand:SI 3 "s_register_operand" "r")
8147 (match_operand:SI 4 "const_shift_operand" "n")]))))
8148 (set (match_operand:SI 0 "s_register_operand" "=r")
8149 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8152 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8153 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8154 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8155 "ldr%?b\\t%5, [%0, -%3%S2]!"
8156 [(set_attr "type" "load")
8157 (set_attr "predicable" "yes")]
8160 (define_insn "*strsi_shiftpreinc"
8161 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8162 [(match_operand:SI 3 "s_register_operand" "r")
8163 (match_operand:SI 4 "const_shift_operand" "n")])
8164 (match_operand:SI 1 "s_register_operand" "0")))
8165 (match_operand:SI 5 "s_register_operand" "r"))
8166 (set (match_operand:SI 0 "s_register_operand" "=r")
8167 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8170 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8171 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8172 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8173 "str%?\\t%5, [%0, %3%S2]!"
8174 [(set_attr "type" "store1")
8175 (set_attr "predicable" "yes")]
8178 (define_insn "*strsi_shiftpredec"
8179 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8180 (match_operator:SI 2 "shift_operator"
8181 [(match_operand:SI 3 "s_register_operand" "r")
8182 (match_operand:SI 4 "const_shift_operand" "n")])))
8183 (match_operand:SI 5 "s_register_operand" "r"))
8184 (set (match_operand:SI 0 "s_register_operand" "=r")
8185 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8188 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8189 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8190 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8191 "str%?\\t%5, [%0, -%3%S2]!"
8192 [(set_attr "type" "store1")
8193 (set_attr "predicable" "yes")]
8196 (define_insn "*loadsi_shiftpreinc"
8197 [(set (match_operand:SI 5 "s_register_operand" "=r")
8198 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8199 [(match_operand:SI 3 "s_register_operand" "r")
8200 (match_operand:SI 4 "const_shift_operand" "n")])
8201 (match_operand:SI 1 "s_register_operand" "0"))))
8202 (set (match_operand:SI 0 "s_register_operand" "=r")
8203 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8206 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8207 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8208 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8209 "ldr%?\\t%5, [%0, %3%S2]!"
8210 [(set_attr "type" "load")
8211 (set_attr "predicable" "yes")]
8214 (define_insn "*loadsi_shiftpredec"
8215 [(set (match_operand:SI 5 "s_register_operand" "=r")
8216 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8217 (match_operator:SI 2 "shift_operator"
8218 [(match_operand:SI 3 "s_register_operand" "r")
8219 (match_operand:SI 4 "const_shift_operand" "n")]))))
8220 (set (match_operand:SI 0 "s_register_operand" "=r")
8221 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8224 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8225 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8226 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8227 "ldr%?\\t%5, [%0, -%3%S2]!"
8228 [(set_attr "type" "load")
8229 (set_attr "predicable" "yes")])
8231 (define_insn "*loadhi_shiftpreinc"
8232 [(set (match_operand:HI 5 "s_register_operand" "=r")
8233 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8234 [(match_operand:SI 3 "s_register_operand" "r")
8235 (match_operand:SI 4 "const_shift_operand" "n")])
8236 (match_operand:SI 1 "s_register_operand" "0"))))
8237 (set (match_operand:SI 0 "s_register_operand" "=r")
8238 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8241 && !BYTES_BIG_ENDIAN
8242 && !TARGET_MMU_TRAPS
8244 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8245 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8246 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8247 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8248 [(set_attr "type" "load")
8249 (set_attr "predicable" "yes")]
8252 (define_insn "*loadhi_shiftpredec"
8253 [(set (match_operand:HI 5 "s_register_operand" "=r")
8254 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8255 (match_operator:SI 2 "shift_operator"
8256 [(match_operand:SI 3 "s_register_operand" "r")
8257 (match_operand:SI 4 "const_shift_operand" "n")]))))
8258 (set (match_operand:SI 0 "s_register_operand" "=r")
8259 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8262 && !BYTES_BIG_ENDIAN
8263 && !TARGET_MMU_TRAPS
8265 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8266 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8267 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8268 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8269 [(set_attr "type" "load")
8270 (set_attr "predicable" "yes")]
8273 ; It can also support extended post-inc expressions, but combine doesn't
8275 ; It doesn't seem worth adding peepholes for anything but the most common
8276 ; cases since, unlike combine, the increment must immediately follow the load
8277 ; for this pattern to match.
8278 ; We must watch to see that the source/destination register isn't also the
8279 ; same as the base address register, and that if the index is a register,
8280 ; that it is not the same as the base address register. In such cases the
8281 ; instruction that we would generate would have UNPREDICTABLE behavior so
8285 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8286 (match_operand:QI 2 "s_register_operand" "r"))
8288 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8290 && (REGNO (operands[2]) != REGNO (operands[0]))
8291 && (GET_CODE (operands[1]) != REG
8292 || (REGNO (operands[1]) != REGNO (operands[0])))"
8293 "str%?b\\t%2, [%0], %1"
8297 [(set (match_operand:QI 0 "s_register_operand" "=r")
8298 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8300 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8302 && REGNO (operands[0]) != REGNO(operands[1])
8303 && (GET_CODE (operands[2]) != REG
8304 || REGNO(operands[0]) != REGNO (operands[2]))"
8305 "ldr%?b\\t%0, [%1], %2"
8309 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8310 (match_operand:SI 2 "s_register_operand" "r"))
8312 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8314 && (REGNO (operands[2]) != REGNO (operands[0]))
8315 && (GET_CODE (operands[1]) != REG
8316 || (REGNO (operands[1]) != REGNO (operands[0])))"
8317 "str%?\\t%2, [%0], %1"
8321 [(set (match_operand:HI 0 "s_register_operand" "=r")
8322 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8324 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8326 && !BYTES_BIG_ENDIAN
8327 && !TARGET_MMU_TRAPS
8329 && REGNO (operands[0]) != REGNO(operands[1])
8330 && (GET_CODE (operands[2]) != REG
8331 || REGNO(operands[0]) != REGNO (operands[2]))"
8332 "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8336 [(set (match_operand:SI 0 "s_register_operand" "=r")
8337 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8339 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8341 && REGNO (operands[0]) != REGNO(operands[1])
8342 && (GET_CODE (operands[2]) != REG
8343 || REGNO(operands[0]) != REGNO (operands[2]))"
8344 "ldr%?\\t%0, [%1], %2"
8348 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8349 (match_operand:SI 1 "index_operand" "rJ")))
8350 (match_operand:QI 2 "s_register_operand" "r"))
8351 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8353 && (REGNO (operands[2]) != REGNO (operands[0]))
8354 && (GET_CODE (operands[1]) != REG
8355 || (REGNO (operands[1]) != REGNO (operands[0])))"
8356 "str%?b\\t%2, [%0, %1]!"
8360 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8361 [(match_operand:SI 0 "s_register_operand" "r")
8362 (match_operand:SI 1 "const_int_operand" "n")])
8363 (match_operand:SI 2 "s_register_operand" "+r")))
8364 (match_operand:QI 3 "s_register_operand" "r"))
8365 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8368 && (REGNO (operands[3]) != REGNO (operands[2]))
8369 && (REGNO (operands[0]) != REGNO (operands[2]))"
8370 "str%?b\\t%3, [%2, %0%S4]!"
8373 ; This pattern is never tried by combine, so do it as a peephole
8376 [(set (match_operand:SI 0 "s_register_operand" "")
8377 (match_operand:SI 1 "s_register_operand" ""))
8378 (set (reg:CC CC_REGNUM)
8379 (compare:CC (match_dup 1) (const_int 0)))]
8382 || (!cirrus_fp_register (operands[0], SImode)
8383 && !cirrus_fp_register (operands[1], SImode)))
8385 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8386 (set (match_dup 0) (match_dup 1))])]
8390 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8391 ; reversed, check that the memory references aren't volatile.
8394 [(set (match_operand:SI 0 "s_register_operand" "=r")
8395 (match_operand:SI 4 "memory_operand" "m"))
8396 (set (match_operand:SI 1 "s_register_operand" "=r")
8397 (match_operand:SI 5 "memory_operand" "m"))
8398 (set (match_operand:SI 2 "s_register_operand" "=r")
8399 (match_operand:SI 6 "memory_operand" "m"))
8400 (set (match_operand:SI 3 "s_register_operand" "=r")
8401 (match_operand:SI 7 "memory_operand" "m"))]
8402 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8404 return emit_ldm_seq (operands, 4);
8409 [(set (match_operand:SI 0 "s_register_operand" "=r")
8410 (match_operand:SI 3 "memory_operand" "m"))
8411 (set (match_operand:SI 1 "s_register_operand" "=r")
8412 (match_operand:SI 4 "memory_operand" "m"))
8413 (set (match_operand:SI 2 "s_register_operand" "=r")
8414 (match_operand:SI 5 "memory_operand" "m"))]
8415 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8417 return emit_ldm_seq (operands, 3);
8422 [(set (match_operand:SI 0 "s_register_operand" "=r")
8423 (match_operand:SI 2 "memory_operand" "m"))
8424 (set (match_operand:SI 1 "s_register_operand" "=r")
8425 (match_operand:SI 3 "memory_operand" "m"))]
8426 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8428 return emit_ldm_seq (operands, 2);
8433 [(set (match_operand:SI 4 "memory_operand" "=m")
8434 (match_operand:SI 0 "s_register_operand" "r"))
8435 (set (match_operand:SI 5 "memory_operand" "=m")
8436 (match_operand:SI 1 "s_register_operand" "r"))
8437 (set (match_operand:SI 6 "memory_operand" "=m")
8438 (match_operand:SI 2 "s_register_operand" "r"))
8439 (set (match_operand:SI 7 "memory_operand" "=m")
8440 (match_operand:SI 3 "s_register_operand" "r"))]
8441 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8443 return emit_stm_seq (operands, 4);
8448 [(set (match_operand:SI 3 "memory_operand" "=m")
8449 (match_operand:SI 0 "s_register_operand" "r"))
8450 (set (match_operand:SI 4 "memory_operand" "=m")
8451 (match_operand:SI 1 "s_register_operand" "r"))
8452 (set (match_operand:SI 5 "memory_operand" "=m")
8453 (match_operand:SI 2 "s_register_operand" "r"))]
8454 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8456 return emit_stm_seq (operands, 3);
8461 [(set (match_operand:SI 2 "memory_operand" "=m")
8462 (match_operand:SI 0 "s_register_operand" "r"))
8463 (set (match_operand:SI 3 "memory_operand" "=m")
8464 (match_operand:SI 1 "s_register_operand" "r"))]
8465 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8467 return emit_stm_seq (operands, 2);
8472 [(set (match_operand:SI 0 "s_register_operand" "")
8473 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8475 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8476 [(match_operand:SI 3 "s_register_operand" "")
8477 (match_operand:SI 4 "arm_rhs_operand" "")]))))
8478 (clobber (match_operand:SI 5 "s_register_operand" ""))]
8480 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8481 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8486 ;; This split can be used because CC_Z mode implies that the following
8487 ;; branch will be an equality, or an unsigned inequality, so the sign
8488 ;; extension is not needed.
8491 [(set (reg:CC_Z CC_REGNUM)
8493 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8495 (match_operand 1 "const_int_operand" "")))
8496 (clobber (match_scratch:SI 2 ""))]
8498 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8499 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8500 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8501 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8503 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8507 (define_expand "prologue"
8508 [(clobber (const_int 0))]
8511 arm_expand_prologue ();
8513 thumb_expand_prologue ();
8518 (define_expand "epilogue"
8519 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8523 thumb_expand_epilogue ();
8524 else if (USE_RETURN_INSN (FALSE))
8526 emit_jump_insn (gen_return ());
8529 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8531 gen_rtx_RETURN (VOIDmode)),
8537 ;; Note - although unspec_volatile's USE all hard registers,
8538 ;; USEs are ignored after relaod has completed. Thus we need
8539 ;; to add an unspec of the link register to ensure that flow
8540 ;; does not think that it is unused by the sibcall branch that
8541 ;; will replace the standard function epilogue.
8542 (define_insn "sibcall_epilogue"
8543 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
8544 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
8547 if (USE_RETURN_INSN (FALSE))
8548 return output_return_instruction (const_true_rtx, FALSE, FALSE);
8549 return arm_output_epilogue (FALSE);
8551 ;; Length is absolute worst case
8552 [(set_attr "length" "44")
8553 (set_attr "type" "block")
8554 ;; We don't clobber the conditions, but the potential length of this
8555 ;; operation is sufficient to make conditionalizing the sequence
8556 ;; unlikely to be profitable.
8557 (set_attr "conds" "clob")]
8560 (define_insn "*epilogue_insns"
8561 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8565 return arm_output_epilogue (TRUE);
8566 else /* TARGET_THUMB */
8567 return thumb_unexpanded_epilogue ();
8569 ; Length is absolute worst case
8570 [(set_attr "length" "44")
8571 (set_attr "type" "block")
8572 ;; We don't clobber the conditions, but the potential length of this
8573 ;; operation is sufficient to make conditionalizing the sequence
8574 ;; unlikely to be profitable.
8575 (set_attr "conds" "clob")]
8578 (define_expand "eh_epilogue"
8579 [(use (match_operand:SI 0 "register_operand" "r"))
8580 (use (match_operand:SI 1 "register_operand" "r"))
8581 (use (match_operand:SI 2 "register_operand" "r"))]
8585 cfun->machine->eh_epilogue_sp_ofs = operands[1];
8586 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8588 rtx ra = gen_rtx_REG (Pmode, 2);
8590 emit_move_insn (ra, operands[2]);
8593 /* This is a hack -- we may have crystalized the function type too
8595 cfun->machine->func_type = 0;
8599 ;; This split is only used during output to reduce the number of patterns
8600 ;; that need assembler instructions adding to them. We allowed the setting
8601 ;; of the conditions to be implicit during rtl generation so that
8602 ;; the conditional compare patterns would work. However this conflicts to
8603 ;; some extent with the conditional data operations, so we have to split them
8607 [(set (match_operand:SI 0 "s_register_operand" "")
8608 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8609 [(match_operand 2 "" "") (match_operand 3 "" "")])
8611 (match_operand 4 "" "")))
8612 (clobber (reg:CC CC_REGNUM))]
8613 "TARGET_ARM && reload_completed"
8614 [(set (match_dup 5) (match_dup 6))
8615 (cond_exec (match_dup 7)
8616 (set (match_dup 0) (match_dup 4)))]
8619 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8620 operands[2], operands[3]);
8621 enum rtx_code rc = GET_CODE (operands[1]);
8623 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8624 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8625 if (mode == CCFPmode || mode == CCFPEmode)
8626 rc = reverse_condition_maybe_unordered (rc);
8628 rc = reverse_condition (rc);
8630 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8635 [(set (match_operand:SI 0 "s_register_operand" "")
8636 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8637 [(match_operand 2 "" "") (match_operand 3 "" "")])
8638 (match_operand 4 "" "")
8640 (clobber (reg:CC CC_REGNUM))]
8641 "TARGET_ARM && reload_completed"
8642 [(set (match_dup 5) (match_dup 6))
8643 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8644 (set (match_dup 0) (match_dup 4)))]
8647 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8648 operands[2], operands[3]);
8650 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8651 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8656 [(set (match_operand:SI 0 "s_register_operand" "")
8657 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8658 [(match_operand 2 "" "") (match_operand 3 "" "")])
8659 (match_operand 4 "" "")
8660 (match_operand 5 "" "")))
8661 (clobber (reg:CC CC_REGNUM))]
8662 "TARGET_ARM && reload_completed"
8663 [(set (match_dup 6) (match_dup 7))
8664 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8665 (set (match_dup 0) (match_dup 4)))
8666 (cond_exec (match_dup 8)
8667 (set (match_dup 0) (match_dup 5)))]
8670 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8671 operands[2], operands[3]);
8672 enum rtx_code rc = GET_CODE (operands[1]);
8674 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8675 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8676 if (mode == CCFPmode || mode == CCFPEmode)
8677 rc = reverse_condition_maybe_unordered (rc);
8679 rc = reverse_condition (rc);
8681 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8686 [(set (match_operand:SI 0 "s_register_operand" "")
8687 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8688 [(match_operand:SI 2 "s_register_operand" "")
8689 (match_operand:SI 3 "arm_add_operand" "")])
8690 (match_operand:SI 4 "arm_rhs_operand" "")
8692 (match_operand:SI 5 "s_register_operand" ""))))
8693 (clobber (reg:CC CC_REGNUM))]
8694 "TARGET_ARM && reload_completed"
8695 [(set (match_dup 6) (match_dup 7))
8696 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8697 (set (match_dup 0) (match_dup 4)))
8698 (cond_exec (match_dup 8)
8699 (set (match_dup 0) (not:SI (match_dup 5))))]
8702 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8703 operands[2], operands[3]);
8704 enum rtx_code rc = GET_CODE (operands[1]);
8706 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8707 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8708 if (mode == CCFPmode || mode == CCFPEmode)
8709 rc = reverse_condition_maybe_unordered (rc);
8711 rc = reverse_condition (rc);
8713 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8717 (define_insn "*cond_move_not"
8718 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8719 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8720 [(match_operand 3 "cc_register" "") (const_int 0)])
8721 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8723 (match_operand:SI 2 "s_register_operand" "r,r"))))]
8727 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8728 [(set_attr "conds" "use")
8729 (set_attr "length" "4,8")]
8732 ;; The next two patterns occur when an AND operation is followed by a
8733 ;; scc insn sequence
8735 (define_insn "*sign_extract_onebit"
8736 [(set (match_operand:SI 0 "s_register_operand" "=r")
8737 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8739 (match_operand:SI 2 "const_int_operand" "n")))
8740 (clobber (reg:CC CC_REGNUM))]
8743 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8744 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8745 return \"mvnne\\t%0, #0\";
8747 [(set_attr "conds" "clob")
8748 (set_attr "length" "8")]
8751 (define_insn "*not_signextract_onebit"
8752 [(set (match_operand:SI 0 "s_register_operand" "=r")
8754 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8756 (match_operand:SI 2 "const_int_operand" "n"))))
8757 (clobber (reg:CC CC_REGNUM))]
8760 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8761 output_asm_insn (\"tst\\t%1, %2\", operands);
8762 output_asm_insn (\"mvneq\\t%0, #0\", operands);
8763 return \"movne\\t%0, #0\";
8765 [(set_attr "conds" "clob")
8766 (set_attr "length" "12")]
8769 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
8770 ;; expressions. For simplicity, the first register is also in the unspec
8772 (define_insn "*push_multi"
8773 [(match_parallel 2 "multi_register_push"
8774 [(set (match_operand:BLK 0 "memory_operand" "=m")
8775 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8776 UNSPEC_PUSH_MULT))])]
8780 int num_saves = XVECLEN (operands[2], 0);
8782 /* For the StrongARM at least it is faster to
8783 use STR to store only a single register. */
8785 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8791 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
8793 for (i = 1; i < num_saves; i++)
8795 strcat (pattern, \", %|\");
8797 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
8800 strcat (pattern, \"}\");
8801 output_asm_insn (pattern, operands);
8806 [(set_attr "type" "store4")]
8809 (define_insn "stack_tie"
8810 [(set (mem:BLK (scratch))
8811 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
8812 (match_operand:SI 1 "s_register_operand" "r")]
8816 [(set_attr "length" "0")]
8819 ;; Similarly for the floating point registers
8820 (define_insn "*push_fp_multi"
8821 [(match_parallel 2 "multi_register_push"
8822 [(set (match_operand:BLK 0 "memory_operand" "=m")
8823 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
8824 UNSPEC_PUSH_MULT))])]
8830 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
8831 output_asm_insn (pattern, operands);
8834 [(set_attr "type" "f_store")]
8837 ;; Special patterns for dealing with the constant pool
8839 (define_insn "align_4"
8840 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
8843 assemble_align (32);
8848 (define_insn "consttable_end"
8849 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
8852 making_const_table = FALSE;
8857 (define_insn "consttable_1"
8858 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
8861 making_const_table = TRUE;
8862 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
8866 [(set_attr "length" "4")]
8869 (define_insn "consttable_2"
8870 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
8873 making_const_table = TRUE;
8874 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
8878 [(set_attr "length" "4")]
8881 (define_insn "consttable_4"
8882 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
8886 making_const_table = TRUE;
8887 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8892 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8893 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8897 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
8902 [(set_attr "length" "4")]
8905 (define_insn "consttable_8"
8906 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
8910 making_const_table = TRUE;
8911 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8916 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8917 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8921 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
8926 [(set_attr "length" "8")]
8929 ;; Miscellaneous Thumb patterns
8931 (define_expand "tablejump"
8932 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
8933 (use (label_ref (match_operand 1 "" "")))])]
8938 /* Hopefully, CSE will eliminate this copy. */
8939 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
8940 rtx reg2 = gen_reg_rtx (SImode);
8942 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
8948 (define_insn "*thumb_tablejump"
8949 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
8950 (use (label_ref (match_operand 1 "" "")))]
8953 [(set_attr "length" "2")]
8958 (define_insn "clzsi2"
8959 [(set (match_operand:SI 0 "s_register_operand" "=r")
8960 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
8961 "TARGET_ARM && arm_arch5"
8964 (define_expand "ffssi2"
8965 [(set (match_operand:SI 0 "s_register_operand" "")
8966 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
8967 "TARGET_ARM && arm_arch5"
8972 t1 = gen_reg_rtx (SImode);
8973 t2 = gen_reg_rtx (SImode);
8974 t3 = gen_reg_rtx (SImode);
8976 emit_insn (gen_negsi2 (t1, operands[1]));
8977 emit_insn (gen_andsi3 (t2, operands[1], t1));
8978 emit_insn (gen_clzsi2 (t3, t2));
8979 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
8984 (define_expand "ctzsi2"
8985 [(set (match_operand:SI 0 "s_register_operand" "")
8986 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
8987 "TARGET_ARM && arm_arch5"
8992 t1 = gen_reg_rtx (SImode);
8993 t2 = gen_reg_rtx (SImode);
8994 t3 = gen_reg_rtx (SImode);
8996 emit_insn (gen_negsi2 (t1, operands[1]));
8997 emit_insn (gen_andsi3 (t2, operands[1], t1));
8998 emit_insn (gen_clzsi2 (t3, t2));
8999 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
9004 ;; V5E instructions.
9006 (define_insn "prefetch"
9007 [(prefetch (match_operand:SI 0 "address_operand" "p")
9008 (match_operand:SI 1 "" "")
9009 (match_operand:SI 2 "" ""))]
9010 "TARGET_ARM && arm_arch5e"
9013 ;; General predication pattern
9016 [(match_operator 0 "arm_comparison_operator"
9017 [(match_operand 1 "cc_register" "")
9023 (define_insn "prologue_use"
9024 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
9026 "%@ %0 needed for prologue"