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
170 ; Additions for Cirrus Maverick co-processor:
171 ; mav_farith Floating point arithmetic (4 cycle)
172 ; mav_dmult Double multiplies (7 cycle)
175 "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,mav_farith,mav_dmult"
176 (const_string "normal"))
178 ; Load scheduling, set from the arm_ld_sched variable
179 ; initialized by arm_override_options()
180 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
182 ; condition codes: this one is used by final_prescan_insn to speed up
183 ; conditionalizing instructions. It saves having to scan the rtl to see if
184 ; it uses or alters the condition codes.
186 ; USE means that the condition codes are used by the insn in the process of
187 ; outputting code, this means (at present) that we can't use the insn in
190 ; SET means that the purpose of the insn is to set the condition codes in a
191 ; well defined manner.
193 ; CLOB means that the condition codes are altered in an undefined manner, if
194 ; they are altered at all
196 ; JUMP_CLOB is used when the condition cannot be represented by a single
197 ; instruction (UNEQ and LTGT). These cannot be predicated.
199 ; NOCOND means that the condition codes are neither altered nor affect the
200 ; output of this insn
202 (define_attr "conds" "use,set,clob,jump_clob,nocond"
203 (if_then_else (eq_attr "type" "call")
204 (if_then_else (eq_attr "prog_mode" "prog32")
205 (const_string "clob") (const_string "nocond"))
206 (const_string "nocond")))
208 ; Predicable means that the insn can be conditionally executed based on
209 ; an automatically added predicate (additional patterns are generated by
210 ; gen...). We default to 'no' because no Thumb patterns match this rule
211 ; and not all ARM patterns do.
212 (define_attr "predicable" "no,yes" (const_string "no"))
214 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
215 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
216 ; suffer blockages enough to warrent modelling this (and it can adversely
217 ; affect the schedule).
218 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
220 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
221 ; to stall the processor. Used with model_wbuf above.
222 (define_attr "write_conflict" "no,yes"
223 (if_then_else (eq_attr "type"
224 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
226 (const_string "no")))
228 ; Classify the insns into those that take one cycle and those that take more
229 ; than one on the main cpu execution unit.
230 (define_attr "core_cycles" "single,multi"
231 (if_then_else (eq_attr "type"
232 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
233 (const_string "single")
234 (const_string "multi")))
236 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
237 ;; distant label. Only applicable to Thumb code.
238 (define_attr "far_jump" "yes,no" (const_string "no"))
240 ;; (define_function_unit {name} {num-units} {n-users} {test}
241 ;; {ready-delay} {issue-delay} [{conflict-list}])
243 ;;--------------------------------------------------------------------
244 ;; Floating point unit (FPA)
245 ;;--------------------------------------------------------------------
246 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
247 (eq_attr "type" "fdivx")) 71 69)
249 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
250 (eq_attr "type" "fdivd")) 59 57)
252 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
253 (eq_attr "type" "fdivs")) 31 29)
255 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
256 (eq_attr "type" "fmul")) 9 7)
258 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
259 (eq_attr "type" "ffmul")) 6 4)
261 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
262 (eq_attr "type" "farith")) 4 2)
264 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
265 (eq_attr "type" "ffarith")) 2 2)
267 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
268 (eq_attr "type" "r_2_f")) 5 3)
270 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
271 (eq_attr "type" "f_2_r")) 1 2)
273 ; The fpa10 doesn't really have a memory read unit, but it can start to
274 ; speculatively execute the instruction in the pipeline, provided the data
275 ; is already loaded, so pretend reads have a delay of 2 (and that the
276 ; pipeline is infinite).
278 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
279 (eq_attr "type" "f_load")) 3 1)
281 ;;--------------------------------------------------------------------
283 ;;--------------------------------------------------------------------
284 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
286 ; The write buffer on some of the arm6 processors is hard to model exactly.
287 ; There is room in the buffer for up to two addresses and up to eight words
288 ; of memory, but the two needn't be split evenly. When writing the two
289 ; addresses are fully pipelined. However, a read from memory that is not
290 ; currently in the cache will block until the writes have completed.
291 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
292 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
293 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
294 ; cycle to add as well.
296 (define_function_unit "write_buf" 1 2
297 (and (eq_attr "model_wbuf" "yes")
298 (eq_attr "type" "store1,r_mem_f")) 5 3)
299 (define_function_unit "write_buf" 1 2
300 (and (eq_attr "model_wbuf" "yes")
301 (eq_attr "type" "store2")) 7 4)
302 (define_function_unit "write_buf" 1 2
303 (and (eq_attr "model_wbuf" "yes")
304 (eq_attr "type" "store3")) 9 5)
305 (define_function_unit "write_buf" 1 2
306 (and (eq_attr "model_wbuf" "yes")
307 (eq_attr "type" "store4")) 11 6)
309 ;;--------------------------------------------------------------------
310 ;; Write blockage unit
311 ;;--------------------------------------------------------------------
312 ; The write_blockage unit models (partially), the fact that reads will stall
313 ; until the write buffer empties.
314 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
315 ; so we don't model them here
316 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
317 (eq_attr "type" "store1")) 5 5
318 [(eq_attr "write_conflict" "yes")])
319 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
320 (eq_attr "type" "store2")) 7 7
321 [(eq_attr "write_conflict" "yes")])
322 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
323 (eq_attr "type" "store3")) 9 9
324 [(eq_attr "write_conflict" "yes")])
325 (define_function_unit "write_blockage" 1 0
326 (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
327 [(eq_attr "write_conflict" "yes")])
328 (define_function_unit "write_blockage" 1 0
329 (and (eq_attr "model_wbuf" "yes")
330 (eq_attr "write_conflict" "yes")) 1 1)
332 ;;--------------------------------------------------------------------
334 ;;--------------------------------------------------------------------
335 ; Everything must spend at least one cycle in the core unit
336 (define_function_unit "core" 1 0 (eq_attr "core_cycles" "single") 1 1)
338 (define_function_unit "core" 1 0
339 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
341 (define_function_unit "core" 1 0
342 (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
344 ;; We do not need to conditionalize the define_function_unit immediately
345 ;; above. This one will be ignored for anything other than xscale
346 ;; compiles and for xscale compiles it provides a larger delay
347 ;; and the scheduler will DTRT.
348 ;; FIXME: this test needs to be revamped to not depend on this feature
351 (define_function_unit "core" 1 0
352 (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
353 (eq_attr "is_xscale" "yes"))
356 (define_function_unit "core" 1 0
357 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
359 (define_function_unit "core" 1 0
360 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
362 (define_function_unit "core" 1 0
363 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
365 (define_function_unit "core" 1 0
366 (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
368 (define_function_unit "core" 1 0
369 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
371 (define_function_unit "core" 1 0
372 (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
374 (define_function_unit "core" 1 0
375 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
376 (eq_attr "type" "mult")) 4 4)
378 (define_function_unit "core" 1 0
379 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
380 (eq_attr "type" "mult")) 3 2)
382 (define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
384 (define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
386 (define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
388 (define_function_unit "core" 1 0
389 (and (eq_attr "core_cycles" "multi")
390 (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
392 (include "cirrus.md")
394 ;;---------------------------------------------------------------------------
399 ;; Note: For DImode insns, there is normally no reason why operands should
400 ;; not be in the same register, what we don't want is for something being
401 ;; written to partially overlap something that is an input.
402 ;; Cirrus 64bit additions should not be split because we have a native
403 ;; 64bit addition instructions.
405 (define_expand "adddi3"
407 [(set (match_operand:DI 0 "s_register_operand" "")
408 (plus:DI (match_operand:DI 1 "s_register_operand" "")
409 (match_operand:DI 2 "s_register_operand" "")))
410 (clobber (reg:CC CC_REGNUM))])]
415 if (!cirrus_fp_register (operands[0], DImode))
416 operands[0] = force_reg (DImode, operands[0]);
417 if (!cirrus_fp_register (operands[1], DImode))
418 operands[1] = force_reg (DImode, operands[1]);
419 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
425 if (GET_CODE (operands[1]) != REG)
426 operands[1] = force_reg (SImode, operands[1]);
427 if (GET_CODE (operands[2]) != REG)
428 operands[2] = force_reg (SImode, operands[2]);
433 (define_insn "*thumb_adddi3"
434 [(set (match_operand:DI 0 "register_operand" "=l")
435 (plus:DI (match_operand:DI 1 "register_operand" "%0")
436 (match_operand:DI 2 "register_operand" "l")))
437 (clobber (reg:CC CC_REGNUM))
440 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
441 [(set_attr "length" "4")]
444 (define_insn_and_split "*arm_adddi3"
445 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
446 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
447 (match_operand:DI 2 "s_register_operand" "r, 0")))
448 (clobber (reg:CC CC_REGNUM))]
449 "TARGET_ARM && !TARGET_CIRRUS"
451 "TARGET_ARM && reload_completed"
452 [(parallel [(set (reg:CC_C CC_REGNUM)
453 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
455 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
456 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
457 (plus:SI (match_dup 4) (match_dup 5))))]
460 operands[3] = gen_highpart (SImode, operands[0]);
461 operands[0] = gen_lowpart (SImode, operands[0]);
462 operands[4] = gen_highpart (SImode, operands[1]);
463 operands[1] = gen_lowpart (SImode, operands[1]);
464 operands[5] = gen_highpart (SImode, operands[2]);
465 operands[2] = gen_lowpart (SImode, operands[2]);
467 [(set_attr "conds" "clob")
468 (set_attr "length" "8")]
471 (define_insn_and_split "*adddi_sesidi_di"
472 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
473 (plus:DI (sign_extend:DI
474 (match_operand:SI 2 "s_register_operand" "r,r"))
475 (match_operand:DI 1 "s_register_operand" "r,0")))
476 (clobber (reg:CC CC_REGNUM))]
477 "TARGET_ARM && !TARGET_CIRRUS"
479 "TARGET_ARM && reload_completed"
480 [(parallel [(set (reg:CC_C CC_REGNUM)
481 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
483 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
484 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
485 (plus:SI (ashiftrt:SI (match_dup 2)
490 operands[3] = gen_highpart (SImode, operands[0]);
491 operands[0] = gen_lowpart (SImode, operands[0]);
492 operands[4] = gen_highpart (SImode, operands[1]);
493 operands[1] = gen_lowpart (SImode, operands[1]);
494 operands[2] = gen_lowpart (SImode, operands[2]);
496 [(set_attr "conds" "clob")
497 (set_attr "length" "8")]
500 (define_insn_and_split "*adddi_zesidi_di"
501 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
502 (plus:DI (zero_extend:DI
503 (match_operand:SI 2 "s_register_operand" "r,r"))
504 (match_operand:DI 1 "s_register_operand" "r,0")))
505 (clobber (reg:CC CC_REGNUM))]
506 "TARGET_ARM && !TARGET_CIRRUS"
508 "TARGET_ARM && reload_completed"
509 [(parallel [(set (reg:CC_C CC_REGNUM)
510 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
512 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
513 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
514 (plus:SI (match_dup 4) (const_int 0))))]
517 operands[3] = gen_highpart (SImode, operands[0]);
518 operands[0] = gen_lowpart (SImode, operands[0]);
519 operands[4] = gen_highpart (SImode, operands[1]);
520 operands[1] = gen_lowpart (SImode, operands[1]);
521 operands[2] = gen_lowpart (SImode, operands[2]);
523 [(set_attr "conds" "clob")
524 (set_attr "length" "8")]
527 (define_expand "addsi3"
528 [(set (match_operand:SI 0 "s_register_operand" "")
529 (plus:SI (match_operand:SI 1 "s_register_operand" "")
530 (match_operand:SI 2 "reg_or_int_operand" "")))]
533 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
535 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
537 (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
543 ; If there is a scratch available, this will be faster than synthesising the
546 [(match_scratch:SI 3 "r")
547 (set (match_operand:SI 0 "s_register_operand" "")
548 (plus:SI (match_operand:SI 1 "s_register_operand" "")
549 (match_operand:SI 2 "const_int_operand" "")))]
551 !(const_ok_for_arm (INTVAL (operands[2]))
552 || const_ok_for_arm (-INTVAL (operands[2])))
553 && const_ok_for_arm (~INTVAL (operands[2]))"
554 [(set (match_dup 3) (match_dup 2))
555 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
559 (define_insn_and_split "*arm_addsi3"
560 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
561 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
562 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
569 GET_CODE (operands[2]) == CONST_INT
570 && !(const_ok_for_arm (INTVAL (operands[2]))
571 || const_ok_for_arm (-INTVAL (operands[2])))"
572 [(clobber (const_int 0))]
574 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
578 [(set_attr "length" "4,4,16")
579 (set_attr "predicable" "yes")]
582 ;; Register group 'k' is a single register group containing only the stack
583 ;; register. Trying to reload it will always fail catastrophically,
584 ;; so never allow those alternatives to match if reloading is needed.
586 (define_insn "*thumb_addsi3"
587 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
588 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
589 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
592 static const char * const asms[] =
594 \"add\\t%0, %0, %2\",
595 \"sub\\t%0, %0, #%n2\",
596 \"add\\t%0, %1, %2\",
597 \"add\\t%0, %0, %2\",
598 \"add\\t%0, %0, %2\",
599 \"add\\t%0, %1, %2\",
602 if ((which_alternative == 2 || which_alternative == 6)
603 && GET_CODE (operands[2]) == CONST_INT
604 && INTVAL (operands[2]) < 0)
605 return \"sub\\t%0, %1, #%n2\";
606 return asms[which_alternative];
608 [(set_attr "length" "2")]
611 ;; Reloading and elimination of the frame pointer can
612 ;; sometimes cause this optimization to be missed.
614 [(set (match_operand:SI 0 "register_operand" "")
615 (match_operand:SI 1 "const_int_operand" ""))
617 (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
619 && REGNO (operands[2]) == STACK_POINTER_REGNUM
620 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
621 && (INTVAL (operands[1]) & 3) == 0"
622 [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
626 (define_insn "*addsi3_compare0"
627 [(set (reg:CC_NOOV CC_REGNUM)
629 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
630 (match_operand:SI 2 "arm_add_operand" "rI,L"))
632 (set (match_operand:SI 0 "s_register_operand" "=r,r")
633 (plus:SI (match_dup 1) (match_dup 2)))]
637 sub%?s\\t%0, %1, #%n2"
638 [(set_attr "conds" "set")]
641 (define_insn "*addsi3_compare0_scratch"
642 [(set (reg:CC_NOOV CC_REGNUM)
644 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
645 (match_operand:SI 1 "arm_add_operand" "rI,L"))
651 [(set_attr "conds" "set")]
654 ;; These patterns are the same ones as the two regular addsi3_compare0
655 ;; patterns, except we write them slightly different - the combiner
656 ;; tends to generate them this way.
657 (define_insn "*addsi3_compare0_for_combiner"
658 [(set (reg:CC CC_REGNUM)
660 (match_operand:SI 1 "s_register_operand" "r,r")
661 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
662 (set (match_operand:SI 0 "s_register_operand" "=r,r")
663 (plus:SI (match_dup 1) (match_dup 2)))]
667 sub%?s\\t%0, %1, #%n2"
668 [(set_attr "conds" "set")]
671 (define_insn "*addsi3_compare0_scratch_for_combiner"
672 [(set (reg:CC CC_REGNUM)
674 (match_operand:SI 0 "s_register_operand" "r,r")
675 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
680 [(set_attr "conds" "set")]
683 ;; The next four insns work because they compare the result with one of
684 ;; the operands, and we know that the use of the condition code is
685 ;; either GEU or LTU, so we can use the carry flag from the addition
686 ;; instead of doing the compare a second time.
687 (define_insn "*addsi3_compare_op1"
688 [(set (reg:CC_C CC_REGNUM)
690 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
691 (match_operand:SI 2 "arm_add_operand" "rI,L"))
693 (set (match_operand:SI 0 "s_register_operand" "=r,r")
694 (plus:SI (match_dup 1) (match_dup 2)))]
698 sub%?s\\t%0, %1, #%n2"
699 [(set_attr "conds" "set")]
702 (define_insn "*addsi3_compare_op2"
703 [(set (reg:CC_C CC_REGNUM)
705 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
706 (match_operand:SI 2 "arm_add_operand" "rI,L"))
708 (set (match_operand:SI 0 "s_register_operand" "=r,r")
709 (plus:SI (match_dup 1) (match_dup 2)))]
713 sub%?s\\t%0, %1, #%n2"
714 [(set_attr "conds" "set")]
717 (define_insn "*compare_addsi2_op0"
718 [(set (reg:CC_C CC_REGNUM)
720 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
721 (match_operand:SI 1 "arm_add_operand" "rI,L"))
727 [(set_attr "conds" "set")]
730 (define_insn "*compare_addsi2_op1"
731 [(set (reg:CC_C CC_REGNUM)
733 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
734 (match_operand:SI 1 "arm_add_operand" "rI,L"))
740 [(set_attr "conds" "set")]
743 (define_insn "*addsi3_carryin"
744 [(set (match_operand:SI 0 "s_register_operand" "=r")
745 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
746 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
747 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
750 [(set_attr "conds" "use")]
753 (define_insn "*addsi3_carryin_shift"
754 [(set (match_operand:SI 0 "s_register_operand" "")
755 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
757 (match_operator:SI 2 "shift_operator"
758 [(match_operand:SI 3 "s_register_operand" "")
759 (match_operand:SI 4 "reg_or_int_operand" "")])
760 (match_operand:SI 1 "s_register_operand" ""))))]
762 "adc%?\\t%0, %1, %3%S2"
763 [(set_attr "conds" "use")]
766 (define_insn "*addsi3_carryin_alt1"
767 [(set (match_operand:SI 0 "s_register_operand" "=r")
768 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
769 (match_operand:SI 2 "arm_rhs_operand" "rI"))
770 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
773 [(set_attr "conds" "use")]
776 (define_insn "*addsi3_carryin_alt2"
777 [(set (match_operand:SI 0 "s_register_operand" "=r")
778 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
779 (match_operand:SI 1 "s_register_operand" "r"))
780 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
783 [(set_attr "conds" "use")]
786 (define_insn "*addsi3_carryin_alt3"
787 [(set (match_operand:SI 0 "s_register_operand" "=r")
788 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
789 (match_operand:SI 2 "arm_rhs_operand" "rI"))
790 (match_operand:SI 1 "s_register_operand" "r")))]
793 [(set_attr "conds" "use")]
796 (define_insn "incscc"
797 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
798 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
799 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
800 (match_operand:SI 1 "s_register_operand" "0,?r")))]
804 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
805 [(set_attr "conds" "use")
806 (set_attr "length" "4,8")]
809 (define_insn "*arm_addsf3"
810 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
811 (plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
812 (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
813 "TARGET_ARM && TARGET_HARD_FLOAT"
816 suf%?s\\t%0, %1, #%N2"
817 [(set_attr "type" "farith")
818 (set_attr "predicable" "yes")]
821 (define_insn "*arm_adddf3"
822 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
823 (plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
824 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
825 "TARGET_ARM && TARGET_HARD_FLOAT"
828 suf%?d\\t%0, %1, #%N2"
829 [(set_attr "type" "farith")
830 (set_attr "predicable" "yes")]
833 (define_insn "*adddf_esfdf_df"
834 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
835 (plus:DF (float_extend:DF
836 (match_operand:SF 1 "s_register_operand" "f,f"))
837 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
838 "TARGET_ARM && TARGET_HARD_FLOAT"
841 suf%?d\\t%0, %1, #%N2"
842 [(set_attr "type" "farith")
843 (set_attr "predicable" "yes")]
846 (define_insn "*adddf_df_esfdf"
847 [(set (match_operand:DF 0 "s_register_operand" "=f")
848 (plus:DF (match_operand:DF 1 "s_register_operand" "f")
850 (match_operand:SF 2 "s_register_operand" "f"))))]
851 "TARGET_ARM && TARGET_HARD_FLOAT"
852 "adf%?d\\t%0, %1, %2"
853 [(set_attr "type" "farith")
854 (set_attr "predicable" "yes")]
857 (define_insn "*adddf_esfdf_esfdf"
858 [(set (match_operand:DF 0 "s_register_operand" "=f")
859 (plus:DF (float_extend:DF
860 (match_operand:SF 1 "s_register_operand" "f"))
862 (match_operand:SF 2 "s_register_operand" "f"))))]
863 "TARGET_ARM && TARGET_HARD_FLOAT"
864 "adf%?d\\t%0, %1, %2"
865 [(set_attr "type" "farith")
866 (set_attr "predicable" "yes")]
869 (define_expand "subdi3"
871 [(set (match_operand:DI 0 "s_register_operand" "")
872 (minus:DI (match_operand:DI 1 "s_register_operand" "")
873 (match_operand:DI 2 "s_register_operand" "")))
874 (clobber (reg:CC CC_REGNUM))])]
879 && cirrus_fp_register (operands[0], DImode)
880 && cirrus_fp_register (operands[1], DImode))
882 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
888 if (GET_CODE (operands[1]) != REG)
889 operands[1] = force_reg (SImode, operands[1]);
890 if (GET_CODE (operands[2]) != REG)
891 operands[2] = force_reg (SImode, operands[2]);
896 (define_insn "*arm_subdi3"
897 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
898 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
899 (match_operand:DI 2 "s_register_operand" "r,0,0")))
900 (clobber (reg:CC CC_REGNUM))]
902 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
903 [(set_attr "conds" "clob")
904 (set_attr "length" "8")]
907 (define_insn "*thumb_subdi3"
908 [(set (match_operand:DI 0 "register_operand" "=l")
909 (minus:DI (match_operand:DI 1 "register_operand" "0")
910 (match_operand:DI 2 "register_operand" "l")))
911 (clobber (reg:CC CC_REGNUM))]
913 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
914 [(set_attr "length" "4")]
917 (define_insn "*subdi_di_zesidi"
918 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
919 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
921 (match_operand:SI 2 "s_register_operand" "r,r"))))
922 (clobber (reg:CC CC_REGNUM))]
924 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
925 [(set_attr "conds" "clob")
926 (set_attr "length" "8")]
929 (define_insn "*subdi_di_sesidi"
930 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
931 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
933 (match_operand:SI 2 "s_register_operand" "r,r"))))
934 (clobber (reg:CC CC_REGNUM))]
936 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
937 [(set_attr "conds" "clob")
938 (set_attr "length" "8")]
941 (define_insn "*subdi_zesidi_di"
942 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
943 (minus:DI (zero_extend:DI
944 (match_operand:SI 2 "s_register_operand" "r,r"))
945 (match_operand:DI 1 "s_register_operand" "?r,0")))
946 (clobber (reg:CC CC_REGNUM))]
948 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
949 [(set_attr "conds" "clob")
950 (set_attr "length" "8")]
953 (define_insn "*subdi_sesidi_di"
954 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
955 (minus:DI (sign_extend:DI
956 (match_operand:SI 2 "s_register_operand" "r,r"))
957 (match_operand:DI 1 "s_register_operand" "?r,0")))
958 (clobber (reg:CC CC_REGNUM))]
960 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
961 [(set_attr "conds" "clob")
962 (set_attr "length" "8")]
965 (define_insn "*subdi_zesidi_zesidi"
966 [(set (match_operand:DI 0 "s_register_operand" "=r")
967 (minus:DI (zero_extend:DI
968 (match_operand:SI 1 "s_register_operand" "r"))
970 (match_operand:SI 2 "s_register_operand" "r"))))
971 (clobber (reg:CC CC_REGNUM))]
973 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
974 [(set_attr "conds" "clob")
975 (set_attr "length" "8")]
978 (define_expand "subsi3"
979 [(set (match_operand:SI 0 "s_register_operand" "")
980 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
981 (match_operand:SI 2 "s_register_operand" "")))]
984 if (GET_CODE (operands[1]) == CONST_INT)
988 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
991 : preserve_subexpressions_p ()));
994 else /* TARGET_THUMB */
995 operands[1] = force_reg (SImode, operands[1]);
1000 (define_insn "*thumb_subsi3_insn"
1001 [(set (match_operand:SI 0 "register_operand" "=l")
1002 (minus:SI (match_operand:SI 1 "register_operand" "l")
1003 (match_operand:SI 2 "register_operand" "l")))]
1006 [(set_attr "length" "2")]
1009 (define_insn_and_split "*arm_subsi3_insn"
1010 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1011 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
1012 (match_operand:SI 2 "s_register_operand" "r,r")))]
1018 && GET_CODE (operands[1]) == CONST_INT
1019 && !const_ok_for_arm (INTVAL (operands[1]))"
1020 [(clobber (const_int 0))]
1022 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1026 [(set_attr "length" "4,16")
1027 (set_attr "predicable" "yes")]
1031 [(match_scratch:SI 3 "r")
1032 (set (match_operand:SI 0 "s_register_operand" "")
1033 (minus:SI (match_operand:SI 1 "const_int_operand" "")
1034 (match_operand:SI 2 "s_register_operand" "")))]
1036 && !const_ok_for_arm (INTVAL (operands[1]))
1037 && const_ok_for_arm (~INTVAL (operands[1]))"
1038 [(set (match_dup 3) (match_dup 1))
1039 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1043 (define_insn "*subsi3_compare0"
1044 [(set (reg:CC_NOOV CC_REGNUM)
1046 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1047 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1049 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1050 (minus:SI (match_dup 1) (match_dup 2)))]
1054 rsb%?s\\t%0, %2, %1"
1055 [(set_attr "conds" "set")]
1058 (define_insn "decscc"
1059 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1060 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1061 (match_operator:SI 2 "arm_comparison_operator"
1062 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1066 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1067 [(set_attr "conds" "use")
1068 (set_attr "length" "*,8")]
1071 (define_insn "*arm_subsf3"
1072 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1073 (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1074 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1075 "TARGET_ARM && TARGET_HARD_FLOAT"
1078 rsf%?s\\t%0, %2, %1"
1079 [(set_attr "type" "farith")]
1082 (define_insn "*arm_subdf3"
1083 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1084 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1085 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1086 "TARGET_ARM && TARGET_HARD_FLOAT"
1089 rsf%?d\\t%0, %2, %1"
1090 [(set_attr "type" "farith")
1091 (set_attr "predicable" "yes")]
1094 (define_insn "*subdf_esfdf_df"
1095 [(set (match_operand:DF 0 "s_register_operand" "=f")
1096 (minus:DF (float_extend:DF
1097 (match_operand:SF 1 "s_register_operand" "f"))
1098 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1099 "TARGET_ARM && TARGET_HARD_FLOAT"
1100 "suf%?d\\t%0, %1, %2"
1101 [(set_attr "type" "farith")
1102 (set_attr "predicable" "yes")]
1105 (define_insn "*subdf_df_esfdf"
1106 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1107 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1109 (match_operand:SF 2 "s_register_operand" "f,f"))))]
1110 "TARGET_ARM && TARGET_HARD_FLOAT"
1113 rsf%?d\\t%0, %2, %1"
1114 [(set_attr "type" "farith")
1115 (set_attr "predicable" "yes")]
1118 (define_insn "*subdf_esfdf_esfdf"
1119 [(set (match_operand:DF 0 "s_register_operand" "=f")
1120 (minus:DF (float_extend:DF
1121 (match_operand:SF 1 "s_register_operand" "f"))
1123 (match_operand:SF 2 "s_register_operand" "f"))))]
1124 "TARGET_ARM && TARGET_HARD_FLOAT"
1125 "suf%?d\\t%0, %1, %2"
1126 [(set_attr "type" "farith")
1127 (set_attr "predicable" "yes")]
1130 ;; Multiplication insns
1132 (define_expand "mulsi3"
1133 [(set (match_operand:SI 0 "s_register_operand" "")
1134 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1135 (match_operand:SI 1 "s_register_operand" "")))]
1140 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1141 (define_insn "*arm_mulsi3"
1142 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1143 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1144 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1146 "mul%?\\t%0, %2, %1"
1147 [(set_attr "type" "mult")
1148 (set_attr "predicable" "yes")]
1151 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1152 ; 1 and 2; are the same, because reload will make operand 0 match
1153 ; operand 1 without realizing that this conflicts with operand 2. We fix
1154 ; this by adding another alternative to match this case, and then `reload'
1155 ; it ourselves. This alternative must come first.
1156 (define_insn "*thumb_mulsi3"
1157 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1158 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1159 (match_operand:SI 2 "register_operand" "l,l,l")))]
1162 if (which_alternative < 2)
1163 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1165 return \"mul\\t%0, %0, %2\";
1167 [(set_attr "length" "4,4,2")
1168 (set_attr "type" "mult")]
1171 (define_insn "*mulsi3_compare0"
1172 [(set (reg:CC_NOOV CC_REGNUM)
1173 (compare:CC_NOOV (mult:SI
1174 (match_operand:SI 2 "s_register_operand" "r,r")
1175 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1177 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1178 (mult:SI (match_dup 2) (match_dup 1)))]
1179 "TARGET_ARM && !arm_is_xscale"
1180 "mul%?s\\t%0, %2, %1"
1181 [(set_attr "conds" "set")
1182 (set_attr "type" "mult")]
1185 (define_insn "*mulsi_compare0_scratch"
1186 [(set (reg:CC_NOOV CC_REGNUM)
1187 (compare:CC_NOOV (mult:SI
1188 (match_operand:SI 2 "s_register_operand" "r,r")
1189 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1191 (clobber (match_scratch:SI 0 "=&r,&r"))]
1192 "TARGET_ARM && !arm_is_xscale"
1193 "mul%?s\\t%0, %2, %1"
1194 [(set_attr "conds" "set")
1195 (set_attr "type" "mult")]
1198 ;; Unnamed templates to match MLA instruction.
1200 (define_insn "*mulsi3addsi"
1201 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1203 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1204 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1205 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1207 "mla%?\\t%0, %2, %1, %3"
1208 [(set_attr "type" "mult")
1209 (set_attr "predicable" "yes")]
1212 (define_insn "*mulsi3addsi_compare0"
1213 [(set (reg:CC_NOOV CC_REGNUM)
1216 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1217 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1218 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1220 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1221 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1223 "TARGET_ARM && !arm_is_xscale"
1224 "mla%?s\\t%0, %2, %1, %3"
1225 [(set_attr "conds" "set")
1226 (set_attr "type" "mult")]
1229 (define_insn "*mulsi3addsi_compare0_scratch"
1230 [(set (reg:CC_NOOV CC_REGNUM)
1233 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1234 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1235 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1237 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1238 "TARGET_ARM && !arm_is_xscale"
1239 "mla%?s\\t%0, %2, %1, %3"
1240 [(set_attr "conds" "set")
1241 (set_attr "type" "mult")]
1244 ;; Unnamed template to match long long multiply-accumlate (smlal)
1246 (define_insn "*mulsidi3adddi"
1247 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1250 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1251 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1252 (match_operand:DI 1 "s_register_operand" "0")))]
1253 "TARGET_ARM && arm_fast_multiply"
1254 "smlal%?\\t%Q0, %R0, %3, %2"
1255 [(set_attr "type" "mult")
1256 (set_attr "predicable" "yes")]
1259 (define_insn "mulsidi3"
1260 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1262 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1263 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1264 "TARGET_ARM && arm_fast_multiply"
1265 "smull%?\\t%Q0, %R0, %1, %2"
1266 [(set_attr "type" "mult")
1267 (set_attr "predicable" "yes")]
1270 (define_insn "umulsidi3"
1271 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1273 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1274 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1275 "TARGET_ARM && arm_fast_multiply"
1276 "umull%?\\t%Q0, %R0, %1, %2"
1277 [(set_attr "type" "mult")
1278 (set_attr "predicable" "yes")]
1281 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1283 (define_insn "*umulsidi3adddi"
1284 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1287 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1288 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1289 (match_operand:DI 1 "s_register_operand" "0")))]
1290 "TARGET_ARM && arm_fast_multiply"
1291 "umlal%?\\t%Q0, %R0, %3, %2"
1292 [(set_attr "type" "mult")
1293 (set_attr "predicable" "yes")]
1296 (define_insn "smulsi3_highpart"
1297 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1301 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1302 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1304 (clobber (match_scratch:SI 3 "=&r,&r"))]
1305 "TARGET_ARM && arm_fast_multiply"
1306 "smull%?\\t%3, %0, %2, %1"
1307 [(set_attr "type" "mult")
1308 (set_attr "predicable" "yes")]
1311 (define_insn "umulsi3_highpart"
1312 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1316 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1317 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1319 (clobber (match_scratch:SI 3 "=&r,&r"))]
1320 "TARGET_ARM && arm_fast_multiply"
1321 "umull%?\\t%3, %0, %2, %1"
1322 [(set_attr "type" "mult")
1323 (set_attr "predicable" "yes")]
1326 (define_insn "mulhisi3"
1327 [(set (match_operand:SI 0 "s_register_operand" "=r")
1328 (mult:SI (sign_extend:SI
1329 (match_operand:HI 1 "s_register_operand" "%r"))
1331 (match_operand:HI 2 "s_register_operand" "r"))))]
1332 "TARGET_ARM && arm_is_xscale"
1333 "smulbb%?\\t%0, %1, %2"
1334 [(set_attr "type" "mult")]
1337 (define_insn "*mulhisi3addsi"
1338 [(set (match_operand:SI 0 "s_register_operand" "=r")
1339 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1340 (mult:SI (sign_extend:SI
1341 (match_operand:HI 2 "s_register_operand" "%r"))
1343 (match_operand:HI 3 "s_register_operand" "r")))))]
1344 "TARGET_ARM && arm_is_xscale"
1345 "smlabb%?\\t%0, %2, %3, %1"
1346 [(set_attr "type" "mult")]
1349 (define_insn "*mulhidi3adddi"
1350 [(set (match_operand:DI 0 "s_register_operand" "=r")
1352 (match_operand:DI 1 "s_register_operand" "0")
1353 (mult:DI (sign_extend:DI
1354 (match_operand:HI 2 "s_register_operand" "%r"))
1356 (match_operand:HI 3 "s_register_operand" "r")))))]
1357 "TARGET_ARM && arm_is_xscale"
1358 "smlalbb%?\\t%Q0, %R0, %2, %3"
1359 [(set_attr "type" "mult")])
1361 (define_insn "*arm_mulsf3"
1362 [(set (match_operand:SF 0 "s_register_operand" "=f")
1363 (mult:SF (match_operand:SF 1 "s_register_operand" "f")
1364 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1365 "TARGET_ARM && TARGET_HARD_FLOAT"
1366 "fml%?s\\t%0, %1, %2"
1367 [(set_attr "type" "ffmul")
1368 (set_attr "predicable" "yes")]
1371 (define_insn "*arm_muldf3"
1372 [(set (match_operand:DF 0 "s_register_operand" "=f")
1373 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1374 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1375 "TARGET_ARM && TARGET_HARD_FLOAT"
1376 "muf%?d\\t%0, %1, %2"
1377 [(set_attr "type" "fmul")
1378 (set_attr "predicable" "yes")]
1381 (define_insn "*muldf_esfdf_df"
1382 [(set (match_operand:DF 0 "s_register_operand" "=f")
1383 (mult:DF (float_extend:DF
1384 (match_operand:SF 1 "s_register_operand" "f"))
1385 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1386 "TARGET_ARM && TARGET_HARD_FLOAT"
1387 "muf%?d\\t%0, %1, %2"
1388 [(set_attr "type" "fmul")
1389 (set_attr "predicable" "yes")]
1392 (define_insn "*muldf_df_esfdf"
1393 [(set (match_operand:DF 0 "s_register_operand" "=f")
1394 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1396 (match_operand:SF 2 "s_register_operand" "f"))))]
1397 "TARGET_ARM && TARGET_HARD_FLOAT"
1398 "muf%?d\\t%0, %1, %2"
1399 [(set_attr "type" "fmul")
1400 (set_attr "predicable" "yes")]
1403 (define_insn "*muldf_esfdf_esfdf"
1404 [(set (match_operand:DF 0 "s_register_operand" "=f")
1406 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f"))
1407 (float_extend:DF (match_operand:SF 2 "s_register_operand" "f"))))]
1408 "TARGET_ARM && TARGET_HARD_FLOAT"
1409 "muf%?d\\t%0, %1, %2"
1410 [(set_attr "type" "fmul")
1411 (set_attr "predicable" "yes")]
1416 (define_insn "divsf3"
1417 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1418 (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1419 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1420 "TARGET_ARM && TARGET_HARD_FLOAT"
1423 frd%?s\\t%0, %2, %1"
1424 [(set_attr "type" "fdivs")
1425 (set_attr "predicable" "yes")]
1428 (define_insn "divdf3"
1429 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1430 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1431 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1432 "TARGET_ARM && TARGET_HARD_FLOAT"
1435 rdf%?d\\t%0, %2, %1"
1436 [(set_attr "type" "fdivd")
1437 (set_attr "predicable" "yes")]
1440 (define_insn "*divdf_esfdf_df"
1441 [(set (match_operand:DF 0 "s_register_operand" "=f")
1442 (div:DF (float_extend:DF
1443 (match_operand:SF 1 "s_register_operand" "f"))
1444 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1445 "TARGET_ARM && TARGET_HARD_FLOAT"
1446 "dvf%?d\\t%0, %1, %2"
1447 [(set_attr "type" "fdivd")
1448 (set_attr "predicable" "yes")]
1451 (define_insn "*divdf_df_esfdf"
1452 [(set (match_operand:DF 0 "s_register_operand" "=f")
1453 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1455 (match_operand:SF 2 "s_register_operand" "f"))))]
1456 "TARGET_ARM && TARGET_HARD_FLOAT"
1457 "rdf%?d\\t%0, %2, %1"
1458 [(set_attr "type" "fdivd")
1459 (set_attr "predicable" "yes")]
1462 (define_insn "*divdf_esfdf_esfdf"
1463 [(set (match_operand:DF 0 "s_register_operand" "=f")
1464 (div:DF (float_extend:DF
1465 (match_operand:SF 1 "s_register_operand" "f"))
1467 (match_operand:SF 2 "s_register_operand" "f"))))]
1468 "TARGET_ARM && TARGET_HARD_FLOAT"
1469 "dvf%?d\\t%0, %1, %2"
1470 [(set_attr "type" "fdivd")
1471 (set_attr "predicable" "yes")]
1476 (define_insn "modsf3"
1477 [(set (match_operand:SF 0 "s_register_operand" "=f")
1478 (mod:SF (match_operand:SF 1 "s_register_operand" "f")
1479 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1480 "TARGET_ARM && TARGET_HARD_FLOAT"
1481 "rmf%?s\\t%0, %1, %2"
1482 [(set_attr "type" "fdivs")
1483 (set_attr "predicable" "yes")]
1486 (define_insn "moddf3"
1487 [(set (match_operand:DF 0 "s_register_operand" "=f")
1488 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1489 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1490 "TARGET_ARM && TARGET_HARD_FLOAT"
1491 "rmf%?d\\t%0, %1, %2"
1492 [(set_attr "type" "fdivd")
1493 (set_attr "predicable" "yes")]
1496 (define_insn "*moddf_esfdf_df"
1497 [(set (match_operand:DF 0 "s_register_operand" "=f")
1498 (mod:DF (float_extend:DF
1499 (match_operand:SF 1 "s_register_operand" "f"))
1500 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1501 "TARGET_ARM && TARGET_HARD_FLOAT"
1502 "rmf%?d\\t%0, %1, %2"
1503 [(set_attr "type" "fdivd")
1504 (set_attr "predicable" "yes")]
1507 (define_insn "*moddf_df_esfdf"
1508 [(set (match_operand:DF 0 "s_register_operand" "=f")
1509 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1511 (match_operand:SF 2 "s_register_operand" "f"))))]
1512 "TARGET_ARM && TARGET_HARD_FLOAT"
1513 "rmf%?d\\t%0, %1, %2"
1514 [(set_attr "type" "fdivd")
1515 (set_attr "predicable" "yes")]
1518 (define_insn "*moddf_esfdf_esfdf"
1519 [(set (match_operand:DF 0 "s_register_operand" "=f")
1520 (mod:DF (float_extend:DF
1521 (match_operand:SF 1 "s_register_operand" "f"))
1523 (match_operand:SF 2 "s_register_operand" "f"))))]
1524 "TARGET_ARM && TARGET_HARD_FLOAT"
1525 "rmf%?d\\t%0, %1, %2"
1526 [(set_attr "type" "fdivd")
1527 (set_attr "predicable" "yes")]
1530 ;; Boolean and,ior,xor insns
1532 ;; Split up double word logical operations
1534 ;; Split up simple DImode logical operations. Simply perform the logical
1535 ;; operation on the upper and lower halves of the registers.
1537 [(set (match_operand:DI 0 "s_register_operand" "")
1538 (match_operator:DI 6 "logical_binary_operator"
1539 [(match_operand:DI 1 "s_register_operand" "")
1540 (match_operand:DI 2 "s_register_operand" "")]))]
1541 "TARGET_ARM && reload_completed"
1542 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1543 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1546 operands[3] = gen_highpart (SImode, operands[0]);
1547 operands[0] = gen_lowpart (SImode, operands[0]);
1548 operands[4] = gen_highpart (SImode, operands[1]);
1549 operands[1] = gen_lowpart (SImode, operands[1]);
1550 operands[5] = gen_highpart (SImode, operands[2]);
1551 operands[2] = gen_lowpart (SImode, operands[2]);
1556 [(set (match_operand:DI 0 "s_register_operand" "")
1557 (match_operator:DI 6 "logical_binary_operator"
1558 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1559 (match_operand:DI 1 "s_register_operand" "")]))]
1560 "TARGET_ARM && reload_completed"
1561 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1562 (set (match_dup 3) (match_op_dup:SI 6
1563 [(ashiftrt:SI (match_dup 2) (const_int 31))
1567 operands[3] = gen_highpart (SImode, operands[0]);
1568 operands[0] = gen_lowpart (SImode, operands[0]);
1569 operands[4] = gen_highpart (SImode, operands[1]);
1570 operands[1] = gen_lowpart (SImode, operands[1]);
1571 operands[5] = gen_highpart (SImode, operands[2]);
1572 operands[2] = gen_lowpart (SImode, operands[2]);
1576 ;; The zero extend of operand 2 means we can just copy the high part of
1577 ;; operand1 into operand0.
1579 [(set (match_operand:DI 0 "s_register_operand" "")
1581 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1582 (match_operand:DI 1 "s_register_operand" "")))]
1583 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1584 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1585 (set (match_dup 3) (match_dup 4))]
1588 operands[4] = gen_highpart (SImode, operands[1]);
1589 operands[3] = gen_highpart (SImode, operands[0]);
1590 operands[0] = gen_lowpart (SImode, operands[0]);
1591 operands[1] = gen_lowpart (SImode, operands[1]);
1595 ;; The zero extend of operand 2 means we can just copy the high part of
1596 ;; operand1 into operand0.
1598 [(set (match_operand:DI 0 "s_register_operand" "")
1600 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1601 (match_operand:DI 1 "s_register_operand" "")))]
1602 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1603 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1604 (set (match_dup 3) (match_dup 4))]
1607 operands[4] = gen_highpart (SImode, operands[1]);
1608 operands[3] = gen_highpart (SImode, operands[0]);
1609 operands[0] = gen_lowpart (SImode, operands[0]);
1610 operands[1] = gen_lowpart (SImode, operands[1]);
1614 (define_insn "anddi3"
1615 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1616 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1617 (match_operand:DI 2 "s_register_operand" "r,r")))]
1620 [(set_attr "length" "8")]
1623 (define_insn_and_split "*anddi_zesidi_di"
1624 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1625 (and:DI (zero_extend:DI
1626 (match_operand:SI 2 "s_register_operand" "r,r"))
1627 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1630 "TARGET_ARM && reload_completed"
1631 ; The zero extend of operand 2 clears the high word of the output
1633 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1634 (set (match_dup 3) (const_int 0))]
1637 operands[3] = gen_highpart (SImode, operands[0]);
1638 operands[0] = gen_lowpart (SImode, operands[0]);
1639 operands[1] = gen_lowpart (SImode, operands[1]);
1641 [(set_attr "length" "8")]
1644 (define_insn "*anddi_sesdi_di"
1645 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1646 (and:DI (sign_extend:DI
1647 (match_operand:SI 2 "s_register_operand" "r,r"))
1648 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1651 [(set_attr "length" "8")]
1654 (define_expand "andsi3"
1655 [(set (match_operand:SI 0 "s_register_operand" "")
1656 (and:SI (match_operand:SI 1 "s_register_operand" "")
1657 (match_operand:SI 2 "reg_or_int_operand" "")))]
1662 if (GET_CODE (operands[2]) == CONST_INT)
1664 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1667 ? 0 : preserve_subexpressions_p ()));
1671 else /* TARGET_THUMB */
1673 if (GET_CODE (operands[2]) != CONST_INT)
1674 operands[2] = force_reg (SImode, operands[2]);
1679 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1681 operands[2] = force_reg (SImode,
1682 GEN_INT (~INTVAL (operands[2])));
1684 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1689 for (i = 9; i <= 31; i++)
1691 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1693 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1697 else if ((((HOST_WIDE_INT) 1) << i) - 1
1698 == ~INTVAL (operands[2]))
1700 rtx shift = GEN_INT (i);
1701 rtx reg = gen_reg_rtx (SImode);
1703 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1704 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1710 operands[2] = force_reg (SImode, operands[2]);
1716 (define_insn_and_split "*arm_andsi3_insn"
1717 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1718 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1719 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1723 bic%?\\t%0, %1, #%B2
1726 && GET_CODE (operands[2]) == CONST_INT
1727 && !(const_ok_for_arm (INTVAL (operands[2]))
1728 || const_ok_for_arm (~INTVAL (operands[2])))"
1729 [(clobber (const_int 0))]
1731 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1735 [(set_attr "length" "4,4,16")
1736 (set_attr "predicable" "yes")]
1739 (define_insn "*thumb_andsi3_insn"
1740 [(set (match_operand:SI 0 "register_operand" "=l")
1741 (and:SI (match_operand:SI 1 "register_operand" "%0")
1742 (match_operand:SI 2 "register_operand" "l")))]
1745 [(set_attr "length" "2")]
1748 (define_insn "*andsi3_compare0"
1749 [(set (reg:CC_NOOV CC_REGNUM)
1751 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1752 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1754 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1755 (and:SI (match_dup 1) (match_dup 2)))]
1759 bic%?s\\t%0, %1, #%B2"
1760 [(set_attr "conds" "set")]
1763 (define_insn "*andsi3_compare0_scratch"
1764 [(set (reg:CC_NOOV CC_REGNUM)
1766 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1767 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1769 (clobber (match_scratch:SI 2 "=X,r"))]
1773 bic%?s\\t%2, %0, #%B1"
1774 [(set_attr "conds" "set")]
1777 (define_insn "*zeroextractsi_compare0_scratch"
1778 [(set (reg:CC_NOOV CC_REGNUM)
1779 (compare:CC_NOOV (zero_extract:SI
1780 (match_operand:SI 0 "s_register_operand" "r")
1781 (match_operand 1 "const_int_operand" "n")
1782 (match_operand 2 "const_int_operand" "n"))
1785 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1786 && INTVAL (operands[1]) > 0
1787 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1788 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1790 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1791 << INTVAL (operands[2]));
1792 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1795 [(set_attr "conds" "set")]
1798 (define_insn "*ne_zeroextractsi"
1799 [(set (match_operand:SI 0 "s_register_operand" "=r")
1800 (ne:SI (zero_extract:SI
1801 (match_operand:SI 1 "s_register_operand" "r")
1802 (match_operand:SI 2 "const_int_operand" "n")
1803 (match_operand:SI 3 "const_int_operand" "n"))
1805 (clobber (reg:CC CC_REGNUM))]
1807 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1808 && INTVAL (operands[2]) > 0
1809 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1810 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1812 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1813 << INTVAL (operands[3]));
1814 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1815 return \"movne\\t%0, #1\";
1817 [(set_attr "conds" "clob")
1818 (set_attr "length" "8")]
1821 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1822 ;;; represented by the bitfield, then this will produce incorrect results.
1823 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1824 ;;; which have a real bit-field insert instruction, the truncation happens
1825 ;;; in the bit-field insert instruction itself. Since arm does not have a
1826 ;;; bit-field insert instruction, we would have to emit code here to truncate
1827 ;;; the value before we insert. This loses some of the advantage of having
1828 ;;; this insv pattern, so this pattern needs to be reevalutated.
1830 (define_expand "insv"
1831 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1832 (match_operand:SI 1 "general_operand" "")
1833 (match_operand:SI 2 "general_operand" ""))
1834 (match_operand:SI 3 "reg_or_int_operand" ""))]
1838 int start_bit = INTVAL (operands[2]);
1839 int width = INTVAL (operands[1]);
1840 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1841 rtx target, subtarget;
1843 target = operands[0];
1844 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1845 subreg as the final target. */
1846 if (GET_CODE (target) == SUBREG)
1848 subtarget = gen_reg_rtx (SImode);
1849 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1850 < GET_MODE_SIZE (SImode))
1851 target = SUBREG_REG (target);
1856 if (GET_CODE (operands[3]) == CONST_INT)
1858 /* Since we are inserting a known constant, we may be able to
1859 reduce the number of bits that we have to clear so that
1860 the mask becomes simple. */
1861 /* ??? This code does not check to see if the new mask is actually
1862 simpler. It may not be. */
1863 rtx op1 = gen_reg_rtx (SImode);
1864 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1865 start of this pattern. */
1866 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1867 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1869 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1870 emit_insn (gen_iorsi3 (subtarget, op1,
1871 GEN_INT (op3_value << start_bit)));
1873 else if (start_bit == 0
1874 && !(const_ok_for_arm (mask)
1875 || const_ok_for_arm (~mask)))
1877 /* A Trick, since we are setting the bottom bits in the word,
1878 we can shift operand[3] up, operand[0] down, OR them together
1879 and rotate the result back again. This takes 3 insns, and
1880 the third might be mergable into another op. */
1881 /* The shift up copes with the possibility that operand[3] is
1882 wider than the bitfield. */
1883 rtx op0 = gen_reg_rtx (SImode);
1884 rtx op1 = gen_reg_rtx (SImode);
1886 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1887 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1888 emit_insn (gen_iorsi3 (op1, op1, op0));
1889 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1891 else if ((width + start_bit == 32)
1892 && !(const_ok_for_arm (mask)
1893 || const_ok_for_arm (~mask)))
1895 /* Similar trick, but slightly less efficient. */
1897 rtx op0 = gen_reg_rtx (SImode);
1898 rtx op1 = gen_reg_rtx (SImode);
1900 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1901 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1902 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1903 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1907 rtx op0 = GEN_INT (mask);
1908 rtx op1 = gen_reg_rtx (SImode);
1909 rtx op2 = gen_reg_rtx (SImode);
1911 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1913 rtx tmp = gen_reg_rtx (SImode);
1915 emit_insn (gen_movsi (tmp, op0));
1919 /* Mask out any bits in operand[3] that are not needed. */
1920 emit_insn (gen_andsi3 (op1, operands[3], op0));
1922 if (GET_CODE (op0) == CONST_INT
1923 && (const_ok_for_arm (mask << start_bit)
1924 || const_ok_for_arm (~(mask << start_bit))))
1926 op0 = GEN_INT (~(mask << start_bit));
1927 emit_insn (gen_andsi3 (op2, operands[0], op0));
1931 if (GET_CODE (op0) == CONST_INT)
1933 rtx tmp = gen_reg_rtx (SImode);
1935 emit_insn (gen_movsi (tmp, op0));
1940 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1942 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1946 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1948 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1951 if (subtarget != target)
1953 /* If TARGET is still a SUBREG, then it must be wider than a word,
1954 so we must be careful only to set the subword we were asked to. */
1955 if (GET_CODE (target) == SUBREG)
1956 emit_move_insn (target, subtarget);
1958 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1965 ; constants for op 2 will never be given to these patterns.
1966 (define_insn_and_split "*anddi_notdi_di"
1967 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1968 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1969 (match_operand:DI 2 "s_register_operand" "0,r")))]
1972 "TARGET_ARM && reload_completed"
1973 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1974 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1977 operands[3] = gen_highpart (SImode, operands[0]);
1978 operands[0] = gen_lowpart (SImode, operands[0]);
1979 operands[4] = gen_highpart (SImode, operands[1]);
1980 operands[1] = gen_lowpart (SImode, operands[1]);
1981 operands[5] = gen_highpart (SImode, operands[2]);
1982 operands[2] = gen_lowpart (SImode, operands[2]);
1984 [(set_attr "length" "8")
1985 (set_attr "predicable" "yes")]
1988 (define_insn_and_split "*anddi_notzesidi_di"
1989 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1990 (and:DI (not:DI (zero_extend:DI
1991 (match_operand:SI 2 "s_register_operand" "r,r")))
1992 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1995 bic%?\\t%Q0, %Q1, %2
1997 ; (not (zero_extend ...)) allows us to just copy the high word from
1998 ; operand1 to operand0.
2001 && operands[0] != operands[1]"
2002 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2003 (set (match_dup 3) (match_dup 4))]
2006 operands[3] = gen_highpart (SImode, operands[0]);
2007 operands[0] = gen_lowpart (SImode, operands[0]);
2008 operands[4] = gen_highpart (SImode, operands[1]);
2009 operands[1] = gen_lowpart (SImode, operands[1]);
2011 [(set_attr "length" "4,8")
2012 (set_attr "predicable" "yes")]
2015 (define_insn_and_split "*anddi_notsesidi_di"
2016 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2017 (and:DI (not:DI (sign_extend:DI
2018 (match_operand:SI 2 "s_register_operand" "r,r")))
2019 (match_operand:DI 1 "s_register_operand" "0,r")))]
2022 "TARGET_ARM && reload_completed"
2023 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2024 (set (match_dup 3) (and:SI (not:SI
2025 (ashiftrt:SI (match_dup 2) (const_int 31)))
2029 operands[3] = gen_highpart (SImode, operands[0]);
2030 operands[0] = gen_lowpart (SImode, operands[0]);
2031 operands[4] = gen_highpart (SImode, operands[1]);
2032 operands[1] = gen_lowpart (SImode, operands[1]);
2034 [(set_attr "length" "8")
2035 (set_attr "predicable" "yes")]
2038 (define_insn "andsi_notsi_si"
2039 [(set (match_operand:SI 0 "s_register_operand" "=r")
2040 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2041 (match_operand:SI 1 "s_register_operand" "r")))]
2043 "bic%?\\t%0, %1, %2"
2044 [(set_attr "predicable" "yes")]
2047 (define_insn "bicsi3"
2048 [(set (match_operand:SI 0 "register_operand" "=l")
2049 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2050 (match_operand:SI 2 "register_operand" "0")))]
2053 [(set_attr "length" "2")]
2056 (define_insn "andsi_not_shiftsi_si"
2057 [(set (match_operand:SI 0 "s_register_operand" "=r")
2058 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2059 [(match_operand:SI 2 "s_register_operand" "r")
2060 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2061 (match_operand:SI 1 "s_register_operand" "r")))]
2063 "bic%?\\t%0, %1, %2%S4"
2064 [(set_attr "predicable" "yes")
2065 (set_attr "shift" "2")
2069 (define_insn "*andsi_notsi_si_compare0"
2070 [(set (reg:CC_NOOV CC_REGNUM)
2072 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2073 (match_operand:SI 1 "s_register_operand" "r"))
2075 (set (match_operand:SI 0 "s_register_operand" "=r")
2076 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2078 "bic%?s\\t%0, %1, %2"
2079 [(set_attr "conds" "set")]
2082 (define_insn "*andsi_notsi_si_compare0_scratch"
2083 [(set (reg:CC_NOOV CC_REGNUM)
2085 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2086 (match_operand:SI 1 "s_register_operand" "r"))
2088 (clobber (match_scratch:SI 0 "=r"))]
2090 "bic%?s\\t%0, %1, %2"
2091 [(set_attr "conds" "set")]
2094 (define_insn "iordi3"
2095 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2096 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2097 (match_operand:DI 2 "s_register_operand" "r,r")))]
2100 [(set_attr "length" "8")
2101 (set_attr "predicable" "yes")]
2104 (define_insn "*iordi_zesidi_di"
2105 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2106 (ior:DI (zero_extend:DI
2107 (match_operand:SI 2 "s_register_operand" "r,r"))
2108 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2111 orr%?\\t%Q0, %Q1, %2
2113 [(set_attr "length" "4,8")
2114 (set_attr "predicable" "yes")]
2117 (define_insn "*iordi_sesidi_di"
2118 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2119 (ior:DI (sign_extend:DI
2120 (match_operand:SI 2 "s_register_operand" "r,r"))
2121 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2124 [(set_attr "length" "8")
2125 (set_attr "predicable" "yes")]
2128 (define_expand "iorsi3"
2129 [(set (match_operand:SI 0 "s_register_operand" "")
2130 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2131 (match_operand:SI 2 "reg_or_int_operand" "")))]
2134 if (GET_CODE (operands[2]) == CONST_INT)
2138 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2141 ? 0 : preserve_subexpressions_p ()));
2144 else /* TARGET_THUMB */
2145 operands [2] = force_reg (SImode, operands [2]);
2150 (define_insn_and_split "*arm_iorsi3"
2151 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2152 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2153 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2159 && GET_CODE (operands[2]) == CONST_INT
2160 && !const_ok_for_arm (INTVAL (operands[2]))"
2161 [(clobber (const_int 0))]
2163 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2167 [(set_attr "length" "4,16")
2168 (set_attr "predicable" "yes")]
2171 (define_insn "*thumb_iorsi3"
2172 [(set (match_operand:SI 0 "register_operand" "=l")
2173 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2174 (match_operand:SI 2 "register_operand" "l")))]
2177 [(set_attr "length" "2")]
2181 [(match_scratch:SI 3 "r")
2182 (set (match_operand:SI 0 "s_register_operand" "")
2183 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2184 (match_operand:SI 2 "const_int_operand" "")))]
2186 && !const_ok_for_arm (INTVAL (operands[2]))
2187 && const_ok_for_arm (~INTVAL (operands[2]))"
2188 [(set (match_dup 3) (match_dup 2))
2189 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2193 (define_insn "*iorsi3_compare0"
2194 [(set (reg:CC_NOOV CC_REGNUM)
2195 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2196 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2198 (set (match_operand:SI 0 "s_register_operand" "=r")
2199 (ior:SI (match_dup 1) (match_dup 2)))]
2201 "orr%?s\\t%0, %1, %2"
2202 [(set_attr "conds" "set")]
2205 (define_insn "*iorsi3_compare0_scratch"
2206 [(set (reg:CC_NOOV CC_REGNUM)
2207 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2208 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2210 (clobber (match_scratch:SI 0 "=r"))]
2212 "orr%?s\\t%0, %1, %2"
2213 [(set_attr "conds" "set")]
2216 (define_insn "xordi3"
2217 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2218 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2219 (match_operand:DI 2 "s_register_operand" "r,r")))]
2222 [(set_attr "length" "8")
2223 (set_attr "predicable" "yes")]
2226 (define_insn "*xordi_zesidi_di"
2227 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2228 (xor:DI (zero_extend:DI
2229 (match_operand:SI 2 "s_register_operand" "r,r"))
2230 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2233 eor%?\\t%Q0, %Q1, %2
2235 [(set_attr "length" "4,8")
2236 (set_attr "predicable" "yes")]
2239 (define_insn "*xordi_sesidi_di"
2240 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2241 (xor:DI (sign_extend:DI
2242 (match_operand:SI 2 "s_register_operand" "r,r"))
2243 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2246 [(set_attr "length" "8")
2247 (set_attr "predicable" "yes")]
2250 (define_expand "xorsi3"
2251 [(set (match_operand:SI 0 "s_register_operand" "")
2252 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2253 (match_operand:SI 2 "arm_rhs_operand" "")))]
2256 if (GET_CODE (operands[2]) == CONST_INT)
2257 operands[2] = force_reg (SImode, operands[2]);
2261 (define_insn "*arm_xorsi3"
2262 [(set (match_operand:SI 0 "s_register_operand" "=r")
2263 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2264 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2266 "eor%?\\t%0, %1, %2"
2267 [(set_attr "predicable" "yes")]
2270 (define_insn "*thumb_xorsi3"
2271 [(set (match_operand:SI 0 "register_operand" "=l")
2272 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2273 (match_operand:SI 2 "register_operand" "l")))]
2276 [(set_attr "length" "2")]
2279 (define_insn "*xorsi3_compare0"
2280 [(set (reg:CC_NOOV CC_REGNUM)
2281 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2282 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2284 (set (match_operand:SI 0 "s_register_operand" "=r")
2285 (xor:SI (match_dup 1) (match_dup 2)))]
2287 "eor%?s\\t%0, %1, %2"
2288 [(set_attr "conds" "set")]
2291 (define_insn "*xorsi3_compare0_scratch"
2292 [(set (reg:CC_NOOV CC_REGNUM)
2293 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2294 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2298 [(set_attr "conds" "set")]
2301 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2302 ; (NOT D) we can sometimes merge the final NOT into one of the following
2306 [(set (match_operand:SI 0 "s_register_operand" "")
2307 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2308 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2309 (match_operand:SI 3 "arm_rhs_operand" "")))
2310 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2312 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2313 (not:SI (match_dup 3))))
2314 (set (match_dup 0) (not:SI (match_dup 4)))]
2318 (define_insn "*andsi_iorsi3_notsi"
2319 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2320 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2321 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2322 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2324 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2325 [(set_attr "length" "8")
2326 (set_attr "predicable" "yes")]
2331 ;; Minimum and maximum insns
2333 (define_insn "smaxsi3"
2334 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2335 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2336 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2337 (clobber (reg:CC CC_REGNUM))]
2340 cmp\\t%1, %2\;movlt\\t%0, %2
2341 cmp\\t%1, %2\;movge\\t%0, %1
2342 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2343 [(set_attr "conds" "clob")
2344 (set_attr "length" "8,8,12")]
2347 (define_insn "sminsi3"
2348 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2349 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2350 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2351 (clobber (reg:CC CC_REGNUM))]
2354 cmp\\t%1, %2\;movge\\t%0, %2
2355 cmp\\t%1, %2\;movlt\\t%0, %1
2356 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2357 [(set_attr "conds" "clob")
2358 (set_attr "length" "8,8,12")]
2361 (define_insn "umaxsi3"
2362 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2363 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2364 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2365 (clobber (reg:CC CC_REGNUM))]
2368 cmp\\t%1, %2\;movcc\\t%0, %2
2369 cmp\\t%1, %2\;movcs\\t%0, %1
2370 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2371 [(set_attr "conds" "clob")
2372 (set_attr "length" "8,8,12")]
2375 (define_insn "uminsi3"
2376 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2377 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2378 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2379 (clobber (reg:CC CC_REGNUM))]
2382 cmp\\t%1, %2\;movcs\\t%0, %2
2383 cmp\\t%1, %2\;movcc\\t%0, %1
2384 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2385 [(set_attr "conds" "clob")
2386 (set_attr "length" "8,8,12")]
2389 (define_insn "*store_minmaxsi"
2390 [(set (match_operand:SI 0 "memory_operand" "=m")
2391 (match_operator:SI 3 "minmax_operator"
2392 [(match_operand:SI 1 "s_register_operand" "r")
2393 (match_operand:SI 2 "s_register_operand" "r")]))
2394 (clobber (reg:CC CC_REGNUM))]
2397 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2399 output_asm_insn (\"cmp\\t%1, %2\", operands);
2400 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2401 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2404 [(set_attr "conds" "clob")
2405 (set_attr "length" "12")
2406 (set_attr "type" "store1")]
2409 ; Reject the frame pointer in operand[1], since reloading this after
2410 ; it has been eliminated can cause carnage.
2411 (define_insn "*minmax_arithsi"
2412 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2413 (match_operator:SI 4 "shiftable_operator"
2414 [(match_operator:SI 5 "minmax_operator"
2415 [(match_operand:SI 2 "s_register_operand" "r,r")
2416 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2417 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2418 (clobber (reg:CC CC_REGNUM))]
2420 && (GET_CODE (operands[1]) != REG
2421 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2422 && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2425 enum rtx_code code = GET_CODE (operands[4]);
2427 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2429 output_asm_insn (\"cmp\\t%2, %3\", operands);
2430 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2431 if (which_alternative != 0 || operands[3] != const0_rtx
2432 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2433 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2436 [(set_attr "conds" "clob")
2437 (set_attr "length" "12")]
2441 ;; Shift and rotation insns
2443 (define_expand "ashlsi3"
2444 [(set (match_operand:SI 0 "s_register_operand" "")
2445 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2446 (match_operand:SI 2 "arm_rhs_operand" "")))]
2449 if (GET_CODE (operands[2]) == CONST_INT
2450 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2452 emit_insn (gen_movsi (operands[0], const0_rtx));
2458 (define_insn "*thumb_ashlsi3"
2459 [(set (match_operand:SI 0 "register_operand" "=l,l")
2460 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2461 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2464 [(set_attr "length" "2")]
2467 (define_expand "ashrsi3"
2468 [(set (match_operand:SI 0 "s_register_operand" "")
2469 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2470 (match_operand:SI 2 "arm_rhs_operand" "")))]
2473 if (GET_CODE (operands[2]) == CONST_INT
2474 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2475 operands[2] = GEN_INT (31);
2479 (define_insn "*thumb_ashrsi3"
2480 [(set (match_operand:SI 0 "register_operand" "=l,l")
2481 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2482 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2485 [(set_attr "length" "2")]
2488 (define_expand "lshrsi3"
2489 [(set (match_operand:SI 0 "s_register_operand" "")
2490 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2491 (match_operand:SI 2 "arm_rhs_operand" "")))]
2494 if (GET_CODE (operands[2]) == CONST_INT
2495 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2497 emit_insn (gen_movsi (operands[0], const0_rtx));
2503 (define_insn "*thumb_lshrsi3"
2504 [(set (match_operand:SI 0 "register_operand" "=l,l")
2505 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2506 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2509 [(set_attr "length" "2")]
2512 (define_expand "rotlsi3"
2513 [(set (match_operand:SI 0 "s_register_operand" "")
2514 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2515 (match_operand:SI 2 "reg_or_int_operand" "")))]
2518 if (GET_CODE (operands[2]) == CONST_INT)
2519 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2522 rtx reg = gen_reg_rtx (SImode);
2523 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2529 (define_expand "rotrsi3"
2530 [(set (match_operand:SI 0 "s_register_operand" "")
2531 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2532 (match_operand:SI 2 "arm_rhs_operand" "")))]
2537 if (GET_CODE (operands[2]) == CONST_INT
2538 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2539 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2541 else /* TARGET_THUMB */
2543 if (GET_CODE (operands [2]) == CONST_INT)
2544 operands [2] = force_reg (SImode, operands[2]);
2549 (define_insn "*thumb_rotrsi3"
2550 [(set (match_operand:SI 0 "register_operand" "=l")
2551 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2552 (match_operand:SI 2 "register_operand" "l")))]
2555 [(set_attr "length" "2")]
2558 (define_expand "ashldi3"
2559 [(set (match_operand:DI 0 "s_register_operand" "")
2560 (ashift:DI (match_operand:DI 1 "general_operand" "")
2561 (match_operand:SI 2 "general_operand" "")))]
2562 "TARGET_ARM && (TARGET_CIRRUS)"
2564 if (! s_register_operand (operands[1], DImode))
2565 operands[1] = copy_to_mode_reg (DImode, operands[1]);
2566 if (! s_register_operand (operands[2], SImode))
2567 operands[2] = copy_to_mode_reg (SImode, operands[2]);
2571 (define_insn "*arm_shiftsi3"
2572 [(set (match_operand:SI 0 "s_register_operand" "=r")
2573 (match_operator:SI 3 "shift_operator"
2574 [(match_operand:SI 1 "s_register_operand" "r")
2575 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2578 [(set_attr "predicable" "yes")
2579 (set_attr "shift" "1")
2583 (define_insn "*shiftsi3_compare0"
2584 [(set (reg:CC_NOOV CC_REGNUM)
2585 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2586 [(match_operand:SI 1 "s_register_operand" "r")
2587 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2589 (set (match_operand:SI 0 "s_register_operand" "=r")
2590 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2592 "mov%?s\\t%0, %1%S3"
2593 [(set_attr "conds" "set")
2594 (set_attr "shift" "1")
2598 (define_insn "*shiftsi3_compare0_scratch"
2599 [(set (reg:CC_NOOV CC_REGNUM)
2600 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2601 [(match_operand:SI 1 "s_register_operand" "r")
2602 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2604 (clobber (match_scratch:SI 0 "=r"))]
2606 "mov%?s\\t%0, %1%S3"
2607 [(set_attr "conds" "set")
2608 (set_attr "shift" "1")
2612 (define_insn "*notsi_shiftsi"
2613 [(set (match_operand:SI 0 "s_register_operand" "=r")
2614 (not:SI (match_operator:SI 3 "shift_operator"
2615 [(match_operand:SI 1 "s_register_operand" "r")
2616 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2619 [(set_attr "predicable" "yes")
2620 (set_attr "shift" "1")
2624 (define_insn "*notsi_shiftsi_compare0"
2625 [(set (reg:CC_NOOV CC_REGNUM)
2626 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2627 [(match_operand:SI 1 "s_register_operand" "r")
2628 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2630 (set (match_operand:SI 0 "s_register_operand" "=r")
2631 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2633 "mvn%?s\\t%0, %1%S3"
2634 [(set_attr "conds" "set")
2635 (set_attr "shift" "1")
2639 (define_insn "*not_shiftsi_compare0_scratch"
2640 [(set (reg:CC_NOOV CC_REGNUM)
2641 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2642 [(match_operand:SI 1 "s_register_operand" "r")
2643 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2645 (clobber (match_scratch:SI 0 "=r"))]
2647 "mvn%?s\\t%0, %1%S3"
2648 [(set_attr "conds" "set")
2649 (set_attr "shift" "1")
2653 ;; We don't really have extzv, but defining this using shifts helps
2654 ;; to reduce register pressure later on.
2656 (define_expand "extzv"
2658 (ashift:SI (match_operand:SI 1 "register_operand" "")
2659 (match_operand:SI 2 "const_int_operand" "")))
2660 (set (match_operand:SI 0 "register_operand" "")
2661 (lshiftrt:SI (match_dup 4)
2662 (match_operand:SI 3 "const_int_operand" "")))]
2666 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2667 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2669 operands[3] = GEN_INT (rshift);
2673 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2677 operands[2] = GEN_INT (lshift);
2678 operands[4] = gen_reg_rtx (SImode);
2683 ;; Unary arithmetic insns
2685 (define_expand "negdi2"
2687 [(set (match_operand:DI 0 "s_register_operand" "")
2688 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2689 (clobber (reg:CC CC_REGNUM))])]
2694 if (GET_CODE (operands[1]) != REG)
2695 operands[1] = force_reg (SImode, operands[1]);
2700 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2701 ;; The second alternative is to allow the common case of a *full* overlap.
2702 (define_insn "*arm_negdi2"
2703 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2704 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2705 (clobber (reg:CC CC_REGNUM))]
2707 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2708 [(set_attr "conds" "clob")
2709 (set_attr "length" "8")]
2712 (define_insn "*thumb_negdi2"
2713 [(set (match_operand:DI 0 "register_operand" "=&l")
2714 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2715 (clobber (reg:CC CC_REGNUM))]
2717 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2718 [(set_attr "length" "6")]
2721 (define_expand "negsi2"
2722 [(set (match_operand:SI 0 "s_register_operand" "")
2723 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2728 (define_insn "*arm_negsi2"
2729 [(set (match_operand:SI 0 "s_register_operand" "=r")
2730 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2732 "rsb%?\\t%0, %1, #0"
2733 [(set_attr "predicable" "yes")]
2736 (define_insn "*thumb_negsi2"
2737 [(set (match_operand:SI 0 "register_operand" "=l")
2738 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2741 [(set_attr "length" "2")]
2744 (define_insn "*arm_negsf2"
2745 [(set (match_operand:SF 0 "s_register_operand" "=f")
2746 (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
2747 "TARGET_ARM && TARGET_HARD_FLOAT"
2749 [(set_attr "type" "ffarith")
2750 (set_attr "predicable" "yes")]
2753 (define_insn "*arm_negdf2"
2754 [(set (match_operand:DF 0 "s_register_operand" "=f")
2755 (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
2756 "TARGET_ARM && TARGET_HARD_FLOAT"
2758 [(set_attr "type" "ffarith")
2759 (set_attr "predicable" "yes")]
2762 (define_insn "*negdf_esfdf"
2763 [(set (match_operand:DF 0 "s_register_operand" "=f")
2764 (neg:DF (float_extend:DF
2765 (match_operand:SF 1 "s_register_operand" "f"))))]
2766 "TARGET_ARM && TARGET_HARD_FLOAT"
2768 [(set_attr "type" "ffarith")
2769 (set_attr "predicable" "yes")]
2772 ;; abssi2 doesn't really clobber the condition codes if a different register
2773 ;; is being set. To keep things simple, assume during rtl manipulations that
2774 ;; it does, but tell the final scan operator the truth. Similarly for
2777 (define_insn "*arm_abssi2"
2778 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2779 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2780 (clobber (reg:CC CC_REGNUM))]
2783 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2784 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2785 [(set_attr "conds" "clob,*")
2786 (set_attr "shift" "1")
2787 ;; predicable can't be set based on the variant, so left as no
2788 (set_attr "length" "8")]
2791 (define_insn "*neg_abssi2"
2792 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2793 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2794 (clobber (reg:CC CC_REGNUM))]
2797 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2798 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2799 [(set_attr "conds" "clob,*")
2800 (set_attr "shift" "1")
2801 ;; predicable can't be set based on the variant, so left as no
2802 (set_attr "length" "8")]
2805 (define_insn "*arm_abssf2"
2806 [(set (match_operand:SF 0 "s_register_operand" "=f")
2807 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
2808 "TARGET_ARM && TARGET_HARD_FLOAT"
2810 [(set_attr "type" "ffarith")
2811 (set_attr "predicable" "yes")]
2814 (define_insn "*arm_absdf2"
2815 [(set (match_operand:DF 0 "s_register_operand" "=f")
2816 (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
2817 "TARGET_ARM && TARGET_HARD_FLOAT"
2819 [(set_attr "type" "ffarith")
2820 (set_attr "predicable" "yes")]
2823 (define_insn "*absdf_esfdf"
2824 [(set (match_operand:DF 0 "s_register_operand" "=f")
2825 (abs:DF (float_extend:DF
2826 (match_operand:SF 1 "s_register_operand" "f"))))]
2827 "TARGET_ARM && TARGET_HARD_FLOAT"
2829 [(set_attr "type" "ffarith")
2830 (set_attr "predicable" "yes")]
2833 (define_insn "sqrtsf2"
2834 [(set (match_operand:SF 0 "s_register_operand" "=f")
2835 (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
2836 "TARGET_ARM && TARGET_HARD_FLOAT"
2838 [(set_attr "type" "float_em")
2839 (set_attr "predicable" "yes")]
2842 (define_insn "sqrtdf2"
2843 [(set (match_operand:DF 0 "s_register_operand" "=f")
2844 (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
2845 "TARGET_ARM && TARGET_HARD_FLOAT"
2847 [(set_attr "type" "float_em")
2848 (set_attr "predicable" "yes")]
2851 (define_insn "*sqrtdf_esfdf"
2852 [(set (match_operand:DF 0 "s_register_operand" "=f")
2853 (sqrt:DF (float_extend:DF
2854 (match_operand:SF 1 "s_register_operand" "f"))))]
2855 "TARGET_ARM && TARGET_HARD_FLOAT"
2857 [(set_attr "type" "float_em")
2858 (set_attr "predicable" "yes")]
2861 (define_insn_and_split "one_cmpldi2"
2862 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2863 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2866 "TARGET_ARM && reload_completed"
2867 [(set (match_dup 0) (not:SI (match_dup 1)))
2868 (set (match_dup 2) (not:SI (match_dup 3)))]
2871 operands[2] = gen_highpart (SImode, operands[0]);
2872 operands[0] = gen_lowpart (SImode, operands[0]);
2873 operands[3] = gen_highpart (SImode, operands[1]);
2874 operands[1] = gen_lowpart (SImode, operands[1]);
2876 [(set_attr "length" "8")
2877 (set_attr "predicable" "yes")]
2880 (define_expand "one_cmplsi2"
2881 [(set (match_operand:SI 0 "s_register_operand" "")
2882 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2887 (define_insn "*arm_one_cmplsi2"
2888 [(set (match_operand:SI 0 "s_register_operand" "=r")
2889 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
2892 [(set_attr "predicable" "yes")]
2895 (define_insn "*thumb_one_cmplsi2"
2896 [(set (match_operand:SI 0 "register_operand" "=l")
2897 (not:SI (match_operand:SI 1 "register_operand" "l")))]
2900 [(set_attr "length" "2")]
2903 (define_insn "*notsi_compare0"
2904 [(set (reg:CC_NOOV CC_REGNUM)
2905 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2907 (set (match_operand:SI 0 "s_register_operand" "=r")
2908 (not:SI (match_dup 1)))]
2911 [(set_attr "conds" "set")]
2914 (define_insn "*notsi_compare0_scratch"
2915 [(set (reg:CC_NOOV CC_REGNUM)
2916 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2918 (clobber (match_scratch:SI 0 "=r"))]
2921 [(set_attr "conds" "set")]
2924 ;; Fixed <--> Floating conversion insns
2926 (define_insn "*arm_floatsisf2"
2927 [(set (match_operand:SF 0 "s_register_operand" "=f")
2928 (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
2929 "TARGET_ARM && TARGET_HARD_FLOAT"
2931 [(set_attr "type" "r_2_f")
2932 (set_attr "predicable" "yes")]
2935 (define_insn "*arm_floatsidf2"
2936 [(set (match_operand:DF 0 "s_register_operand" "=f")
2937 (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
2938 "TARGET_ARM && TARGET_HARD_FLOAT"
2940 [(set_attr "type" "r_2_f")
2941 (set_attr "predicable" "yes")]
2944 (define_insn "*arm_fix_truncsfsi2"
2945 [(set (match_operand:SI 0 "s_register_operand" "=r")
2946 (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
2947 "TARGET_ARM && TARGET_HARD_FLOAT"
2949 [(set_attr "type" "f_2_r")
2950 (set_attr "predicable" "yes")]
2953 (define_insn "*arm_fix_truncdfsi2"
2954 [(set (match_operand:SI 0 "s_register_operand" "=r")
2955 (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
2956 "TARGET_ARM && TARGET_HARD_FLOAT"
2958 [(set_attr "type" "f_2_r")
2959 (set_attr "predicable" "yes")]
2964 (define_insn "*arm_truncdfsf2"
2965 [(set (match_operand:SF 0 "s_register_operand" "=f")
2967 (match_operand:DF 1 "s_register_operand" "f")))]
2968 "TARGET_ARM && TARGET_HARD_FLOAT"
2970 [(set_attr "type" "ffarith")
2971 (set_attr "predicable" "yes")]
2974 ;; Zero and sign extension instructions.
2976 (define_insn "zero_extendsidi2"
2977 [(set (match_operand:DI 0 "s_register_operand" "=r")
2978 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2981 if (REGNO (operands[1])
2982 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2983 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2984 return \"mov%?\\t%R0, #0\";
2986 [(set_attr "length" "8")
2987 (set_attr "predicable" "yes")]
2990 (define_insn "zero_extendqidi2"
2991 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
2992 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2995 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
2996 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
2997 [(set_attr "length" "8")
2998 (set_attr "predicable" "yes")
2999 (set_attr "type" "*,load")
3000 (set_attr "pool_range" "*,4092")
3001 (set_attr "neg_pool_range" "*,4084")]
3004 (define_insn "extendsidi2"
3005 [(set (match_operand:DI 0 "s_register_operand" "=r")
3006 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3009 if (REGNO (operands[1])
3010 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3011 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3012 return \"mov%?\\t%R0, %Q0, asr #31\";
3014 [(set_attr "length" "8")
3015 (set_attr "shift" "1")
3016 (set_attr "predicable" "yes")]
3019 (define_expand "zero_extendhisi2"
3021 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3023 (set (match_operand:SI 0 "s_register_operand" "")
3024 (lshiftrt:SI (match_dup 2) (const_int 16)))]
3030 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3032 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3033 here because the insn below will generate an LDRH instruction
3034 rather than an LDR instruction, so we cannot get an unaligned
3036 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3037 gen_rtx_ZERO_EXTEND (SImode,
3041 if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3043 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3046 if (!s_register_operand (operands[1], HImode))
3047 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3048 operands[1] = gen_lowpart (SImode, operands[1]);
3049 operands[2] = gen_reg_rtx (SImode);
3051 else /* TARGET_THUMB */
3053 if (GET_CODE (operands[1]) == MEM)
3057 tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3058 tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3065 if (!s_register_operand (operands[1], HImode))
3066 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3067 operands[1] = gen_lowpart (SImode, operands[1]);
3068 operands[2] = gen_reg_rtx (SImode);
3070 ops[0] = operands[2];
3071 ops[1] = operands[1];
3072 ops[2] = GEN_INT (16);
3074 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3075 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3077 ops[0] = operands[0];
3078 ops[1] = operands[2];
3079 ops[2] = GEN_INT (16);
3081 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3082 gen_rtx_LSHIFTRT (SImode, ops[1],
3090 (define_insn "*thumb_zero_extendhisi2"
3091 [(set (match_operand:SI 0 "register_operand" "=l")
3092 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3095 rtx mem = XEXP (operands[1], 0);
3097 if (GET_CODE (mem) == CONST)
3098 mem = XEXP (mem, 0);
3100 if (GET_CODE (mem) == LABEL_REF)
3101 return \"ldr\\t%0, %1\";
3103 if (GET_CODE (mem) == PLUS)
3105 rtx a = XEXP (mem, 0);
3106 rtx b = XEXP (mem, 1);
3108 /* This can happen due to bugs in reload. */
3109 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3112 ops[0] = operands[0];
3115 output_asm_insn (\"mov %0, %1\", ops);
3117 XEXP (mem, 0) = operands[0];
3120 else if ( GET_CODE (a) == LABEL_REF
3121 && GET_CODE (b) == CONST_INT)
3122 return \"ldr\\t%0, %1\";
3125 return \"ldrh\\t%0, %1\";
3127 [(set_attr "length" "4")
3128 (set_attr "type" "load")
3129 (set_attr "pool_range" "60")]
3132 (define_insn "*arm_zero_extendhisi2"
3133 [(set (match_operand:SI 0 "s_register_operand" "=r")
3134 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3135 "TARGET_ARM && arm_arch4"
3137 [(set_attr "type" "load")
3138 (set_attr "predicable" "yes")
3139 (set_attr "pool_range" "256")
3140 (set_attr "neg_pool_range" "244")]
3144 [(set (match_operand:SI 0 "s_register_operand" "")
3145 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3146 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3147 "TARGET_ARM && (!arm_arch4)"
3148 [(set (match_dup 2) (match_dup 1))
3149 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3151 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3157 [(set (match_operand:SI 0 "s_register_operand" "")
3158 (match_operator:SI 3 "shiftable_operator"
3159 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3160 (match_operand:SI 4 "s_register_operand" "")]))
3161 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3162 "TARGET_ARM && (!arm_arch4)"
3163 [(set (match_dup 2) (match_dup 1))
3166 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3168 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3173 (define_expand "zero_extendqisi2"
3174 [(set (match_operand:SI 0 "s_register_operand" "")
3175 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3178 if (GET_CODE (operands[1]) != MEM)
3182 emit_insn (gen_andsi3 (operands[0],
3183 gen_lowpart (SImode, operands[1]),
3186 else /* TARGET_THUMB */
3188 rtx temp = gen_reg_rtx (SImode);
3191 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3192 operands[1] = gen_lowpart (SImode, operands[1]);
3195 ops[1] = operands[1];
3196 ops[2] = GEN_INT (24);
3198 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3199 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3201 ops[0] = operands[0];
3203 ops[2] = GEN_INT (24);
3205 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3206 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3213 (define_insn "*thumb_zero_extendqisi2"
3214 [(set (match_operand:SI 0 "register_operand" "=l")
3215 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3218 [(set_attr "length" "2")
3219 (set_attr "type" "load")
3220 (set_attr "pool_range" "32")]
3223 (define_insn "*arm_zero_extendqisi2"
3224 [(set (match_operand:SI 0 "s_register_operand" "=r")
3225 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3227 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3228 [(set_attr "type" "load")
3229 (set_attr "predicable" "yes")
3230 (set_attr "pool_range" "4096")
3231 (set_attr "neg_pool_range" "4084")]
3235 [(set (match_operand:SI 0 "s_register_operand" "")
3236 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3237 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3238 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3239 [(set (match_dup 2) (match_dup 1))
3240 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3244 (define_insn "*compareqi_eq0"
3245 [(set (reg:CC_Z CC_REGNUM)
3246 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3250 [(set_attr "conds" "set")]
3253 (define_expand "extendhisi2"
3255 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3257 (set (match_operand:SI 0 "s_register_operand" "")
3258 (ashiftrt:SI (match_dup 2)
3263 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3265 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3266 here because the insn below will generate an LDRH instruction
3267 rather than an LDR instruction, so we cannot get an unaligned
3269 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3270 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3274 if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3276 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3279 if (!s_register_operand (operands[1], HImode))
3280 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3281 operands[1] = gen_lowpart (SImode, operands[1]);
3282 operands[2] = gen_reg_rtx (SImode);
3288 ops[0] = operands[2];
3289 ops[1] = operands[1];
3290 ops[2] = GEN_INT (16);
3292 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3293 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3295 ops[0] = operands[0];
3296 ops[1] = operands[2];
3297 ops[2] = GEN_INT (16);
3299 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3300 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3307 (define_insn "*thumb_extendhisi2_insn"
3308 [(set (match_operand:SI 0 "register_operand" "=l")
3309 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3310 (clobber (match_scratch:SI 2 "=&l"))]
3315 rtx mem = XEXP (operands[1], 0);
3317 /* This code used to try to use 'V', and fix the address only if it was
3318 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3319 range of QImode offsets, and offsettable_address_p does a QImode
3322 if (GET_CODE (mem) == CONST)
3323 mem = XEXP (mem, 0);
3325 if (GET_CODE (mem) == LABEL_REF)
3326 return \"ldr\\t%0, %1\";
3328 if (GET_CODE (mem) == PLUS)
3330 rtx a = XEXP (mem, 0);
3331 rtx b = XEXP (mem, 1);
3333 if (GET_CODE (a) == LABEL_REF
3334 && GET_CODE (b) == CONST_INT)
3335 return \"ldr\\t%0, %1\";
3337 if (GET_CODE (b) == REG)
3338 return \"ldrsh\\t%0, %1\";
3346 ops[2] = const0_rtx;
3349 if (GET_CODE (ops[1]) != REG)
3355 ops[0] = operands[0];
3356 ops[3] = operands[2];
3357 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3360 [(set_attr "length" "4")
3361 (set_attr "type" "load")
3362 (set_attr "pool_range" "1020")]
3365 (define_expand "extendhisi2_mem"
3366 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3368 (zero_extend:SI (match_dup 7)))
3369 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3370 (set (match_operand:SI 0 "" "")
3371 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3376 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3378 mem1 = gen_rtx_MEM (QImode, addr);
3379 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3380 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3381 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3382 operands[0] = gen_lowpart (SImode, operands[0]);
3384 operands[2] = gen_reg_rtx (SImode);
3385 operands[3] = gen_reg_rtx (SImode);
3386 operands[6] = gen_reg_rtx (SImode);
3389 if (BYTES_BIG_ENDIAN)
3391 operands[4] = operands[2];
3392 operands[5] = operands[3];
3396 operands[4] = operands[3];
3397 operands[5] = operands[2];
3402 (define_insn "*arm_extendhisi_insn"
3403 [(set (match_operand:SI 0 "s_register_operand" "=r")
3404 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3405 "TARGET_ARM && arm_arch4"
3407 [(set_attr "type" "load")
3408 (set_attr "predicable" "yes")
3409 (set_attr "pool_range" "256")
3410 (set_attr "neg_pool_range" "244")]
3414 [(set (match_operand:SI 0 "s_register_operand" "")
3415 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3416 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3417 "TARGET_ARM && (!arm_arch4)"
3418 [(set (match_dup 2) (match_dup 1))
3419 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3421 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3427 [(set (match_operand:SI 0 "s_register_operand" "")
3428 (match_operator:SI 3 "shiftable_operator"
3429 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3430 (match_operand:SI 4 "s_register_operand" "")]))
3431 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3432 "TARGET_ARM && (!arm_arch4)"
3433 [(set (match_dup 2) (match_dup 1))
3436 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3437 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3442 (define_expand "extendqihi2"
3444 (ashift:SI (match_operand:QI 1 "general_operand" "")
3446 (set (match_operand:HI 0 "s_register_operand" "")
3447 (ashiftrt:SI (match_dup 2)
3452 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3454 emit_insn (gen_rtx_SET (VOIDmode,
3456 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3459 if (!s_register_operand (operands[1], QImode))
3460 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3461 operands[0] = gen_lowpart (SImode, operands[0]);
3462 operands[1] = gen_lowpart (SImode, operands[1]);
3463 operands[2] = gen_reg_rtx (SImode);
3467 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3468 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3469 (define_insn "*extendqihi_insn"
3470 [(set (match_operand:HI 0 "s_register_operand" "=r")
3471 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3472 "TARGET_ARM && arm_arch4"
3474 /* If the address is invalid, this will split the instruction into two. */
3475 if (bad_signed_byte_operand (operands[1], VOIDmode))
3477 return \"ldr%?sb\\t%0, %1\";
3479 [(set_attr "type" "load")
3480 (set_attr "predicable" "yes")
3481 (set_attr "length" "8")
3482 (set_attr "pool_range" "256")
3483 (set_attr "neg_pool_range" "244")]
3487 [(set (match_operand:HI 0 "s_register_operand" "")
3488 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3489 "TARGET_ARM && arm_arch4 && reload_completed"
3490 [(set (match_dup 3) (match_dup 1))
3491 (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3494 HOST_WIDE_INT offset;
3496 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3497 operands[2] = gen_rtx_MEM (QImode, operands[3]);
3498 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3499 operands[1] = XEXP (operands[1], 0);
3500 if (GET_CODE (operands[1]) == PLUS
3501 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3502 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3503 || const_ok_for_arm (-offset)))
3505 HOST_WIDE_INT low = (offset > 0
3506 ? (offset & 0xff) : -((-offset) & 0xff));
3507 XEXP (operands[2], 0) = plus_constant (operands[3], low);
3508 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3510 /* Ensure the sum is in correct canonical form */
3511 else if (GET_CODE (operands[1]) == PLUS
3512 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3513 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3514 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3515 XEXP (operands[1], 1),
3516 XEXP (operands[1], 0));
3520 (define_expand "extendqisi2"
3522 (ashift:SI (match_operand:QI 1 "general_operand" "")
3524 (set (match_operand:SI 0 "s_register_operand" "")
3525 (ashiftrt:SI (match_dup 2)
3530 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3532 emit_insn (gen_rtx_SET (VOIDmode,
3534 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3537 if (!s_register_operand (operands[1], QImode))
3538 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3539 operands[1] = gen_lowpart (SImode, operands[1]);
3540 operands[2] = gen_reg_rtx (SImode);
3546 ops[0] = operands[2];
3547 ops[1] = operands[1];
3548 ops[2] = GEN_INT (24);
3550 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3551 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3553 ops[0] = operands[0];
3554 ops[1] = operands[2];
3555 ops[2] = GEN_INT (24);
3557 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3558 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3565 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3566 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3567 (define_insn "*arm_extendqisi_insn"
3568 [(set (match_operand:SI 0 "s_register_operand" "=r")
3569 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3570 "TARGET_ARM && arm_arch4"
3572 /* If the address is invalid, this will split the instruction into two. */
3573 if (bad_signed_byte_operand (operands[1], VOIDmode))
3575 return \"ldr%?sb\\t%0, %1\";
3577 [(set_attr "type" "load")
3578 (set_attr "predicable" "yes")
3579 (set_attr "length" "8")
3580 (set_attr "pool_range" "256")
3581 (set_attr "neg_pool_range" "244")]
3585 [(set (match_operand:SI 0 "s_register_operand" "")
3586 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3587 "TARGET_ARM && arm_arch4 && reload_completed"
3588 [(set (match_dup 0) (match_dup 1))
3589 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3592 HOST_WIDE_INT offset;
3594 operands[2] = gen_rtx_MEM (QImode, operands[0]);
3595 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3596 operands[1] = XEXP (operands[1], 0);
3597 if (GET_CODE (operands[1]) == PLUS
3598 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3599 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3600 || const_ok_for_arm (-offset)))
3602 HOST_WIDE_INT low = (offset > 0
3603 ? (offset & 0xff) : -((-offset) & 0xff));
3604 XEXP (operands[2], 0) = plus_constant (operands[0], low);
3605 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3607 /* Ensure the sum is in correct canonical form */
3608 else if (GET_CODE (operands[1]) == PLUS
3609 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3610 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3611 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3612 XEXP (operands[1], 1),
3613 XEXP (operands[1], 0));
3617 (define_insn "*thumb_extendqisi2_insn"
3618 [(set (match_operand:SI 0 "register_operand" "=l,l")
3619 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3624 rtx mem = XEXP (operands[1], 0);
3626 if (GET_CODE (mem) == CONST)
3627 mem = XEXP (mem, 0);
3629 if (GET_CODE (mem) == LABEL_REF)
3630 return \"ldr\\t%0, %1\";
3632 if (GET_CODE (mem) == PLUS
3633 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3634 return \"ldr\\t%0, %1\";
3636 if (which_alternative == 0)
3637 return \"ldrsb\\t%0, %1\";
3639 ops[0] = operands[0];
3641 if (GET_CODE (mem) == PLUS)
3643 rtx a = XEXP (mem, 0);
3644 rtx b = XEXP (mem, 1);
3649 if (GET_CODE (a) == REG)
3651 if (GET_CODE (b) == REG)
3652 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3653 else if (REGNO (a) == REGNO (ops[0]))
3655 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3656 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3657 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3660 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3662 else if (GET_CODE (b) != REG)
3666 if (REGNO (b) == REGNO (ops[0]))
3668 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3669 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3670 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3673 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3676 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3678 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3679 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3680 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3685 ops[2] = const0_rtx;
3687 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3691 [(set_attr "length" "2,6")
3692 (set_attr "type" "load,load")
3693 (set_attr "pool_range" "32,32")]
3696 (define_expand "extendsfdf2"
3697 [(set (match_operand:DF 0 "s_register_operand" "")
3698 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
3699 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3703 (define_insn "*arm_extendsfdf2"
3704 [(set (match_operand:DF 0 "s_register_operand" "=f")
3705 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
3706 "TARGET_ARM && TARGET_HARD_FLOAT"
3708 [(set_attr "type" "ffarith")
3709 (set_attr "predicable" "yes")]
3712 ;; Move insns (including loads and stores)
3714 ;; XXX Just some ideas about movti.
3715 ;; I don't think these are a good idea on the arm, there just aren't enough
3717 ;;(define_expand "loadti"
3718 ;; [(set (match_operand:TI 0 "s_register_operand" "")
3719 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
3722 ;;(define_expand "storeti"
3723 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3724 ;; (match_operand:TI 1 "s_register_operand" ""))]
3727 ;;(define_expand "movti"
3728 ;; [(set (match_operand:TI 0 "general_operand" "")
3729 ;; (match_operand:TI 1 "general_operand" ""))]
3735 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3736 ;; operands[1] = copy_to_reg (operands[1]);
3737 ;; if (GET_CODE (operands[0]) == MEM)
3738 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3739 ;; else if (GET_CODE (operands[1]) == MEM)
3740 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3744 ;; emit_insn (insn);
3748 ;; Recognize garbage generated above.
3751 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3752 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3756 ;; register mem = (which_alternative < 3);
3757 ;; register const char *template;
3759 ;; operands[mem] = XEXP (operands[mem], 0);
3760 ;; switch (which_alternative)
3762 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3763 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
3764 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
3765 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
3766 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
3767 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
3769 ;; output_asm_insn (template, operands);
3773 (define_expand "movdi"
3774 [(set (match_operand:DI 0 "general_operand" "")
3775 (match_operand:DI 1 "general_operand" ""))]
3780 if (!no_new_pseudos)
3782 if (GET_CODE (operands[0]) != REG)
3783 operands[1] = force_reg (DImode, operands[1]);
3789 (define_insn "*arm_movdi"
3790 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3791 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
3792 "TARGET_ARM && !TARGET_CIRRUS"
3794 return (output_move_double (operands));
3796 [(set_attr "length" "8")
3797 (set_attr "type" "*,load,store2")
3798 (set_attr "pool_range" "*,1020,*")
3799 (set_attr "neg_pool_range" "*,1008,*")]
3802 ;;; ??? This should have alternatives for constants.
3803 ;;; ??? This was originally identical to the movdf_insn pattern.
3804 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3805 ;;; thumb_reorg with a memory reference.
3806 (define_insn "*thumb_movdi_insn"
3807 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3808 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
3811 && ( register_operand (operands[0], DImode)
3812 || register_operand (operands[1], DImode))"
3815 switch (which_alternative)
3819 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3820 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
3821 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
3823 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3825 operands[1] = GEN_INT (- INTVAL (operands[1]));
3826 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3828 return \"ldmia\\t%1, {%0, %H0}\";
3830 return \"stmia\\t%0, {%1, %H1}\";
3832 return thumb_load_double_from_address (operands);
3834 operands[2] = gen_rtx (MEM, SImode,
3835 plus_constant (XEXP (operands[0], 0), 4));
3836 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3839 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3840 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
3841 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
3844 [(set_attr "length" "4,4,6,2,2,6,4,4")
3845 (set_attr "type" "*,*,*,load,store2,load,store2,*")
3846 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
3849 (define_expand "movsi"
3850 [(set (match_operand:SI 0 "general_operand" "")
3851 (match_operand:SI 1 "general_operand" ""))]
3856 /* Everything except mem = const or mem = mem can be done easily */
3857 if (GET_CODE (operands[0]) == MEM)
3858 operands[1] = force_reg (SImode, operands[1]);
3859 if (GET_CODE (operands[1]) == CONST_INT
3860 && !(const_ok_for_arm (INTVAL (operands[1]))
3861 || const_ok_for_arm (~INTVAL (operands[1]))))
3863 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3866 : preserve_subexpressions_p ()));
3870 else /* TARGET_THUMB.... */
3872 if (!no_new_pseudos)
3874 if (GET_CODE (operands[0]) != REG)
3875 operands[1] = force_reg (SImode, operands[1]);
3880 && (CONSTANT_P (operands[1])
3881 || symbol_mentioned_p (operands[1])
3882 || label_mentioned_p (operands[1])))
3883 operands[1] = legitimize_pic_address (operands[1], SImode,
3884 (no_new_pseudos ? operands[0] : 0));
3888 (define_insn "*arm_movsi_insn"
3889 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
3890 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
3892 && ( register_operand (operands[0], SImode)
3893 || register_operand (operands[1], SImode))"
3899 [(set_attr "type" "*,*,load,store1")
3900 (set_attr "predicable" "yes")
3901 (set_attr "pool_range" "*,*,4096,*")
3902 (set_attr "neg_pool_range" "*,*,4084,*")]
3906 [(set (match_operand:SI 0 "s_register_operand" "")
3907 (match_operand:SI 1 "const_int_operand" ""))]
3909 && (!(const_ok_for_arm (INTVAL (operands[1]))
3910 || const_ok_for_arm (~INTVAL (operands[1]))))"
3911 [(clobber (const_int 0))]
3913 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3919 (define_insn "*thumb_movsi_insn"
3920 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
3921 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
3923 && ( register_operand (operands[0], SImode)
3924 || register_operand (operands[1], SImode))"
3935 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
3936 (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
3937 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
3941 [(set (match_operand:SI 0 "register_operand" "")
3942 (match_operand:SI 1 "const_int_operand" ""))]
3943 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
3944 [(set (match_dup 0) (match_dup 1))
3945 (set (match_dup 0) (neg:SI (match_dup 0)))]
3946 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
3950 [(set (match_operand:SI 0 "register_operand" "")
3951 (match_operand:SI 1 "const_int_operand" ""))]
3952 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
3953 [(set (match_dup 0) (match_dup 1))
3954 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
3957 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
3958 unsigned HOST_WIDE_INT mask = 0xff;
3961 for (i = 0; i < 25; i++)
3962 if ((val & (mask << i)) == val)
3965 /* Shouldn't happen, but we don't want to split if the shift is zero. */
3969 operands[1] = GEN_INT (val >> i);
3970 operands[2] = GEN_INT (i);
3974 ;; When generating pic, we need to load the symbol offset into a register.
3975 ;; So that the optimizer does not confuse this with a normal symbol load
3976 ;; we use an unspec. The offset will be loaded from a constant pool entry,
3977 ;; since that is the only type of relocation we can use.
3979 ;; The rather odd constraints on the following are to force reload to leave
3980 ;; the insn alone, and to force the minipool generation pass to then move
3981 ;; the GOT symbol to memory.
3983 (define_insn "pic_load_addr_arm"
3984 [(set (match_operand:SI 0 "s_register_operand" "=r")
3985 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3986 "TARGET_ARM && flag_pic"
3988 [(set_attr "type" "load")
3989 (set (attr "pool_range") (const_int 4096))
3990 (set (attr "neg_pool_range") (const_int 4084))]
3993 (define_insn "pic_load_addr_thumb"
3994 [(set (match_operand:SI 0 "s_register_operand" "=l")
3995 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3996 "TARGET_THUMB && flag_pic"
3998 [(set_attr "type" "load")
3999 (set (attr "pool_range") (const_int 1024))]
4002 ;; This variant is used for AOF assembly, since it needs to mention the
4003 ;; pic register in the rtl.
4004 (define_expand "pic_load_addr_based"
4005 [(set (match_operand:SI 0 "s_register_operand" "=r")
4006 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4007 "TARGET_ARM && flag_pic"
4008 "operands[2] = pic_offset_table_rtx;"
4011 (define_insn "*pic_load_addr_based_insn"
4012 [(set (match_operand:SI 0 "s_register_operand" "=r")
4013 (unspec:SI [(match_operand 1 "" "")
4014 (match_operand 2 "s_register_operand" "r")]
4016 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4018 #ifdef AOF_ASSEMBLER
4019 operands[1] = aof_pic_entry (operands[1]);
4021 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4024 [(set_attr "type" "load")
4025 (set (attr "pool_range")
4026 (if_then_else (eq_attr "is_thumb" "yes")
4029 (set (attr "neg_pool_range")
4030 (if_then_else (eq_attr "is_thumb" "yes")
4035 (define_insn "pic_add_dot_plus_four"
4036 [(set (match_operand:SI 0 "register_operand" "+r")
4037 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
4038 (use (label_ref (match_operand 1 "" "")))]
4039 "TARGET_THUMB && flag_pic"
4041 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4042 CODE_LABEL_NUMBER (operands[1]));
4043 return \"add\\t%0, %|pc\";
4045 [(set_attr "length" "2")]
4048 (define_insn "pic_add_dot_plus_eight"
4049 [(set (match_operand:SI 0 "register_operand" "+r")
4050 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
4051 (use (label_ref (match_operand 1 "" "")))]
4052 "TARGET_ARM && flag_pic"
4054 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4055 CODE_LABEL_NUMBER (operands[1]));
4056 return \"add%?\\t%0, %|pc, %0\";
4058 [(set_attr "predicable" "yes")]
4061 (define_expand "builtin_setjmp_receiver"
4062 [(label_ref (match_operand 0 "" ""))]
4066 arm_finalize_pic (0);
4070 ;; If copying one reg to another we can set the condition codes according to
4071 ;; its value. Such a move is common after a return from subroutine and the
4072 ;; result is being tested against zero.
4074 (define_insn "*movsi_compare0"
4075 [(set (reg:CC CC_REGNUM)
4076 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4078 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4083 sub%?s\\t%0, %1, #0"
4084 [(set_attr "conds" "set")]
4087 ;; Subroutine to store a half word from a register into memory.
4088 ;; Operand 0 is the source register (HImode)
4089 ;; Operand 1 is the destination address in a register (SImode)
4091 ;; In both this routine and the next, we must be careful not to spill
4092 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4093 ;; can generate unrecognizable rtl.
4095 (define_expand "storehi"
4096 [;; store the low byte
4097 (set (match_operand 1 "" "") (match_dup 3))
4098 ;; extract the high byte
4100 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4101 ;; store the high byte
4102 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
4106 rtx op1 = operands[1];
4107 rtx addr = XEXP (op1, 0);
4108 enum rtx_code code = GET_CODE (addr);
4110 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4112 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4114 operands[4] = adjust_address (op1, QImode, 1);
4115 operands[1] = adjust_address (operands[1], QImode, 0);
4116 operands[3] = gen_lowpart (QImode, operands[0]);
4117 operands[0] = gen_lowpart (SImode, operands[0]);
4118 operands[2] = gen_reg_rtx (SImode);
4122 (define_expand "storehi_bigend"
4123 [(set (match_dup 4) (match_dup 3))
4125 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4126 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 3))]
4130 rtx op1 = operands[1];
4131 rtx addr = XEXP (op1, 0);
4132 enum rtx_code code = GET_CODE (addr);
4134 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4136 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4138 operands[4] = adjust_address (op1, QImode, 1);
4139 operands[1] = adjust_address (operands[1], QImode, 0);
4140 operands[3] = gen_lowpart (QImode, operands[0]);
4141 operands[0] = gen_lowpart (SImode, operands[0]);
4142 operands[2] = gen_reg_rtx (SImode);
4146 ;; Subroutine to store a half word integer constant into memory.
4147 (define_expand "storeinthi"
4148 [(set (match_operand 0 "" "")
4149 (subreg:QI (match_operand 1 "" "") 0))
4150 (set (match_dup 3) (match_dup 2))]
4154 HOST_WIDE_INT value = INTVAL (operands[1]);
4155 rtx addr = XEXP (operands[0], 0);
4156 rtx op0 = operands[0];
4157 enum rtx_code code = GET_CODE (addr);
4159 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4161 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4163 operands[1] = gen_reg_rtx (SImode);
4164 if (BYTES_BIG_ENDIAN)
4166 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4167 if ((value & 255) == ((value >> 8) & 255))
4168 operands[2] = operands[1];
4171 operands[2] = gen_reg_rtx (SImode);
4172 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4177 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4178 if ((value & 255) == ((value >> 8) & 255))
4179 operands[2] = operands[1];
4182 operands[2] = gen_reg_rtx (SImode);
4183 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4187 operands[3] = adjust_address (op0, QImode, 1);
4188 operands[0] = adjust_address (operands[0], QImode, 0);
4189 operands[2] = gen_lowpart (QImode, operands[2]);
4193 (define_expand "storehi_single_op"
4194 [(set (match_operand:HI 0 "memory_operand" "")
4195 (match_operand:HI 1 "general_operand" ""))]
4196 "TARGET_ARM && arm_arch4"
4198 if (!s_register_operand (operands[1], HImode))
4199 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4203 (define_expand "movhi"
4204 [(set (match_operand:HI 0 "general_operand" "")
4205 (match_operand:HI 1 "general_operand" ""))]
4210 if (!no_new_pseudos)
4212 if (GET_CODE (operands[0]) == MEM)
4216 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4219 if (GET_CODE (operands[1]) == CONST_INT)
4220 emit_insn (gen_storeinthi (operands[0], operands[1]));
4223 if (GET_CODE (operands[1]) == MEM)
4224 operands[1] = force_reg (HImode, operands[1]);
4225 if (BYTES_BIG_ENDIAN)
4226 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4228 emit_insn (gen_storehi (operands[1], operands[0]));
4232 /* Sign extend a constant, and keep it in an SImode reg. */
4233 else if (GET_CODE (operands[1]) == CONST_INT)
4235 rtx reg = gen_reg_rtx (SImode);
4236 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4238 /* If the constant is already valid, leave it alone. */
4239 if (!const_ok_for_arm (val))
4241 /* If setting all the top bits will make the constant
4242 loadable in a single instruction, then set them.
4243 Otherwise, sign extend the number. */
4245 if (const_ok_for_arm (~(val | ~0xffff)))
4247 else if (val & 0x8000)
4251 emit_insn (gen_movsi (reg, GEN_INT (val)));
4252 operands[1] = gen_lowpart (HImode, reg);
4254 else if (arm_arch4 && !no_new_pseudos && optimize > 0
4255 && GET_CODE (operands[1]) == MEM)
4257 rtx reg = gen_reg_rtx (SImode);
4259 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4260 operands[1] = gen_lowpart (HImode, reg);
4262 else if (!arm_arch4)
4264 /* Note: We do not have to worry about TARGET_MMU_TRAPS
4265 for v4 and up architectures because LDRH instructions will
4266 be used to access the HI values, and these cannot generate
4267 unaligned word access faults in the MMU. */
4268 if (GET_CODE (operands[1]) == MEM)
4270 if (TARGET_MMU_TRAPS)
4273 rtx offset = const0_rtx;
4274 rtx reg = gen_reg_rtx (SImode);
4276 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4277 || (GET_CODE (base) == PLUS
4278 && (GET_CODE (offset = XEXP (base, 1))
4280 && ((INTVAL(offset) & 1) != 1)
4281 && GET_CODE (base = XEXP (base, 0)) == REG))
4282 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4284 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4287 new = gen_rtx_MEM (SImode,
4288 plus_constant (base, new_offset));
4289 MEM_COPY_ATTRIBUTES (new, operands[1]);
4290 emit_insn (gen_movsi (reg, new));
4291 if (((INTVAL (offset) & 2) != 0)
4292 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4294 rtx reg2 = gen_reg_rtx (SImode);
4296 emit_insn (gen_lshrsi3 (reg2, reg,
4302 emit_insn (gen_movhi_bytes (reg, operands[1]));
4304 operands[1] = gen_lowpart (HImode, reg);
4306 else if (BYTES_BIG_ENDIAN)
4309 rtx offset = const0_rtx;
4311 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4312 || (GET_CODE (base) == PLUS
4313 && (GET_CODE (offset = XEXP (base, 1))
4315 && GET_CODE (base = XEXP (base, 0)) == REG))
4316 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4318 rtx reg = gen_reg_rtx (SImode);
4321 if ((INTVAL (offset) & 2) == 2)
4323 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4324 new = gen_rtx_MEM (SImode,
4325 plus_constant (base,
4327 MEM_COPY_ATTRIBUTES (new, operands[1]);
4328 emit_insn (gen_movsi (reg, new));
4332 new = gen_rtx_MEM (SImode,
4333 XEXP (operands[1], 0));
4334 MEM_COPY_ATTRIBUTES (new, operands[1]);
4335 emit_insn (gen_rotated_loadsi (reg, new));
4338 operands[1] = gen_lowpart (HImode, reg);
4342 emit_insn (gen_movhi_bigend (operands[0],
4350 /* Handle loading a large integer during reload */
4351 else if (GET_CODE (operands[1]) == CONST_INT
4352 && !const_ok_for_arm (INTVAL (operands[1]))
4353 && !const_ok_for_arm (~INTVAL (operands[1])))
4355 /* Writing a constant to memory needs a scratch, which should
4356 be handled with SECONDARY_RELOADs. */
4357 if (GET_CODE (operands[0]) != REG)
4360 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4361 emit_insn (gen_movsi (operands[0], operands[1]));
4365 else /* TARGET_THUMB */
4367 if (!no_new_pseudos)
4369 if (GET_CODE (operands[0]) != REG)
4370 operands[1] = force_reg (HImode, operands[1]);
4372 /* ??? We shouldn't really get invalid addresses here, but this can
4373 happen if we are passed a SP (never OK for HImode/QImode) or
4374 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4375 HImode/QImode) relative address. */
4376 /* ??? This should perhaps be fixed elsewhere, for instance, in
4377 fixup_stack_1, by checking for other kinds of invalid addresses,
4378 e.g. a bare reference to a virtual register. This may confuse the
4379 alpha though, which must handle this case differently. */
4380 if (GET_CODE (operands[0]) == MEM
4381 && !memory_address_p (GET_MODE (operands[0]),
4382 XEXP (operands[0], 0)))
4384 = replace_equiv_address (operands[0],
4385 copy_to_reg (XEXP (operands[0], 0)));
4387 if (GET_CODE (operands[1]) == MEM
4388 && !memory_address_p (GET_MODE (operands[1]),
4389 XEXP (operands[1], 0)))
4391 = replace_equiv_address (operands[1],
4392 copy_to_reg (XEXP (operands[1], 0)));
4394 /* Handle loading a large integer during reload */
4395 else if (GET_CODE (operands[1]) == CONST_INT
4396 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4398 /* Writing a constant to memory needs a scratch, which should
4399 be handled with SECONDARY_RELOADs. */
4400 if (GET_CODE (operands[0]) != REG)
4403 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4404 emit_insn (gen_movsi (operands[0], operands[1]));
4411 (define_insn "*thumb_movhi_insn"
4412 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4413 (match_operand:HI 1 "general_operand" "l,mn,l,*h,*r,I"))]
4415 && ( register_operand (operands[0], HImode)
4416 || register_operand (operands[1], HImode))"
4418 switch (which_alternative)
4420 case 0: return \"add %0, %1, #0\";
4421 case 2: return \"strh %1, %0\";
4422 case 3: return \"mov %0, %1\";
4423 case 4: return \"mov %0, %1\";
4424 case 5: return \"mov %0, %1\";
4427 /* The stack pointer can end up being taken as an index register.
4428 Catch this case here and deal with it. */
4429 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4430 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4431 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4434 ops[0] = operands[0];
4435 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4437 output_asm_insn (\"mov %0, %1\", ops);
4439 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4442 return \"ldrh %0, %1\";
4444 [(set_attr "length" "2,4,2,2,2,2")
4445 (set_attr "type" "*,load,store1,*,*,*")
4446 (set_attr "pool_range" "*,64,*,*,*,*")]
4450 (define_insn "rotated_loadsi"
4451 [(set (match_operand:SI 0 "s_register_operand" "=r")
4452 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4454 "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4459 ops[0] = operands[0];
4460 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4461 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4464 [(set_attr "type" "load")
4465 (set_attr "predicable" "yes")]
4468 (define_expand "movhi_bytes"
4469 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4471 (zero_extend:SI (match_dup 6)))
4472 (set (match_operand:SI 0 "" "")
4473 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4478 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4480 mem1 = gen_rtx_MEM (QImode, addr);
4481 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4482 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4483 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4484 operands[0] = gen_lowpart (SImode, operands[0]);
4486 operands[2] = gen_reg_rtx (SImode);
4487 operands[3] = gen_reg_rtx (SImode);
4490 if (BYTES_BIG_ENDIAN)
4492 operands[4] = operands[2];
4493 operands[5] = operands[3];
4497 operands[4] = operands[3];
4498 operands[5] = operands[2];
4503 (define_expand "movhi_bigend"
4505 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4508 (ashiftrt:SI (match_dup 2) (const_int 16)))
4509 (set (match_operand:HI 0 "s_register_operand" "")
4510 (subreg:HI (match_dup 3) 0))]
4513 operands[2] = gen_reg_rtx (SImode);
4514 operands[3] = gen_reg_rtx (SImode);
4518 ;; Pattern to recognize insn generated default case above
4519 (define_insn "*movhi_insn_arch4"
4520 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4521 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4524 && (GET_CODE (operands[1]) != CONST_INT
4525 || const_ok_for_arm (INTVAL (operands[1]))
4526 || const_ok_for_arm (~INTVAL (operands[1])))"
4528 mov%?\\t%0, %1\\t%@ movhi
4529 mvn%?\\t%0, #%B1\\t%@ movhi
4530 str%?h\\t%1, %0\\t%@ movhi
4531 ldr%?h\\t%0, %1\\t%@ movhi"
4532 [(set_attr "type" "*,*,store1,load")
4533 (set_attr "predicable" "yes")
4534 (set_attr "pool_range" "*,*,*,256")
4535 (set_attr "neg_pool_range" "*,*,*,244")]
4538 (define_insn "*movhi_insn_littleend"
4539 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4540 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4543 && !BYTES_BIG_ENDIAN
4544 && !TARGET_MMU_TRAPS
4545 && (GET_CODE (operands[1]) != CONST_INT
4546 || const_ok_for_arm (INTVAL (operands[1]))
4547 || const_ok_for_arm (~INTVAL (operands[1])))"
4549 mov%?\\t%0, %1\\t%@ movhi
4550 mvn%?\\t%0, #%B1\\t%@ movhi
4551 ldr%?\\t%0, %1\\t%@ movhi"
4552 [(set_attr "type" "*,*,load")
4553 (set_attr "predicable" "yes")
4554 (set_attr "pool_range" "4096")
4555 (set_attr "neg_pool_range" "4084")]
4558 (define_insn "*movhi_insn_bigend"
4559 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4560 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4564 && !TARGET_MMU_TRAPS
4565 && (GET_CODE (operands[1]) != CONST_INT
4566 || const_ok_for_arm (INTVAL (operands[1]))
4567 || const_ok_for_arm (~INTVAL (operands[1])))"
4569 mov%?\\t%0, %1\\t%@ movhi
4570 mvn%?\\t%0, #%B1\\t%@ movhi
4571 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4572 [(set_attr "type" "*,*,load")
4573 (set_attr "predicable" "yes")
4574 (set_attr "length" "4,4,8")
4575 (set_attr "pool_range" "*,*,4092")
4576 (set_attr "neg_pool_range" "*,*,4084")]
4579 (define_insn "*loadhi_si_bigend"
4580 [(set (match_operand:SI 0 "s_register_operand" "=r")
4581 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
4585 && !TARGET_MMU_TRAPS"
4586 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4587 [(set_attr "type" "load")
4588 (set_attr "predicable" "yes")
4589 (set_attr "pool_range" "4096")
4590 (set_attr "neg_pool_range" "4084")]
4593 (define_insn "*movhi_bytes"
4594 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4595 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4596 "TARGET_ARM && TARGET_MMU_TRAPS"
4598 mov%?\\t%0, %1\\t%@ movhi
4599 mvn%?\\t%0, #%B1\\t%@ movhi"
4600 [(set_attr "predicable" "yes")]
4603 (define_insn "thumb_movhi_clobber"
4604 [(set (match_operand:HI 0 "memory_operand" "=m")
4605 (match_operand:HI 1 "register_operand" "l"))
4606 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4612 ;; We use a DImode scratch because we may occasionally need an additional
4613 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4614 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4615 (define_expand "reload_outhi"
4616 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4617 (match_operand:HI 1 "s_register_operand" "r")
4618 (match_operand:DI 2 "s_register_operand" "=&l")])]
4621 arm_reload_out_hi (operands);
4623 thumb_reload_out_hi (operands);
4628 (define_expand "reload_inhi"
4629 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4630 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4631 (match_operand:DI 2 "s_register_operand" "=&r")])]
4632 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4635 arm_reload_in_hi (operands);
4637 thumb_reload_out_hi (operands);
4641 (define_expand "movqi"
4642 [(set (match_operand:QI 0 "general_operand" "")
4643 (match_operand:QI 1 "general_operand" ""))]
4648 /* Everything except mem = const or mem = mem can be done easily */
4650 if (!no_new_pseudos)
4652 if (GET_CODE (operands[1]) == CONST_INT)
4654 rtx reg = gen_reg_rtx (SImode);
4656 emit_insn (gen_movsi (reg, operands[1]));
4657 operands[1] = gen_lowpart (QImode, reg);
4659 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4661 rtx reg = gen_reg_rtx (SImode);
4663 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4664 operands[1] = gen_lowpart (QImode, reg);
4666 if (GET_CODE (operands[0]) == MEM)
4667 operands[1] = force_reg (QImode, operands[1]);
4670 else /* TARGET_THUMB */
4672 if (!no_new_pseudos)
4674 if (GET_CODE (operands[0]) != REG)
4675 operands[1] = force_reg (QImode, operands[1]);
4677 /* ??? We shouldn't really get invalid addresses here, but this can
4678 happen if we are passed a SP (never OK for HImode/QImode) or
4679 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4680 HImode/QImode) relative address. */
4681 /* ??? This should perhaps be fixed elsewhere, for instance, in
4682 fixup_stack_1, by checking for other kinds of invalid addresses,
4683 e.g. a bare reference to a virtual register. This may confuse the
4684 alpha though, which must handle this case differently. */
4685 if (GET_CODE (operands[0]) == MEM
4686 && !memory_address_p (GET_MODE (operands[0]),
4687 XEXP (operands[0], 0)))
4689 = replace_equiv_address (operands[0],
4690 copy_to_reg (XEXP (operands[0], 0)));
4691 if (GET_CODE (operands[1]) == MEM
4692 && !memory_address_p (GET_MODE (operands[1]),
4693 XEXP (operands[1], 0)))
4695 = replace_equiv_address (operands[1],
4696 copy_to_reg (XEXP (operands[1], 0)));
4698 /* Handle loading a large integer during reload */
4699 else if (GET_CODE (operands[1]) == CONST_INT
4700 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4702 /* Writing a constant to memory needs a scratch, which should
4703 be handled with SECONDARY_RELOADs. */
4704 if (GET_CODE (operands[0]) != REG)
4707 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4708 emit_insn (gen_movsi (operands[0], operands[1]));
4716 (define_insn "*arm_movqi_insn"
4717 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4718 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4720 && ( register_operand (operands[0], QImode)
4721 || register_operand (operands[1], QImode))"
4727 [(set_attr "type" "*,*,load,store1")
4728 (set_attr "predicable" "yes")]
4731 (define_insn "*thumb_movqi_insn"
4732 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4733 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
4735 && ( register_operand (operands[0], QImode)
4736 || register_operand (operands[1], QImode))"
4744 [(set_attr "length" "2")
4745 (set_attr "type" "*,load,store1,*,*,*")
4746 (set_attr "pool_range" "*,32,*,*,*,*")]
4749 (define_expand "movsf"
4750 [(set (match_operand:SF 0 "general_operand" "")
4751 (match_operand:SF 1 "general_operand" ""))]
4756 if (GET_CODE (operands[0]) == MEM)
4757 operands[1] = force_reg (SFmode, operands[1]);
4759 else /* TARGET_THUMB */
4761 if (!no_new_pseudos)
4763 if (GET_CODE (operands[0]) != REG)
4764 operands[1] = force_reg (SFmode, operands[1]);
4771 [(set (match_operand:SF 0 "nonimmediate_operand" "")
4772 (match_operand:SF 1 "immediate_operand" ""))]
4774 && !TARGET_HARD_FLOAT
4776 && GET_CODE (operands[1]) == CONST_DOUBLE"
4777 [(set (match_dup 2) (match_dup 3))]
4779 operands[2] = gen_lowpart (SImode, operands[0]);
4780 operands[3] = gen_lowpart (SImode, operands[1]);
4781 if (operands[2] == 0 || operands[3] == 0)
4786 (define_insn "*arm_movsf_hard_insn"
4787 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
4788 (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
4790 && TARGET_HARD_FLOAT
4791 && (GET_CODE (operands[0]) != MEM
4792 || register_operand (operands[1], SFmode))"
4798 str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
4799 stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
4801 ldr%?\\t%0, %1\\t%@ float
4802 str%?\\t%1, %0\\t%@ float"
4803 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
4804 (set_attr "predicable" "yes")
4806 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
4807 (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
4808 (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
4811 ;; Exactly the same as above, except that all `f' cases are deleted.
4812 ;; This is necessary to prevent reload from ever trying to use a `f' reg
4813 ;; when -msoft-float.
4815 (define_insn "*arm_movsf_soft_insn"
4816 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4817 (match_operand:SF 1 "general_operand" "r,mE,r"))]
4820 && TARGET_SOFT_FLOAT
4821 && (GET_CODE (operands[0]) != MEM
4822 || register_operand (operands[1], SFmode))"
4825 ldr%?\\t%0, %1\\t%@ float
4826 str%?\\t%1, %0\\t%@ float"
4827 [(set_attr "length" "4,4,4")
4828 (set_attr "predicable" "yes")
4829 (set_attr "type" "*,load,store1")
4830 (set_attr "pool_range" "*,4096,*")
4831 (set_attr "neg_pool_range" "*,4084,*")]
4834 ;;; ??? This should have alternatives for constants.
4835 (define_insn "*thumb_movsf_insn"
4836 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4837 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
4839 && ( register_operand (operands[0], SFmode)
4840 || register_operand (operands[1], SFmode))"
4849 [(set_attr "length" "2")
4850 (set_attr "type" "*,load,store1,load,store1,*,*")
4851 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
4854 (define_expand "movdf"
4855 [(set (match_operand:DF 0 "general_operand" "")
4856 (match_operand:DF 1 "general_operand" ""))]
4861 if (GET_CODE (operands[0]) == MEM)
4862 operands[1] = force_reg (DFmode, operands[1]);
4864 else /* TARGET_THUMB */
4866 if (!no_new_pseudos)
4868 if (GET_CODE (operands[0]) != REG)
4869 operands[1] = force_reg (DFmode, operands[1]);
4875 ;; Reloading a df mode value stored in integer regs to memory can require a
4877 (define_expand "reload_outdf"
4878 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
4879 (match_operand:DF 1 "s_register_operand" "r")
4880 (match_operand:SI 2 "s_register_operand" "=&r")]
4884 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
4887 operands[2] = XEXP (operands[0], 0);
4888 else if (code == POST_INC || code == PRE_DEC)
4890 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
4891 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
4892 emit_insn (gen_movdi (operands[0], operands[1]));
4895 else if (code == PRE_INC)
4897 rtx reg = XEXP (XEXP (operands[0], 0), 0);
4899 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
4902 else if (code == POST_DEC)
4903 operands[2] = XEXP (XEXP (operands[0], 0), 0);
4905 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
4906 XEXP (XEXP (operands[0], 0), 1)));
4908 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
4911 if (code == POST_DEC)
4912 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
4918 (define_insn "*movdf_hard_insn"
4919 [(set (match_operand:DF 0 "nonimmediate_operand"
4920 "=r,Q,r,m,r, f, f,f, m,!f,!r")
4921 (match_operand:DF 1 "general_operand"
4922 "Q, r,r,r,mF,fG,H,mF,f,r, f"))]
4924 && TARGET_HARD_FLOAT
4925 && (GET_CODE (operands[0]) != MEM
4926 || register_operand (operands[1], DFmode))"
4929 switch (which_alternative)
4932 case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
4933 case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
4934 case 2: case 3: case 4: return output_move_double (operands);
4935 case 5: return \"mvf%?d\\t%0, %1\";
4936 case 6: return \"mnf%?d\\t%0, #%N1\";
4937 case 7: return \"ldf%?d\\t%0, %1\";
4938 case 8: return \"stf%?d\\t%1, %0\";
4939 case 9: return output_mov_double_fpu_from_arm (operands);
4940 case 10: return output_mov_double_arm_from_fpu (operands);
4944 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
4945 (set_attr "predicable" "yes")
4947 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
4948 (set_attr "pool_range" "*,*,*,*,1020,*,*,1024,*,*,*")
4949 (set_attr "neg_pool_range" "*,*,*,*,1008,*,*,1008,*,*,*")]
4952 ;; Software floating point version. This is essentially the same as movdi.
4953 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
4956 (define_insn "*movdf_soft_insn"
4957 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
4958 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
4959 "TARGET_ARM && TARGET_SOFT_FLOAT
4962 "* return output_move_double (operands);"
4963 [(set_attr "length" "8,8,8")
4964 (set_attr "type" "*,load,store2")
4965 (set_attr "pool_range" "1020")
4966 (set_attr "neg_pool_range" "1008")]
4969 ;;; ??? This should have alternatives for constants.
4970 ;;; ??? This was originally identical to the movdi_insn pattern.
4971 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
4972 ;;; thumb_reorg with a memory reference.
4973 (define_insn "*thumb_movdf_insn"
4974 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
4975 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
4977 && ( register_operand (operands[0], DFmode)
4978 || register_operand (operands[1], DFmode))"
4980 switch (which_alternative)
4984 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4985 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4986 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4988 return \"ldmia\\t%1, {%0, %H0}\";
4990 return \"stmia\\t%0, {%1, %H1}\";
4992 return thumb_load_double_from_address (operands);
4994 operands[2] = gen_rtx (MEM, SImode,
4995 plus_constant (XEXP (operands[0], 0), 4));
4996 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4999 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5000 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5001 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5004 [(set_attr "length" "4,2,2,6,4,4")
5005 (set_attr "type" "*,load,store2,load,store2,*")
5006 (set_attr "pool_range" "*,*,*,1020,*,*")]
5010 ;; Saving and restoring the floating point registers in the prologue should
5011 ;; be done in XFmode, even though we don't support that for anything else
5012 ;; (Well, strictly it's 'internal representation', but that's effectively
5015 (define_insn "*movxf_hard_insn"
5016 [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
5017 (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
5018 "TARGET_ARM && TARGET_HARD_FLOAT && reload_completed"
5020 switch (which_alternative)
5023 case 0: return \"mvf%?e\\t%0, %1\";
5024 case 1: return \"mnf%?e\\t%0, #%N1\";
5025 case 2: return \"ldf%?e\\t%0, %1\";
5026 case 3: return \"stf%?e\\t%1, %0\";
5027 case 4: return output_mov_long_double_fpu_from_arm (operands);
5028 case 5: return output_mov_long_double_arm_from_fpu (operands);
5029 case 6: return output_mov_long_double_arm_from_arm (operands);
5032 [(set_attr "length" "4,4,4,4,8,8,12")
5033 (set_attr "predicable" "yes")
5034 (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
5035 (set_attr "pool_range" "*,*,1024,*,*,*,*")
5036 (set_attr "neg_pool_range" "*,*,1004,*,*,*,*")]
5040 ;; load- and store-multiple insns
5041 ;; The arm can load/store any set of registers, provided that they are in
5042 ;; ascending order; but that is beyond GCC so stick with what it knows.
5044 (define_expand "load_multiple"
5045 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5046 (match_operand:SI 1 "" ""))
5047 (use (match_operand:SI 2 "" ""))])]
5050 /* Support only fixed point registers. */
5051 if (GET_CODE (operands[2]) != CONST_INT
5052 || INTVAL (operands[2]) > 14
5053 || INTVAL (operands[2]) < 2
5054 || GET_CODE (operands[1]) != MEM
5055 || GET_CODE (operands[0]) != REG
5056 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5057 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5061 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5062 force_reg (SImode, XEXP (operands[1], 0)),
5063 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5064 MEM_IN_STRUCT_P(operands[1]),
5065 MEM_SCALAR_P (operands[1]));
5069 ;; Load multiple with write-back
5071 (define_insn "*ldmsi_postinc4"
5072 [(match_parallel 0 "load_multiple_operation"
5073 [(set (match_operand:SI 1 "s_register_operand" "=r")
5074 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5076 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5077 (mem:SI (match_dup 2)))
5078 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5079 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5080 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5081 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5082 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5083 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5084 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5085 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5086 [(set_attr "type" "load")
5087 (set_attr "predicable" "yes")]
5090 (define_insn "*ldmsi_postinc3"
5091 [(match_parallel 0 "load_multiple_operation"
5092 [(set (match_operand:SI 1 "s_register_operand" "=r")
5093 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5095 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5096 (mem:SI (match_dup 2)))
5097 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5098 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5099 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5100 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5101 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5102 "ldm%?ia\\t%1!, {%3, %4, %5}"
5103 [(set_attr "type" "load")
5104 (set_attr "predicable" "yes")]
5107 (define_insn "*ldmsi_postinc2"
5108 [(match_parallel 0 "load_multiple_operation"
5109 [(set (match_operand:SI 1 "s_register_operand" "=r")
5110 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5112 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5113 (mem:SI (match_dup 2)))
5114 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5115 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5116 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5117 "ldm%?ia\\t%1!, {%3, %4}"
5118 [(set_attr "type" "load")
5119 (set_attr "predicable" "yes")]
5122 ;; Ordinary load multiple
5124 (define_insn "*ldmsi4"
5125 [(match_parallel 0 "load_multiple_operation"
5126 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5127 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5128 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5129 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5130 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5131 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5132 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5133 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5134 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5135 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5136 [(set_attr "type" "load")
5137 (set_attr "predicable" "yes")]
5140 (define_insn "*ldmsi3"
5141 [(match_parallel 0 "load_multiple_operation"
5142 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5143 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5144 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5145 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5146 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5147 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5148 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5149 "ldm%?ia\\t%1, {%2, %3, %4}"
5150 [(set_attr "type" "load")
5151 (set_attr "predicable" "yes")]
5154 (define_insn "*ldmsi2"
5155 [(match_parallel 0 "load_multiple_operation"
5156 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5157 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5158 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5159 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5160 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5161 "ldm%?ia\\t%1, {%2, %3}"
5162 [(set_attr "type" "load")
5163 (set_attr "predicable" "yes")]
5166 (define_expand "store_multiple"
5167 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5168 (match_operand:SI 1 "" ""))
5169 (use (match_operand:SI 2 "" ""))])]
5172 /* Support only fixed point registers */
5173 if (GET_CODE (operands[2]) != CONST_INT
5174 || INTVAL (operands[2]) > 14
5175 || INTVAL (operands[2]) < 2
5176 || GET_CODE (operands[1]) != REG
5177 || GET_CODE (operands[0]) != MEM
5178 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5179 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5183 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5184 force_reg (SImode, XEXP (operands[0], 0)),
5185 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5186 MEM_IN_STRUCT_P(operands[0]),
5187 MEM_SCALAR_P (operands[0]));
5191 ;; Store multiple with write-back
5193 (define_insn "*stmsi_postinc4"
5194 [(match_parallel 0 "store_multiple_operation"
5195 [(set (match_operand:SI 1 "s_register_operand" "=r")
5196 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5198 (set (mem:SI (match_dup 2))
5199 (match_operand:SI 3 "arm_hard_register_operand" ""))
5200 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5201 (match_operand:SI 4 "arm_hard_register_operand" ""))
5202 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5203 (match_operand:SI 5 "arm_hard_register_operand" ""))
5204 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5205 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5206 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5207 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5208 [(set_attr "predicable" "yes")
5209 (set_attr "type" "store4")]
5212 (define_insn "*stmsi_postinc3"
5213 [(match_parallel 0 "store_multiple_operation"
5214 [(set (match_operand:SI 1 "s_register_operand" "=r")
5215 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5217 (set (mem:SI (match_dup 2))
5218 (match_operand:SI 3 "arm_hard_register_operand" ""))
5219 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5220 (match_operand:SI 4 "arm_hard_register_operand" ""))
5221 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5222 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5223 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5224 "stm%?ia\\t%1!, {%3, %4, %5}"
5225 [(set_attr "predicable" "yes")
5226 (set_attr "type" "store3")]
5229 (define_insn "*stmsi_postinc2"
5230 [(match_parallel 0 "store_multiple_operation"
5231 [(set (match_operand:SI 1 "s_register_operand" "=r")
5232 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5234 (set (mem:SI (match_dup 2))
5235 (match_operand:SI 3 "arm_hard_register_operand" ""))
5236 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5237 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5238 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5239 "stm%?ia\\t%1!, {%3, %4}"
5240 [(set_attr "predicable" "yes")
5241 (set_attr "type" "store2")]
5244 ;; Ordinary store multiple
5246 (define_insn "*stmsi4"
5247 [(match_parallel 0 "store_multiple_operation"
5248 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5249 (match_operand:SI 2 "arm_hard_register_operand" ""))
5250 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5251 (match_operand:SI 3 "arm_hard_register_operand" ""))
5252 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5253 (match_operand:SI 4 "arm_hard_register_operand" ""))
5254 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5255 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5256 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5257 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5258 [(set_attr "predicable" "yes")
5259 (set_attr "type" "store4")]
5262 (define_insn "*stmsi3"
5263 [(match_parallel 0 "store_multiple_operation"
5264 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5265 (match_operand:SI 2 "arm_hard_register_operand" ""))
5266 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5267 (match_operand:SI 3 "arm_hard_register_operand" ""))
5268 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5269 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5270 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5271 "stm%?ia\\t%1, {%2, %3, %4}"
5272 [(set_attr "predicable" "yes")
5273 (set_attr "type" "store3")]
5276 (define_insn "*stmsi2"
5277 [(match_parallel 0 "store_multiple_operation"
5278 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5279 (match_operand:SI 2 "arm_hard_register_operand" ""))
5280 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5281 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5282 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5283 "stm%?ia\\t%1, {%2, %3}"
5284 [(set_attr "predicable" "yes")
5285 (set_attr "type" "store2")]
5288 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5289 ;; We could let this apply for blocks of less than this, but it clobbers so
5290 ;; many registers that there is then probably a better way.
5292 (define_expand "movstrqi"
5293 [(match_operand:BLK 0 "general_operand" "")
5294 (match_operand:BLK 1 "general_operand" "")
5295 (match_operand:SI 2 "const_int_operand" "")
5296 (match_operand:SI 3 "const_int_operand" "")]
5301 if (arm_gen_movstrqi (operands))
5305 else /* TARGET_THUMB */
5307 if ( INTVAL (operands[3]) != 4
5308 || INTVAL (operands[2]) > 48)
5311 thumb_expand_movstrqi (operands);
5317 ;; Thumb block-move insns
5319 (define_insn "movmem12b"
5320 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5321 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5322 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5323 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5324 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5325 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5326 (set (match_operand:SI 0 "register_operand" "=l")
5327 (plus:SI (match_dup 2) (const_int 12)))
5328 (set (match_operand:SI 1 "register_operand" "=l")
5329 (plus:SI (match_dup 3) (const_int 12)))
5330 (clobber (match_scratch:SI 4 "=&l"))
5331 (clobber (match_scratch:SI 5 "=&l"))
5332 (clobber (match_scratch:SI 6 "=&l"))]
5334 "* return thumb_output_move_mem_multiple (3, operands);"
5335 [(set_attr "length" "4")
5336 ; This isn't entirely accurate... It loads as well, but in terms of
5337 ; scheduling the following insn it is better to consider it as a store
5338 (set_attr "type" "store3")]
5341 (define_insn "movmem8b"
5342 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5343 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5344 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5345 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5346 (set (match_operand:SI 0 "register_operand" "=l")
5347 (plus:SI (match_dup 2) (const_int 8)))
5348 (set (match_operand:SI 1 "register_operand" "=l")
5349 (plus:SI (match_dup 3) (const_int 8)))
5350 (clobber (match_scratch:SI 4 "=&l"))
5351 (clobber (match_scratch:SI 5 "=&l"))]
5353 "* return thumb_output_move_mem_multiple (2, operands);"
5354 [(set_attr "length" "4")
5355 ; This isn't entirely accurate... It loads as well, but in terms of
5356 ; scheduling the following insn it is better to consider it as a store
5357 (set_attr "type" "store2")]
5362 ;; Compare & branch insns
5363 ;; The range calcualations are based as follows:
5364 ;; For forward branches, the address calculation returns the address of
5365 ;; the next instruction. This is 2 beyond the branch instruction.
5366 ;; For backward branches, the address calculation returns the address of
5367 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5368 ;; instruction for the shortest sequence, and 4 before the branch instruction
5369 ;; if we have to jump around an unconditional branch.
5370 ;; To the basic branch range the PC offset must be added (this is +4).
5371 ;; So for forward branches we have
5372 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5373 ;; And for backward branches we have
5374 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5376 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5377 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5379 (define_insn "cbranchsi4"
5382 (match_operator 0 "arm_comparison_operator"
5383 [(match_operand:SI 1 "register_operand" "l,r")
5384 (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5385 (label_ref (match_operand 3 "" ""))
5389 output_asm_insn (\"cmp\\t%1, %2\", operands);
5390 switch (get_attr_length (insn))
5392 case 4: return \"b%d0\\t%l3\";
5393 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5394 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5397 [(set (attr "far_jump")
5399 (eq_attr "length" "8")
5400 (const_string "yes")
5401 (const_string "no")))
5402 (set (attr "length")
5404 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5405 (le (minus (match_dup 3) (pc)) (const_int 256)))
5408 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5409 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5414 (define_insn "*negated_cbranchsi4"
5417 (match_operator 0 "arm_comparison_operator"
5418 [(match_operand:SI 1 "register_operand" "l")
5419 (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5420 (label_ref (match_operand 3 "" ""))
5424 output_asm_insn (\"cmn\\t%1, %2\", operands);
5425 switch (get_attr_length (insn))
5427 case 4: return \"b%d0\\t%l3\";
5428 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5429 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5432 [(set (attr "far_jump")
5434 (eq_attr "length" "8")
5435 (const_string "yes")
5436 (const_string "no")))
5437 (set (attr "length")
5439 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5440 (le (minus (match_dup 3) (pc)) (const_int 256)))
5443 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5444 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5450 ;; Comparison and test insns
5452 (define_expand "cmpsi"
5453 [(match_operand:SI 0 "s_register_operand" "")
5454 (match_operand:SI 1 "arm_add_operand" "")]
5457 arm_compare_op0 = operands[0];
5458 arm_compare_op1 = operands[1];
5463 (define_expand "cmpsf"
5464 [(match_operand:SF 0 "s_register_operand" "")
5465 (match_operand:SF 1 "fpu_rhs_operand" "")]
5466 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5468 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
5469 operands[1] = force_reg (SFmode, operands[1]);
5471 arm_compare_op0 = operands[0];
5472 arm_compare_op1 = operands[1];
5477 (define_expand "cmpdf"
5478 [(match_operand:DF 0 "s_register_operand" "")
5479 (match_operand:DF 1 "fpu_rhs_operand" "")]
5480 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5482 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
5483 operands[1] = force_reg (DFmode, operands[1]);
5485 arm_compare_op0 = operands[0];
5486 arm_compare_op1 = operands[1];
5491 (define_insn "*arm_cmpsi_insn"
5492 [(set (reg:CC CC_REGNUM)
5493 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5494 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
5499 [(set_attr "conds" "set")]
5502 (define_insn "*cmpsi_shiftsi"
5503 [(set (reg:CC CC_REGNUM)
5504 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5505 (match_operator:SI 3 "shift_operator"
5506 [(match_operand:SI 1 "s_register_operand" "r")
5507 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
5510 [(set_attr "conds" "set")
5511 (set_attr "shift" "1")
5515 (define_insn "*cmpsi_shiftsi_swp"
5516 [(set (reg:CC_SWP CC_REGNUM)
5517 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5518 [(match_operand:SI 1 "s_register_operand" "r")
5519 (match_operand:SI 2 "reg_or_int_operand" "rM")])
5520 (match_operand:SI 0 "s_register_operand" "r")))]
5523 [(set_attr "conds" "set")
5524 (set_attr "shift" "1")
5528 (define_insn "*cmpsi_neg_shiftsi"
5529 [(set (reg:CC CC_REGNUM)
5530 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5531 (neg:SI (match_operator:SI 3 "shift_operator"
5532 [(match_operand:SI 1 "s_register_operand" "r")
5533 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5536 [(set_attr "conds" "set")
5537 (set_attr "shift" "1")
5541 (define_insn "*cmpsf_insn"
5542 [(set (reg:CCFP CC_REGNUM)
5543 (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
5544 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5545 "TARGET_ARM && TARGET_HARD_FLOAT"
5549 [(set_attr "conds" "set")
5550 (set_attr "type" "f_2_r")]
5553 (define_insn "*cmpdf_insn"
5554 [(set (reg:CCFP CC_REGNUM)
5555 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
5556 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5557 "TARGET_ARM && TARGET_HARD_FLOAT"
5561 [(set_attr "conds" "set")
5562 (set_attr "type" "f_2_r")]
5565 (define_insn "*cmpesfdf_df"
5566 [(set (reg:CCFP CC_REGNUM)
5567 (compare:CCFP (float_extend:DF
5568 (match_operand:SF 0 "s_register_operand" "f,f"))
5569 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5570 "TARGET_ARM && TARGET_HARD_FLOAT"
5574 [(set_attr "conds" "set")
5575 (set_attr "type" "f_2_r")]
5578 (define_insn "*cmpdf_esfdf"
5579 [(set (reg:CCFP CC_REGNUM)
5580 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5582 (match_operand:SF 1 "s_register_operand" "f"))))]
5583 "TARGET_ARM && TARGET_HARD_FLOAT"
5585 [(set_attr "conds" "set")
5586 (set_attr "type" "f_2_r")]
5589 ;; Cirrus SF compare instruction
5590 (define_insn "*cirrus_cmpsf"
5591 [(set (reg:CCFP CC_REGNUM)
5592 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
5593 (match_operand:SF 1 "cirrus_fp_register" "v")))]
5594 "TARGET_ARM && TARGET_CIRRUS"
5595 "cfcmps%?\\tr15, %V0, %V1"
5596 [(set_attr "type" "mav_farith")
5597 (set_attr "cirrus" "compare")]
5600 ;; Cirrus DF compare instruction
5601 (define_insn "*cirrus_cmpdf"
5602 [(set (reg:CCFP CC_REGNUM)
5603 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
5604 (match_operand:DF 1 "cirrus_fp_register" "v")))]
5605 "TARGET_ARM && TARGET_CIRRUS"
5606 "cfcmpd%?\\tr15, %V0, %V1"
5607 [(set_attr "type" "mav_farith")
5608 (set_attr "cirrus" "compare")]
5611 ;; Cirrus DI compare instruction
5612 (define_expand "cmpdi"
5613 [(match_operand:DI 0 "cirrus_fp_register" "")
5614 (match_operand:DI 1 "cirrus_fp_register" "")]
5615 "TARGET_ARM && TARGET_CIRRUS"
5617 arm_compare_op0 = operands[0];
5618 arm_compare_op1 = operands[1];
5622 (define_insn "*cirrus_cmpdi"
5623 [(set (reg:CC CC_REGNUM)
5624 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
5625 (match_operand:DI 1 "cirrus_fp_register" "v")))]
5626 "TARGET_ARM && TARGET_CIRRUS"
5627 "cfcmp64%?\\tr15, %V0, %V1"
5628 [(set_attr "type" "mav_farith")
5629 (set_attr "cirrus" "compare")]
5632 (define_insn "*cmpsf_trap"
5633 [(set (reg:CCFPE CC_REGNUM)
5634 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
5635 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5636 "TARGET_ARM && TARGET_HARD_FLOAT"
5640 [(set_attr "conds" "set")
5641 (set_attr "type" "f_2_r")]
5644 (define_insn "*cmpdf_trap"
5645 [(set (reg:CCFPE CC_REGNUM)
5646 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
5647 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5648 "TARGET_ARM && TARGET_HARD_FLOAT"
5652 [(set_attr "conds" "set")
5653 (set_attr "type" "f_2_r")]
5656 (define_insn "*cmp_esfdf_df_trap"
5657 [(set (reg:CCFPE CC_REGNUM)
5658 (compare:CCFPE (float_extend:DF
5659 (match_operand:SF 0 "s_register_operand" "f,f"))
5660 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5661 "TARGET_ARM && TARGET_HARD_FLOAT"
5665 [(set_attr "conds" "set")
5666 (set_attr "type" "f_2_r")]
5669 (define_insn "*cmp_df_esfdf_trap"
5670 [(set (reg:CCFPE CC_REGNUM)
5671 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
5673 (match_operand:SF 1 "s_register_operand" "f"))))]
5674 "TARGET_ARM && TARGET_HARD_FLOAT"
5676 [(set_attr "conds" "set")
5677 (set_attr "type" "f_2_r")]
5680 ; This insn allows redundant compares to be removed by cse, nothing should
5681 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5682 ; is deleted later on. The match_dup will match the mode here, so that
5683 ; mode changes of the condition codes aren't lost by this even though we don't
5684 ; specify what they are.
5686 (define_insn "*deleted_compare"
5687 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5689 "\\t%@ deleted compare"
5690 [(set_attr "conds" "set")
5691 (set_attr "length" "0")]
5695 ;; Conditional branch insns
5697 (define_expand "beq"
5699 (if_then_else (eq (match_dup 1) (const_int 0))
5700 (label_ref (match_operand 0 "" ""))
5703 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5706 (define_expand "bne"
5708 (if_then_else (ne (match_dup 1) (const_int 0))
5709 (label_ref (match_operand 0 "" ""))
5712 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5715 (define_expand "bgt"
5717 (if_then_else (gt (match_dup 1) (const_int 0))
5718 (label_ref (match_operand 0 "" ""))
5721 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5724 (define_expand "ble"
5726 (if_then_else (le (match_dup 1) (const_int 0))
5727 (label_ref (match_operand 0 "" ""))
5730 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5733 (define_expand "bge"
5735 (if_then_else (ge (match_dup 1) (const_int 0))
5736 (label_ref (match_operand 0 "" ""))
5739 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5742 (define_expand "blt"
5744 (if_then_else (lt (match_dup 1) (const_int 0))
5745 (label_ref (match_operand 0 "" ""))
5748 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5751 (define_expand "bgtu"
5753 (if_then_else (gtu (match_dup 1) (const_int 0))
5754 (label_ref (match_operand 0 "" ""))
5757 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5760 (define_expand "bleu"
5762 (if_then_else (leu (match_dup 1) (const_int 0))
5763 (label_ref (match_operand 0 "" ""))
5766 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5769 (define_expand "bgeu"
5771 (if_then_else (geu (match_dup 1) (const_int 0))
5772 (label_ref (match_operand 0 "" ""))
5775 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5778 (define_expand "bltu"
5780 (if_then_else (ltu (match_dup 1) (const_int 0))
5781 (label_ref (match_operand 0 "" ""))
5784 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5787 (define_expand "bunordered"
5789 (if_then_else (unordered (match_dup 1) (const_int 0))
5790 (label_ref (match_operand 0 "" ""))
5792 "TARGET_ARM && TARGET_HARD_FLOAT"
5793 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5797 (define_expand "bordered"
5799 (if_then_else (ordered (match_dup 1) (const_int 0))
5800 (label_ref (match_operand 0 "" ""))
5802 "TARGET_ARM && TARGET_HARD_FLOAT"
5803 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5807 (define_expand "bungt"
5809 (if_then_else (ungt (match_dup 1) (const_int 0))
5810 (label_ref (match_operand 0 "" ""))
5812 "TARGET_ARM && TARGET_HARD_FLOAT"
5813 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5816 (define_expand "bunlt"
5818 (if_then_else (unlt (match_dup 1) (const_int 0))
5819 (label_ref (match_operand 0 "" ""))
5821 "TARGET_ARM && TARGET_HARD_FLOAT"
5822 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5825 (define_expand "bunge"
5827 (if_then_else (unge (match_dup 1) (const_int 0))
5828 (label_ref (match_operand 0 "" ""))
5830 "TARGET_ARM && TARGET_HARD_FLOAT"
5831 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5834 (define_expand "bunle"
5836 (if_then_else (unle (match_dup 1) (const_int 0))
5837 (label_ref (match_operand 0 "" ""))
5839 "TARGET_ARM && TARGET_HARD_FLOAT"
5840 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5843 ;; The following two patterns need two branch instructions, since there is
5844 ;; no single instruction that will handle all cases.
5845 (define_expand "buneq"
5847 (if_then_else (uneq (match_dup 1) (const_int 0))
5848 (label_ref (match_operand 0 "" ""))
5850 "TARGET_ARM && TARGET_HARD_FLOAT"
5851 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
5854 (define_expand "bltgt"
5856 (if_then_else (ltgt (match_dup 1) (const_int 0))
5857 (label_ref (match_operand 0 "" ""))
5859 "TARGET_ARM && TARGET_HARD_FLOAT"
5860 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
5864 ;; Patterns to match conditional branch insns.
5867 ; Special pattern to match UNEQ.
5868 (define_insn "*arm_buneq"
5870 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5871 (label_ref (match_operand 0 "" ""))
5873 "TARGET_ARM && TARGET_HARD_FLOAT"
5875 if (arm_ccfsm_state != 0)
5878 return \"bvs\\t%l0\;beq\\t%l0\";
5880 [(set_attr "conds" "jump_clob")
5881 (set_attr "length" "8")]
5884 ; Special pattern to match LTGT.
5885 (define_insn "*arm_bltgt"
5887 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5888 (label_ref (match_operand 0 "" ""))
5890 "TARGET_ARM && TARGET_HARD_FLOAT"
5892 if (arm_ccfsm_state != 0)
5895 return \"bmi\\t%l0\;bgt\\t%l0\";
5897 [(set_attr "conds" "jump_clob")
5898 (set_attr "length" "8")]
5901 (define_insn "*arm_cond_branch"
5903 (if_then_else (match_operator 1 "arm_comparison_operator"
5904 [(match_operand 2 "cc_register" "") (const_int 0)])
5905 (label_ref (match_operand 0 "" ""))
5909 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5911 arm_ccfsm_state += 2;
5914 return \"b%d1\\t%l0\";
5916 [(set_attr "conds" "use")]
5919 ; Special pattern to match reversed UNEQ.
5920 (define_insn "*arm_buneq_reversed"
5922 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5924 (label_ref (match_operand 0 "" ""))))]
5925 "TARGET_ARM && TARGET_HARD_FLOAT"
5927 if (arm_ccfsm_state != 0)
5930 return \"bmi\\t%l0\;bgt\\t%l0\";
5932 [(set_attr "conds" "jump_clob")
5933 (set_attr "length" "8")]
5936 ; Special pattern to match reversed LTGT.
5937 (define_insn "*arm_bltgt_reversed"
5939 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5941 (label_ref (match_operand 0 "" ""))))]
5942 "TARGET_ARM && TARGET_HARD_FLOAT"
5944 if (arm_ccfsm_state != 0)
5947 return \"bvs\\t%l0\;beq\\t%l0\";
5949 [(set_attr "conds" "jump_clob")
5950 (set_attr "length" "8")]
5953 (define_insn "*arm_cond_branch_reversed"
5955 (if_then_else (match_operator 1 "arm_comparison_operator"
5956 [(match_operand 2 "cc_register" "") (const_int 0)])
5958 (label_ref (match_operand 0 "" ""))))]
5961 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5963 arm_ccfsm_state += 2;
5966 return \"b%D1\\t%l0\";
5968 [(set_attr "conds" "use")]
5975 (define_expand "seq"
5976 [(set (match_operand:SI 0 "s_register_operand" "=r")
5977 (eq:SI (match_dup 1) (const_int 0)))]
5979 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5982 (define_expand "sne"
5983 [(set (match_operand:SI 0 "s_register_operand" "=r")
5984 (ne:SI (match_dup 1) (const_int 0)))]
5986 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5989 (define_expand "sgt"
5990 [(set (match_operand:SI 0 "s_register_operand" "=r")
5991 (gt:SI (match_dup 1) (const_int 0)))]
5993 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5996 (define_expand "sle"
5997 [(set (match_operand:SI 0 "s_register_operand" "=r")
5998 (le:SI (match_dup 1) (const_int 0)))]
6000 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6003 (define_expand "sge"
6004 [(set (match_operand:SI 0 "s_register_operand" "=r")
6005 (ge:SI (match_dup 1) (const_int 0)))]
6007 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6010 (define_expand "slt"
6011 [(set (match_operand:SI 0 "s_register_operand" "=r")
6012 (lt:SI (match_dup 1) (const_int 0)))]
6014 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6017 (define_expand "sgtu"
6018 [(set (match_operand:SI 0 "s_register_operand" "=r")
6019 (gtu:SI (match_dup 1) (const_int 0)))]
6021 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6024 (define_expand "sleu"
6025 [(set (match_operand:SI 0 "s_register_operand" "=r")
6026 (leu:SI (match_dup 1) (const_int 0)))]
6028 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6031 (define_expand "sgeu"
6032 [(set (match_operand:SI 0 "s_register_operand" "=r")
6033 (geu:SI (match_dup 1) (const_int 0)))]
6035 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6038 (define_expand "sltu"
6039 [(set (match_operand:SI 0 "s_register_operand" "=r")
6040 (ltu:SI (match_dup 1) (const_int 0)))]
6042 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6045 (define_expand "sunordered"
6046 [(set (match_operand:SI 0 "s_register_operand" "=r")
6047 (unordered:SI (match_dup 1) (const_int 0)))]
6048 "TARGET_ARM && TARGET_HARD_FLOAT"
6049 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6053 (define_expand "sordered"
6054 [(set (match_operand:SI 0 "s_register_operand" "=r")
6055 (ordered:SI (match_dup 1) (const_int 0)))]
6056 "TARGET_ARM && TARGET_HARD_FLOAT"
6057 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6061 (define_expand "sungt"
6062 [(set (match_operand:SI 0 "s_register_operand" "=r")
6063 (ungt:SI (match_dup 1) (const_int 0)))]
6064 "TARGET_ARM && TARGET_HARD_FLOAT"
6065 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6069 (define_expand "sunge"
6070 [(set (match_operand:SI 0 "s_register_operand" "=r")
6071 (unge:SI (match_dup 1) (const_int 0)))]
6072 "TARGET_ARM && TARGET_HARD_FLOAT"
6073 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6077 (define_expand "sunlt"
6078 [(set (match_operand:SI 0 "s_register_operand" "=r")
6079 (unlt:SI (match_dup 1) (const_int 0)))]
6080 "TARGET_ARM && TARGET_HARD_FLOAT"
6081 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6085 (define_expand "sunle"
6086 [(set (match_operand:SI 0 "s_register_operand" "=r")
6087 (unle:SI (match_dup 1) (const_int 0)))]
6088 "TARGET_ARM && TARGET_HARD_FLOAT"
6089 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6093 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6094 ;;; simple ARM instructions.
6096 ; (define_expand "suneq"
6097 ; [(set (match_operand:SI 0 "s_register_operand" "=r")
6098 ; (uneq:SI (match_dup 1) (const_int 0)))]
6099 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6103 ; (define_expand "sltgt"
6104 ; [(set (match_operand:SI 0 "s_register_operand" "=r")
6105 ; (ltgt:SI (match_dup 1) (const_int 0)))]
6106 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6110 (define_insn "*mov_scc"
6111 [(set (match_operand:SI 0 "s_register_operand" "=r")
6112 (match_operator:SI 1 "arm_comparison_operator"
6113 [(match_operand 2 "cc_register" "") (const_int 0)]))]
6115 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6116 [(set_attr "conds" "use")
6117 (set_attr "length" "8")]
6120 (define_insn "*mov_negscc"
6121 [(set (match_operand:SI 0 "s_register_operand" "=r")
6122 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
6123 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6125 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6126 [(set_attr "conds" "use")
6127 (set_attr "length" "8")]
6130 (define_insn "*mov_notscc"
6131 [(set (match_operand:SI 0 "s_register_operand" "=r")
6132 (not:SI (match_operator:SI 1 "arm_comparison_operator"
6133 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6135 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6136 [(set_attr "conds" "use")
6137 (set_attr "length" "8")]
6141 ;; Conditional move insns
6143 (define_expand "movsicc"
6144 [(set (match_operand:SI 0 "s_register_operand" "")
6145 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6146 (match_operand:SI 2 "arm_not_operand" "")
6147 (match_operand:SI 3 "arm_not_operand" "")))]
6151 enum rtx_code code = GET_CODE (operands[1]);
6154 if (code == UNEQ || code == LTGT)
6157 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6158 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6162 (define_expand "movsfcc"
6163 [(set (match_operand:SF 0 "s_register_operand" "")
6164 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6165 (match_operand:SF 2 "s_register_operand" "")
6166 (match_operand:SF 3 "nonmemory_operand" "")))]
6170 enum rtx_code code = GET_CODE (operands[1]);
6173 if (code == UNEQ || code == LTGT)
6176 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
6177 Otherwise, ensure it is a valid FP add operand */
6178 if ((!TARGET_HARD_FLOAT)
6179 || (!fpu_add_operand (operands[3], SFmode)))
6180 operands[3] = force_reg (SFmode, operands[3]);
6182 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6183 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6187 (define_expand "movdfcc"
6188 [(set (match_operand:DF 0 "s_register_operand" "")
6189 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6190 (match_operand:DF 2 "s_register_operand" "")
6191 (match_operand:DF 3 "fpu_add_operand" "")))]
6192 "TARGET_ARM && TARGET_HARD_FLOAT"
6195 enum rtx_code code = GET_CODE (operands[1]);
6198 if (code == UNEQ || code == LTGT)
6201 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6202 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6206 (define_insn "*movsicc_insn"
6207 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6209 (match_operator 3 "arm_comparison_operator"
6210 [(match_operand 4 "cc_register" "") (const_int 0)])
6211 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6212 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6219 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6220 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6221 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6222 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6223 [(set_attr "length" "4,4,4,4,8,8,8,8")
6224 (set_attr "conds" "use")]
6227 (define_insn "*movsfcc_hard_insn"
6228 [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6230 (match_operator 3 "arm_comparison_operator"
6231 [(match_operand 4 "cc_register" "") (const_int 0)])
6232 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6233 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6234 "TARGET_ARM && TARGET_HARD_FLOAT"
6240 mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
6241 mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
6242 mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
6243 mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
6244 [(set_attr "length" "4,4,4,4,8,8,8,8")
6245 (set_attr "type" "ffarith")
6246 (set_attr "conds" "use")]
6249 (define_insn "*movsfcc_soft_insn"
6250 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6251 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
6252 [(match_operand 4 "cc_register" "") (const_int 0)])
6253 (match_operand:SF 1 "s_register_operand" "0,r")
6254 (match_operand:SF 2 "s_register_operand" "r,0")))]
6255 "TARGET_ARM && TARGET_SOFT_FLOAT"
6259 [(set_attr "conds" "use")]
6262 (define_insn "*movdfcc_insn"
6263 [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6265 (match_operator 3 "arm_comparison_operator"
6266 [(match_operand 4 "cc_register" "") (const_int 0)])
6267 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6268 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6269 "TARGET_ARM && TARGET_HARD_FLOAT"
6275 mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
6276 mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
6277 mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
6278 mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
6279 [(set_attr "length" "4,4,4,4,8,8,8,8")
6280 (set_attr "type" "ffarith")
6281 (set_attr "conds" "use")]
6285 ;; Jump and linkage insns
6287 (define_expand "jump"
6289 (label_ref (match_operand 0 "" "")))]
6294 (define_insn "*arm_jump"
6296 (label_ref (match_operand 0 "" "")))]
6300 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6302 arm_ccfsm_state += 2;
6305 return \"b%?\\t%l0\";
6308 [(set_attr "predicable" "yes")]
6311 (define_insn "*thumb_jump"
6313 (label_ref (match_operand 0 "" "")))]
6316 if (get_attr_length (insn) == 2)
6318 return \"bl\\t%l0\\t%@ far jump\";
6320 [(set (attr "far_jump")
6322 (eq_attr "length" "4")
6323 (const_string "yes")
6324 (const_string "no")))
6325 (set (attr "length")
6327 (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6328 (le (minus (match_dup 0) (pc)) (const_int 2044)))
6333 (define_expand "call"
6334 [(parallel [(call (match_operand 0 "memory_operand" "")
6335 (match_operand 1 "general_operand" ""))
6336 (use (match_operand 2 "" ""))
6337 (clobber (reg:SI LR_REGNUM))])]
6343 /* In an untyped call, we can get NULL for operand 2. */
6344 if (operands[2] == NULL_RTX)
6345 operands[2] = const0_rtx;
6347 /* This is to decide if we should generate indirect calls by loading the
6348 32 bit address of the callee into a register before performing the
6349 branch and link. operand[2] encodes the long_call/short_call
6350 attribute of the function being called. This attribute is set whenever
6351 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6352 is used, and the short_call attribute can also be set if function is
6353 declared as static or if it has already been defined in the current
6354 compilation unit. See arm.c and arm.h for info about this. The third
6355 parameter to arm_is_longcall_p is used to tell it which pattern
6357 callee = XEXP (operands[0], 0);
6359 if (GET_CODE (callee) != REG
6360 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6361 XEXP (operands[0], 0) = force_reg (Pmode, callee);
6365 (define_insn "*call_reg"
6366 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
6367 (match_operand 1 "" ""))
6368 (use (match_operand 2 "" ""))
6369 (clobber (reg:SI LR_REGNUM))]
6372 return output_call (operands);
6374 ;; length is worst case, normally it is only two
6375 [(set_attr "length" "12")
6376 (set_attr "type" "call")]
6379 (define_insn "*call_mem"
6380 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
6381 (match_operand 1 "" ""))
6382 (use (match_operand 2 "" ""))
6383 (clobber (reg:SI LR_REGNUM))]
6386 return output_call_mem (operands);
6388 [(set_attr "length" "12")
6389 (set_attr "type" "call")]
6392 (define_insn "*call_indirect"
6393 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6394 (match_operand 1 "" ""))
6395 (use (match_operand 2 "" ""))
6396 (clobber (reg:SI LR_REGNUM))]
6400 if (TARGET_CALLER_INTERWORKING)
6401 return \"bl\\t%__interwork_call_via_%0\";
6403 return \"bl\\t%__call_via_%0\";
6405 [(set_attr "type" "call")]
6408 (define_insn "*call_value_indirect"
6409 [(set (match_operand 0 "" "=l")
6410 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6411 (match_operand 2 "" "")))
6412 (use (match_operand 3 "" ""))
6413 (clobber (reg:SI LR_REGNUM))]
6417 if (TARGET_CALLER_INTERWORKING)
6418 return \"bl\\t%__interwork_call_via_%1\";
6420 return \"bl\\t%__call_via_%1\";
6422 [(set_attr "type" "call")]
6425 (define_expand "call_value"
6426 [(parallel [(set (match_operand 0 "" "")
6427 (call (match_operand 1 "memory_operand" "")
6428 (match_operand 2 "general_operand" "")))
6429 (use (match_operand 3 "" ""))
6430 (clobber (reg:SI LR_REGNUM))])]
6434 rtx callee = XEXP (operands[1], 0);
6436 /* In an untyped call, we can get NULL for operand 2. */
6437 if (operands[3] == 0)
6438 operands[3] = const0_rtx;
6440 /* See the comment in define_expand \"call\". */
6441 if (GET_CODE (callee) != REG
6442 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6443 XEXP (operands[1], 0) = force_reg (Pmode, callee);
6447 (define_insn "*call_value_reg"
6448 [(set (match_operand 0 "" "=r,f,v")
6449 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r,r"))
6450 (match_operand 2 "" "")))
6451 (use (match_operand 3 "" ""))
6452 (clobber (reg:SI LR_REGNUM))]
6455 return output_call (&operands[1]);
6457 [(set_attr "length" "12")
6458 (set_attr "type" "call")]
6461 (define_insn "*call_value_mem"
6462 [(set (match_operand 0 "" "=r,f,v")
6463 (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m,m"))
6464 (match_operand 2 "" "")))
6465 (use (match_operand 3 "" ""))
6466 (clobber (reg:SI LR_REGNUM))]
6467 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6469 return output_call_mem (&operands[1]);
6471 [(set_attr "length" "12")
6472 (set_attr "type" "call")]
6475 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6476 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6478 (define_insn "*call_symbol"
6479 [(call (mem:SI (match_operand:SI 0 "" "X"))
6480 (match_operand 1 "" ""))
6481 (use (match_operand 2 "" ""))
6482 (clobber (reg:SI LR_REGNUM))]
6484 && (GET_CODE (operands[0]) == SYMBOL_REF)
6485 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6488 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6490 [(set_attr "type" "call")]
6493 (define_insn "*call_value_symbol"
6494 [(set (match_operand 0 "s_register_operand" "=r,f,v")
6495 (call (mem:SI (match_operand:SI 1 "" "X,X,X"))
6496 (match_operand:SI 2 "" "")))
6497 (use (match_operand 3 "" ""))
6498 (clobber (reg:SI LR_REGNUM))]
6500 && (GET_CODE (operands[1]) == SYMBOL_REF)
6501 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6504 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6506 [(set_attr "type" "call")]
6509 (define_insn "*call_insn"
6510 [(call (mem:SI (match_operand:SI 0 "" "X"))
6511 (match_operand:SI 1 "" ""))
6512 (use (match_operand 2 "" ""))
6513 (clobber (reg:SI LR_REGNUM))]
6515 && GET_CODE (operands[0]) == SYMBOL_REF
6516 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6518 [(set_attr "length" "4")
6519 (set_attr "type" "call")]
6522 (define_insn "*call_value_insn"
6523 [(set (match_operand 0 "register_operand" "=l")
6524 (call (mem:SI (match_operand 1 "" "X"))
6525 (match_operand 2 "" "")))
6526 (use (match_operand 3 "" ""))
6527 (clobber (reg:SI LR_REGNUM))]
6529 && GET_CODE (operands[1]) == SYMBOL_REF
6530 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6532 [(set_attr "length" "4")
6533 (set_attr "type" "call")]
6536 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6537 (define_expand "sibcall"
6538 [(parallel [(call (match_operand 0 "memory_operand" "")
6539 (match_operand 1 "general_operand" ""))
6541 (use (match_operand 2 "" ""))])]
6545 if (operands[2] == NULL_RTX)
6546 operands[2] = const0_rtx;
6550 (define_expand "sibcall_value"
6551 [(parallel [(set (match_operand 0 "register_operand" "")
6552 (call (match_operand 1 "memory_operand" "")
6553 (match_operand 2 "general_operand" "")))
6555 (use (match_operand 3 "" ""))])]
6559 if (operands[3] == NULL_RTX)
6560 operands[3] = const0_rtx;
6564 (define_insn "*sibcall_insn"
6565 [(call (mem:SI (match_operand:SI 0 "" "X"))
6566 (match_operand 1 "" ""))
6568 (use (match_operand 2 "" ""))]
6569 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6571 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6573 [(set_attr "type" "call")]
6576 (define_insn "*sibcall_value_insn"
6577 [(set (match_operand 0 "s_register_operand" "=r,f,v")
6578 (call (mem:SI (match_operand:SI 1 "" "X,X,X"))
6579 (match_operand 2 "" "")))
6581 (use (match_operand 3 "" ""))]
6582 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6584 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6586 [(set_attr "type" "call")]
6589 ;; Often the return insn will be the same as loading from memory, so set attr
6590 (define_insn "return"
6592 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6595 if (arm_ccfsm_state == 2)
6597 arm_ccfsm_state += 2;
6600 return output_return_instruction (const_true_rtx, TRUE, FALSE);
6602 [(set_attr "type" "load")
6603 (set_attr "predicable" "yes")]
6606 (define_insn "*cond_return"
6608 (if_then_else (match_operator 0 "arm_comparison_operator"
6609 [(match_operand 1 "cc_register" "") (const_int 0)])
6612 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6615 if (arm_ccfsm_state == 2)
6617 arm_ccfsm_state += 2;
6620 return output_return_instruction (operands[0], TRUE, FALSE);
6622 [(set_attr "conds" "use")
6623 (set_attr "type" "load")]
6626 (define_insn "*cond_return_inverted"
6628 (if_then_else (match_operator 0 "arm_comparison_operator"
6629 [(match_operand 1 "cc_register" "") (const_int 0)])
6632 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6635 if (arm_ccfsm_state == 2)
6637 arm_ccfsm_state += 2;
6640 return output_return_instruction (operands[0], TRUE, TRUE);
6642 [(set_attr "conds" "use")
6643 (set_attr "type" "load")]
6646 ;; Generate a sequence of instructions to determine if the processor is
6647 ;; in 26-bit or 32-bit mode, and return the appropriate return address
6650 (define_expand "return_addr_mask"
6652 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6654 (set (match_operand:SI 0 "s_register_operand" "")
6655 (if_then_else:SI (eq (match_dup 1) (const_int 0))
6657 (const_int 67108860)))] ; 0x03fffffc
6660 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
6663 (define_insn "*check_arch2"
6664 [(set (match_operand:CC_NOOV 0 "cc_register" "")
6665 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6668 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
6669 [(set_attr "length" "8")
6670 (set_attr "conds" "set")]
6673 ;; Call subroutine returning any type.
6675 (define_expand "untyped_call"
6676 [(parallel [(call (match_operand 0 "" "")
6678 (match_operand 1 "" "")
6679 (match_operand 2 "" "")])]
6685 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6687 for (i = 0; i < XVECLEN (operands[2], 0); i++)
6689 rtx set = XVECEXP (operands[2], 0, i);
6691 emit_move_insn (SET_DEST (set), SET_SRC (set));
6694 /* The optimizer does not know that the call sets the function value
6695 registers we stored in the result block. We avoid problems by
6696 claiming that all hard registers are used and clobbered at this
6698 emit_insn (gen_blockage ());
6704 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6705 ;; all of memory. This blocks insns from being moved across this point.
6707 (define_insn "blockage"
6708 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6711 [(set_attr "length" "0")
6712 (set_attr "type" "block")]
6715 (define_expand "casesi"
6716 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6717 (match_operand:SI 1 "const_int_operand" "") ; lower bound
6718 (match_operand:SI 2 "const_int_operand" "") ; total range
6719 (match_operand:SI 3 "" "") ; table label
6720 (match_operand:SI 4 "" "")] ; Out of range label
6725 if (operands[1] != const0_rtx)
6727 reg = gen_reg_rtx (SImode);
6729 emit_insn (gen_addsi3 (reg, operands[0],
6730 GEN_INT (-INTVAL (operands[1]))));
6734 if (!const_ok_for_arm (INTVAL (operands[2])))
6735 operands[2] = force_reg (SImode, operands[2]);
6737 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6743 ;; The USE in this pattern is needed to tell flow analysis that this is
6744 ;; a CASESI insn. It has no other purpose.
6745 (define_insn "casesi_internal"
6746 [(parallel [(set (pc)
6748 (leu (match_operand:SI 0 "s_register_operand" "r")
6749 (match_operand:SI 1 "arm_rhs_operand" "rI"))
6750 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6751 (label_ref (match_operand 2 "" ""))))
6752 (label_ref (match_operand 3 "" ""))))
6753 (clobber (reg:CC CC_REGNUM))
6754 (use (label_ref (match_dup 2)))])]
6758 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6759 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6761 [(set_attr "conds" "clob")
6762 (set_attr "length" "12")]
6765 (define_expand "indirect_jump"
6767 (match_operand:SI 0 "s_register_operand" ""))]
6772 (define_insn "*arm_indirect_jump"
6774 (match_operand:SI 0 "s_register_operand" "r"))]
6776 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6777 [(set_attr "predicable" "yes")]
6780 ;; Although not supported by the define_expand above,
6781 ;; cse/combine may generate this form.
6782 (define_insn "*load_indirect_jump"
6784 (match_operand:SI 0 "memory_operand" "m"))]
6786 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6787 [(set_attr "type" "load")
6788 (set_attr "pool_range" "4096")
6789 (set_attr "neg_pool_range" "4084")
6790 (set_attr "predicable" "yes")]
6793 (define_insn "*thumb_indirect_jump"
6795 (match_operand:SI 0 "register_operand" "l*r"))]
6798 [(set_attr "conds" "clob")
6799 (set_attr "length" "2")]
6810 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6811 return \"mov\\tr8, r8\";
6813 [(set (attr "length")
6814 (if_then_else (eq_attr "is_thumb" "yes")
6820 ;; Patterns to allow combination of arithmetic, cond code and shifts
6822 (define_insn "*arith_shiftsi"
6823 [(set (match_operand:SI 0 "s_register_operand" "=r")
6824 (match_operator:SI 1 "shiftable_operator"
6825 [(match_operator:SI 3 "shift_operator"
6826 [(match_operand:SI 4 "s_register_operand" "r")
6827 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6828 (match_operand:SI 2 "s_register_operand" "r")]))]
6830 "%i1%?\\t%0, %2, %4%S3"
6831 [(set_attr "predicable" "yes")
6832 (set_attr "shift" "4")
6836 (define_insn "*arith_shiftsi_compare0"
6837 [(set (reg:CC_NOOV CC_REGNUM)
6838 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6839 [(match_operator:SI 3 "shift_operator"
6840 [(match_operand:SI 4 "s_register_operand" "r")
6841 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6842 (match_operand:SI 2 "s_register_operand" "r")])
6844 (set (match_operand:SI 0 "s_register_operand" "=r")
6845 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6848 "%i1%?s\\t%0, %2, %4%S3"
6849 [(set_attr "conds" "set")
6850 (set_attr "shift" "4")
6854 (define_insn "*arith_shiftsi_compare0_scratch"
6855 [(set (reg:CC_NOOV CC_REGNUM)
6856 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6857 [(match_operator:SI 3 "shift_operator"
6858 [(match_operand:SI 4 "s_register_operand" "r")
6859 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6860 (match_operand:SI 2 "s_register_operand" "r")])
6862 (clobber (match_scratch:SI 0 "=r"))]
6864 "%i1%?s\\t%0, %2, %4%S3"
6865 [(set_attr "conds" "set")
6866 (set_attr "shift" "4")
6870 (define_insn "*sub_shiftsi"
6871 [(set (match_operand:SI 0 "s_register_operand" "=r")
6872 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6873 (match_operator:SI 2 "shift_operator"
6874 [(match_operand:SI 3 "s_register_operand" "r")
6875 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
6877 "sub%?\\t%0, %1, %3%S2"
6878 [(set_attr "predicable" "yes")
6879 (set_attr "shift" "3")
6883 (define_insn "*sub_shiftsi_compare0"
6884 [(set (reg:CC_NOOV CC_REGNUM)
6886 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6887 (match_operator:SI 2 "shift_operator"
6888 [(match_operand:SI 3 "s_register_operand" "r")
6889 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6891 (set (match_operand:SI 0 "s_register_operand" "=r")
6892 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6895 "sub%?s\\t%0, %1, %3%S2"
6896 [(set_attr "conds" "set")
6897 (set_attr "shift" "3")
6901 (define_insn "*sub_shiftsi_compare0_scratch"
6902 [(set (reg:CC_NOOV CC_REGNUM)
6904 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6905 (match_operator:SI 2 "shift_operator"
6906 [(match_operand:SI 3 "s_register_operand" "r")
6907 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6909 (clobber (match_scratch:SI 0 "=r"))]
6911 "sub%?s\\t%0, %1, %3%S2"
6912 [(set_attr "conds" "set")
6913 (set_attr "shift" "3")
6919 (define_insn "*and_scc"
6920 [(set (match_operand:SI 0 "s_register_operand" "=r")
6921 (and:SI (match_operator:SI 1 "arm_comparison_operator"
6922 [(match_operand 3 "cc_register" "") (const_int 0)])
6923 (match_operand:SI 2 "s_register_operand" "r")))]
6925 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
6926 [(set_attr "conds" "use")
6927 (set_attr "length" "8")]
6930 (define_insn "*ior_scc"
6931 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6932 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
6933 [(match_operand 3 "cc_register" "") (const_int 0)])
6934 (match_operand:SI 1 "s_register_operand" "0,?r")))]
6938 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
6939 [(set_attr "conds" "use")
6940 (set_attr "length" "4,8")]
6943 (define_insn "*compare_scc"
6944 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6945 (match_operator:SI 1 "arm_comparison_operator"
6946 [(match_operand:SI 2 "s_register_operand" "r,r")
6947 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
6948 (clobber (reg:CC CC_REGNUM))]
6951 if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
6952 return \"mov\\t%0, %2, lsr #31\";
6954 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
6955 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
6957 if (GET_CODE (operands[1]) == NE)
6959 if (which_alternative == 1)
6960 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
6961 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
6963 if (which_alternative == 1)
6964 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
6966 output_asm_insn (\"cmp\\t%2, %3\", operands);
6967 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
6969 [(set_attr "conds" "clob")
6970 (set_attr "length" "12")]
6973 (define_insn "*cond_move"
6974 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
6975 (if_then_else:SI (match_operator 3 "equality_operator"
6976 [(match_operator 4 "arm_comparison_operator"
6977 [(match_operand 5 "cc_register" "") (const_int 0)])
6979 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
6980 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
6983 if (GET_CODE (operands[3]) == NE)
6985 if (which_alternative != 1)
6986 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
6987 if (which_alternative != 0)
6988 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
6991 if (which_alternative != 0)
6992 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6993 if (which_alternative != 1)
6994 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
6997 [(set_attr "conds" "use")
6998 (set_attr "length" "4,4,8")]
7001 (define_insn "*cond_arith"
7002 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7003 (match_operator:SI 5 "shiftable_operator"
7004 [(match_operator:SI 4 "arm_comparison_operator"
7005 [(match_operand:SI 2 "s_register_operand" "r,r")
7006 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7007 (match_operand:SI 1 "s_register_operand" "0,?r")]))
7008 (clobber (reg:CC CC_REGNUM))]
7011 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7012 return \"%i5\\t%0, %1, %2, lsr #31\";
7014 output_asm_insn (\"cmp\\t%2, %3\", operands);
7015 if (GET_CODE (operands[5]) == AND)
7016 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7017 else if (GET_CODE (operands[5]) == MINUS)
7018 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7019 else if (which_alternative != 0)
7020 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7021 return \"%i5%d4\\t%0, %1, #1\";
7023 [(set_attr "conds" "clob")
7024 (set_attr "length" "12")]
7027 (define_insn "*cond_sub"
7028 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7029 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7030 (match_operator:SI 4 "arm_comparison_operator"
7031 [(match_operand:SI 2 "s_register_operand" "r,r")
7032 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7033 (clobber (reg:CC CC_REGNUM))]
7036 output_asm_insn (\"cmp\\t%2, %3\", operands);
7037 if (which_alternative != 0)
7038 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7039 return \"sub%d4\\t%0, %1, #1\";
7041 [(set_attr "conds" "clob")
7042 (set_attr "length" "8,12")]
7045 (define_insn "*cmp_ite0"
7046 [(set (match_operand 6 "dominant_cc_register" "")
7049 (match_operator 4 "arm_comparison_operator"
7050 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7051 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7052 (match_operator:SI 5 "arm_comparison_operator"
7053 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7054 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7060 static const char * const opcodes[4][2] =
7062 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7063 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7064 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7065 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7066 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7067 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7068 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7069 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7072 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7074 return opcodes[which_alternative][swap];
7076 [(set_attr "conds" "set")
7077 (set_attr "length" "8")]
7080 (define_insn "*cmp_ite1"
7081 [(set (match_operand 6 "dominant_cc_register" "")
7084 (match_operator 4 "arm_comparison_operator"
7085 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7086 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7087 (match_operator:SI 5 "arm_comparison_operator"
7088 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7089 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7095 static const char * const opcodes[4][2] =
7097 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7098 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7099 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7100 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7101 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7102 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7103 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7104 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7107 comparison_dominates_p (GET_CODE (operands[5]),
7108 reverse_condition (GET_CODE (operands[4])));
7110 return opcodes[which_alternative][swap];
7112 [(set_attr "conds" "set")
7113 (set_attr "length" "8")]
7116 (define_insn "*cmp_and"
7117 [(set (match_operand 6 "dominant_cc_register" "")
7120 (match_operator 4 "arm_comparison_operator"
7121 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7122 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7123 (match_operator:SI 5 "arm_comparison_operator"
7124 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7125 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7130 static const char *const opcodes[4][2] =
7132 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7133 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7134 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7135 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7136 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7137 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7138 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7139 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7142 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7144 return opcodes[which_alternative][swap];
7146 [(set_attr "conds" "set")
7147 (set_attr "predicable" "no")
7148 (set_attr "length" "8")]
7151 (define_insn "*cmp_ior"
7152 [(set (match_operand 6 "dominant_cc_register" "")
7155 (match_operator 4 "arm_comparison_operator"
7156 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7157 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7158 (match_operator:SI 5 "arm_comparison_operator"
7159 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7160 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7165 static const char *const opcodes[4][2] =
7167 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7168 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7169 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7170 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7171 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7172 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7173 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7174 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7177 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7179 return opcodes[which_alternative][swap];
7182 [(set_attr "conds" "set")
7183 (set_attr "length" "8")]
7186 (define_insn "*negscc"
7187 [(set (match_operand:SI 0 "s_register_operand" "=r")
7188 (neg:SI (match_operator 3 "arm_comparison_operator"
7189 [(match_operand:SI 1 "s_register_operand" "r")
7190 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7191 (clobber (reg:CC CC_REGNUM))]
7194 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7195 return \"mov\\t%0, %1, asr #31\";
7197 if (GET_CODE (operands[3]) == NE)
7198 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7200 if (GET_CODE (operands[3]) == GT)
7201 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7203 output_asm_insn (\"cmp\\t%1, %2\", operands);
7204 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7205 return \"mvn%d3\\t%0, #0\";
7207 [(set_attr "conds" "clob")
7208 (set_attr "length" "12")]
7211 (define_insn "movcond"
7212 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7214 (match_operator 5 "arm_comparison_operator"
7215 [(match_operand:SI 3 "s_register_operand" "r,r,r")
7216 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7217 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7218 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
7219 (clobber (reg:CC CC_REGNUM))]
7222 if (GET_CODE (operands[5]) == LT
7223 && (operands[4] == const0_rtx))
7225 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7227 if (operands[2] == const0_rtx)
7228 return \"and\\t%0, %1, %3, asr #31\";
7229 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
7231 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7233 if (operands[1] == const0_rtx)
7234 return \"bic\\t%0, %2, %3, asr #31\";
7235 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
7237 /* The only case that falls through to here is when both ops 1 & 2
7241 if (GET_CODE (operands[5]) == GE
7242 && (operands[4] == const0_rtx))
7244 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7246 if (operands[2] == const0_rtx)
7247 return \"bic\\t%0, %1, %3, asr #31\";
7248 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7250 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7252 if (operands[1] == const0_rtx)
7253 return \"and\\t%0, %2, %3, asr #31\";
7254 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7256 /* The only case that falls through to here is when both ops 1 & 2
7259 if (GET_CODE (operands[4]) == CONST_INT
7260 && !const_ok_for_arm (INTVAL (operands[4])))
7261 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7263 output_asm_insn (\"cmp\\t%3, %4\", operands);
7264 if (which_alternative != 0)
7265 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7266 if (which_alternative != 1)
7267 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7270 [(set_attr "conds" "clob")
7271 (set_attr "length" "8,8,12")]
7274 (define_insn "*ifcompare_plus_move"
7275 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7276 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7277 [(match_operand:SI 4 "s_register_operand" "r,r")
7278 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7280 (match_operand:SI 2 "s_register_operand" "r,r")
7281 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7282 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7283 (clobber (reg:CC CC_REGNUM))]
7286 [(set_attr "conds" "clob")
7287 (set_attr "length" "8,12")]
7290 (define_insn "*if_plus_move"
7291 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7293 (match_operator 4 "arm_comparison_operator"
7294 [(match_operand 5 "cc_register" "") (const_int 0)])
7296 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7297 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7298 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7302 sub%d4\\t%0, %2, #%n3
7303 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7304 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7305 [(set_attr "conds" "use")
7306 (set_attr "length" "4,4,8,8")
7307 (set_attr "type" "*,*,*,*")]
7310 (define_insn "*ifcompare_move_plus"
7311 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7312 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7313 [(match_operand:SI 4 "s_register_operand" "r,r")
7314 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7315 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7317 (match_operand:SI 2 "s_register_operand" "r,r")
7318 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7319 (clobber (reg:CC CC_REGNUM))]
7322 [(set_attr "conds" "clob")
7323 (set_attr "length" "8,12")]
7326 (define_insn "*if_move_plus"
7327 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7329 (match_operator 4 "arm_comparison_operator"
7330 [(match_operand 5 "cc_register" "") (const_int 0)])
7331 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7333 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7334 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7338 sub%D4\\t%0, %2, #%n3
7339 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7340 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7341 [(set_attr "conds" "use")
7342 (set_attr "length" "4,4,8,8")
7343 (set_attr "type" "*,*,*,*")]
7346 (define_insn "*ifcompare_arith_arith"
7347 [(set (match_operand:SI 0 "s_register_operand" "=r")
7348 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7349 [(match_operand:SI 5 "s_register_operand" "r")
7350 (match_operand:SI 6 "arm_add_operand" "rIL")])
7351 (match_operator:SI 8 "shiftable_operator"
7352 [(match_operand:SI 1 "s_register_operand" "r")
7353 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7354 (match_operator:SI 7 "shiftable_operator"
7355 [(match_operand:SI 3 "s_register_operand" "r")
7356 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7357 (clobber (reg:CC CC_REGNUM))]
7360 [(set_attr "conds" "clob")
7361 (set_attr "length" "12")]
7364 (define_insn "*if_arith_arith"
7365 [(set (match_operand:SI 0 "s_register_operand" "=r")
7366 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7367 [(match_operand 8 "cc_register" "") (const_int 0)])
7368 (match_operator:SI 6 "shiftable_operator"
7369 [(match_operand:SI 1 "s_register_operand" "r")
7370 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7371 (match_operator:SI 7 "shiftable_operator"
7372 [(match_operand:SI 3 "s_register_operand" "r")
7373 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7375 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7376 [(set_attr "conds" "use")
7377 (set_attr "length" "8")]
7380 (define_insn "*ifcompare_arith_move"
7381 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7382 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7383 [(match_operand:SI 2 "s_register_operand" "r,r")
7384 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7385 (match_operator:SI 7 "shiftable_operator"
7386 [(match_operand:SI 4 "s_register_operand" "r,r")
7387 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7388 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7389 (clobber (reg:CC CC_REGNUM))]
7392 /* If we have an operation where (op x 0) is the identity operation and
7393 the conditional operator is LT or GE and we are comparing against zero and
7394 everything is in registers then we can do this in two instructions */
7395 if (operands[3] == const0_rtx
7396 && GET_CODE (operands[7]) != AND
7397 && GET_CODE (operands[5]) == REG
7398 && GET_CODE (operands[1]) == REG
7399 && REGNO (operands[1]) == REGNO (operands[4])
7400 && REGNO (operands[4]) != REGNO (operands[0]))
7402 if (GET_CODE (operands[6]) == LT)
7403 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7404 else if (GET_CODE (operands[6]) == GE)
7405 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7407 if (GET_CODE (operands[3]) == CONST_INT
7408 && !const_ok_for_arm (INTVAL (operands[3])))
7409 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7411 output_asm_insn (\"cmp\\t%2, %3\", operands);
7412 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7413 if (which_alternative != 0)
7414 return \"mov%D6\\t%0, %1\";
7417 [(set_attr "conds" "clob")
7418 (set_attr "length" "8,12")]
7421 (define_insn "*if_arith_move"
7422 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7423 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7424 [(match_operand 6 "cc_register" "") (const_int 0)])
7425 (match_operator:SI 5 "shiftable_operator"
7426 [(match_operand:SI 2 "s_register_operand" "r,r")
7427 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7428 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7432 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7433 [(set_attr "conds" "use")
7434 (set_attr "length" "4,8")
7435 (set_attr "type" "*,*")]
7438 (define_insn "*ifcompare_move_arith"
7439 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7440 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7441 [(match_operand:SI 4 "s_register_operand" "r,r")
7442 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7443 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7444 (match_operator:SI 7 "shiftable_operator"
7445 [(match_operand:SI 2 "s_register_operand" "r,r")
7446 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7447 (clobber (reg:CC CC_REGNUM))]
7450 /* If we have an operation where (op x 0) is the identity operation and
7451 the conditional operator is LT or GE and we are comparing against zero and
7452 everything is in registers then we can do this in two instructions */
7453 if (operands[5] == const0_rtx
7454 && GET_CODE (operands[7]) != AND
7455 && GET_CODE (operands[3]) == REG
7456 && GET_CODE (operands[1]) == REG
7457 && REGNO (operands[1]) == REGNO (operands[2])
7458 && REGNO (operands[2]) != REGNO (operands[0]))
7460 if (GET_CODE (operands[6]) == GE)
7461 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7462 else if (GET_CODE (operands[6]) == LT)
7463 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7466 if (GET_CODE (operands[5]) == CONST_INT
7467 && !const_ok_for_arm (INTVAL (operands[5])))
7468 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7470 output_asm_insn (\"cmp\\t%4, %5\", operands);
7472 if (which_alternative != 0)
7473 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7474 return \"%I7%D6\\t%0, %2, %3\";
7476 [(set_attr "conds" "clob")
7477 (set_attr "length" "8,12")]
7480 (define_insn "*if_move_arith"
7481 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7483 (match_operator 4 "arm_comparison_operator"
7484 [(match_operand 6 "cc_register" "") (const_int 0)])
7485 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7486 (match_operator:SI 5 "shiftable_operator"
7487 [(match_operand:SI 2 "s_register_operand" "r,r")
7488 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7492 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7493 [(set_attr "conds" "use")
7494 (set_attr "length" "4,8")
7495 (set_attr "type" "*,*")]
7498 (define_insn "*ifcompare_move_not"
7499 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7501 (match_operator 5 "arm_comparison_operator"
7502 [(match_operand:SI 3 "s_register_operand" "r,r")
7503 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7504 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7506 (match_operand:SI 2 "s_register_operand" "r,r"))))
7507 (clobber (reg:CC CC_REGNUM))]
7510 [(set_attr "conds" "clob")
7511 (set_attr "length" "8,12")]
7514 (define_insn "*if_move_not"
7515 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7517 (match_operator 4 "arm_comparison_operator"
7518 [(match_operand 3 "cc_register" "") (const_int 0)])
7519 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7520 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7524 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7525 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7526 [(set_attr "conds" "use")
7527 (set_attr "length" "4,8,8")]
7530 (define_insn "*ifcompare_not_move"
7531 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7533 (match_operator 5 "arm_comparison_operator"
7534 [(match_operand:SI 3 "s_register_operand" "r,r")
7535 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7537 (match_operand:SI 2 "s_register_operand" "r,r"))
7538 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7539 (clobber (reg:CC CC_REGNUM))]
7542 [(set_attr "conds" "clob")
7543 (set_attr "length" "8,12")]
7546 (define_insn "*if_not_move"
7547 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7549 (match_operator 4 "arm_comparison_operator"
7550 [(match_operand 3 "cc_register" "") (const_int 0)])
7551 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7552 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7556 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7557 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7558 [(set_attr "conds" "use")
7559 (set_attr "length" "4,8,8")]
7562 (define_insn "*ifcompare_shift_move"
7563 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7565 (match_operator 6 "arm_comparison_operator"
7566 [(match_operand:SI 4 "s_register_operand" "r,r")
7567 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7568 (match_operator:SI 7 "shift_operator"
7569 [(match_operand:SI 2 "s_register_operand" "r,r")
7570 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7571 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7572 (clobber (reg:CC CC_REGNUM))]
7575 [(set_attr "conds" "clob")
7576 (set_attr "length" "8,12")]
7579 (define_insn "*if_shift_move"
7580 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7582 (match_operator 5 "arm_comparison_operator"
7583 [(match_operand 6 "cc_register" "") (const_int 0)])
7584 (match_operator:SI 4 "shift_operator"
7585 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7586 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7587 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7591 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7592 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7593 [(set_attr "conds" "use")
7594 (set_attr "shift" "2")
7595 (set_attr "length" "4,8,8")]
7598 (define_insn "*ifcompare_move_shift"
7599 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7601 (match_operator 6 "arm_comparison_operator"
7602 [(match_operand:SI 4 "s_register_operand" "r,r")
7603 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7604 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7605 (match_operator:SI 7 "shift_operator"
7606 [(match_operand:SI 2 "s_register_operand" "r,r")
7607 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7608 (clobber (reg:CC CC_REGNUM))]
7611 [(set_attr "conds" "clob")
7612 (set_attr "length" "8,12")]
7615 (define_insn "*if_move_shift"
7616 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7618 (match_operator 5 "arm_comparison_operator"
7619 [(match_operand 6 "cc_register" "") (const_int 0)])
7620 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7621 (match_operator:SI 4 "shift_operator"
7622 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7623 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7627 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7628 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7629 [(set_attr "conds" "use")
7630 (set_attr "shift" "2")
7631 (set_attr "length" "4,8,8")]
7634 (define_insn "*ifcompare_shift_shift"
7635 [(set (match_operand:SI 0 "s_register_operand" "=r")
7637 (match_operator 7 "arm_comparison_operator"
7638 [(match_operand:SI 5 "s_register_operand" "r")
7639 (match_operand:SI 6 "arm_add_operand" "rIL")])
7640 (match_operator:SI 8 "shift_operator"
7641 [(match_operand:SI 1 "s_register_operand" "r")
7642 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7643 (match_operator:SI 9 "shift_operator"
7644 [(match_operand:SI 3 "s_register_operand" "r")
7645 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7646 (clobber (reg:CC CC_REGNUM))]
7649 [(set_attr "conds" "clob")
7650 (set_attr "length" "12")]
7653 (define_insn "*if_shift_shift"
7654 [(set (match_operand:SI 0 "s_register_operand" "=r")
7656 (match_operator 5 "arm_comparison_operator"
7657 [(match_operand 8 "cc_register" "") (const_int 0)])
7658 (match_operator:SI 6 "shift_operator"
7659 [(match_operand:SI 1 "s_register_operand" "r")
7660 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7661 (match_operator:SI 7 "shift_operator"
7662 [(match_operand:SI 3 "s_register_operand" "r")
7663 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7665 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7666 [(set_attr "conds" "use")
7667 (set_attr "shift" "1")
7668 (set_attr "length" "8")]
7671 (define_insn "*ifcompare_not_arith"
7672 [(set (match_operand:SI 0 "s_register_operand" "=r")
7674 (match_operator 6 "arm_comparison_operator"
7675 [(match_operand:SI 4 "s_register_operand" "r")
7676 (match_operand:SI 5 "arm_add_operand" "rIL")])
7677 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7678 (match_operator:SI 7 "shiftable_operator"
7679 [(match_operand:SI 2 "s_register_operand" "r")
7680 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7681 (clobber (reg:CC CC_REGNUM))]
7684 [(set_attr "conds" "clob")
7685 (set_attr "length" "12")]
7688 (define_insn "*if_not_arith"
7689 [(set (match_operand:SI 0 "s_register_operand" "=r")
7691 (match_operator 5 "arm_comparison_operator"
7692 [(match_operand 4 "cc_register" "") (const_int 0)])
7693 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7694 (match_operator:SI 6 "shiftable_operator"
7695 [(match_operand:SI 2 "s_register_operand" "r")
7696 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7698 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7699 [(set_attr "conds" "use")
7700 (set_attr "length" "8")]
7703 (define_insn "*ifcompare_arith_not"
7704 [(set (match_operand:SI 0 "s_register_operand" "=r")
7706 (match_operator 6 "arm_comparison_operator"
7707 [(match_operand:SI 4 "s_register_operand" "r")
7708 (match_operand:SI 5 "arm_add_operand" "rIL")])
7709 (match_operator:SI 7 "shiftable_operator"
7710 [(match_operand:SI 2 "s_register_operand" "r")
7711 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7712 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7713 (clobber (reg:CC CC_REGNUM))]
7716 [(set_attr "conds" "clob")
7717 (set_attr "length" "12")]
7720 (define_insn "*if_arith_not"
7721 [(set (match_operand:SI 0 "s_register_operand" "=r")
7723 (match_operator 5 "arm_comparison_operator"
7724 [(match_operand 4 "cc_register" "") (const_int 0)])
7725 (match_operator:SI 6 "shiftable_operator"
7726 [(match_operand:SI 2 "s_register_operand" "r")
7727 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7728 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7730 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7731 [(set_attr "conds" "use")
7732 (set_attr "length" "8")]
7735 (define_insn "*ifcompare_neg_move"
7736 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7738 (match_operator 5 "arm_comparison_operator"
7739 [(match_operand:SI 3 "s_register_operand" "r,r")
7740 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7741 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7742 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7743 (clobber (reg:CC CC_REGNUM))]
7746 [(set_attr "conds" "clob")
7747 (set_attr "length" "8,12")]
7750 (define_insn "*if_neg_move"
7751 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7753 (match_operator 4 "arm_comparison_operator"
7754 [(match_operand 3 "cc_register" "") (const_int 0)])
7755 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7756 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7760 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7761 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
7762 [(set_attr "conds" "use")
7763 (set_attr "length" "4,8,8")]
7766 (define_insn "*ifcompare_move_neg"
7767 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7769 (match_operator 5 "arm_comparison_operator"
7770 [(match_operand:SI 3 "s_register_operand" "r,r")
7771 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7772 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7773 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
7774 (clobber (reg:CC CC_REGNUM))]
7777 [(set_attr "conds" "clob")
7778 (set_attr "length" "8,12")]
7781 (define_insn "*if_move_neg"
7782 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7784 (match_operator 4 "arm_comparison_operator"
7785 [(match_operand 3 "cc_register" "") (const_int 0)])
7786 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7787 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7791 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
7792 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
7793 [(set_attr "conds" "use")
7794 (set_attr "length" "4,8,8")]
7797 (define_insn "*arith_adjacentmem"
7798 [(set (match_operand:SI 0 "s_register_operand" "=r")
7799 (match_operator:SI 1 "shiftable_operator"
7800 [(match_operand:SI 2 "memory_operand" "m")
7801 (match_operand:SI 3 "memory_operand" "m")]))
7802 (clobber (match_scratch:SI 4 "=r"))]
7803 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
7808 int val1 = 0, val2 = 0;
7810 if (REGNO (operands[0]) > REGNO (operands[4]))
7812 ldm[1] = operands[4];
7813 ldm[2] = operands[0];
7817 ldm[1] = operands[0];
7818 ldm[2] = operands[4];
7820 if (GET_CODE (XEXP (operands[2], 0)) != REG)
7821 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
7822 if (GET_CODE (XEXP (operands[3], 0)) != REG)
7823 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
7824 arith[0] = operands[0];
7825 arith[3] = operands[1];
7839 ldm[0] = ops[0] = operands[4];
7840 ops[1] = XEXP (XEXP (operands[2], 0), 0);
7841 ops[2] = XEXP (XEXP (operands[2], 0), 1);
7842 output_add_immediate (ops);
7844 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7846 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7850 ldm[0] = XEXP (operands[3], 0);
7852 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7854 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7858 ldm[0] = XEXP (operands[2], 0);
7860 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7862 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7864 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
7867 [(set_attr "length" "12")
7868 (set_attr "predicable" "yes")
7869 (set_attr "type" "load")]
7872 ;; the arm can support extended pre-inc instructions
7874 ;; In all these cases, we use operands 0 and 1 for the register being
7875 ;; incremented because those are the operands that local-alloc will
7876 ;; tie and these are the pair most likely to be tieable (and the ones
7877 ;; that will benefit the most).
7879 ;; We reject the frame pointer if it occurs anywhere in these patterns since
7880 ;; elimination will cause too many headaches.
7882 (define_insn "*strqi_preinc"
7883 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7884 (match_operand:SI 2 "index_operand" "rJ")))
7885 (match_operand:QI 3 "s_register_operand" "r"))
7886 (set (match_operand:SI 0 "s_register_operand" "=r")
7887 (plus:SI (match_dup 1) (match_dup 2)))]
7889 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7890 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7891 && (GET_CODE (operands[2]) != REG
7892 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7893 "str%?b\\t%3, [%0, %2]!"
7894 [(set_attr "type" "store1")
7895 (set_attr "predicable" "yes")]
7898 (define_insn "*strqi_predec"
7899 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7900 (match_operand:SI 2 "s_register_operand" "r")))
7901 (match_operand:QI 3 "s_register_operand" "r"))
7902 (set (match_operand:SI 0 "s_register_operand" "=r")
7903 (minus:SI (match_dup 1) (match_dup 2)))]
7905 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7906 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7907 && (GET_CODE (operands[2]) != REG
7908 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7909 "str%?b\\t%3, [%0, -%2]!"
7910 [(set_attr "type" "store1")
7911 (set_attr "predicable" "yes")]
7914 (define_insn "*loadqi_preinc"
7915 [(set (match_operand:QI 3 "s_register_operand" "=r")
7916 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7917 (match_operand:SI 2 "index_operand" "rJ"))))
7918 (set (match_operand:SI 0 "s_register_operand" "=r")
7919 (plus:SI (match_dup 1) (match_dup 2)))]
7921 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7922 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7923 && (GET_CODE (operands[2]) != REG
7924 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7925 "ldr%?b\\t%3, [%0, %2]!"
7926 [(set_attr "type" "load")
7927 (set_attr "predicable" "yes")]
7930 (define_insn "*loadqi_predec"
7931 [(set (match_operand:QI 3 "s_register_operand" "=r")
7932 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7933 (match_operand:SI 2 "s_register_operand" "r"))))
7934 (set (match_operand:SI 0 "s_register_operand" "=r")
7935 (minus:SI (match_dup 1) (match_dup 2)))]
7937 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7938 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7939 && (GET_CODE (operands[2]) != REG
7940 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7941 "ldr%?b\\t%3, [%0, -%2]!"
7942 [(set_attr "type" "load")
7943 (set_attr "predicable" "yes")]
7946 (define_insn "*loadqisi_preinc"
7947 [(set (match_operand:SI 3 "s_register_operand" "=r")
7949 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7950 (match_operand:SI 2 "index_operand" "rJ")))))
7951 (set (match_operand:SI 0 "s_register_operand" "=r")
7952 (plus:SI (match_dup 1) (match_dup 2)))]
7954 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7955 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7956 && (GET_CODE (operands[2]) != REG
7957 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7958 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
7959 [(set_attr "type" "load")
7960 (set_attr "predicable" "yes")]
7963 (define_insn "*loadqisi_predec"
7964 [(set (match_operand:SI 3 "s_register_operand" "=r")
7966 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7967 (match_operand:SI 2 "s_register_operand" "r")))))
7968 (set (match_operand:SI 0 "s_register_operand" "=r")
7969 (minus:SI (match_dup 1) (match_dup 2)))]
7971 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7972 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7973 && (GET_CODE (operands[2]) != REG
7974 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7975 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
7976 [(set_attr "type" "load")
7977 (set_attr "predicable" "yes")]
7980 (define_insn "*strsi_preinc"
7981 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7982 (match_operand:SI 2 "index_operand" "rJ")))
7983 (match_operand:SI 3 "s_register_operand" "r"))
7984 (set (match_operand:SI 0 "s_register_operand" "=r")
7985 (plus:SI (match_dup 1) (match_dup 2)))]
7987 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7988 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7989 && (GET_CODE (operands[2]) != REG
7990 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7991 "str%?\\t%3, [%0, %2]!"
7992 [(set_attr "type" "store1")
7993 (set_attr "predicable" "yes")]
7996 (define_insn "*strsi_predec"
7997 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7998 (match_operand:SI 2 "s_register_operand" "r")))
7999 (match_operand:SI 3 "s_register_operand" "r"))
8000 (set (match_operand:SI 0 "s_register_operand" "=r")
8001 (minus:SI (match_dup 1) (match_dup 2)))]
8003 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8004 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8005 && (GET_CODE (operands[2]) != REG
8006 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8007 "str%?\\t%3, [%0, -%2]!"
8008 [(set_attr "type" "store1")
8009 (set_attr "predicable" "yes")]
8012 (define_insn "*loadsi_preinc"
8013 [(set (match_operand:SI 3 "s_register_operand" "=r")
8014 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8015 (match_operand:SI 2 "index_operand" "rJ"))))
8016 (set (match_operand:SI 0 "s_register_operand" "=r")
8017 (plus:SI (match_dup 1) (match_dup 2)))]
8019 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8020 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8021 && (GET_CODE (operands[2]) != REG
8022 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8023 "ldr%?\\t%3, [%0, %2]!"
8024 [(set_attr "type" "load")
8025 (set_attr "predicable" "yes")]
8028 (define_insn "*loadsi_predec"
8029 [(set (match_operand:SI 3 "s_register_operand" "=r")
8030 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8031 (match_operand:SI 2 "s_register_operand" "r"))))
8032 (set (match_operand:SI 0 "s_register_operand" "=r")
8033 (minus:SI (match_dup 1) (match_dup 2)))]
8035 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8036 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8037 && (GET_CODE (operands[2]) != REG
8038 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8039 "ldr%?\\t%3, [%0, -%2]!"
8040 [(set_attr "type" "load")
8041 (set_attr "predicable" "yes")]
8044 (define_insn "*loadhi_preinc"
8045 [(set (match_operand:HI 3 "s_register_operand" "=r")
8046 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8047 (match_operand:SI 2 "index_operand" "rJ"))))
8048 (set (match_operand:SI 0 "s_register_operand" "=r")
8049 (plus:SI (match_dup 1) (match_dup 2)))]
8051 && !BYTES_BIG_ENDIAN
8052 && !TARGET_MMU_TRAPS
8054 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8055 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8056 && (GET_CODE (operands[2]) != REG
8057 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8058 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8059 [(set_attr "type" "load")
8060 (set_attr "predicable" "yes")]
8063 (define_insn "*loadhi_predec"
8064 [(set (match_operand:HI 3 "s_register_operand" "=r")
8065 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8066 (match_operand:SI 2 "s_register_operand" "r"))))
8067 (set (match_operand:SI 0 "s_register_operand" "=r")
8068 (minus:SI (match_dup 1) (match_dup 2)))]
8070 && !BYTES_BIG_ENDIAN
8071 && !TARGET_MMU_TRAPS
8073 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8074 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8075 && (GET_CODE (operands[2]) != REG
8076 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8077 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8078 [(set_attr "type" "load")
8079 (set_attr "predicable" "yes")]
8082 (define_insn "*strqi_shiftpreinc"
8083 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8084 [(match_operand:SI 3 "s_register_operand" "r")
8085 (match_operand:SI 4 "const_shift_operand" "n")])
8086 (match_operand:SI 1 "s_register_operand" "0")))
8087 (match_operand:QI 5 "s_register_operand" "r"))
8088 (set (match_operand:SI 0 "s_register_operand" "=r")
8089 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8092 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8093 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8094 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8095 "str%?b\\t%5, [%0, %3%S2]!"
8096 [(set_attr "type" "store1")
8097 (set_attr "predicable" "yes")]
8100 (define_insn "*strqi_shiftpredec"
8101 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8102 (match_operator:SI 2 "shift_operator"
8103 [(match_operand:SI 3 "s_register_operand" "r")
8104 (match_operand:SI 4 "const_shift_operand" "n")])))
8105 (match_operand:QI 5 "s_register_operand" "r"))
8106 (set (match_operand:SI 0 "s_register_operand" "=r")
8107 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8110 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8111 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8112 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8113 "str%?b\\t%5, [%0, -%3%S2]!"
8114 [(set_attr "type" "store1")
8115 (set_attr "predicable" "yes")]
8118 (define_insn "*loadqi_shiftpreinc"
8119 [(set (match_operand:QI 5 "s_register_operand" "=r")
8120 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8121 [(match_operand:SI 3 "s_register_operand" "r")
8122 (match_operand:SI 4 "const_shift_operand" "n")])
8123 (match_operand:SI 1 "s_register_operand" "0"))))
8124 (set (match_operand:SI 0 "s_register_operand" "=r")
8125 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8128 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8129 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8130 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8131 "ldr%?b\\t%5, [%0, %3%S2]!"
8132 [(set_attr "type" "load")
8133 (set_attr "predicable" "yes")]
8136 (define_insn "*loadqi_shiftpredec"
8137 [(set (match_operand:QI 5 "s_register_operand" "=r")
8138 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8139 (match_operator:SI 2 "shift_operator"
8140 [(match_operand:SI 3 "s_register_operand" "r")
8141 (match_operand:SI 4 "const_shift_operand" "n")]))))
8142 (set (match_operand:SI 0 "s_register_operand" "=r")
8143 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8146 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8147 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8148 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8149 "ldr%?b\\t%5, [%0, -%3%S2]!"
8150 [(set_attr "type" "load")
8151 (set_attr "predicable" "yes")]
8154 (define_insn "*strsi_shiftpreinc"
8155 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8156 [(match_operand:SI 3 "s_register_operand" "r")
8157 (match_operand:SI 4 "const_shift_operand" "n")])
8158 (match_operand:SI 1 "s_register_operand" "0")))
8159 (match_operand:SI 5 "s_register_operand" "r"))
8160 (set (match_operand:SI 0 "s_register_operand" "=r")
8161 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8164 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8165 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8166 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8167 "str%?\\t%5, [%0, %3%S2]!"
8168 [(set_attr "type" "store1")
8169 (set_attr "predicable" "yes")]
8172 (define_insn "*strsi_shiftpredec"
8173 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8174 (match_operator:SI 2 "shift_operator"
8175 [(match_operand:SI 3 "s_register_operand" "r")
8176 (match_operand:SI 4 "const_shift_operand" "n")])))
8177 (match_operand:SI 5 "s_register_operand" "r"))
8178 (set (match_operand:SI 0 "s_register_operand" "=r")
8179 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8182 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8183 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8184 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8185 "str%?\\t%5, [%0, -%3%S2]!"
8186 [(set_attr "type" "store1")
8187 (set_attr "predicable" "yes")]
8190 (define_insn "*loadsi_shiftpreinc"
8191 [(set (match_operand:SI 5 "s_register_operand" "=r")
8192 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8193 [(match_operand:SI 3 "s_register_operand" "r")
8194 (match_operand:SI 4 "const_shift_operand" "n")])
8195 (match_operand:SI 1 "s_register_operand" "0"))))
8196 (set (match_operand:SI 0 "s_register_operand" "=r")
8197 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8200 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8201 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8202 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8203 "ldr%?\\t%5, [%0, %3%S2]!"
8204 [(set_attr "type" "load")
8205 (set_attr "predicable" "yes")]
8208 (define_insn "*loadsi_shiftpredec"
8209 [(set (match_operand:SI 5 "s_register_operand" "=r")
8210 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8211 (match_operator:SI 2 "shift_operator"
8212 [(match_operand:SI 3 "s_register_operand" "r")
8213 (match_operand:SI 4 "const_shift_operand" "n")]))))
8214 (set (match_operand:SI 0 "s_register_operand" "=r")
8215 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8218 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8219 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8220 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8221 "ldr%?\\t%5, [%0, -%3%S2]!"
8222 [(set_attr "type" "load")
8223 (set_attr "predicable" "yes")])
8225 (define_insn "*loadhi_shiftpreinc"
8226 [(set (match_operand:HI 5 "s_register_operand" "=r")
8227 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8228 [(match_operand:SI 3 "s_register_operand" "r")
8229 (match_operand:SI 4 "const_shift_operand" "n")])
8230 (match_operand:SI 1 "s_register_operand" "0"))))
8231 (set (match_operand:SI 0 "s_register_operand" "=r")
8232 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8235 && !BYTES_BIG_ENDIAN
8236 && !TARGET_MMU_TRAPS
8238 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8239 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8240 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8241 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8242 [(set_attr "type" "load")
8243 (set_attr "predicable" "yes")]
8246 (define_insn "*loadhi_shiftpredec"
8247 [(set (match_operand:HI 5 "s_register_operand" "=r")
8248 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8249 (match_operator:SI 2 "shift_operator"
8250 [(match_operand:SI 3 "s_register_operand" "r")
8251 (match_operand:SI 4 "const_shift_operand" "n")]))))
8252 (set (match_operand:SI 0 "s_register_operand" "=r")
8253 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8256 && !BYTES_BIG_ENDIAN
8257 && !TARGET_MMU_TRAPS
8259 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8260 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8261 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8262 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8263 [(set_attr "type" "load")
8264 (set_attr "predicable" "yes")]
8267 ; It can also support extended post-inc expressions, but combine doesn't
8269 ; It doesn't seem worth adding peepholes for anything but the most common
8270 ; cases since, unlike combine, the increment must immediately follow the load
8271 ; for this pattern to match.
8272 ; We must watch to see that the source/destination register isn't also the
8273 ; same as the base address register, and that if the index is a register,
8274 ; that it is not the same as the base address register. In such cases the
8275 ; instruction that we would generate would have UNPREDICTABLE behavior so
8279 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8280 (match_operand:QI 2 "s_register_operand" "r"))
8282 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8284 && (REGNO (operands[2]) != REGNO (operands[0]))
8285 && (GET_CODE (operands[1]) != REG
8286 || (REGNO (operands[1]) != REGNO (operands[0])))"
8287 "str%?b\\t%2, [%0], %1"
8291 [(set (match_operand:QI 0 "s_register_operand" "=r")
8292 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8294 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8296 && REGNO (operands[0]) != REGNO(operands[1])
8297 && (GET_CODE (operands[2]) != REG
8298 || REGNO(operands[0]) != REGNO (operands[2]))"
8299 "ldr%?b\\t%0, [%1], %2"
8303 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8304 (match_operand:SI 2 "s_register_operand" "r"))
8306 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8308 && (REGNO (operands[2]) != REGNO (operands[0]))
8309 && (GET_CODE (operands[1]) != REG
8310 || (REGNO (operands[1]) != REGNO (operands[0])))"
8311 "str%?\\t%2, [%0], %1"
8315 [(set (match_operand:HI 0 "s_register_operand" "=r")
8316 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8318 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8320 && !BYTES_BIG_ENDIAN
8321 && !TARGET_MMU_TRAPS
8323 && REGNO (operands[0]) != REGNO(operands[1])
8324 && (GET_CODE (operands[2]) != REG
8325 || REGNO(operands[0]) != REGNO (operands[2]))"
8326 "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8330 [(set (match_operand:SI 0 "s_register_operand" "=r")
8331 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8333 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8335 && REGNO (operands[0]) != REGNO(operands[1])
8336 && (GET_CODE (operands[2]) != REG
8337 || REGNO(operands[0]) != REGNO (operands[2]))"
8338 "ldr%?\\t%0, [%1], %2"
8342 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8343 (match_operand:SI 1 "index_operand" "rJ")))
8344 (match_operand:QI 2 "s_register_operand" "r"))
8345 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8347 && (REGNO (operands[2]) != REGNO (operands[0]))
8348 && (GET_CODE (operands[1]) != REG
8349 || (REGNO (operands[1]) != REGNO (operands[0])))"
8350 "str%?b\\t%2, [%0, %1]!"
8354 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8355 [(match_operand:SI 0 "s_register_operand" "r")
8356 (match_operand:SI 1 "const_int_operand" "n")])
8357 (match_operand:SI 2 "s_register_operand" "+r")))
8358 (match_operand:QI 3 "s_register_operand" "r"))
8359 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8362 && (REGNO (operands[3]) != REGNO (operands[2]))
8363 && (REGNO (operands[0]) != REGNO (operands[2]))"
8364 "str%?b\\t%3, [%2, %0%S4]!"
8367 ; This pattern is never tried by combine, so do it as a peephole
8370 [(set (match_operand:SI 0 "s_register_operand" "")
8371 (match_operand:SI 1 "s_register_operand" ""))
8372 (set (reg:CC CC_REGNUM)
8373 (compare:CC (match_dup 1) (const_int 0)))]
8376 || (!cirrus_fp_register (operands[0], SImode)
8377 && !cirrus_fp_register (operands[1], SImode)))
8379 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8380 (set (match_dup 0) (match_dup 1))])]
8384 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8385 ; reversed, check that the memory references aren't volatile.
8388 [(set (match_operand:SI 0 "s_register_operand" "=r")
8389 (match_operand:SI 4 "memory_operand" "m"))
8390 (set (match_operand:SI 1 "s_register_operand" "=r")
8391 (match_operand:SI 5 "memory_operand" "m"))
8392 (set (match_operand:SI 2 "s_register_operand" "=r")
8393 (match_operand:SI 6 "memory_operand" "m"))
8394 (set (match_operand:SI 3 "s_register_operand" "=r")
8395 (match_operand:SI 7 "memory_operand" "m"))]
8396 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8398 return emit_ldm_seq (operands, 4);
8403 [(set (match_operand:SI 0 "s_register_operand" "=r")
8404 (match_operand:SI 3 "memory_operand" "m"))
8405 (set (match_operand:SI 1 "s_register_operand" "=r")
8406 (match_operand:SI 4 "memory_operand" "m"))
8407 (set (match_operand:SI 2 "s_register_operand" "=r")
8408 (match_operand:SI 5 "memory_operand" "m"))]
8409 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8411 return emit_ldm_seq (operands, 3);
8416 [(set (match_operand:SI 0 "s_register_operand" "=r")
8417 (match_operand:SI 2 "memory_operand" "m"))
8418 (set (match_operand:SI 1 "s_register_operand" "=r")
8419 (match_operand:SI 3 "memory_operand" "m"))]
8420 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8422 return emit_ldm_seq (operands, 2);
8427 [(set (match_operand:SI 4 "memory_operand" "=m")
8428 (match_operand:SI 0 "s_register_operand" "r"))
8429 (set (match_operand:SI 5 "memory_operand" "=m")
8430 (match_operand:SI 1 "s_register_operand" "r"))
8431 (set (match_operand:SI 6 "memory_operand" "=m")
8432 (match_operand:SI 2 "s_register_operand" "r"))
8433 (set (match_operand:SI 7 "memory_operand" "=m")
8434 (match_operand:SI 3 "s_register_operand" "r"))]
8435 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8437 return emit_stm_seq (operands, 4);
8442 [(set (match_operand:SI 3 "memory_operand" "=m")
8443 (match_operand:SI 0 "s_register_operand" "r"))
8444 (set (match_operand:SI 4 "memory_operand" "=m")
8445 (match_operand:SI 1 "s_register_operand" "r"))
8446 (set (match_operand:SI 5 "memory_operand" "=m")
8447 (match_operand:SI 2 "s_register_operand" "r"))]
8448 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8450 return emit_stm_seq (operands, 3);
8455 [(set (match_operand:SI 2 "memory_operand" "=m")
8456 (match_operand:SI 0 "s_register_operand" "r"))
8457 (set (match_operand:SI 3 "memory_operand" "=m")
8458 (match_operand:SI 1 "s_register_operand" "r"))]
8459 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8461 return emit_stm_seq (operands, 2);
8466 [(set (match_operand:SI 0 "s_register_operand" "")
8467 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8469 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8470 [(match_operand:SI 3 "s_register_operand" "")
8471 (match_operand:SI 4 "arm_rhs_operand" "")]))))
8472 (clobber (match_operand:SI 5 "s_register_operand" ""))]
8474 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8475 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8480 ;; This split can be used because CC_Z mode implies that the following
8481 ;; branch will be an equality, or an unsigned inequality, so the sign
8482 ;; extension is not needed.
8485 [(set (reg:CC_Z CC_REGNUM)
8487 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8489 (match_operand 1 "const_int_operand" "")))
8490 (clobber (match_scratch:SI 2 ""))]
8492 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8493 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8494 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8495 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8497 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8501 (define_expand "prologue"
8502 [(clobber (const_int 0))]
8505 arm_expand_prologue ();
8507 thumb_expand_prologue ();
8512 (define_expand "epilogue"
8513 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8517 thumb_expand_epilogue ();
8518 else if (USE_RETURN_INSN (FALSE))
8520 emit_jump_insn (gen_return ());
8523 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8525 gen_rtx_RETURN (VOIDmode)),
8531 ;; Note - although unspec_volatile's USE all hard registers,
8532 ;; USEs are ignored after relaod has completed. Thus we need
8533 ;; to add an unspec of the link register to ensure that flow
8534 ;; does not think that it is unused by the sibcall branch that
8535 ;; will replace the standard function epilogue.
8536 (define_insn "sibcall_epilogue"
8537 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
8538 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
8541 if (USE_RETURN_INSN (FALSE))
8542 return output_return_instruction (const_true_rtx, FALSE, FALSE);
8543 return arm_output_epilogue (FALSE);
8545 ;; Length is absolute worst case
8546 [(set_attr "length" "44")
8547 (set_attr "type" "block")
8548 ;; We don't clobber the conditions, but the potential length of this
8549 ;; operation is sufficient to make conditionalizing the sequence
8550 ;; unlikely to be profitable.
8551 (set_attr "conds" "clob")]
8554 (define_insn "*epilogue_insns"
8555 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8559 return arm_output_epilogue (TRUE);
8560 else /* TARGET_THUMB */
8561 return thumb_unexpanded_epilogue ();
8563 ; Length is absolute worst case
8564 [(set_attr "length" "44")
8565 (set_attr "type" "block")
8566 ;; We don't clobber the conditions, but the potential length of this
8567 ;; operation is sufficient to make conditionalizing the sequence
8568 ;; unlikely to be profitable.
8569 (set_attr "conds" "clob")]
8572 (define_expand "eh_epilogue"
8573 [(use (match_operand:SI 0 "register_operand" "r"))
8574 (use (match_operand:SI 1 "register_operand" "r"))
8575 (use (match_operand:SI 2 "register_operand" "r"))]
8579 cfun->machine->eh_epilogue_sp_ofs = operands[1];
8580 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8582 rtx ra = gen_rtx_REG (Pmode, 2);
8584 emit_move_insn (ra, operands[2]);
8587 /* This is a hack -- we may have crystalized the function type too
8589 cfun->machine->func_type = 0;
8593 ;; This split is only used during output to reduce the number of patterns
8594 ;; that need assembler instructions adding to them. We allowed the setting
8595 ;; of the conditions to be implicit during rtl generation so that
8596 ;; the conditional compare patterns would work. However this conflicts to
8597 ;; some extent with the conditional data operations, so we have to split them
8601 [(set (match_operand:SI 0 "s_register_operand" "")
8602 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8603 [(match_operand 2 "" "") (match_operand 3 "" "")])
8605 (match_operand 4 "" "")))
8606 (clobber (reg:CC CC_REGNUM))]
8607 "TARGET_ARM && reload_completed"
8608 [(set (match_dup 5) (match_dup 6))
8609 (cond_exec (match_dup 7)
8610 (set (match_dup 0) (match_dup 4)))]
8613 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8614 operands[2], operands[3]);
8615 enum rtx_code rc = GET_CODE (operands[1]);
8617 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8618 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8619 if (mode == CCFPmode || mode == CCFPEmode)
8620 rc = reverse_condition_maybe_unordered (rc);
8622 rc = reverse_condition (rc);
8624 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8629 [(set (match_operand:SI 0 "s_register_operand" "")
8630 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8631 [(match_operand 2 "" "") (match_operand 3 "" "")])
8632 (match_operand 4 "" "")
8634 (clobber (reg:CC CC_REGNUM))]
8635 "TARGET_ARM && reload_completed"
8636 [(set (match_dup 5) (match_dup 6))
8637 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8638 (set (match_dup 0) (match_dup 4)))]
8641 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8642 operands[2], operands[3]);
8644 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8645 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8650 [(set (match_operand:SI 0 "s_register_operand" "")
8651 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8652 [(match_operand 2 "" "") (match_operand 3 "" "")])
8653 (match_operand 4 "" "")
8654 (match_operand 5 "" "")))
8655 (clobber (reg:CC CC_REGNUM))]
8656 "TARGET_ARM && reload_completed"
8657 [(set (match_dup 6) (match_dup 7))
8658 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8659 (set (match_dup 0) (match_dup 4)))
8660 (cond_exec (match_dup 8)
8661 (set (match_dup 0) (match_dup 5)))]
8664 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8665 operands[2], operands[3]);
8666 enum rtx_code rc = GET_CODE (operands[1]);
8668 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8669 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8670 if (mode == CCFPmode || mode == CCFPEmode)
8671 rc = reverse_condition_maybe_unordered (rc);
8673 rc = reverse_condition (rc);
8675 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8680 [(set (match_operand:SI 0 "s_register_operand" "")
8681 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8682 [(match_operand:SI 2 "s_register_operand" "")
8683 (match_operand:SI 3 "arm_add_operand" "")])
8684 (match_operand:SI 4 "arm_rhs_operand" "")
8686 (match_operand:SI 5 "s_register_operand" ""))))
8687 (clobber (reg:CC CC_REGNUM))]
8688 "TARGET_ARM && reload_completed"
8689 [(set (match_dup 6) (match_dup 7))
8690 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8691 (set (match_dup 0) (match_dup 4)))
8692 (cond_exec (match_dup 8)
8693 (set (match_dup 0) (not:SI (match_dup 5))))]
8696 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8697 operands[2], operands[3]);
8698 enum rtx_code rc = GET_CODE (operands[1]);
8700 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8701 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8702 if (mode == CCFPmode || mode == CCFPEmode)
8703 rc = reverse_condition_maybe_unordered (rc);
8705 rc = reverse_condition (rc);
8707 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8711 (define_insn "*cond_move_not"
8712 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8713 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8714 [(match_operand 3 "cc_register" "") (const_int 0)])
8715 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8717 (match_operand:SI 2 "s_register_operand" "r,r"))))]
8721 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8722 [(set_attr "conds" "use")
8723 (set_attr "length" "4,8")]
8726 ;; The next two patterns occur when an AND operation is followed by a
8727 ;; scc insn sequence
8729 (define_insn "*sign_extract_onebit"
8730 [(set (match_operand:SI 0 "s_register_operand" "=r")
8731 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8733 (match_operand:SI 2 "const_int_operand" "n")))
8734 (clobber (reg:CC CC_REGNUM))]
8737 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8738 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8739 return \"mvnne\\t%0, #0\";
8741 [(set_attr "conds" "clob")
8742 (set_attr "length" "8")]
8745 (define_insn "*not_signextract_onebit"
8746 [(set (match_operand:SI 0 "s_register_operand" "=r")
8748 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8750 (match_operand:SI 2 "const_int_operand" "n"))))
8751 (clobber (reg:CC CC_REGNUM))]
8754 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8755 output_asm_insn (\"tst\\t%1, %2\", operands);
8756 output_asm_insn (\"mvneq\\t%0, #0\", operands);
8757 return \"movne\\t%0, #0\";
8759 [(set_attr "conds" "clob")
8760 (set_attr "length" "12")]
8763 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
8764 ;; expressions. For simplicity, the first register is also in the unspec
8766 (define_insn "*push_multi"
8767 [(match_parallel 2 "multi_register_push"
8768 [(set (match_operand:BLK 0 "memory_operand" "=m")
8769 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8770 UNSPEC_PUSH_MULT))])]
8774 int num_saves = XVECLEN (operands[2], 0);
8776 /* For the StrongARM at least it is faster to
8777 use STR to store only a single register. */
8779 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8785 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
8787 for (i = 1; i < num_saves; i++)
8789 strcat (pattern, \", %|\");
8791 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
8794 strcat (pattern, \"}\");
8795 output_asm_insn (pattern, operands);
8800 [(set_attr "type" "store4")]
8803 (define_insn "stack_tie"
8804 [(set (mem:BLK (scratch))
8805 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
8806 (match_operand:SI 1 "s_register_operand" "r")]
8810 [(set_attr "length" "0")]
8813 ;; Similarly for the floating point registers
8814 (define_insn "*push_fp_multi"
8815 [(match_parallel 2 "multi_register_push"
8816 [(set (match_operand:BLK 0 "memory_operand" "=m")
8817 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
8818 UNSPEC_PUSH_MULT))])]
8824 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
8825 output_asm_insn (pattern, operands);
8828 [(set_attr "type" "f_store")]
8831 ;; Special patterns for dealing with the constant pool
8833 (define_insn "align_4"
8834 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
8837 assemble_align (32);
8842 (define_insn "consttable_end"
8843 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
8846 making_const_table = FALSE;
8851 (define_insn "consttable_1"
8852 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
8855 making_const_table = TRUE;
8856 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
8860 [(set_attr "length" "4")]
8863 (define_insn "consttable_2"
8864 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
8867 making_const_table = TRUE;
8868 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
8872 [(set_attr "length" "4")]
8875 (define_insn "consttable_4"
8876 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
8880 making_const_table = TRUE;
8881 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8886 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8887 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8891 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
8896 [(set_attr "length" "4")]
8899 (define_insn "consttable_8"
8900 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
8904 making_const_table = TRUE;
8905 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8910 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8911 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8915 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
8920 [(set_attr "length" "8")]
8923 ;; Miscellaneous Thumb patterns
8925 (define_expand "tablejump"
8926 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
8927 (use (label_ref (match_operand 1 "" "")))])]
8932 /* Hopefully, CSE will eliminate this copy. */
8933 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
8934 rtx reg2 = gen_reg_rtx (SImode);
8936 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
8942 (define_insn "*thumb_tablejump"
8943 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
8944 (use (label_ref (match_operand 1 "" "")))]
8947 [(set_attr "length" "2")]
8952 (define_insn "clzsi2"
8953 [(set (match_operand:SI 0 "s_register_operand" "=r")
8954 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
8955 "TARGET_ARM && arm_arch5"
8958 (define_expand "ffssi2"
8959 [(set (match_operand:SI 0 "s_register_operand" "")
8960 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
8961 "TARGET_ARM && arm_arch5"
8966 t1 = gen_reg_rtx (SImode);
8967 t2 = gen_reg_rtx (SImode);
8968 t3 = gen_reg_rtx (SImode);
8970 emit_insn (gen_negsi2 (t1, operands[1]));
8971 emit_insn (gen_andsi3 (t2, operands[1], t1));
8972 emit_insn (gen_clzsi2 (t3, t2));
8973 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
8978 (define_expand "ctzsi2"
8979 [(set (match_operand:SI 0 "s_register_operand" "")
8980 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
8981 "TARGET_ARM && arm_arch5"
8986 t1 = gen_reg_rtx (SImode);
8987 t2 = gen_reg_rtx (SImode);
8988 t3 = gen_reg_rtx (SImode);
8990 emit_insn (gen_negsi2 (t1, operands[1]));
8991 emit_insn (gen_andsi3 (t2, operands[1], t1));
8992 emit_insn (gen_clzsi2 (t3, t2));
8993 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
8998 ;; V5E instructions.
9000 (define_insn "prefetch"
9001 [(prefetch (match_operand:SI 0 "address_operand" "p")
9002 (match_operand:SI 1 "" "")
9003 (match_operand:SI 2 "" ""))]
9004 "TARGET_ARM && arm_arch5e"
9007 ;; General predication pattern
9010 [(match_operator 0 "arm_comparison_operator"
9011 [(match_operand 1 "cc_register" "")
9017 (define_insn "prologue_use"
9018 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
9020 "%@ %0 needed for prologue"