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_expand "addsf3"
810 [(set (match_operand:SF 0 "s_register_operand" "")
811 (plus:SF (match_operand:SF 1 "s_register_operand" "")
812 (match_operand:SF 2 "fpu_add_operand" "")))]
813 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
816 && !cirrus_fp_register (operands[2], SFmode))
817 operands[2] = force_reg (SFmode, operands[2]);
820 (define_insn "*arm_addsf3"
821 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
822 (plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
823 (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
824 "TARGET_ARM && TARGET_HARD_FLOAT"
827 suf%?s\\t%0, %1, #%N2"
828 [(set_attr "type" "farith")
829 (set_attr "predicable" "yes")]
832 (define_expand "adddf3"
833 [(set (match_operand:DF 0 "s_register_operand" "")
834 (plus:DF (match_operand:DF 1 "s_register_operand" "")
835 (match_operand:DF 2 "fpu_add_operand" "")))]
836 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
839 && !cirrus_fp_register (operands[2], DFmode))
840 operands[2] = force_reg (DFmode, operands[2]);
843 (define_insn "*arm_adddf3"
844 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
845 (plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
846 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
847 "TARGET_ARM && TARGET_HARD_FLOAT"
850 suf%?d\\t%0, %1, #%N2"
851 [(set_attr "type" "farith")
852 (set_attr "predicable" "yes")]
855 (define_insn "*adddf_esfdf_df"
856 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
857 (plus:DF (float_extend:DF
858 (match_operand:SF 1 "s_register_operand" "f,f"))
859 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
860 "TARGET_ARM && TARGET_HARD_FLOAT"
863 suf%?d\\t%0, %1, #%N2"
864 [(set_attr "type" "farith")
865 (set_attr "predicable" "yes")]
868 (define_insn "*adddf_df_esfdf"
869 [(set (match_operand:DF 0 "s_register_operand" "=f")
870 (plus:DF (match_operand:DF 1 "s_register_operand" "f")
872 (match_operand:SF 2 "s_register_operand" "f"))))]
873 "TARGET_ARM && TARGET_HARD_FLOAT"
874 "adf%?d\\t%0, %1, %2"
875 [(set_attr "type" "farith")
876 (set_attr "predicable" "yes")]
879 (define_insn "*adddf_esfdf_esfdf"
880 [(set (match_operand:DF 0 "s_register_operand" "=f")
881 (plus:DF (float_extend:DF
882 (match_operand:SF 1 "s_register_operand" "f"))
884 (match_operand:SF 2 "s_register_operand" "f"))))]
885 "TARGET_ARM && TARGET_HARD_FLOAT"
886 "adf%?d\\t%0, %1, %2"
887 [(set_attr "type" "farith")
888 (set_attr "predicable" "yes")]
891 (define_expand "subdi3"
893 [(set (match_operand:DI 0 "s_register_operand" "")
894 (minus:DI (match_operand:DI 1 "s_register_operand" "")
895 (match_operand:DI 2 "s_register_operand" "")))
896 (clobber (reg:CC CC_REGNUM))])]
901 && cirrus_fp_register (operands[0], DImode)
902 && cirrus_fp_register (operands[1], DImode))
904 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
910 if (GET_CODE (operands[1]) != REG)
911 operands[1] = force_reg (SImode, operands[1]);
912 if (GET_CODE (operands[2]) != REG)
913 operands[2] = force_reg (SImode, operands[2]);
918 (define_insn "*arm_subdi3"
919 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
920 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
921 (match_operand:DI 2 "s_register_operand" "r,0,0")))
922 (clobber (reg:CC CC_REGNUM))]
924 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
925 [(set_attr "conds" "clob")
926 (set_attr "length" "8")]
929 (define_insn "*thumb_subdi3"
930 [(set (match_operand:DI 0 "register_operand" "=l")
931 (minus:DI (match_operand:DI 1 "register_operand" "0")
932 (match_operand:DI 2 "register_operand" "l")))
933 (clobber (reg:CC CC_REGNUM))]
935 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
936 [(set_attr "length" "4")]
939 (define_insn "*subdi_di_zesidi"
940 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
941 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
943 (match_operand:SI 2 "s_register_operand" "r,r"))))
944 (clobber (reg:CC CC_REGNUM))]
946 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
947 [(set_attr "conds" "clob")
948 (set_attr "length" "8")]
951 (define_insn "*subdi_di_sesidi"
952 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
953 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
955 (match_operand:SI 2 "s_register_operand" "r,r"))))
956 (clobber (reg:CC CC_REGNUM))]
958 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
959 [(set_attr "conds" "clob")
960 (set_attr "length" "8")]
963 (define_insn "*subdi_zesidi_di"
964 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
965 (minus:DI (zero_extend:DI
966 (match_operand:SI 2 "s_register_operand" "r,r"))
967 (match_operand:DI 1 "s_register_operand" "?r,0")))
968 (clobber (reg:CC CC_REGNUM))]
970 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
971 [(set_attr "conds" "clob")
972 (set_attr "length" "8")]
975 (define_insn "*subdi_sesidi_di"
976 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
977 (minus:DI (sign_extend:DI
978 (match_operand:SI 2 "s_register_operand" "r,r"))
979 (match_operand:DI 1 "s_register_operand" "?r,0")))
980 (clobber (reg:CC CC_REGNUM))]
982 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
983 [(set_attr "conds" "clob")
984 (set_attr "length" "8")]
987 (define_insn "*subdi_zesidi_zesidi"
988 [(set (match_operand:DI 0 "s_register_operand" "=r")
989 (minus:DI (zero_extend:DI
990 (match_operand:SI 1 "s_register_operand" "r"))
992 (match_operand:SI 2 "s_register_operand" "r"))))
993 (clobber (reg:CC CC_REGNUM))]
995 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
996 [(set_attr "conds" "clob")
997 (set_attr "length" "8")]
1000 (define_expand "subsi3"
1001 [(set (match_operand:SI 0 "s_register_operand" "")
1002 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1003 (match_operand:SI 2 "s_register_operand" "")))]
1006 if (GET_CODE (operands[1]) == CONST_INT)
1010 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1013 : preserve_subexpressions_p ()));
1016 else /* TARGET_THUMB */
1017 operands[1] = force_reg (SImode, operands[1]);
1022 (define_insn "*thumb_subsi3_insn"
1023 [(set (match_operand:SI 0 "register_operand" "=l")
1024 (minus:SI (match_operand:SI 1 "register_operand" "l")
1025 (match_operand:SI 2 "register_operand" "l")))]
1028 [(set_attr "length" "2")]
1031 (define_insn_and_split "*arm_subsi3_insn"
1032 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1033 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
1034 (match_operand:SI 2 "s_register_operand" "r,r")))]
1040 && GET_CODE (operands[1]) == CONST_INT
1041 && !const_ok_for_arm (INTVAL (operands[1]))"
1042 [(clobber (const_int 0))]
1044 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1048 [(set_attr "length" "4,16")
1049 (set_attr "predicable" "yes")]
1053 [(match_scratch:SI 3 "r")
1054 (set (match_operand:SI 0 "s_register_operand" "")
1055 (minus:SI (match_operand:SI 1 "const_int_operand" "")
1056 (match_operand:SI 2 "s_register_operand" "")))]
1058 && !const_ok_for_arm (INTVAL (operands[1]))
1059 && const_ok_for_arm (~INTVAL (operands[1]))"
1060 [(set (match_dup 3) (match_dup 1))
1061 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1065 (define_insn "*subsi3_compare0"
1066 [(set (reg:CC_NOOV CC_REGNUM)
1068 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1069 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1071 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1072 (minus:SI (match_dup 1) (match_dup 2)))]
1076 rsb%?s\\t%0, %2, %1"
1077 [(set_attr "conds" "set")]
1080 (define_insn "decscc"
1081 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1082 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1083 (match_operator:SI 2 "arm_comparison_operator"
1084 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1088 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1089 [(set_attr "conds" "use")
1090 (set_attr "length" "*,8")]
1093 (define_expand "subsf3"
1094 [(set (match_operand:SF 0 "s_register_operand" "")
1095 (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "")
1096 (match_operand:SF 2 "fpu_rhs_operand" "")))]
1097 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1101 if (!cirrus_fp_register (operands[1], SFmode))
1102 operands[1] = force_reg (SFmode, operands[1]);
1103 if (!cirrus_fp_register (operands[2], SFmode))
1104 operands[2] = force_reg (SFmode, operands[2]);
1108 (define_insn "*arm_subsf3"
1109 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1110 (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1111 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1112 "TARGET_ARM && TARGET_HARD_FLOAT"
1115 rsf%?s\\t%0, %2, %1"
1116 [(set_attr "type" "farith")]
1119 (define_expand "subdf3"
1120 [(set (match_operand:DF 0 "s_register_operand" "")
1121 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "")
1122 (match_operand:DF 2 "fpu_rhs_operand" "")))]
1123 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1127 if (!cirrus_fp_register (operands[1], DFmode))
1128 operands[1] = force_reg (DFmode, operands[1]);
1129 if (!cirrus_fp_register (operands[2], DFmode))
1130 operands[2] = force_reg (DFmode, operands[2]);
1134 (define_insn "*arm_subdf3"
1135 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1136 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1137 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1138 "TARGET_ARM && TARGET_HARD_FLOAT"
1141 rsf%?d\\t%0, %2, %1"
1142 [(set_attr "type" "farith")
1143 (set_attr "predicable" "yes")]
1146 (define_insn "*subdf_esfdf_df"
1147 [(set (match_operand:DF 0 "s_register_operand" "=f")
1148 (minus:DF (float_extend:DF
1149 (match_operand:SF 1 "s_register_operand" "f"))
1150 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1151 "TARGET_ARM && TARGET_HARD_FLOAT"
1152 "suf%?d\\t%0, %1, %2"
1153 [(set_attr "type" "farith")
1154 (set_attr "predicable" "yes")]
1157 (define_insn "*subdf_df_esfdf"
1158 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1159 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1161 (match_operand:SF 2 "s_register_operand" "f,f"))))]
1162 "TARGET_ARM && TARGET_HARD_FLOAT"
1165 rsf%?d\\t%0, %2, %1"
1166 [(set_attr "type" "farith")
1167 (set_attr "predicable" "yes")]
1170 (define_insn "*subdf_esfdf_esfdf"
1171 [(set (match_operand:DF 0 "s_register_operand" "=f")
1172 (minus:DF (float_extend:DF
1173 (match_operand:SF 1 "s_register_operand" "f"))
1175 (match_operand:SF 2 "s_register_operand" "f"))))]
1176 "TARGET_ARM && TARGET_HARD_FLOAT"
1177 "suf%?d\\t%0, %1, %2"
1178 [(set_attr "type" "farith")
1179 (set_attr "predicable" "yes")]
1182 ;; Multiplication insns
1184 (define_expand "mulsi3"
1185 [(set (match_operand:SI 0 "s_register_operand" "")
1186 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1187 (match_operand:SI 1 "s_register_operand" "")))]
1192 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1193 (define_insn "*arm_mulsi3"
1194 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1195 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1196 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1198 "mul%?\\t%0, %2, %1"
1199 [(set_attr "type" "mult")
1200 (set_attr "predicable" "yes")]
1203 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1204 ; 1 and 2; are the same, because reload will make operand 0 match
1205 ; operand 1 without realizing that this conflicts with operand 2. We fix
1206 ; this by adding another alternative to match this case, and then `reload'
1207 ; it ourselves. This alternative must come first.
1208 (define_insn "*thumb_mulsi3"
1209 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1210 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1211 (match_operand:SI 2 "register_operand" "l,l,l")))]
1214 if (which_alternative < 2)
1215 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1217 return \"mul\\t%0, %0, %2\";
1219 [(set_attr "length" "4,4,2")
1220 (set_attr "type" "mult")]
1223 (define_insn "*mulsi3_compare0"
1224 [(set (reg:CC_NOOV CC_REGNUM)
1225 (compare:CC_NOOV (mult:SI
1226 (match_operand:SI 2 "s_register_operand" "r,r")
1227 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1229 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1230 (mult:SI (match_dup 2) (match_dup 1)))]
1231 "TARGET_ARM && !arm_is_xscale"
1232 "mul%?s\\t%0, %2, %1"
1233 [(set_attr "conds" "set")
1234 (set_attr "type" "mult")]
1237 (define_insn "*mulsi_compare0_scratch"
1238 [(set (reg:CC_NOOV CC_REGNUM)
1239 (compare:CC_NOOV (mult:SI
1240 (match_operand:SI 2 "s_register_operand" "r,r")
1241 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1243 (clobber (match_scratch:SI 0 "=&r,&r"))]
1244 "TARGET_ARM && !arm_is_xscale"
1245 "mul%?s\\t%0, %2, %1"
1246 [(set_attr "conds" "set")
1247 (set_attr "type" "mult")]
1250 ;; Unnamed templates to match MLA instruction.
1252 (define_insn "*mulsi3addsi"
1253 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1255 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1256 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1257 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1259 "mla%?\\t%0, %2, %1, %3"
1260 [(set_attr "type" "mult")
1261 (set_attr "predicable" "yes")]
1264 (define_insn "*mulsi3addsi_compare0"
1265 [(set (reg:CC_NOOV CC_REGNUM)
1268 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1269 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1270 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1272 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1273 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1275 "TARGET_ARM && !arm_is_xscale"
1276 "mla%?s\\t%0, %2, %1, %3"
1277 [(set_attr "conds" "set")
1278 (set_attr "type" "mult")]
1281 (define_insn "*mulsi3addsi_compare0_scratch"
1282 [(set (reg:CC_NOOV CC_REGNUM)
1285 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1286 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1287 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1289 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1290 "TARGET_ARM && !arm_is_xscale"
1291 "mla%?s\\t%0, %2, %1, %3"
1292 [(set_attr "conds" "set")
1293 (set_attr "type" "mult")]
1296 ;; Unnamed template to match long long multiply-accumlate (smlal)
1298 (define_insn "*mulsidi3adddi"
1299 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1302 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1303 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1304 (match_operand:DI 1 "s_register_operand" "0")))]
1305 "TARGET_ARM && arm_fast_multiply"
1306 "smlal%?\\t%Q0, %R0, %3, %2"
1307 [(set_attr "type" "mult")
1308 (set_attr "predicable" "yes")]
1311 (define_insn "mulsidi3"
1312 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1314 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1315 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1316 "TARGET_ARM && arm_fast_multiply"
1317 "smull%?\\t%Q0, %R0, %1, %2"
1318 [(set_attr "type" "mult")
1319 (set_attr "predicable" "yes")]
1322 (define_insn "umulsidi3"
1323 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1325 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1326 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1327 "TARGET_ARM && arm_fast_multiply"
1328 "umull%?\\t%Q0, %R0, %1, %2"
1329 [(set_attr "type" "mult")
1330 (set_attr "predicable" "yes")]
1333 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1335 (define_insn "*umulsidi3adddi"
1336 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1339 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1340 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1341 (match_operand:DI 1 "s_register_operand" "0")))]
1342 "TARGET_ARM && arm_fast_multiply"
1343 "umlal%?\\t%Q0, %R0, %3, %2"
1344 [(set_attr "type" "mult")
1345 (set_attr "predicable" "yes")]
1348 (define_insn "smulsi3_highpart"
1349 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1353 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1354 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1356 (clobber (match_scratch:SI 3 "=&r,&r"))]
1357 "TARGET_ARM && arm_fast_multiply"
1358 "smull%?\\t%3, %0, %2, %1"
1359 [(set_attr "type" "mult")
1360 (set_attr "predicable" "yes")]
1363 (define_insn "umulsi3_highpart"
1364 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1368 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1369 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1371 (clobber (match_scratch:SI 3 "=&r,&r"))]
1372 "TARGET_ARM && arm_fast_multiply"
1373 "umull%?\\t%3, %0, %2, %1"
1374 [(set_attr "type" "mult")
1375 (set_attr "predicable" "yes")]
1378 (define_insn "mulhisi3"
1379 [(set (match_operand:SI 0 "s_register_operand" "=r")
1380 (mult:SI (sign_extend:SI
1381 (match_operand:HI 1 "s_register_operand" "%r"))
1383 (match_operand:HI 2 "s_register_operand" "r"))))]
1384 "TARGET_ARM && arm_arch5e"
1385 "smulbb%?\\t%0, %1, %2"
1386 [(set_attr "type" "mult")
1387 (set_attr "predicable" "yes")]
1390 (define_insn "*mulhisi3tb"
1391 [(set (match_operand:SI 0 "s_register_operand" "=r")
1392 (mult:SI (ashiftrt:SI
1393 (match_operand:SI 1 "s_register_operand" "r")
1396 (match_operand:HI 2 "s_register_operand" "r"))))]
1397 "TARGET_ARM && arm_arch5e"
1398 "smultb%?\\t%0, %1, %2"
1399 [(set_attr "type" "mult")
1400 (set_attr "predicable" "yes")]
1403 (define_insn "*mulhisi3bt"
1404 [(set (match_operand:SI 0 "s_register_operand" "=r")
1405 (mult:SI (sign_extend:SI
1406 (match_operand:HI 1 "s_register_operand" "r"))
1408 (match_operand:SI 2 "s_register_operand" "r")
1410 "TARGET_ARM && arm_arch5e"
1411 "smulbt%?\\t%0, %1, %2"
1412 [(set_attr "type" "mult")
1413 (set_attr "predicable" "yes")]
1416 (define_insn "*mulhisi3tt"
1417 [(set (match_operand:SI 0 "s_register_operand" "=r")
1418 (mult:SI (ashiftrt:SI
1419 (match_operand:SI 1 "s_register_operand" "r")
1422 (match_operand:SI 2 "s_register_operand" "r")
1424 "TARGET_ARM && arm_arch5e"
1425 "smultt%?\\t%0, %1, %2"
1426 [(set_attr "type" "mult")
1427 (set_attr "predicable" "yes")]
1430 (define_insn "*mulhisi3addsi"
1431 [(set (match_operand:SI 0 "s_register_operand" "=r")
1432 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1433 (mult:SI (sign_extend:SI
1434 (match_operand:HI 2 "s_register_operand" "%r"))
1436 (match_operand:HI 3 "s_register_operand" "r")))))]
1437 "TARGET_ARM && arm_arch5e"
1438 "smlabb%?\\t%0, %2, %3, %1"
1439 [(set_attr "type" "mult")
1440 (set_attr "predicable" "yes")]
1443 (define_insn "*mulhidi3adddi"
1444 [(set (match_operand:DI 0 "s_register_operand" "=r")
1446 (match_operand:DI 1 "s_register_operand" "0")
1447 (mult:DI (sign_extend:DI
1448 (match_operand:HI 2 "s_register_operand" "%r"))
1450 (match_operand:HI 3 "s_register_operand" "r")))))]
1451 "TARGET_ARM && arm_arch5e"
1452 "smlalbb%?\\t%Q0, %R0, %2, %3"
1453 [(set_attr "type" "mult")
1454 (set_attr "predicable" "yes")])
1456 (define_expand "mulsf3"
1457 [(set (match_operand:SF 0 "s_register_operand" "")
1458 (mult:SF (match_operand:SF 1 "s_register_operand" "")
1459 (match_operand:SF 2 "fpu_rhs_operand" "")))]
1460 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1463 && !cirrus_fp_register (operands[2], SFmode))
1464 operands[2] = force_reg (SFmode, operands[2]);
1467 (define_insn "*arm_mulsf3"
1468 [(set (match_operand:SF 0 "s_register_operand" "=f")
1469 (mult:SF (match_operand:SF 1 "s_register_operand" "f")
1470 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1471 "TARGET_ARM && TARGET_HARD_FLOAT"
1472 "fml%?s\\t%0, %1, %2"
1473 [(set_attr "type" "ffmul")
1474 (set_attr "predicable" "yes")]
1477 (define_expand "muldf3"
1478 [(set (match_operand:DF 0 "s_register_operand" "")
1479 (mult:DF (match_operand:DF 1 "s_register_operand" "")
1480 (match_operand:DF 2 "fpu_rhs_operand" "")))]
1481 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1484 && !cirrus_fp_register (operands[2], DFmode))
1485 operands[2] = force_reg (DFmode, operands[2]);
1488 (define_insn "*arm_muldf3"
1489 [(set (match_operand:DF 0 "s_register_operand" "=f")
1490 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1491 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1492 "TARGET_ARM && TARGET_HARD_FLOAT"
1493 "muf%?d\\t%0, %1, %2"
1494 [(set_attr "type" "fmul")
1495 (set_attr "predicable" "yes")]
1498 (define_insn "*muldf_esfdf_df"
1499 [(set (match_operand:DF 0 "s_register_operand" "=f")
1500 (mult:DF (float_extend:DF
1501 (match_operand:SF 1 "s_register_operand" "f"))
1502 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1503 "TARGET_ARM && TARGET_HARD_FLOAT"
1504 "muf%?d\\t%0, %1, %2"
1505 [(set_attr "type" "fmul")
1506 (set_attr "predicable" "yes")]
1509 (define_insn "*muldf_df_esfdf"
1510 [(set (match_operand:DF 0 "s_register_operand" "=f")
1511 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1513 (match_operand:SF 2 "s_register_operand" "f"))))]
1514 "TARGET_ARM && TARGET_HARD_FLOAT"
1515 "muf%?d\\t%0, %1, %2"
1516 [(set_attr "type" "fmul")
1517 (set_attr "predicable" "yes")]
1520 (define_insn "*muldf_esfdf_esfdf"
1521 [(set (match_operand:DF 0 "s_register_operand" "=f")
1523 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f"))
1524 (float_extend:DF (match_operand:SF 2 "s_register_operand" "f"))))]
1525 "TARGET_ARM && TARGET_HARD_FLOAT"
1526 "muf%?d\\t%0, %1, %2"
1527 [(set_attr "type" "fmul")
1528 (set_attr "predicable" "yes")]
1533 (define_insn "divsf3"
1534 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1535 (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1536 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1537 "TARGET_ARM && TARGET_HARD_FLOAT"
1540 frd%?s\\t%0, %2, %1"
1541 [(set_attr "type" "fdivs")
1542 (set_attr "predicable" "yes")]
1545 (define_insn "divdf3"
1546 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1547 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1548 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1549 "TARGET_ARM && TARGET_HARD_FLOAT"
1552 rdf%?d\\t%0, %2, %1"
1553 [(set_attr "type" "fdivd")
1554 (set_attr "predicable" "yes")]
1557 (define_insn "*divdf_esfdf_df"
1558 [(set (match_operand:DF 0 "s_register_operand" "=f")
1559 (div:DF (float_extend:DF
1560 (match_operand:SF 1 "s_register_operand" "f"))
1561 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1562 "TARGET_ARM && TARGET_HARD_FLOAT"
1563 "dvf%?d\\t%0, %1, %2"
1564 [(set_attr "type" "fdivd")
1565 (set_attr "predicable" "yes")]
1568 (define_insn "*divdf_df_esfdf"
1569 [(set (match_operand:DF 0 "s_register_operand" "=f")
1570 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1572 (match_operand:SF 2 "s_register_operand" "f"))))]
1573 "TARGET_ARM && TARGET_HARD_FLOAT"
1574 "rdf%?d\\t%0, %2, %1"
1575 [(set_attr "type" "fdivd")
1576 (set_attr "predicable" "yes")]
1579 (define_insn "*divdf_esfdf_esfdf"
1580 [(set (match_operand:DF 0 "s_register_operand" "=f")
1581 (div:DF (float_extend:DF
1582 (match_operand:SF 1 "s_register_operand" "f"))
1584 (match_operand:SF 2 "s_register_operand" "f"))))]
1585 "TARGET_ARM && TARGET_HARD_FLOAT"
1586 "dvf%?d\\t%0, %1, %2"
1587 [(set_attr "type" "fdivd")
1588 (set_attr "predicable" "yes")]
1593 (define_insn "modsf3"
1594 [(set (match_operand:SF 0 "s_register_operand" "=f")
1595 (mod:SF (match_operand:SF 1 "s_register_operand" "f")
1596 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1597 "TARGET_ARM && TARGET_HARD_FLOAT"
1598 "rmf%?s\\t%0, %1, %2"
1599 [(set_attr "type" "fdivs")
1600 (set_attr "predicable" "yes")]
1603 (define_insn "moddf3"
1604 [(set (match_operand:DF 0 "s_register_operand" "=f")
1605 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1606 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1607 "TARGET_ARM && TARGET_HARD_FLOAT"
1608 "rmf%?d\\t%0, %1, %2"
1609 [(set_attr "type" "fdivd")
1610 (set_attr "predicable" "yes")]
1613 (define_insn "*moddf_esfdf_df"
1614 [(set (match_operand:DF 0 "s_register_operand" "=f")
1615 (mod:DF (float_extend:DF
1616 (match_operand:SF 1 "s_register_operand" "f"))
1617 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1618 "TARGET_ARM && TARGET_HARD_FLOAT"
1619 "rmf%?d\\t%0, %1, %2"
1620 [(set_attr "type" "fdivd")
1621 (set_attr "predicable" "yes")]
1624 (define_insn "*moddf_df_esfdf"
1625 [(set (match_operand:DF 0 "s_register_operand" "=f")
1626 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1628 (match_operand:SF 2 "s_register_operand" "f"))))]
1629 "TARGET_ARM && TARGET_HARD_FLOAT"
1630 "rmf%?d\\t%0, %1, %2"
1631 [(set_attr "type" "fdivd")
1632 (set_attr "predicable" "yes")]
1635 (define_insn "*moddf_esfdf_esfdf"
1636 [(set (match_operand:DF 0 "s_register_operand" "=f")
1637 (mod:DF (float_extend:DF
1638 (match_operand:SF 1 "s_register_operand" "f"))
1640 (match_operand:SF 2 "s_register_operand" "f"))))]
1641 "TARGET_ARM && TARGET_HARD_FLOAT"
1642 "rmf%?d\\t%0, %1, %2"
1643 [(set_attr "type" "fdivd")
1644 (set_attr "predicable" "yes")]
1647 ;; Boolean and,ior,xor insns
1649 ;; Split up double word logical operations
1651 ;; Split up simple DImode logical operations. Simply perform the logical
1652 ;; operation on the upper and lower halves of the registers.
1654 [(set (match_operand:DI 0 "s_register_operand" "")
1655 (match_operator:DI 6 "logical_binary_operator"
1656 [(match_operand:DI 1 "s_register_operand" "")
1657 (match_operand:DI 2 "s_register_operand" "")]))]
1658 "TARGET_ARM && reload_completed"
1659 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1660 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1663 operands[3] = gen_highpart (SImode, operands[0]);
1664 operands[0] = gen_lowpart (SImode, operands[0]);
1665 operands[4] = gen_highpart (SImode, operands[1]);
1666 operands[1] = gen_lowpart (SImode, operands[1]);
1667 operands[5] = gen_highpart (SImode, operands[2]);
1668 operands[2] = gen_lowpart (SImode, operands[2]);
1673 [(set (match_operand:DI 0 "s_register_operand" "")
1674 (match_operator:DI 6 "logical_binary_operator"
1675 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1676 (match_operand:DI 1 "s_register_operand" "")]))]
1677 "TARGET_ARM && reload_completed"
1678 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1679 (set (match_dup 3) (match_op_dup:SI 6
1680 [(ashiftrt:SI (match_dup 2) (const_int 31))
1684 operands[3] = gen_highpart (SImode, operands[0]);
1685 operands[0] = gen_lowpart (SImode, operands[0]);
1686 operands[4] = gen_highpart (SImode, operands[1]);
1687 operands[1] = gen_lowpart (SImode, operands[1]);
1688 operands[5] = gen_highpart (SImode, operands[2]);
1689 operands[2] = gen_lowpart (SImode, operands[2]);
1693 ;; The zero extend of operand 2 means we can just copy the high part of
1694 ;; operand1 into operand0.
1696 [(set (match_operand:DI 0 "s_register_operand" "")
1698 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1699 (match_operand:DI 1 "s_register_operand" "")))]
1700 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1701 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1702 (set (match_dup 3) (match_dup 4))]
1705 operands[4] = gen_highpart (SImode, operands[1]);
1706 operands[3] = gen_highpart (SImode, operands[0]);
1707 operands[0] = gen_lowpart (SImode, operands[0]);
1708 operands[1] = gen_lowpart (SImode, operands[1]);
1712 ;; The zero extend of operand 2 means we can just copy the high part of
1713 ;; operand1 into operand0.
1715 [(set (match_operand:DI 0 "s_register_operand" "")
1717 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1718 (match_operand:DI 1 "s_register_operand" "")))]
1719 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1720 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1721 (set (match_dup 3) (match_dup 4))]
1724 operands[4] = gen_highpart (SImode, operands[1]);
1725 operands[3] = gen_highpart (SImode, operands[0]);
1726 operands[0] = gen_lowpart (SImode, operands[0]);
1727 operands[1] = gen_lowpart (SImode, operands[1]);
1731 (define_insn "anddi3"
1732 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1733 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1734 (match_operand:DI 2 "s_register_operand" "r,r")))]
1737 [(set_attr "length" "8")]
1740 (define_insn_and_split "*anddi_zesidi_di"
1741 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1742 (and:DI (zero_extend:DI
1743 (match_operand:SI 2 "s_register_operand" "r,r"))
1744 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1747 "TARGET_ARM && reload_completed"
1748 ; The zero extend of operand 2 clears the high word of the output
1750 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1751 (set (match_dup 3) (const_int 0))]
1754 operands[3] = gen_highpart (SImode, operands[0]);
1755 operands[0] = gen_lowpart (SImode, operands[0]);
1756 operands[1] = gen_lowpart (SImode, operands[1]);
1758 [(set_attr "length" "8")]
1761 (define_insn "*anddi_sesdi_di"
1762 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1763 (and:DI (sign_extend:DI
1764 (match_operand:SI 2 "s_register_operand" "r,r"))
1765 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1768 [(set_attr "length" "8")]
1771 (define_expand "andsi3"
1772 [(set (match_operand:SI 0 "s_register_operand" "")
1773 (and:SI (match_operand:SI 1 "s_register_operand" "")
1774 (match_operand:SI 2 "reg_or_int_operand" "")))]
1779 if (GET_CODE (operands[2]) == CONST_INT)
1781 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1784 ? 0 : preserve_subexpressions_p ()));
1788 else /* TARGET_THUMB */
1790 if (GET_CODE (operands[2]) != CONST_INT)
1791 operands[2] = force_reg (SImode, operands[2]);
1796 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1798 operands[2] = force_reg (SImode,
1799 GEN_INT (~INTVAL (operands[2])));
1801 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1806 for (i = 9; i <= 31; i++)
1808 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1810 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1814 else if ((((HOST_WIDE_INT) 1) << i) - 1
1815 == ~INTVAL (operands[2]))
1817 rtx shift = GEN_INT (i);
1818 rtx reg = gen_reg_rtx (SImode);
1820 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1821 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1827 operands[2] = force_reg (SImode, operands[2]);
1833 (define_insn_and_split "*arm_andsi3_insn"
1834 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1835 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1836 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1840 bic%?\\t%0, %1, #%B2
1843 && GET_CODE (operands[2]) == CONST_INT
1844 && !(const_ok_for_arm (INTVAL (operands[2]))
1845 || const_ok_for_arm (~INTVAL (operands[2])))"
1846 [(clobber (const_int 0))]
1848 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1852 [(set_attr "length" "4,4,16")
1853 (set_attr "predicable" "yes")]
1856 (define_insn "*thumb_andsi3_insn"
1857 [(set (match_operand:SI 0 "register_operand" "=l")
1858 (and:SI (match_operand:SI 1 "register_operand" "%0")
1859 (match_operand:SI 2 "register_operand" "l")))]
1862 [(set_attr "length" "2")]
1865 (define_insn "*andsi3_compare0"
1866 [(set (reg:CC_NOOV CC_REGNUM)
1868 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1869 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1871 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1872 (and:SI (match_dup 1) (match_dup 2)))]
1876 bic%?s\\t%0, %1, #%B2"
1877 [(set_attr "conds" "set")]
1880 (define_insn "*andsi3_compare0_scratch"
1881 [(set (reg:CC_NOOV CC_REGNUM)
1883 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1884 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1886 (clobber (match_scratch:SI 2 "=X,r"))]
1890 bic%?s\\t%2, %0, #%B1"
1891 [(set_attr "conds" "set")]
1894 (define_insn "*zeroextractsi_compare0_scratch"
1895 [(set (reg:CC_NOOV CC_REGNUM)
1896 (compare:CC_NOOV (zero_extract:SI
1897 (match_operand:SI 0 "s_register_operand" "r")
1898 (match_operand 1 "const_int_operand" "n")
1899 (match_operand 2 "const_int_operand" "n"))
1902 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1903 && INTVAL (operands[1]) > 0
1904 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1905 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1907 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1908 << INTVAL (operands[2]));
1909 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1912 [(set_attr "conds" "set")]
1915 (define_insn "*ne_zeroextractsi"
1916 [(set (match_operand:SI 0 "s_register_operand" "=r")
1917 (ne:SI (zero_extract:SI
1918 (match_operand:SI 1 "s_register_operand" "r")
1919 (match_operand:SI 2 "const_int_operand" "n")
1920 (match_operand:SI 3 "const_int_operand" "n"))
1922 (clobber (reg:CC CC_REGNUM))]
1924 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1925 && INTVAL (operands[2]) > 0
1926 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1927 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1929 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1930 << INTVAL (operands[3]));
1931 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1932 return \"movne\\t%0, #1\";
1934 [(set_attr "conds" "clob")
1935 (set_attr "length" "8")]
1938 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1939 ;;; represented by the bitfield, then this will produce incorrect results.
1940 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1941 ;;; which have a real bit-field insert instruction, the truncation happens
1942 ;;; in the bit-field insert instruction itself. Since arm does not have a
1943 ;;; bit-field insert instruction, we would have to emit code here to truncate
1944 ;;; the value before we insert. This loses some of the advantage of having
1945 ;;; this insv pattern, so this pattern needs to be reevalutated.
1947 (define_expand "insv"
1948 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1949 (match_operand:SI 1 "general_operand" "")
1950 (match_operand:SI 2 "general_operand" ""))
1951 (match_operand:SI 3 "reg_or_int_operand" ""))]
1955 int start_bit = INTVAL (operands[2]);
1956 int width = INTVAL (operands[1]);
1957 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1958 rtx target, subtarget;
1960 target = operands[0];
1961 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1962 subreg as the final target. */
1963 if (GET_CODE (target) == SUBREG)
1965 subtarget = gen_reg_rtx (SImode);
1966 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1967 < GET_MODE_SIZE (SImode))
1968 target = SUBREG_REG (target);
1973 if (GET_CODE (operands[3]) == CONST_INT)
1975 /* Since we are inserting a known constant, we may be able to
1976 reduce the number of bits that we have to clear so that
1977 the mask becomes simple. */
1978 /* ??? This code does not check to see if the new mask is actually
1979 simpler. It may not be. */
1980 rtx op1 = gen_reg_rtx (SImode);
1981 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1982 start of this pattern. */
1983 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1984 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1986 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1987 emit_insn (gen_iorsi3 (subtarget, op1,
1988 GEN_INT (op3_value << start_bit)));
1990 else if (start_bit == 0
1991 && !(const_ok_for_arm (mask)
1992 || const_ok_for_arm (~mask)))
1994 /* A Trick, since we are setting the bottom bits in the word,
1995 we can shift operand[3] up, operand[0] down, OR them together
1996 and rotate the result back again. This takes 3 insns, and
1997 the third might be mergable into another op. */
1998 /* The shift up copes with the possibility that operand[3] is
1999 wider than the bitfield. */
2000 rtx op0 = gen_reg_rtx (SImode);
2001 rtx op1 = gen_reg_rtx (SImode);
2003 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2004 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2005 emit_insn (gen_iorsi3 (op1, op1, op0));
2006 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2008 else if ((width + start_bit == 32)
2009 && !(const_ok_for_arm (mask)
2010 || const_ok_for_arm (~mask)))
2012 /* Similar trick, but slightly less efficient. */
2014 rtx op0 = gen_reg_rtx (SImode);
2015 rtx op1 = gen_reg_rtx (SImode);
2017 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2018 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2019 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2020 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2024 rtx op0 = GEN_INT (mask);
2025 rtx op1 = gen_reg_rtx (SImode);
2026 rtx op2 = gen_reg_rtx (SImode);
2028 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2030 rtx tmp = gen_reg_rtx (SImode);
2032 emit_insn (gen_movsi (tmp, op0));
2036 /* Mask out any bits in operand[3] that are not needed. */
2037 emit_insn (gen_andsi3 (op1, operands[3], op0));
2039 if (GET_CODE (op0) == CONST_INT
2040 && (const_ok_for_arm (mask << start_bit)
2041 || const_ok_for_arm (~(mask << start_bit))))
2043 op0 = GEN_INT (~(mask << start_bit));
2044 emit_insn (gen_andsi3 (op2, operands[0], op0));
2048 if (GET_CODE (op0) == CONST_INT)
2050 rtx tmp = gen_reg_rtx (SImode);
2052 emit_insn (gen_movsi (tmp, op0));
2057 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
2059 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2063 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
2065 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2068 if (subtarget != target)
2070 /* If TARGET is still a SUBREG, then it must be wider than a word,
2071 so we must be careful only to set the subword we were asked to. */
2072 if (GET_CODE (target) == SUBREG)
2073 emit_move_insn (target, subtarget);
2075 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2082 ; constants for op 2 will never be given to these patterns.
2083 (define_insn_and_split "*anddi_notdi_di"
2084 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2085 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2086 (match_operand:DI 2 "s_register_operand" "0,r")))]
2089 "TARGET_ARM && reload_completed"
2090 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2091 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2094 operands[3] = gen_highpart (SImode, operands[0]);
2095 operands[0] = gen_lowpart (SImode, operands[0]);
2096 operands[4] = gen_highpart (SImode, operands[1]);
2097 operands[1] = gen_lowpart (SImode, operands[1]);
2098 operands[5] = gen_highpart (SImode, operands[2]);
2099 operands[2] = gen_lowpart (SImode, operands[2]);
2101 [(set_attr "length" "8")
2102 (set_attr "predicable" "yes")]
2105 (define_insn_and_split "*anddi_notzesidi_di"
2106 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2107 (and:DI (not:DI (zero_extend:DI
2108 (match_operand:SI 2 "s_register_operand" "r,r")))
2109 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2112 bic%?\\t%Q0, %Q1, %2
2114 ; (not (zero_extend ...)) allows us to just copy the high word from
2115 ; operand1 to operand0.
2118 && operands[0] != operands[1]"
2119 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2120 (set (match_dup 3) (match_dup 4))]
2123 operands[3] = gen_highpart (SImode, operands[0]);
2124 operands[0] = gen_lowpart (SImode, operands[0]);
2125 operands[4] = gen_highpart (SImode, operands[1]);
2126 operands[1] = gen_lowpart (SImode, operands[1]);
2128 [(set_attr "length" "4,8")
2129 (set_attr "predicable" "yes")]
2132 (define_insn_and_split "*anddi_notsesidi_di"
2133 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2134 (and:DI (not:DI (sign_extend:DI
2135 (match_operand:SI 2 "s_register_operand" "r,r")))
2136 (match_operand:DI 1 "s_register_operand" "0,r")))]
2139 "TARGET_ARM && reload_completed"
2140 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2141 (set (match_dup 3) (and:SI (not:SI
2142 (ashiftrt:SI (match_dup 2) (const_int 31)))
2146 operands[3] = gen_highpart (SImode, operands[0]);
2147 operands[0] = gen_lowpart (SImode, operands[0]);
2148 operands[4] = gen_highpart (SImode, operands[1]);
2149 operands[1] = gen_lowpart (SImode, operands[1]);
2151 [(set_attr "length" "8")
2152 (set_attr "predicable" "yes")]
2155 (define_insn "andsi_notsi_si"
2156 [(set (match_operand:SI 0 "s_register_operand" "=r")
2157 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2158 (match_operand:SI 1 "s_register_operand" "r")))]
2160 "bic%?\\t%0, %1, %2"
2161 [(set_attr "predicable" "yes")]
2164 (define_insn "bicsi3"
2165 [(set (match_operand:SI 0 "register_operand" "=l")
2166 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2167 (match_operand:SI 2 "register_operand" "0")))]
2170 [(set_attr "length" "2")]
2173 (define_insn "andsi_not_shiftsi_si"
2174 [(set (match_operand:SI 0 "s_register_operand" "=r")
2175 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2176 [(match_operand:SI 2 "s_register_operand" "r")
2177 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2178 (match_operand:SI 1 "s_register_operand" "r")))]
2180 "bic%?\\t%0, %1, %2%S4"
2181 [(set_attr "predicable" "yes")
2182 (set_attr "shift" "2")
2186 (define_insn "*andsi_notsi_si_compare0"
2187 [(set (reg:CC_NOOV CC_REGNUM)
2189 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2190 (match_operand:SI 1 "s_register_operand" "r"))
2192 (set (match_operand:SI 0 "s_register_operand" "=r")
2193 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2195 "bic%?s\\t%0, %1, %2"
2196 [(set_attr "conds" "set")]
2199 (define_insn "*andsi_notsi_si_compare0_scratch"
2200 [(set (reg:CC_NOOV CC_REGNUM)
2202 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2203 (match_operand:SI 1 "s_register_operand" "r"))
2205 (clobber (match_scratch:SI 0 "=r"))]
2207 "bic%?s\\t%0, %1, %2"
2208 [(set_attr "conds" "set")]
2211 (define_insn "iordi3"
2212 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2213 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2214 (match_operand:DI 2 "s_register_operand" "r,r")))]
2217 [(set_attr "length" "8")
2218 (set_attr "predicable" "yes")]
2221 (define_insn "*iordi_zesidi_di"
2222 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2223 (ior:DI (zero_extend:DI
2224 (match_operand:SI 2 "s_register_operand" "r,r"))
2225 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2228 orr%?\\t%Q0, %Q1, %2
2230 [(set_attr "length" "4,8")
2231 (set_attr "predicable" "yes")]
2234 (define_insn "*iordi_sesidi_di"
2235 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2236 (ior:DI (sign_extend:DI
2237 (match_operand:SI 2 "s_register_operand" "r,r"))
2238 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2241 [(set_attr "length" "8")
2242 (set_attr "predicable" "yes")]
2245 (define_expand "iorsi3"
2246 [(set (match_operand:SI 0 "s_register_operand" "")
2247 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2248 (match_operand:SI 2 "reg_or_int_operand" "")))]
2251 if (GET_CODE (operands[2]) == CONST_INT)
2255 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2258 ? 0 : preserve_subexpressions_p ()));
2261 else /* TARGET_THUMB */
2262 operands [2] = force_reg (SImode, operands [2]);
2267 (define_insn_and_split "*arm_iorsi3"
2268 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2269 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2270 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2276 && GET_CODE (operands[2]) == CONST_INT
2277 && !const_ok_for_arm (INTVAL (operands[2]))"
2278 [(clobber (const_int 0))]
2280 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2284 [(set_attr "length" "4,16")
2285 (set_attr "predicable" "yes")]
2288 (define_insn "*thumb_iorsi3"
2289 [(set (match_operand:SI 0 "register_operand" "=l")
2290 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2291 (match_operand:SI 2 "register_operand" "l")))]
2294 [(set_attr "length" "2")]
2298 [(match_scratch:SI 3 "r")
2299 (set (match_operand:SI 0 "s_register_operand" "")
2300 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2301 (match_operand:SI 2 "const_int_operand" "")))]
2303 && !const_ok_for_arm (INTVAL (operands[2]))
2304 && const_ok_for_arm (~INTVAL (operands[2]))"
2305 [(set (match_dup 3) (match_dup 2))
2306 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2310 (define_insn "*iorsi3_compare0"
2311 [(set (reg:CC_NOOV CC_REGNUM)
2312 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2313 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2315 (set (match_operand:SI 0 "s_register_operand" "=r")
2316 (ior:SI (match_dup 1) (match_dup 2)))]
2318 "orr%?s\\t%0, %1, %2"
2319 [(set_attr "conds" "set")]
2322 (define_insn "*iorsi3_compare0_scratch"
2323 [(set (reg:CC_NOOV CC_REGNUM)
2324 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2325 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2327 (clobber (match_scratch:SI 0 "=r"))]
2329 "orr%?s\\t%0, %1, %2"
2330 [(set_attr "conds" "set")]
2333 (define_insn "xordi3"
2334 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2335 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2336 (match_operand:DI 2 "s_register_operand" "r,r")))]
2339 [(set_attr "length" "8")
2340 (set_attr "predicable" "yes")]
2343 (define_insn "*xordi_zesidi_di"
2344 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2345 (xor:DI (zero_extend:DI
2346 (match_operand:SI 2 "s_register_operand" "r,r"))
2347 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2350 eor%?\\t%Q0, %Q1, %2
2352 [(set_attr "length" "4,8")
2353 (set_attr "predicable" "yes")]
2356 (define_insn "*xordi_sesidi_di"
2357 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2358 (xor:DI (sign_extend:DI
2359 (match_operand:SI 2 "s_register_operand" "r,r"))
2360 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2363 [(set_attr "length" "8")
2364 (set_attr "predicable" "yes")]
2367 (define_expand "xorsi3"
2368 [(set (match_operand:SI 0 "s_register_operand" "")
2369 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2370 (match_operand:SI 2 "arm_rhs_operand" "")))]
2373 if (GET_CODE (operands[2]) == CONST_INT)
2374 operands[2] = force_reg (SImode, operands[2]);
2378 (define_insn "*arm_xorsi3"
2379 [(set (match_operand:SI 0 "s_register_operand" "=r")
2380 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2381 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2383 "eor%?\\t%0, %1, %2"
2384 [(set_attr "predicable" "yes")]
2387 (define_insn "*thumb_xorsi3"
2388 [(set (match_operand:SI 0 "register_operand" "=l")
2389 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2390 (match_operand:SI 2 "register_operand" "l")))]
2393 [(set_attr "length" "2")]
2396 (define_insn "*xorsi3_compare0"
2397 [(set (reg:CC_NOOV CC_REGNUM)
2398 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2399 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2401 (set (match_operand:SI 0 "s_register_operand" "=r")
2402 (xor:SI (match_dup 1) (match_dup 2)))]
2404 "eor%?s\\t%0, %1, %2"
2405 [(set_attr "conds" "set")]
2408 (define_insn "*xorsi3_compare0_scratch"
2409 [(set (reg:CC_NOOV CC_REGNUM)
2410 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2411 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2415 [(set_attr "conds" "set")]
2418 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2419 ; (NOT D) we can sometimes merge the final NOT into one of the following
2423 [(set (match_operand:SI 0 "s_register_operand" "")
2424 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2425 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2426 (match_operand:SI 3 "arm_rhs_operand" "")))
2427 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2429 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2430 (not:SI (match_dup 3))))
2431 (set (match_dup 0) (not:SI (match_dup 4)))]
2435 (define_insn "*andsi_iorsi3_notsi"
2436 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2437 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2438 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2439 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2441 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2442 [(set_attr "length" "8")
2443 (set_attr "predicable" "yes")]
2448 ;; Minimum and maximum insns
2450 (define_insn "smaxsi3"
2451 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2452 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2453 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2454 (clobber (reg:CC CC_REGNUM))]
2457 cmp\\t%1, %2\;movlt\\t%0, %2
2458 cmp\\t%1, %2\;movge\\t%0, %1
2459 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2460 [(set_attr "conds" "clob")
2461 (set_attr "length" "8,8,12")]
2464 (define_insn "sminsi3"
2465 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2466 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2467 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2468 (clobber (reg:CC CC_REGNUM))]
2471 cmp\\t%1, %2\;movge\\t%0, %2
2472 cmp\\t%1, %2\;movlt\\t%0, %1
2473 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2474 [(set_attr "conds" "clob")
2475 (set_attr "length" "8,8,12")]
2478 (define_insn "umaxsi3"
2479 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2480 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2481 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2482 (clobber (reg:CC CC_REGNUM))]
2485 cmp\\t%1, %2\;movcc\\t%0, %2
2486 cmp\\t%1, %2\;movcs\\t%0, %1
2487 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2488 [(set_attr "conds" "clob")
2489 (set_attr "length" "8,8,12")]
2492 (define_insn "uminsi3"
2493 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2494 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2495 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2496 (clobber (reg:CC CC_REGNUM))]
2499 cmp\\t%1, %2\;movcs\\t%0, %2
2500 cmp\\t%1, %2\;movcc\\t%0, %1
2501 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2502 [(set_attr "conds" "clob")
2503 (set_attr "length" "8,8,12")]
2506 (define_insn "*store_minmaxsi"
2507 [(set (match_operand:SI 0 "memory_operand" "=m")
2508 (match_operator:SI 3 "minmax_operator"
2509 [(match_operand:SI 1 "s_register_operand" "r")
2510 (match_operand:SI 2 "s_register_operand" "r")]))
2511 (clobber (reg:CC CC_REGNUM))]
2514 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2516 output_asm_insn (\"cmp\\t%1, %2\", operands);
2517 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2518 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2521 [(set_attr "conds" "clob")
2522 (set_attr "length" "12")
2523 (set_attr "type" "store1")]
2526 ; Reject the frame pointer in operand[1], since reloading this after
2527 ; it has been eliminated can cause carnage.
2528 (define_insn "*minmax_arithsi"
2529 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2530 (match_operator:SI 4 "shiftable_operator"
2531 [(match_operator:SI 5 "minmax_operator"
2532 [(match_operand:SI 2 "s_register_operand" "r,r")
2533 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2534 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2535 (clobber (reg:CC CC_REGNUM))]
2537 && (GET_CODE (operands[1]) != REG
2538 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2539 && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2542 enum rtx_code code = GET_CODE (operands[4]);
2544 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2546 output_asm_insn (\"cmp\\t%2, %3\", operands);
2547 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2548 if (which_alternative != 0 || operands[3] != const0_rtx
2549 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2550 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2553 [(set_attr "conds" "clob")
2554 (set_attr "length" "12")]
2558 ;; Shift and rotation insns
2560 (define_expand "ashlsi3"
2561 [(set (match_operand:SI 0 "s_register_operand" "")
2562 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2563 (match_operand:SI 2 "arm_rhs_operand" "")))]
2566 if (GET_CODE (operands[2]) == CONST_INT
2567 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2569 emit_insn (gen_movsi (operands[0], const0_rtx));
2575 (define_insn "*thumb_ashlsi3"
2576 [(set (match_operand:SI 0 "register_operand" "=l,l")
2577 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2578 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2581 [(set_attr "length" "2")]
2584 (define_expand "ashrsi3"
2585 [(set (match_operand:SI 0 "s_register_operand" "")
2586 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2587 (match_operand:SI 2 "arm_rhs_operand" "")))]
2590 if (GET_CODE (operands[2]) == CONST_INT
2591 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2592 operands[2] = GEN_INT (31);
2596 (define_insn "*thumb_ashrsi3"
2597 [(set (match_operand:SI 0 "register_operand" "=l,l")
2598 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2599 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2602 [(set_attr "length" "2")]
2605 (define_expand "lshrsi3"
2606 [(set (match_operand:SI 0 "s_register_operand" "")
2607 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2608 (match_operand:SI 2 "arm_rhs_operand" "")))]
2611 if (GET_CODE (operands[2]) == CONST_INT
2612 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2614 emit_insn (gen_movsi (operands[0], const0_rtx));
2620 (define_insn "*thumb_lshrsi3"
2621 [(set (match_operand:SI 0 "register_operand" "=l,l")
2622 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2623 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2626 [(set_attr "length" "2")]
2629 (define_expand "rotlsi3"
2630 [(set (match_operand:SI 0 "s_register_operand" "")
2631 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2632 (match_operand:SI 2 "reg_or_int_operand" "")))]
2635 if (GET_CODE (operands[2]) == CONST_INT)
2636 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2639 rtx reg = gen_reg_rtx (SImode);
2640 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2646 (define_expand "rotrsi3"
2647 [(set (match_operand:SI 0 "s_register_operand" "")
2648 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2649 (match_operand:SI 2 "arm_rhs_operand" "")))]
2654 if (GET_CODE (operands[2]) == CONST_INT
2655 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2656 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2658 else /* TARGET_THUMB */
2660 if (GET_CODE (operands [2]) == CONST_INT)
2661 operands [2] = force_reg (SImode, operands[2]);
2666 (define_insn "*thumb_rotrsi3"
2667 [(set (match_operand:SI 0 "register_operand" "=l")
2668 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2669 (match_operand:SI 2 "register_operand" "l")))]
2672 [(set_attr "length" "2")]
2675 (define_expand "ashldi3"
2676 [(set (match_operand:DI 0 "s_register_operand" "")
2677 (ashift:DI (match_operand:DI 1 "general_operand" "")
2678 (match_operand:SI 2 "general_operand" "")))]
2679 "TARGET_ARM && (TARGET_CIRRUS)"
2681 if (! s_register_operand (operands[1], DImode))
2682 operands[1] = copy_to_mode_reg (DImode, operands[1]);
2683 if (! s_register_operand (operands[2], SImode))
2684 operands[2] = copy_to_mode_reg (SImode, operands[2]);
2688 (define_insn "*arm_shiftsi3"
2689 [(set (match_operand:SI 0 "s_register_operand" "=r")
2690 (match_operator:SI 3 "shift_operator"
2691 [(match_operand:SI 1 "s_register_operand" "r")
2692 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2695 [(set_attr "predicable" "yes")
2696 (set_attr "shift" "1")
2700 (define_insn "*shiftsi3_compare0"
2701 [(set (reg:CC_NOOV CC_REGNUM)
2702 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2703 [(match_operand:SI 1 "s_register_operand" "r")
2704 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2706 (set (match_operand:SI 0 "s_register_operand" "=r")
2707 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2709 "mov%?s\\t%0, %1%S3"
2710 [(set_attr "conds" "set")
2711 (set_attr "shift" "1")
2715 (define_insn "*shiftsi3_compare0_scratch"
2716 [(set (reg:CC_NOOV CC_REGNUM)
2717 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2718 [(match_operand:SI 1 "s_register_operand" "r")
2719 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2721 (clobber (match_scratch:SI 0 "=r"))]
2723 "mov%?s\\t%0, %1%S3"
2724 [(set_attr "conds" "set")
2725 (set_attr "shift" "1")
2729 (define_insn "*notsi_shiftsi"
2730 [(set (match_operand:SI 0 "s_register_operand" "=r")
2731 (not:SI (match_operator:SI 3 "shift_operator"
2732 [(match_operand:SI 1 "s_register_operand" "r")
2733 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2736 [(set_attr "predicable" "yes")
2737 (set_attr "shift" "1")
2741 (define_insn "*notsi_shiftsi_compare0"
2742 [(set (reg:CC_NOOV CC_REGNUM)
2743 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2744 [(match_operand:SI 1 "s_register_operand" "r")
2745 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2747 (set (match_operand:SI 0 "s_register_operand" "=r")
2748 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2750 "mvn%?s\\t%0, %1%S3"
2751 [(set_attr "conds" "set")
2752 (set_attr "shift" "1")
2756 (define_insn "*not_shiftsi_compare0_scratch"
2757 [(set (reg:CC_NOOV CC_REGNUM)
2758 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2759 [(match_operand:SI 1 "s_register_operand" "r")
2760 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2762 (clobber (match_scratch:SI 0 "=r"))]
2764 "mvn%?s\\t%0, %1%S3"
2765 [(set_attr "conds" "set")
2766 (set_attr "shift" "1")
2770 ;; We don't really have extzv, but defining this using shifts helps
2771 ;; to reduce register pressure later on.
2773 (define_expand "extzv"
2775 (ashift:SI (match_operand:SI 1 "register_operand" "")
2776 (match_operand:SI 2 "const_int_operand" "")))
2777 (set (match_operand:SI 0 "register_operand" "")
2778 (lshiftrt:SI (match_dup 4)
2779 (match_operand:SI 3 "const_int_operand" "")))]
2783 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2784 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2786 operands[3] = GEN_INT (rshift);
2790 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2794 operands[2] = GEN_INT (lshift);
2795 operands[4] = gen_reg_rtx (SImode);
2800 ;; Unary arithmetic insns
2802 (define_expand "negdi2"
2804 [(set (match_operand:DI 0 "s_register_operand" "")
2805 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2806 (clobber (reg:CC CC_REGNUM))])]
2811 if (GET_CODE (operands[1]) != REG)
2812 operands[1] = force_reg (SImode, operands[1]);
2817 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2818 ;; The second alternative is to allow the common case of a *full* overlap.
2819 (define_insn "*arm_negdi2"
2820 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2821 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2822 (clobber (reg:CC CC_REGNUM))]
2824 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2825 [(set_attr "conds" "clob")
2826 (set_attr "length" "8")]
2829 (define_insn "*thumb_negdi2"
2830 [(set (match_operand:DI 0 "register_operand" "=&l")
2831 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2832 (clobber (reg:CC CC_REGNUM))]
2834 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2835 [(set_attr "length" "6")]
2838 (define_expand "negsi2"
2839 [(set (match_operand:SI 0 "s_register_operand" "")
2840 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2845 (define_insn "*arm_negsi2"
2846 [(set (match_operand:SI 0 "s_register_operand" "=r")
2847 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2849 "rsb%?\\t%0, %1, #0"
2850 [(set_attr "predicable" "yes")]
2853 (define_insn "*thumb_negsi2"
2854 [(set (match_operand:SI 0 "register_operand" "=l")
2855 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2858 [(set_attr "length" "2")]
2861 (define_expand "negsf2"
2862 [(set (match_operand:SF 0 "s_register_operand" "")
2863 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2864 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2868 (define_expand "negdf2"
2869 [(set (match_operand:DF 0 "s_register_operand" "")
2870 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2871 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2874 (define_insn "*arm_negsf2"
2875 [(set (match_operand:SF 0 "s_register_operand" "=f")
2876 (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
2877 "TARGET_ARM && TARGET_HARD_FLOAT"
2879 [(set_attr "type" "ffarith")
2880 (set_attr "predicable" "yes")]
2883 (define_insn "*arm_negdf2"
2884 [(set (match_operand:DF 0 "s_register_operand" "=f")
2885 (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
2886 "TARGET_ARM && TARGET_HARD_FLOAT"
2888 [(set_attr "type" "ffarith")
2889 (set_attr "predicable" "yes")]
2892 (define_insn "*negdf_esfdf"
2893 [(set (match_operand:DF 0 "s_register_operand" "=f")
2894 (neg:DF (float_extend:DF
2895 (match_operand:SF 1 "s_register_operand" "f"))))]
2896 "TARGET_ARM && TARGET_HARD_FLOAT"
2898 [(set_attr "type" "ffarith")
2899 (set_attr "predicable" "yes")]
2902 ;; abssi2 doesn't really clobber the condition codes if a different register
2903 ;; is being set. To keep things simple, assume during rtl manipulations that
2904 ;; it does, but tell the final scan operator the truth. Similarly for
2907 (define_expand "abssi2"
2909 [(set (match_operand:SI 0 "s_register_operand" "")
2910 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2911 (clobber (reg:CC CC_REGNUM))])]
2915 (define_insn "*arm_abssi2"
2916 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2917 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2918 (clobber (reg:CC CC_REGNUM))]
2921 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2922 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2923 [(set_attr "conds" "clob,*")
2924 (set_attr "shift" "1")
2925 ;; predicable can't be set based on the variant, so left as no
2926 (set_attr "length" "8")]
2929 (define_insn "*neg_abssi2"
2930 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2931 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2932 (clobber (reg:CC CC_REGNUM))]
2935 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2936 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2937 [(set_attr "conds" "clob,*")
2938 (set_attr "shift" "1")
2939 ;; predicable can't be set based on the variant, so left as no
2940 (set_attr "length" "8")]
2943 (define_expand "abssf2"
2944 [(set (match_operand:SF 0 "s_register_operand" "")
2945 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
2946 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2949 (define_insn "*arm_abssf2"
2950 [(set (match_operand:SF 0 "s_register_operand" "=f")
2951 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
2952 "TARGET_ARM && TARGET_HARD_FLOAT"
2954 [(set_attr "type" "ffarith")
2955 (set_attr "predicable" "yes")]
2958 (define_expand "absdf2"
2959 [(set (match_operand:DF 0 "s_register_operand" "")
2960 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
2961 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2964 (define_insn "*arm_absdf2"
2965 [(set (match_operand:DF 0 "s_register_operand" "=f")
2966 (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
2967 "TARGET_ARM && TARGET_HARD_FLOAT"
2969 [(set_attr "type" "ffarith")
2970 (set_attr "predicable" "yes")]
2973 (define_insn "*absdf_esfdf"
2974 [(set (match_operand:DF 0 "s_register_operand" "=f")
2975 (abs:DF (float_extend:DF
2976 (match_operand:SF 1 "s_register_operand" "f"))))]
2977 "TARGET_ARM && TARGET_HARD_FLOAT"
2979 [(set_attr "type" "ffarith")
2980 (set_attr "predicable" "yes")]
2983 (define_insn "sqrtsf2"
2984 [(set (match_operand:SF 0 "s_register_operand" "=f")
2985 (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
2986 "TARGET_ARM && TARGET_HARD_FLOAT"
2988 [(set_attr "type" "float_em")
2989 (set_attr "predicable" "yes")]
2992 (define_insn "sqrtdf2"
2993 [(set (match_operand:DF 0 "s_register_operand" "=f")
2994 (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
2995 "TARGET_ARM && TARGET_HARD_FLOAT"
2997 [(set_attr "type" "float_em")
2998 (set_attr "predicable" "yes")]
3001 (define_insn "*sqrtdf_esfdf"
3002 [(set (match_operand:DF 0 "s_register_operand" "=f")
3003 (sqrt:DF (float_extend:DF
3004 (match_operand:SF 1 "s_register_operand" "f"))))]
3005 "TARGET_ARM && TARGET_HARD_FLOAT"
3007 [(set_attr "type" "float_em")
3008 (set_attr "predicable" "yes")]
3011 (define_insn_and_split "one_cmpldi2"
3012 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3013 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3016 "TARGET_ARM && reload_completed"
3017 [(set (match_dup 0) (not:SI (match_dup 1)))
3018 (set (match_dup 2) (not:SI (match_dup 3)))]
3021 operands[2] = gen_highpart (SImode, operands[0]);
3022 operands[0] = gen_lowpart (SImode, operands[0]);
3023 operands[3] = gen_highpart (SImode, operands[1]);
3024 operands[1] = gen_lowpart (SImode, operands[1]);
3026 [(set_attr "length" "8")
3027 (set_attr "predicable" "yes")]
3030 (define_expand "one_cmplsi2"
3031 [(set (match_operand:SI 0 "s_register_operand" "")
3032 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3037 (define_insn "*arm_one_cmplsi2"
3038 [(set (match_operand:SI 0 "s_register_operand" "=r")
3039 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
3042 [(set_attr "predicable" "yes")]
3045 (define_insn "*thumb_one_cmplsi2"
3046 [(set (match_operand:SI 0 "register_operand" "=l")
3047 (not:SI (match_operand:SI 1 "register_operand" "l")))]
3050 [(set_attr "length" "2")]
3053 (define_insn "*notsi_compare0"
3054 [(set (reg:CC_NOOV CC_REGNUM)
3055 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3057 (set (match_operand:SI 0 "s_register_operand" "=r")
3058 (not:SI (match_dup 1)))]
3061 [(set_attr "conds" "set")]
3064 (define_insn "*notsi_compare0_scratch"
3065 [(set (reg:CC_NOOV CC_REGNUM)
3066 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3068 (clobber (match_scratch:SI 0 "=r"))]
3071 [(set_attr "conds" "set")]
3074 ;; Fixed <--> Floating conversion insns
3076 (define_expand "floatsisf2"
3077 [(set (match_operand:SF 0 "s_register_operand" "")
3078 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3079 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3083 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3088 (define_insn "*arm_floatsisf2"
3089 [(set (match_operand:SF 0 "s_register_operand" "=f")
3090 (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
3091 "TARGET_ARM && TARGET_HARD_FLOAT"
3093 [(set_attr "type" "r_2_f")
3094 (set_attr "predicable" "yes")]
3097 (define_expand "floatsidf2"
3098 [(set (match_operand:DF 0 "s_register_operand" "")
3099 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3100 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3104 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3109 (define_insn "*arm_floatsidf2"
3110 [(set (match_operand:DF 0 "s_register_operand" "=f")
3111 (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
3112 "TARGET_ARM && TARGET_HARD_FLOAT"
3114 [(set_attr "type" "r_2_f")
3115 (set_attr "predicable" "yes")]
3118 (define_expand "fix_truncsfsi2"
3119 [(set (match_operand:SI 0 "s_register_operand" "")
3120 (fix:SI (match_operand:SF 1 "s_register_operand" "")))]
3121 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3125 if (!cirrus_fp_register (operands[0], SImode))
3126 operands[0] = force_reg (SImode, operands[0]);
3127 if (!cirrus_fp_register (operands[1], SFmode))
3128 operands[1] = force_reg (SFmode, operands[0]);
3129 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3134 (define_insn "*arm_fix_truncsfsi2"
3135 [(set (match_operand:SI 0 "s_register_operand" "=r")
3136 (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
3137 "TARGET_ARM && TARGET_HARD_FLOAT"
3139 [(set_attr "type" "f_2_r")
3140 (set_attr "predicable" "yes")]
3143 (define_expand "fix_truncdfsi2"
3144 [(set (match_operand:SI 0 "s_register_operand" "")
3145 (fix:SI (match_operand:DF 1 "s_register_operand" "")))]
3146 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3150 if (!cirrus_fp_register (operands[1], DFmode))
3151 operands[1] = force_reg (DFmode, operands[0]);
3152 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3157 (define_insn "*arm_fix_truncdfsi2"
3158 [(set (match_operand:SI 0 "s_register_operand" "=r")
3159 (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
3160 "TARGET_ARM && TARGET_HARD_FLOAT"
3162 [(set_attr "type" "f_2_r")
3163 (set_attr "predicable" "yes")]
3168 (define_expand "truncdfsf2"
3169 [(set (match_operand:SF 0 "s_register_operand" "")
3171 (match_operand:DF 1 "s_register_operand" "")))]
3172 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3176 (define_insn "*arm_truncdfsf2"
3177 [(set (match_operand:SF 0 "s_register_operand" "=f")
3179 (match_operand:DF 1 "s_register_operand" "f")))]
3180 "TARGET_ARM && TARGET_HARD_FLOAT"
3182 [(set_attr "type" "ffarith")
3183 (set_attr "predicable" "yes")]
3186 ;; Zero and sign extension instructions.
3188 (define_insn "zero_extendsidi2"
3189 [(set (match_operand:DI 0 "s_register_operand" "=r")
3190 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3193 if (REGNO (operands[1])
3194 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3195 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3196 return \"mov%?\\t%R0, #0\";
3198 [(set_attr "length" "8")
3199 (set_attr "predicable" "yes")]
3202 (define_insn "zero_extendqidi2"
3203 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
3204 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3207 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3208 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3209 [(set_attr "length" "8")
3210 (set_attr "predicable" "yes")
3211 (set_attr "type" "*,load")
3212 (set_attr "pool_range" "*,4092")
3213 (set_attr "neg_pool_range" "*,4084")]
3216 (define_insn "extendsidi2"
3217 [(set (match_operand:DI 0 "s_register_operand" "=r")
3218 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3221 if (REGNO (operands[1])
3222 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3223 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3224 return \"mov%?\\t%R0, %Q0, asr #31\";
3226 [(set_attr "length" "8")
3227 (set_attr "shift" "1")
3228 (set_attr "predicable" "yes")]
3231 (define_expand "zero_extendhisi2"
3233 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3235 (set (match_operand:SI 0 "s_register_operand" "")
3236 (lshiftrt:SI (match_dup 2) (const_int 16)))]
3242 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3244 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3245 here because the insn below will generate an LDRH instruction
3246 rather than an LDR instruction, so we cannot get an unaligned
3248 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3249 gen_rtx_ZERO_EXTEND (SImode,
3253 if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3255 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3258 if (!s_register_operand (operands[1], HImode))
3259 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3260 operands[1] = gen_lowpart (SImode, operands[1]);
3261 operands[2] = gen_reg_rtx (SImode);
3263 else /* TARGET_THUMB */
3265 if (GET_CODE (operands[1]) == MEM)
3269 tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3270 tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3277 if (!s_register_operand (operands[1], HImode))
3278 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3279 operands[1] = gen_lowpart (SImode, operands[1]);
3280 operands[2] = gen_reg_rtx (SImode);
3282 ops[0] = operands[2];
3283 ops[1] = operands[1];
3284 ops[2] = GEN_INT (16);
3286 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3287 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3289 ops[0] = operands[0];
3290 ops[1] = operands[2];
3291 ops[2] = GEN_INT (16);
3293 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3294 gen_rtx_LSHIFTRT (SImode, ops[1],
3302 (define_insn "*thumb_zero_extendhisi2"
3303 [(set (match_operand:SI 0 "register_operand" "=l")
3304 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3307 rtx mem = XEXP (operands[1], 0);
3309 if (GET_CODE (mem) == CONST)
3310 mem = XEXP (mem, 0);
3312 if (GET_CODE (mem) == LABEL_REF)
3313 return \"ldr\\t%0, %1\";
3315 if (GET_CODE (mem) == PLUS)
3317 rtx a = XEXP (mem, 0);
3318 rtx b = XEXP (mem, 1);
3320 /* This can happen due to bugs in reload. */
3321 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3324 ops[0] = operands[0];
3327 output_asm_insn (\"mov %0, %1\", ops);
3329 XEXP (mem, 0) = operands[0];
3332 else if ( GET_CODE (a) == LABEL_REF
3333 && GET_CODE (b) == CONST_INT)
3334 return \"ldr\\t%0, %1\";
3337 return \"ldrh\\t%0, %1\";
3339 [(set_attr "length" "4")
3340 (set_attr "type" "load")
3341 (set_attr "pool_range" "60")]
3344 (define_insn "*arm_zero_extendhisi2"
3345 [(set (match_operand:SI 0 "s_register_operand" "=r")
3346 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3347 "TARGET_ARM && arm_arch4"
3349 [(set_attr "type" "load")
3350 (set_attr "predicable" "yes")
3351 (set_attr "pool_range" "256")
3352 (set_attr "neg_pool_range" "244")]
3356 [(set (match_operand:SI 0 "s_register_operand" "")
3357 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3358 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3359 "TARGET_ARM && (!arm_arch4)"
3360 [(set (match_dup 2) (match_dup 1))
3361 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3363 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3369 [(set (match_operand:SI 0 "s_register_operand" "")
3370 (match_operator:SI 3 "shiftable_operator"
3371 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3372 (match_operand:SI 4 "s_register_operand" "")]))
3373 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3374 "TARGET_ARM && (!arm_arch4)"
3375 [(set (match_dup 2) (match_dup 1))
3378 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3380 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3385 (define_expand "zero_extendqisi2"
3386 [(set (match_operand:SI 0 "s_register_operand" "")
3387 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3390 if (GET_CODE (operands[1]) != MEM)
3394 emit_insn (gen_andsi3 (operands[0],
3395 gen_lowpart (SImode, operands[1]),
3398 else /* TARGET_THUMB */
3400 rtx temp = gen_reg_rtx (SImode);
3403 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3404 operands[1] = gen_lowpart (SImode, operands[1]);
3407 ops[1] = operands[1];
3408 ops[2] = GEN_INT (24);
3410 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3411 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3413 ops[0] = operands[0];
3415 ops[2] = GEN_INT (24);
3417 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3418 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3425 (define_insn "*thumb_zero_extendqisi2"
3426 [(set (match_operand:SI 0 "register_operand" "=l")
3427 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3430 [(set_attr "length" "2")
3431 (set_attr "type" "load")
3432 (set_attr "pool_range" "32")]
3435 (define_insn "*arm_zero_extendqisi2"
3436 [(set (match_operand:SI 0 "s_register_operand" "=r")
3437 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3439 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3440 [(set_attr "type" "load")
3441 (set_attr "predicable" "yes")
3442 (set_attr "pool_range" "4096")
3443 (set_attr "neg_pool_range" "4084")]
3447 [(set (match_operand:SI 0 "s_register_operand" "")
3448 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3449 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3450 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3451 [(set (match_dup 2) (match_dup 1))
3452 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3456 (define_insn "*compareqi_eq0"
3457 [(set (reg:CC_Z CC_REGNUM)
3458 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3462 [(set_attr "conds" "set")]
3465 (define_expand "extendhisi2"
3467 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3469 (set (match_operand:SI 0 "s_register_operand" "")
3470 (ashiftrt:SI (match_dup 2)
3475 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3477 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3478 here because the insn below will generate an LDRH instruction
3479 rather than an LDR instruction, so we cannot get an unaligned
3481 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3482 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3486 if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3488 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3491 if (!s_register_operand (operands[1], HImode))
3492 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3493 operands[1] = gen_lowpart (SImode, operands[1]);
3494 operands[2] = gen_reg_rtx (SImode);
3500 ops[0] = operands[2];
3501 ops[1] = operands[1];
3502 ops[2] = GEN_INT (16);
3504 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3505 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3507 ops[0] = operands[0];
3508 ops[1] = operands[2];
3509 ops[2] = GEN_INT (16);
3511 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3512 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3519 (define_insn "*thumb_extendhisi2_insn"
3520 [(set (match_operand:SI 0 "register_operand" "=l")
3521 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3522 (clobber (match_scratch:SI 2 "=&l"))]
3527 rtx mem = XEXP (operands[1], 0);
3529 /* This code used to try to use 'V', and fix the address only if it was
3530 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3531 range of QImode offsets, and offsettable_address_p does a QImode
3534 if (GET_CODE (mem) == CONST)
3535 mem = XEXP (mem, 0);
3537 if (GET_CODE (mem) == LABEL_REF)
3538 return \"ldr\\t%0, %1\";
3540 if (GET_CODE (mem) == PLUS)
3542 rtx a = XEXP (mem, 0);
3543 rtx b = XEXP (mem, 1);
3545 if (GET_CODE (a) == LABEL_REF
3546 && GET_CODE (b) == CONST_INT)
3547 return \"ldr\\t%0, %1\";
3549 if (GET_CODE (b) == REG)
3550 return \"ldrsh\\t%0, %1\";
3558 ops[2] = const0_rtx;
3561 if (GET_CODE (ops[1]) != REG)
3567 ops[0] = operands[0];
3568 ops[3] = operands[2];
3569 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3572 [(set_attr "length" "4")
3573 (set_attr "type" "load")
3574 (set_attr "pool_range" "1020")]
3577 (define_expand "extendhisi2_mem"
3578 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3580 (zero_extend:SI (match_dup 7)))
3581 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3582 (set (match_operand:SI 0 "" "")
3583 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3588 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3590 mem1 = gen_rtx_MEM (QImode, addr);
3591 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3592 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3593 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3594 operands[0] = gen_lowpart (SImode, operands[0]);
3596 operands[2] = gen_reg_rtx (SImode);
3597 operands[3] = gen_reg_rtx (SImode);
3598 operands[6] = gen_reg_rtx (SImode);
3601 if (BYTES_BIG_ENDIAN)
3603 operands[4] = operands[2];
3604 operands[5] = operands[3];
3608 operands[4] = operands[3];
3609 operands[5] = operands[2];
3614 (define_insn "*arm_extendhisi_insn"
3615 [(set (match_operand:SI 0 "s_register_operand" "=r")
3616 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3617 "TARGET_ARM && arm_arch4"
3619 [(set_attr "type" "load")
3620 (set_attr "predicable" "yes")
3621 (set_attr "pool_range" "256")
3622 (set_attr "neg_pool_range" "244")]
3626 [(set (match_operand:SI 0 "s_register_operand" "")
3627 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3628 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3629 "TARGET_ARM && (!arm_arch4)"
3630 [(set (match_dup 2) (match_dup 1))
3631 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3633 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3639 [(set (match_operand:SI 0 "s_register_operand" "")
3640 (match_operator:SI 3 "shiftable_operator"
3641 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3642 (match_operand:SI 4 "s_register_operand" "")]))
3643 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3644 "TARGET_ARM && (!arm_arch4)"
3645 [(set (match_dup 2) (match_dup 1))
3648 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3649 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3654 (define_expand "extendqihi2"
3656 (ashift:SI (match_operand:QI 1 "general_operand" "")
3658 (set (match_operand:HI 0 "s_register_operand" "")
3659 (ashiftrt:SI (match_dup 2)
3664 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3666 emit_insn (gen_rtx_SET (VOIDmode,
3668 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3671 if (!s_register_operand (operands[1], QImode))
3672 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3673 operands[0] = gen_lowpart (SImode, operands[0]);
3674 operands[1] = gen_lowpart (SImode, operands[1]);
3675 operands[2] = gen_reg_rtx (SImode);
3679 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3680 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3681 (define_insn "*extendqihi_insn"
3682 [(set (match_operand:HI 0 "s_register_operand" "=r")
3683 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3684 "TARGET_ARM && arm_arch4"
3686 /* If the address is invalid, this will split the instruction into two. */
3687 if (bad_signed_byte_operand (operands[1], VOIDmode))
3689 return \"ldr%?sb\\t%0, %1\";
3691 [(set_attr "type" "load")
3692 (set_attr "predicable" "yes")
3693 (set_attr "length" "8")
3694 (set_attr "pool_range" "256")
3695 (set_attr "neg_pool_range" "244")]
3699 [(set (match_operand:HI 0 "s_register_operand" "")
3700 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3701 "TARGET_ARM && arm_arch4 && reload_completed"
3702 [(set (match_dup 3) (match_dup 1))
3703 (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3706 HOST_WIDE_INT offset;
3708 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3709 operands[2] = gen_rtx_MEM (QImode, operands[3]);
3710 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3711 operands[1] = XEXP (operands[1], 0);
3712 if (GET_CODE (operands[1]) == PLUS
3713 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3714 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3715 || const_ok_for_arm (-offset)))
3717 HOST_WIDE_INT low = (offset > 0
3718 ? (offset & 0xff) : -((-offset) & 0xff));
3719 XEXP (operands[2], 0) = plus_constant (operands[3], low);
3720 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3722 /* Ensure the sum is in correct canonical form */
3723 else if (GET_CODE (operands[1]) == PLUS
3724 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3725 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3726 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3727 XEXP (operands[1], 1),
3728 XEXP (operands[1], 0));
3732 (define_expand "extendqisi2"
3734 (ashift:SI (match_operand:QI 1 "general_operand" "")
3736 (set (match_operand:SI 0 "s_register_operand" "")
3737 (ashiftrt:SI (match_dup 2)
3742 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3744 emit_insn (gen_rtx_SET (VOIDmode,
3746 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3749 if (!s_register_operand (operands[1], QImode))
3750 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3751 operands[1] = gen_lowpart (SImode, operands[1]);
3752 operands[2] = gen_reg_rtx (SImode);
3758 ops[0] = operands[2];
3759 ops[1] = operands[1];
3760 ops[2] = GEN_INT (24);
3762 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3763 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3765 ops[0] = operands[0];
3766 ops[1] = operands[2];
3767 ops[2] = GEN_INT (24);
3769 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3770 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3777 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3778 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3779 (define_insn "*arm_extendqisi_insn"
3780 [(set (match_operand:SI 0 "s_register_operand" "=r")
3781 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3782 "TARGET_ARM && arm_arch4"
3784 /* If the address is invalid, this will split the instruction into two. */
3785 if (bad_signed_byte_operand (operands[1], VOIDmode))
3787 return \"ldr%?sb\\t%0, %1\";
3789 [(set_attr "type" "load")
3790 (set_attr "predicable" "yes")
3791 (set_attr "length" "8")
3792 (set_attr "pool_range" "256")
3793 (set_attr "neg_pool_range" "244")]
3797 [(set (match_operand:SI 0 "s_register_operand" "")
3798 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3799 "TARGET_ARM && arm_arch4 && reload_completed"
3800 [(set (match_dup 0) (match_dup 1))
3801 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3804 HOST_WIDE_INT offset;
3806 operands[2] = gen_rtx_MEM (QImode, operands[0]);
3807 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3808 operands[1] = XEXP (operands[1], 0);
3809 if (GET_CODE (operands[1]) == PLUS
3810 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3811 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3812 || const_ok_for_arm (-offset)))
3814 HOST_WIDE_INT low = (offset > 0
3815 ? (offset & 0xff) : -((-offset) & 0xff));
3816 XEXP (operands[2], 0) = plus_constant (operands[0], low);
3817 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3819 /* Ensure the sum is in correct canonical form */
3820 else if (GET_CODE (operands[1]) == PLUS
3821 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3822 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3823 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3824 XEXP (operands[1], 1),
3825 XEXP (operands[1], 0));
3829 (define_insn "*thumb_extendqisi2_insn"
3830 [(set (match_operand:SI 0 "register_operand" "=l,l")
3831 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3836 rtx mem = XEXP (operands[1], 0);
3838 if (GET_CODE (mem) == CONST)
3839 mem = XEXP (mem, 0);
3841 if (GET_CODE (mem) == LABEL_REF)
3842 return \"ldr\\t%0, %1\";
3844 if (GET_CODE (mem) == PLUS
3845 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3846 return \"ldr\\t%0, %1\";
3848 if (which_alternative == 0)
3849 return \"ldrsb\\t%0, %1\";
3851 ops[0] = operands[0];
3853 if (GET_CODE (mem) == PLUS)
3855 rtx a = XEXP (mem, 0);
3856 rtx b = XEXP (mem, 1);
3861 if (GET_CODE (a) == REG)
3863 if (GET_CODE (b) == REG)
3864 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3865 else if (REGNO (a) == REGNO (ops[0]))
3867 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3868 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3869 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3872 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3874 else if (GET_CODE (b) != REG)
3878 if (REGNO (b) == REGNO (ops[0]))
3880 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3881 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3882 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3885 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3888 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3890 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3891 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3892 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3897 ops[2] = const0_rtx;
3899 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3903 [(set_attr "length" "2,6")
3904 (set_attr "type" "load,load")
3905 (set_attr "pool_range" "32,32")]
3908 (define_expand "extendsfdf2"
3909 [(set (match_operand:DF 0 "s_register_operand" "")
3910 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
3911 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3915 (define_insn "*arm_extendsfdf2"
3916 [(set (match_operand:DF 0 "s_register_operand" "=f")
3917 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
3918 "TARGET_ARM && TARGET_HARD_FLOAT"
3920 [(set_attr "type" "ffarith")
3921 (set_attr "predicable" "yes")]
3924 ;; Move insns (including loads and stores)
3926 ;; XXX Just some ideas about movti.
3927 ;; I don't think these are a good idea on the arm, there just aren't enough
3929 ;;(define_expand "loadti"
3930 ;; [(set (match_operand:TI 0 "s_register_operand" "")
3931 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
3934 ;;(define_expand "storeti"
3935 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3936 ;; (match_operand:TI 1 "s_register_operand" ""))]
3939 ;;(define_expand "movti"
3940 ;; [(set (match_operand:TI 0 "general_operand" "")
3941 ;; (match_operand:TI 1 "general_operand" ""))]
3947 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3948 ;; operands[1] = copy_to_reg (operands[1]);
3949 ;; if (GET_CODE (operands[0]) == MEM)
3950 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3951 ;; else if (GET_CODE (operands[1]) == MEM)
3952 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3956 ;; emit_insn (insn);
3960 ;; Recognize garbage generated above.
3963 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3964 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3968 ;; register mem = (which_alternative < 3);
3969 ;; register const char *template;
3971 ;; operands[mem] = XEXP (operands[mem], 0);
3972 ;; switch (which_alternative)
3974 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3975 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
3976 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
3977 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
3978 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
3979 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
3981 ;; output_asm_insn (template, operands);
3985 (define_expand "movdi"
3986 [(set (match_operand:DI 0 "general_operand" "")
3987 (match_operand:DI 1 "general_operand" ""))]
3992 if (!no_new_pseudos)
3994 if (GET_CODE (operands[0]) != REG)
3995 operands[1] = force_reg (DImode, operands[1]);
4001 (define_insn "*arm_movdi"
4002 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
4003 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
4004 "TARGET_ARM && !TARGET_CIRRUS"
4006 return (output_move_double (operands));
4008 [(set_attr "length" "8")
4009 (set_attr "type" "*,load,store2")
4010 (set_attr "pool_range" "*,1020,*")
4011 (set_attr "neg_pool_range" "*,1008,*")]
4014 ;;; ??? This should have alternatives for constants.
4015 ;;; ??? This was originally identical to the movdf_insn pattern.
4016 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4017 ;;; thumb_reorg with a memory reference.
4018 (define_insn "*thumb_movdi_insn"
4019 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4020 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
4023 && ( register_operand (operands[0], DImode)
4024 || register_operand (operands[1], DImode))"
4027 switch (which_alternative)
4031 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4032 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4033 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4035 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4037 operands[1] = GEN_INT (- INTVAL (operands[1]));
4038 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4040 return \"ldmia\\t%1, {%0, %H0}\";
4042 return \"stmia\\t%0, {%1, %H1}\";
4044 return thumb_load_double_from_address (operands);
4046 operands[2] = gen_rtx (MEM, SImode,
4047 plus_constant (XEXP (operands[0], 0), 4));
4048 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4051 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4052 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4053 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4056 [(set_attr "length" "4,4,6,2,2,6,4,4")
4057 (set_attr "type" "*,*,*,load,store2,load,store2,*")
4058 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4061 (define_expand "movsi"
4062 [(set (match_operand:SI 0 "general_operand" "")
4063 (match_operand:SI 1 "general_operand" ""))]
4068 /* Everything except mem = const or mem = mem can be done easily */
4069 if (GET_CODE (operands[0]) == MEM)
4070 operands[1] = force_reg (SImode, operands[1]);
4071 if (GET_CODE (operands[1]) == CONST_INT
4072 && !(const_ok_for_arm (INTVAL (operands[1]))
4073 || const_ok_for_arm (~INTVAL (operands[1]))))
4075 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4078 : preserve_subexpressions_p ()));
4082 else /* TARGET_THUMB.... */
4084 if (!no_new_pseudos)
4086 if (GET_CODE (operands[0]) != REG)
4087 operands[1] = force_reg (SImode, operands[1]);
4092 && (CONSTANT_P (operands[1])
4093 || symbol_mentioned_p (operands[1])
4094 || label_mentioned_p (operands[1])))
4095 operands[1] = legitimize_pic_address (operands[1], SImode,
4096 (no_new_pseudos ? operands[0] : 0));
4100 (define_insn "*arm_movsi_insn"
4101 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4102 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
4104 && ( register_operand (operands[0], SImode)
4105 || register_operand (operands[1], SImode))"
4111 [(set_attr "type" "*,*,load,store1")
4112 (set_attr "predicable" "yes")
4113 (set_attr "pool_range" "*,*,4096,*")
4114 (set_attr "neg_pool_range" "*,*,4084,*")]
4118 [(set (match_operand:SI 0 "s_register_operand" "")
4119 (match_operand:SI 1 "const_int_operand" ""))]
4121 && (!(const_ok_for_arm (INTVAL (operands[1]))
4122 || const_ok_for_arm (~INTVAL (operands[1]))))"
4123 [(clobber (const_int 0))]
4125 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4131 (define_insn "*thumb_movsi_insn"
4132 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4133 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
4135 && ( register_operand (operands[0], SImode)
4136 || register_operand (operands[1], SImode))"
4147 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4148 (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
4149 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4153 [(set (match_operand:SI 0 "register_operand" "")
4154 (match_operand:SI 1 "const_int_operand" ""))]
4155 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4156 [(set (match_dup 0) (match_dup 1))
4157 (set (match_dup 0) (neg:SI (match_dup 0)))]
4158 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4162 [(set (match_operand:SI 0 "register_operand" "")
4163 (match_operand:SI 1 "const_int_operand" ""))]
4164 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4165 [(set (match_dup 0) (match_dup 1))
4166 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4169 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4170 unsigned HOST_WIDE_INT mask = 0xff;
4173 for (i = 0; i < 25; i++)
4174 if ((val & (mask << i)) == val)
4177 /* Shouldn't happen, but we don't want to split if the shift is zero. */
4181 operands[1] = GEN_INT (val >> i);
4182 operands[2] = GEN_INT (i);
4186 ;; When generating pic, we need to load the symbol offset into a register.
4187 ;; So that the optimizer does not confuse this with a normal symbol load
4188 ;; we use an unspec. The offset will be loaded from a constant pool entry,
4189 ;; since that is the only type of relocation we can use.
4191 ;; The rather odd constraints on the following are to force reload to leave
4192 ;; the insn alone, and to force the minipool generation pass to then move
4193 ;; the GOT symbol to memory.
4195 (define_insn "pic_load_addr_arm"
4196 [(set (match_operand:SI 0 "s_register_operand" "=r")
4197 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4198 "TARGET_ARM && flag_pic"
4200 [(set_attr "type" "load")
4201 (set (attr "pool_range") (const_int 4096))
4202 (set (attr "neg_pool_range") (const_int 4084))]
4205 (define_insn "pic_load_addr_thumb"
4206 [(set (match_operand:SI 0 "s_register_operand" "=l")
4207 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4208 "TARGET_THUMB && flag_pic"
4210 [(set_attr "type" "load")
4211 (set (attr "pool_range") (const_int 1024))]
4214 ;; This variant is used for AOF assembly, since it needs to mention the
4215 ;; pic register in the rtl.
4216 (define_expand "pic_load_addr_based"
4217 [(set (match_operand:SI 0 "s_register_operand" "=r")
4218 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4219 "TARGET_ARM && flag_pic"
4220 "operands[2] = pic_offset_table_rtx;"
4223 (define_insn "*pic_load_addr_based_insn"
4224 [(set (match_operand:SI 0 "s_register_operand" "=r")
4225 (unspec:SI [(match_operand 1 "" "")
4226 (match_operand 2 "s_register_operand" "r")]
4228 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4230 #ifdef AOF_ASSEMBLER
4231 operands[1] = aof_pic_entry (operands[1]);
4233 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4236 [(set_attr "type" "load")
4237 (set (attr "pool_range")
4238 (if_then_else (eq_attr "is_thumb" "yes")
4241 (set (attr "neg_pool_range")
4242 (if_then_else (eq_attr "is_thumb" "yes")
4247 (define_insn "pic_add_dot_plus_four"
4248 [(set (match_operand:SI 0 "register_operand" "+r")
4249 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
4250 (use (label_ref (match_operand 1 "" "")))]
4251 "TARGET_THUMB && flag_pic"
4253 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4254 CODE_LABEL_NUMBER (operands[1]));
4255 return \"add\\t%0, %|pc\";
4257 [(set_attr "length" "2")]
4260 (define_insn "pic_add_dot_plus_eight"
4261 [(set (match_operand:SI 0 "register_operand" "+r")
4262 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
4263 (use (label_ref (match_operand 1 "" "")))]
4264 "TARGET_ARM && flag_pic"
4266 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4267 CODE_LABEL_NUMBER (operands[1]));
4268 return \"add%?\\t%0, %|pc, %0\";
4270 [(set_attr "predicable" "yes")]
4273 (define_expand "builtin_setjmp_receiver"
4274 [(label_ref (match_operand 0 "" ""))]
4278 arm_finalize_pic (0);
4282 ;; If copying one reg to another we can set the condition codes according to
4283 ;; its value. Such a move is common after a return from subroutine and the
4284 ;; result is being tested against zero.
4286 (define_insn "*movsi_compare0"
4287 [(set (reg:CC CC_REGNUM)
4288 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4290 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4295 sub%?s\\t%0, %1, #0"
4296 [(set_attr "conds" "set")]
4299 ;; Subroutine to store a half word from a register into memory.
4300 ;; Operand 0 is the source register (HImode)
4301 ;; Operand 1 is the destination address in a register (SImode)
4303 ;; In both this routine and the next, we must be careful not to spill
4304 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4305 ;; can generate unrecognizable rtl.
4307 (define_expand "storehi"
4308 [;; store the low byte
4309 (set (match_operand 1 "" "") (match_dup 3))
4310 ;; extract the high byte
4312 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4313 ;; store the high byte
4314 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
4318 rtx op1 = operands[1];
4319 rtx addr = XEXP (op1, 0);
4320 enum rtx_code code = GET_CODE (addr);
4322 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4324 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4326 operands[4] = adjust_address (op1, QImode, 1);
4327 operands[1] = adjust_address (operands[1], QImode, 0);
4328 operands[3] = gen_lowpart (QImode, operands[0]);
4329 operands[0] = gen_lowpart (SImode, operands[0]);
4330 operands[2] = gen_reg_rtx (SImode);
4334 (define_expand "storehi_bigend"
4335 [(set (match_dup 4) (match_dup 3))
4337 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4338 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 3))]
4342 rtx op1 = operands[1];
4343 rtx addr = XEXP (op1, 0);
4344 enum rtx_code code = GET_CODE (addr);
4346 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4348 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4350 operands[4] = adjust_address (op1, QImode, 1);
4351 operands[1] = adjust_address (operands[1], QImode, 0);
4352 operands[3] = gen_lowpart (QImode, operands[0]);
4353 operands[0] = gen_lowpart (SImode, operands[0]);
4354 operands[2] = gen_reg_rtx (SImode);
4358 ;; Subroutine to store a half word integer constant into memory.
4359 (define_expand "storeinthi"
4360 [(set (match_operand 0 "" "")
4361 (subreg:QI (match_operand 1 "" "") 0))
4362 (set (match_dup 3) (match_dup 2))]
4366 HOST_WIDE_INT value = INTVAL (operands[1]);
4367 rtx addr = XEXP (operands[0], 0);
4368 rtx op0 = operands[0];
4369 enum rtx_code code = GET_CODE (addr);
4371 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4373 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4375 operands[1] = gen_reg_rtx (SImode);
4376 if (BYTES_BIG_ENDIAN)
4378 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4379 if ((value & 255) == ((value >> 8) & 255))
4380 operands[2] = operands[1];
4383 operands[2] = gen_reg_rtx (SImode);
4384 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4389 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4390 if ((value & 255) == ((value >> 8) & 255))
4391 operands[2] = operands[1];
4394 operands[2] = gen_reg_rtx (SImode);
4395 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4399 operands[3] = adjust_address (op0, QImode, 1);
4400 operands[0] = adjust_address (operands[0], QImode, 0);
4401 operands[2] = gen_lowpart (QImode, operands[2]);
4405 (define_expand "storehi_single_op"
4406 [(set (match_operand:HI 0 "memory_operand" "")
4407 (match_operand:HI 1 "general_operand" ""))]
4408 "TARGET_ARM && arm_arch4"
4410 if (!s_register_operand (operands[1], HImode))
4411 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4415 (define_expand "movhi"
4416 [(set (match_operand:HI 0 "general_operand" "")
4417 (match_operand:HI 1 "general_operand" ""))]
4422 if (!no_new_pseudos)
4424 if (GET_CODE (operands[0]) == MEM)
4428 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4431 if (GET_CODE (operands[1]) == CONST_INT)
4432 emit_insn (gen_storeinthi (operands[0], operands[1]));
4435 if (GET_CODE (operands[1]) == MEM)
4436 operands[1] = force_reg (HImode, operands[1]);
4437 if (BYTES_BIG_ENDIAN)
4438 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4440 emit_insn (gen_storehi (operands[1], operands[0]));
4444 /* Sign extend a constant, and keep it in an SImode reg. */
4445 else if (GET_CODE (operands[1]) == CONST_INT)
4447 rtx reg = gen_reg_rtx (SImode);
4448 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4450 /* If the constant is already valid, leave it alone. */
4451 if (!const_ok_for_arm (val))
4453 /* If setting all the top bits will make the constant
4454 loadable in a single instruction, then set them.
4455 Otherwise, sign extend the number. */
4457 if (const_ok_for_arm (~(val | ~0xffff)))
4459 else if (val & 0x8000)
4463 emit_insn (gen_movsi (reg, GEN_INT (val)));
4464 operands[1] = gen_lowpart (HImode, reg);
4466 else if (arm_arch4 && !no_new_pseudos && optimize > 0
4467 && GET_CODE (operands[1]) == MEM)
4469 rtx reg = gen_reg_rtx (SImode);
4471 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4472 operands[1] = gen_lowpart (HImode, reg);
4474 else if (!arm_arch4)
4476 /* Note: We do not have to worry about TARGET_MMU_TRAPS
4477 for v4 and up architectures because LDRH instructions will
4478 be used to access the HI values, and these cannot generate
4479 unaligned word access faults in the MMU. */
4480 if (GET_CODE (operands[1]) == MEM)
4482 if (TARGET_MMU_TRAPS)
4485 rtx offset = const0_rtx;
4486 rtx reg = gen_reg_rtx (SImode);
4488 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4489 || (GET_CODE (base) == PLUS
4490 && (GET_CODE (offset = XEXP (base, 1))
4492 && ((INTVAL(offset) & 1) != 1)
4493 && GET_CODE (base = XEXP (base, 0)) == REG))
4494 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4496 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4499 new = gen_rtx_MEM (SImode,
4500 plus_constant (base, new_offset));
4501 MEM_COPY_ATTRIBUTES (new, operands[1]);
4502 emit_insn (gen_movsi (reg, new));
4503 if (((INTVAL (offset) & 2) != 0)
4504 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4506 rtx reg2 = gen_reg_rtx (SImode);
4508 emit_insn (gen_lshrsi3 (reg2, reg,
4514 emit_insn (gen_movhi_bytes (reg, operands[1]));
4516 operands[1] = gen_lowpart (HImode, reg);
4518 else if (BYTES_BIG_ENDIAN)
4521 rtx offset = const0_rtx;
4523 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4524 || (GET_CODE (base) == PLUS
4525 && (GET_CODE (offset = XEXP (base, 1))
4527 && GET_CODE (base = XEXP (base, 0)) == REG))
4528 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4530 rtx reg = gen_reg_rtx (SImode);
4533 if ((INTVAL (offset) & 2) == 2)
4535 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4536 new = gen_rtx_MEM (SImode,
4537 plus_constant (base,
4539 MEM_COPY_ATTRIBUTES (new, operands[1]);
4540 emit_insn (gen_movsi (reg, new));
4544 new = gen_rtx_MEM (SImode,
4545 XEXP (operands[1], 0));
4546 MEM_COPY_ATTRIBUTES (new, operands[1]);
4547 emit_insn (gen_rotated_loadsi (reg, new));
4550 operands[1] = gen_lowpart (HImode, reg);
4554 emit_insn (gen_movhi_bigend (operands[0],
4562 /* Handle loading a large integer during reload */
4563 else if (GET_CODE (operands[1]) == CONST_INT
4564 && !const_ok_for_arm (INTVAL (operands[1]))
4565 && !const_ok_for_arm (~INTVAL (operands[1])))
4567 /* Writing a constant to memory needs a scratch, which should
4568 be handled with SECONDARY_RELOADs. */
4569 if (GET_CODE (operands[0]) != REG)
4572 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4573 emit_insn (gen_movsi (operands[0], operands[1]));
4577 else /* TARGET_THUMB */
4579 if (!no_new_pseudos)
4581 if (GET_CODE (operands[0]) != REG)
4582 operands[1] = force_reg (HImode, operands[1]);
4584 /* ??? We shouldn't really get invalid addresses here, but this can
4585 happen if we are passed a SP (never OK for HImode/QImode) or
4586 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4587 HImode/QImode) relative address. */
4588 /* ??? This should perhaps be fixed elsewhere, for instance, in
4589 fixup_stack_1, by checking for other kinds of invalid addresses,
4590 e.g. a bare reference to a virtual register. This may confuse the
4591 alpha though, which must handle this case differently. */
4592 if (GET_CODE (operands[0]) == MEM
4593 && !memory_address_p (GET_MODE (operands[0]),
4594 XEXP (operands[0], 0)))
4596 = replace_equiv_address (operands[0],
4597 copy_to_reg (XEXP (operands[0], 0)));
4599 if (GET_CODE (operands[1]) == MEM
4600 && !memory_address_p (GET_MODE (operands[1]),
4601 XEXP (operands[1], 0)))
4603 = replace_equiv_address (operands[1],
4604 copy_to_reg (XEXP (operands[1], 0)));
4606 /* Handle loading a large integer during reload */
4607 else if (GET_CODE (operands[1]) == CONST_INT
4608 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4610 /* Writing a constant to memory needs a scratch, which should
4611 be handled with SECONDARY_RELOADs. */
4612 if (GET_CODE (operands[0]) != REG)
4615 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4616 emit_insn (gen_movsi (operands[0], operands[1]));
4623 (define_insn "*thumb_movhi_insn"
4624 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4625 (match_operand:HI 1 "general_operand" "l,mn,l,*h,*r,I"))]
4627 && ( register_operand (operands[0], HImode)
4628 || register_operand (operands[1], HImode))"
4630 switch (which_alternative)
4632 case 0: return \"add %0, %1, #0\";
4633 case 2: return \"strh %1, %0\";
4634 case 3: return \"mov %0, %1\";
4635 case 4: return \"mov %0, %1\";
4636 case 5: return \"mov %0, %1\";
4639 /* The stack pointer can end up being taken as an index register.
4640 Catch this case here and deal with it. */
4641 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4642 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4643 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4646 ops[0] = operands[0];
4647 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4649 output_asm_insn (\"mov %0, %1\", ops);
4651 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4654 return \"ldrh %0, %1\";
4656 [(set_attr "length" "2,4,2,2,2,2")
4657 (set_attr "type" "*,load,store1,*,*,*")
4658 (set_attr "pool_range" "*,64,*,*,*,*")]
4662 (define_insn "rotated_loadsi"
4663 [(set (match_operand:SI 0 "s_register_operand" "=r")
4664 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4666 "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4671 ops[0] = operands[0];
4672 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4673 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4676 [(set_attr "type" "load")
4677 (set_attr "predicable" "yes")]
4680 (define_expand "movhi_bytes"
4681 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4683 (zero_extend:SI (match_dup 6)))
4684 (set (match_operand:SI 0 "" "")
4685 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4690 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4692 mem1 = gen_rtx_MEM (QImode, addr);
4693 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4694 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4695 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4696 operands[0] = gen_lowpart (SImode, operands[0]);
4698 operands[2] = gen_reg_rtx (SImode);
4699 operands[3] = gen_reg_rtx (SImode);
4702 if (BYTES_BIG_ENDIAN)
4704 operands[4] = operands[2];
4705 operands[5] = operands[3];
4709 operands[4] = operands[3];
4710 operands[5] = operands[2];
4715 (define_expand "movhi_bigend"
4717 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4720 (ashiftrt:SI (match_dup 2) (const_int 16)))
4721 (set (match_operand:HI 0 "s_register_operand" "")
4722 (subreg:HI (match_dup 3) 0))]
4725 operands[2] = gen_reg_rtx (SImode);
4726 operands[3] = gen_reg_rtx (SImode);
4730 ;; Pattern to recognize insn generated default case above
4731 (define_insn "*movhi_insn_arch4"
4732 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4733 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4736 && (GET_CODE (operands[1]) != CONST_INT
4737 || const_ok_for_arm (INTVAL (operands[1]))
4738 || const_ok_for_arm (~INTVAL (operands[1])))"
4740 mov%?\\t%0, %1\\t%@ movhi
4741 mvn%?\\t%0, #%B1\\t%@ movhi
4742 str%?h\\t%1, %0\\t%@ movhi
4743 ldr%?h\\t%0, %1\\t%@ movhi"
4744 [(set_attr "type" "*,*,store1,load")
4745 (set_attr "predicable" "yes")
4746 (set_attr "pool_range" "*,*,*,256")
4747 (set_attr "neg_pool_range" "*,*,*,244")]
4750 (define_insn "*movhi_insn_littleend"
4751 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4752 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4755 && !BYTES_BIG_ENDIAN
4756 && !TARGET_MMU_TRAPS
4757 && (GET_CODE (operands[1]) != CONST_INT
4758 || const_ok_for_arm (INTVAL (operands[1]))
4759 || const_ok_for_arm (~INTVAL (operands[1])))"
4761 mov%?\\t%0, %1\\t%@ movhi
4762 mvn%?\\t%0, #%B1\\t%@ movhi
4763 ldr%?\\t%0, %1\\t%@ movhi"
4764 [(set_attr "type" "*,*,load")
4765 (set_attr "predicable" "yes")
4766 (set_attr "pool_range" "4096")
4767 (set_attr "neg_pool_range" "4084")]
4770 (define_insn "*movhi_insn_bigend"
4771 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4772 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4776 && !TARGET_MMU_TRAPS
4777 && (GET_CODE (operands[1]) != CONST_INT
4778 || const_ok_for_arm (INTVAL (operands[1]))
4779 || const_ok_for_arm (~INTVAL (operands[1])))"
4781 mov%?\\t%0, %1\\t%@ movhi
4782 mvn%?\\t%0, #%B1\\t%@ movhi
4783 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4784 [(set_attr "type" "*,*,load")
4785 (set_attr "predicable" "yes")
4786 (set_attr "length" "4,4,8")
4787 (set_attr "pool_range" "*,*,4092")
4788 (set_attr "neg_pool_range" "*,*,4084")]
4791 (define_insn "*loadhi_si_bigend"
4792 [(set (match_operand:SI 0 "s_register_operand" "=r")
4793 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
4797 && !TARGET_MMU_TRAPS"
4798 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4799 [(set_attr "type" "load")
4800 (set_attr "predicable" "yes")
4801 (set_attr "pool_range" "4096")
4802 (set_attr "neg_pool_range" "4084")]
4805 (define_insn "*movhi_bytes"
4806 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4807 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4808 "TARGET_ARM && TARGET_MMU_TRAPS"
4810 mov%?\\t%0, %1\\t%@ movhi
4811 mvn%?\\t%0, #%B1\\t%@ movhi"
4812 [(set_attr "predicable" "yes")]
4815 (define_insn "thumb_movhi_clobber"
4816 [(set (match_operand:HI 0 "memory_operand" "=m")
4817 (match_operand:HI 1 "register_operand" "l"))
4818 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4824 ;; We use a DImode scratch because we may occasionally need an additional
4825 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4826 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4827 (define_expand "reload_outhi"
4828 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4829 (match_operand:HI 1 "s_register_operand" "r")
4830 (match_operand:DI 2 "s_register_operand" "=&l")])]
4833 arm_reload_out_hi (operands);
4835 thumb_reload_out_hi (operands);
4840 (define_expand "reload_inhi"
4841 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4842 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4843 (match_operand:DI 2 "s_register_operand" "=&r")])]
4844 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4847 arm_reload_in_hi (operands);
4849 thumb_reload_out_hi (operands);
4853 (define_expand "movqi"
4854 [(set (match_operand:QI 0 "general_operand" "")
4855 (match_operand:QI 1 "general_operand" ""))]
4860 /* Everything except mem = const or mem = mem can be done easily */
4862 if (!no_new_pseudos)
4864 if (GET_CODE (operands[1]) == CONST_INT)
4866 rtx reg = gen_reg_rtx (SImode);
4868 emit_insn (gen_movsi (reg, operands[1]));
4869 operands[1] = gen_lowpart (QImode, reg);
4871 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4873 rtx reg = gen_reg_rtx (SImode);
4875 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4876 operands[1] = gen_lowpart (QImode, reg);
4878 if (GET_CODE (operands[0]) == MEM)
4879 operands[1] = force_reg (QImode, operands[1]);
4882 else /* TARGET_THUMB */
4884 if (!no_new_pseudos)
4886 if (GET_CODE (operands[0]) != REG)
4887 operands[1] = force_reg (QImode, operands[1]);
4889 /* ??? We shouldn't really get invalid addresses here, but this can
4890 happen if we are passed a SP (never OK for HImode/QImode) or
4891 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4892 HImode/QImode) relative address. */
4893 /* ??? This should perhaps be fixed elsewhere, for instance, in
4894 fixup_stack_1, by checking for other kinds of invalid addresses,
4895 e.g. a bare reference to a virtual register. This may confuse the
4896 alpha though, which must handle this case differently. */
4897 if (GET_CODE (operands[0]) == MEM
4898 && !memory_address_p (GET_MODE (operands[0]),
4899 XEXP (operands[0], 0)))
4901 = replace_equiv_address (operands[0],
4902 copy_to_reg (XEXP (operands[0], 0)));
4903 if (GET_CODE (operands[1]) == MEM
4904 && !memory_address_p (GET_MODE (operands[1]),
4905 XEXP (operands[1], 0)))
4907 = replace_equiv_address (operands[1],
4908 copy_to_reg (XEXP (operands[1], 0)));
4910 /* Handle loading a large integer during reload */
4911 else if (GET_CODE (operands[1]) == CONST_INT
4912 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4914 /* Writing a constant to memory needs a scratch, which should
4915 be handled with SECONDARY_RELOADs. */
4916 if (GET_CODE (operands[0]) != REG)
4919 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4920 emit_insn (gen_movsi (operands[0], operands[1]));
4928 (define_insn "*arm_movqi_insn"
4929 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4930 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4932 && ( register_operand (operands[0], QImode)
4933 || register_operand (operands[1], QImode))"
4939 [(set_attr "type" "*,*,load,store1")
4940 (set_attr "predicable" "yes")]
4943 (define_insn "*thumb_movqi_insn"
4944 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4945 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
4947 && ( register_operand (operands[0], QImode)
4948 || register_operand (operands[1], QImode))"
4956 [(set_attr "length" "2")
4957 (set_attr "type" "*,load,store1,*,*,*")
4958 (set_attr "pool_range" "*,32,*,*,*,*")]
4961 (define_expand "movsf"
4962 [(set (match_operand:SF 0 "general_operand" "")
4963 (match_operand:SF 1 "general_operand" ""))]
4968 if (GET_CODE (operands[0]) == MEM)
4969 operands[1] = force_reg (SFmode, operands[1]);
4971 else /* TARGET_THUMB */
4973 if (!no_new_pseudos)
4975 if (GET_CODE (operands[0]) != REG)
4976 operands[1] = force_reg (SFmode, operands[1]);
4983 [(set (match_operand:SF 0 "nonimmediate_operand" "")
4984 (match_operand:SF 1 "immediate_operand" ""))]
4986 && !TARGET_HARD_FLOAT
4988 && GET_CODE (operands[1]) == CONST_DOUBLE"
4989 [(set (match_dup 2) (match_dup 3))]
4991 operands[2] = gen_lowpart (SImode, operands[0]);
4992 operands[3] = gen_lowpart (SImode, operands[1]);
4993 if (operands[2] == 0 || operands[3] == 0)
4998 (define_insn "*arm_movsf_hard_insn"
4999 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
5000 (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
5002 && TARGET_HARD_FLOAT
5003 && (GET_CODE (operands[0]) != MEM
5004 || register_operand (operands[1], SFmode))"
5010 str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
5011 stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
5013 ldr%?\\t%0, %1\\t%@ float
5014 str%?\\t%1, %0\\t%@ float"
5015 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
5016 (set_attr "predicable" "yes")
5018 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
5019 (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
5020 (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
5023 ;; Exactly the same as above, except that all `f' cases are deleted.
5024 ;; This is necessary to prevent reload from ever trying to use a `f' reg
5025 ;; when -msoft-float.
5027 (define_insn "*arm_movsf_soft_insn"
5028 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5029 (match_operand:SF 1 "general_operand" "r,mE,r"))]
5032 && TARGET_SOFT_FLOAT
5033 && (GET_CODE (operands[0]) != MEM
5034 || register_operand (operands[1], SFmode))"
5037 ldr%?\\t%0, %1\\t%@ float
5038 str%?\\t%1, %0\\t%@ float"
5039 [(set_attr "length" "4,4,4")
5040 (set_attr "predicable" "yes")
5041 (set_attr "type" "*,load,store1")
5042 (set_attr "pool_range" "*,4096,*")
5043 (set_attr "neg_pool_range" "*,4084,*")]
5046 ;;; ??? This should have alternatives for constants.
5047 (define_insn "*thumb_movsf_insn"
5048 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5049 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
5051 && ( register_operand (operands[0], SFmode)
5052 || register_operand (operands[1], SFmode))"
5061 [(set_attr "length" "2")
5062 (set_attr "type" "*,load,store1,load,store1,*,*")
5063 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5066 (define_expand "movdf"
5067 [(set (match_operand:DF 0 "general_operand" "")
5068 (match_operand:DF 1 "general_operand" ""))]
5073 if (GET_CODE (operands[0]) == MEM)
5074 operands[1] = force_reg (DFmode, operands[1]);
5076 else /* TARGET_THUMB */
5078 if (!no_new_pseudos)
5080 if (GET_CODE (operands[0]) != REG)
5081 operands[1] = force_reg (DFmode, operands[1]);
5087 ;; Reloading a df mode value stored in integer regs to memory can require a
5089 (define_expand "reload_outdf"
5090 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5091 (match_operand:DF 1 "s_register_operand" "r")
5092 (match_operand:SI 2 "s_register_operand" "=&r")]
5096 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5099 operands[2] = XEXP (operands[0], 0);
5100 else if (code == POST_INC || code == PRE_DEC)
5102 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5103 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5104 emit_insn (gen_movdi (operands[0], operands[1]));
5107 else if (code == PRE_INC)
5109 rtx reg = XEXP (XEXP (operands[0], 0), 0);
5111 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5114 else if (code == POST_DEC)
5115 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5117 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5118 XEXP (XEXP (operands[0], 0), 1)));
5120 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5123 if (code == POST_DEC)
5124 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5130 (define_insn "*movdf_hard_insn"
5131 [(set (match_operand:DF 0 "nonimmediate_operand"
5132 "=r,Q,r,m,r, f, f,f, m,!f,!r")
5133 (match_operand:DF 1 "general_operand"
5134 "Q, r,r,r,mF,fG,H,mF,f,r, f"))]
5136 && TARGET_HARD_FLOAT
5137 && (GET_CODE (operands[0]) != MEM
5138 || register_operand (operands[1], DFmode))"
5141 switch (which_alternative)
5144 case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
5145 case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
5146 case 2: case 3: case 4: return output_move_double (operands);
5147 case 5: return \"mvf%?d\\t%0, %1\";
5148 case 6: return \"mnf%?d\\t%0, #%N1\";
5149 case 7: return \"ldf%?d\\t%0, %1\";
5150 case 8: return \"stf%?d\\t%1, %0\";
5151 case 9: return output_mov_double_fpu_from_arm (operands);
5152 case 10: return output_mov_double_arm_from_fpu (operands);
5156 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
5157 (set_attr "predicable" "yes")
5159 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
5160 (set_attr "pool_range" "*,*,*,*,1020,*,*,1024,*,*,*")
5161 (set_attr "neg_pool_range" "*,*,*,*,1008,*,*,1008,*,*,*")]
5164 ;; Software floating point version. This is essentially the same as movdi.
5165 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
5168 (define_insn "*movdf_soft_insn"
5169 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5170 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5171 "TARGET_ARM && TARGET_SOFT_FLOAT
5174 "* return output_move_double (operands);"
5175 [(set_attr "length" "8,8,8")
5176 (set_attr "type" "*,load,store2")
5177 (set_attr "pool_range" "1020")
5178 (set_attr "neg_pool_range" "1008")]
5181 ;;; ??? This should have alternatives for constants.
5182 ;;; ??? This was originally identical to the movdi_insn pattern.
5183 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5184 ;;; thumb_reorg with a memory reference.
5185 (define_insn "*thumb_movdf_insn"
5186 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5187 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
5189 && ( register_operand (operands[0], DFmode)
5190 || register_operand (operands[1], DFmode))"
5192 switch (which_alternative)
5196 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5197 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5198 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5200 return \"ldmia\\t%1, {%0, %H0}\";
5202 return \"stmia\\t%0, {%1, %H1}\";
5204 return thumb_load_double_from_address (operands);
5206 operands[2] = gen_rtx (MEM, SImode,
5207 plus_constant (XEXP (operands[0], 0), 4));
5208 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5211 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5212 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5213 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5216 [(set_attr "length" "4,2,2,6,4,4")
5217 (set_attr "type" "*,load,store2,load,store2,*")
5218 (set_attr "pool_range" "*,*,*,1020,*,*")]
5222 ;; Saving and restoring the floating point registers in the prologue should
5223 ;; be done in XFmode, even though we don't support that for anything else
5224 ;; (Well, strictly it's 'internal representation', but that's effectively
5227 (define_insn "*movxf_hard_insn"
5228 [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
5229 (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
5230 "TARGET_ARM && TARGET_HARD_FLOAT && reload_completed"
5232 switch (which_alternative)
5235 case 0: return \"mvf%?e\\t%0, %1\";
5236 case 1: return \"mnf%?e\\t%0, #%N1\";
5237 case 2: return \"ldf%?e\\t%0, %1\";
5238 case 3: return \"stf%?e\\t%1, %0\";
5239 case 4: return output_mov_long_double_fpu_from_arm (operands);
5240 case 5: return output_mov_long_double_arm_from_fpu (operands);
5241 case 6: return output_mov_long_double_arm_from_arm (operands);
5244 [(set_attr "length" "4,4,4,4,8,8,12")
5245 (set_attr "predicable" "yes")
5246 (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
5247 (set_attr "pool_range" "*,*,1024,*,*,*,*")
5248 (set_attr "neg_pool_range" "*,*,1004,*,*,*,*")]
5252 ;; load- and store-multiple insns
5253 ;; The arm can load/store any set of registers, provided that they are in
5254 ;; ascending order; but that is beyond GCC so stick with what it knows.
5256 (define_expand "load_multiple"
5257 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5258 (match_operand:SI 1 "" ""))
5259 (use (match_operand:SI 2 "" ""))])]
5262 /* Support only fixed point registers. */
5263 if (GET_CODE (operands[2]) != CONST_INT
5264 || INTVAL (operands[2]) > 14
5265 || INTVAL (operands[2]) < 2
5266 || GET_CODE (operands[1]) != MEM
5267 || GET_CODE (operands[0]) != REG
5268 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5269 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5273 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5274 force_reg (SImode, XEXP (operands[1], 0)),
5275 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5276 MEM_IN_STRUCT_P(operands[1]),
5277 MEM_SCALAR_P (operands[1]));
5281 ;; Load multiple with write-back
5283 (define_insn "*ldmsi_postinc4"
5284 [(match_parallel 0 "load_multiple_operation"
5285 [(set (match_operand:SI 1 "s_register_operand" "=r")
5286 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5288 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5289 (mem:SI (match_dup 2)))
5290 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5291 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5292 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5293 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5294 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5295 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5296 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5297 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5298 [(set_attr "type" "load")
5299 (set_attr "predicable" "yes")]
5302 (define_insn "*ldmsi_postinc3"
5303 [(match_parallel 0 "load_multiple_operation"
5304 [(set (match_operand:SI 1 "s_register_operand" "=r")
5305 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5307 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5308 (mem:SI (match_dup 2)))
5309 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5310 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5311 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5312 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5313 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5314 "ldm%?ia\\t%1!, {%3, %4, %5}"
5315 [(set_attr "type" "load")
5316 (set_attr "predicable" "yes")]
5319 (define_insn "*ldmsi_postinc2"
5320 [(match_parallel 0 "load_multiple_operation"
5321 [(set (match_operand:SI 1 "s_register_operand" "=r")
5322 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5324 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5325 (mem:SI (match_dup 2)))
5326 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5327 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5328 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5329 "ldm%?ia\\t%1!, {%3, %4}"
5330 [(set_attr "type" "load")
5331 (set_attr "predicable" "yes")]
5334 ;; Ordinary load multiple
5336 (define_insn "*ldmsi4"
5337 [(match_parallel 0 "load_multiple_operation"
5338 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5339 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5340 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5341 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5342 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5343 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5344 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5345 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5346 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5347 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5348 [(set_attr "type" "load")
5349 (set_attr "predicable" "yes")]
5352 (define_insn "*ldmsi3"
5353 [(match_parallel 0 "load_multiple_operation"
5354 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5355 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5356 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5357 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5358 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5359 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5360 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5361 "ldm%?ia\\t%1, {%2, %3, %4}"
5362 [(set_attr "type" "load")
5363 (set_attr "predicable" "yes")]
5366 (define_insn "*ldmsi2"
5367 [(match_parallel 0 "load_multiple_operation"
5368 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5369 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5370 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5371 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5372 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5373 "ldm%?ia\\t%1, {%2, %3}"
5374 [(set_attr "type" "load")
5375 (set_attr "predicable" "yes")]
5378 (define_expand "store_multiple"
5379 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5380 (match_operand:SI 1 "" ""))
5381 (use (match_operand:SI 2 "" ""))])]
5384 /* Support only fixed point registers */
5385 if (GET_CODE (operands[2]) != CONST_INT
5386 || INTVAL (operands[2]) > 14
5387 || INTVAL (operands[2]) < 2
5388 || GET_CODE (operands[1]) != REG
5389 || GET_CODE (operands[0]) != MEM
5390 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5391 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5395 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5396 force_reg (SImode, XEXP (operands[0], 0)),
5397 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5398 MEM_IN_STRUCT_P(operands[0]),
5399 MEM_SCALAR_P (operands[0]));
5403 ;; Store multiple with write-back
5405 (define_insn "*stmsi_postinc4"
5406 [(match_parallel 0 "store_multiple_operation"
5407 [(set (match_operand:SI 1 "s_register_operand" "=r")
5408 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5410 (set (mem:SI (match_dup 2))
5411 (match_operand:SI 3 "arm_hard_register_operand" ""))
5412 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5413 (match_operand:SI 4 "arm_hard_register_operand" ""))
5414 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5415 (match_operand:SI 5 "arm_hard_register_operand" ""))
5416 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5417 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5418 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5419 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5420 [(set_attr "predicable" "yes")
5421 (set_attr "type" "store4")]
5424 (define_insn "*stmsi_postinc3"
5425 [(match_parallel 0 "store_multiple_operation"
5426 [(set (match_operand:SI 1 "s_register_operand" "=r")
5427 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5429 (set (mem:SI (match_dup 2))
5430 (match_operand:SI 3 "arm_hard_register_operand" ""))
5431 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5432 (match_operand:SI 4 "arm_hard_register_operand" ""))
5433 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5434 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5435 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5436 "stm%?ia\\t%1!, {%3, %4, %5}"
5437 [(set_attr "predicable" "yes")
5438 (set_attr "type" "store3")]
5441 (define_insn "*stmsi_postinc2"
5442 [(match_parallel 0 "store_multiple_operation"
5443 [(set (match_operand:SI 1 "s_register_operand" "=r")
5444 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5446 (set (mem:SI (match_dup 2))
5447 (match_operand:SI 3 "arm_hard_register_operand" ""))
5448 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5449 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5450 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5451 "stm%?ia\\t%1!, {%3, %4}"
5452 [(set_attr "predicable" "yes")
5453 (set_attr "type" "store2")]
5456 ;; Ordinary store multiple
5458 (define_insn "*stmsi4"
5459 [(match_parallel 0 "store_multiple_operation"
5460 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5461 (match_operand:SI 2 "arm_hard_register_operand" ""))
5462 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5463 (match_operand:SI 3 "arm_hard_register_operand" ""))
5464 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5465 (match_operand:SI 4 "arm_hard_register_operand" ""))
5466 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5467 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5468 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5469 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5470 [(set_attr "predicable" "yes")
5471 (set_attr "type" "store4")]
5474 (define_insn "*stmsi3"
5475 [(match_parallel 0 "store_multiple_operation"
5476 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5477 (match_operand:SI 2 "arm_hard_register_operand" ""))
5478 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5479 (match_operand:SI 3 "arm_hard_register_operand" ""))
5480 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5481 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5482 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5483 "stm%?ia\\t%1, {%2, %3, %4}"
5484 [(set_attr "predicable" "yes")
5485 (set_attr "type" "store3")]
5488 (define_insn "*stmsi2"
5489 [(match_parallel 0 "store_multiple_operation"
5490 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5491 (match_operand:SI 2 "arm_hard_register_operand" ""))
5492 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5493 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5494 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5495 "stm%?ia\\t%1, {%2, %3}"
5496 [(set_attr "predicable" "yes")
5497 (set_attr "type" "store2")]
5500 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5501 ;; We could let this apply for blocks of less than this, but it clobbers so
5502 ;; many registers that there is then probably a better way.
5504 (define_expand "movstrqi"
5505 [(match_operand:BLK 0 "general_operand" "")
5506 (match_operand:BLK 1 "general_operand" "")
5507 (match_operand:SI 2 "const_int_operand" "")
5508 (match_operand:SI 3 "const_int_operand" "")]
5513 if (arm_gen_movstrqi (operands))
5517 else /* TARGET_THUMB */
5519 if ( INTVAL (operands[3]) != 4
5520 || INTVAL (operands[2]) > 48)
5523 thumb_expand_movstrqi (operands);
5529 ;; Thumb block-move insns
5531 (define_insn "movmem12b"
5532 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5533 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5534 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5535 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5536 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5537 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5538 (set (match_operand:SI 0 "register_operand" "=l")
5539 (plus:SI (match_dup 2) (const_int 12)))
5540 (set (match_operand:SI 1 "register_operand" "=l")
5541 (plus:SI (match_dup 3) (const_int 12)))
5542 (clobber (match_scratch:SI 4 "=&l"))
5543 (clobber (match_scratch:SI 5 "=&l"))
5544 (clobber (match_scratch:SI 6 "=&l"))]
5546 "* return thumb_output_move_mem_multiple (3, operands);"
5547 [(set_attr "length" "4")
5548 ; This isn't entirely accurate... It loads as well, but in terms of
5549 ; scheduling the following insn it is better to consider it as a store
5550 (set_attr "type" "store3")]
5553 (define_insn "movmem8b"
5554 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5555 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5556 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5557 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5558 (set (match_operand:SI 0 "register_operand" "=l")
5559 (plus:SI (match_dup 2) (const_int 8)))
5560 (set (match_operand:SI 1 "register_operand" "=l")
5561 (plus:SI (match_dup 3) (const_int 8)))
5562 (clobber (match_scratch:SI 4 "=&l"))
5563 (clobber (match_scratch:SI 5 "=&l"))]
5565 "* return thumb_output_move_mem_multiple (2, operands);"
5566 [(set_attr "length" "4")
5567 ; This isn't entirely accurate... It loads as well, but in terms of
5568 ; scheduling the following insn it is better to consider it as a store
5569 (set_attr "type" "store2")]
5574 ;; Compare & branch insns
5575 ;; The range calcualations are based as follows:
5576 ;; For forward branches, the address calculation returns the address of
5577 ;; the next instruction. This is 2 beyond the branch instruction.
5578 ;; For backward branches, the address calculation returns the address of
5579 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5580 ;; instruction for the shortest sequence, and 4 before the branch instruction
5581 ;; if we have to jump around an unconditional branch.
5582 ;; To the basic branch range the PC offset must be added (this is +4).
5583 ;; So for forward branches we have
5584 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5585 ;; And for backward branches we have
5586 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5588 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5589 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5591 (define_insn "cbranchsi4"
5594 (match_operator 0 "arm_comparison_operator"
5595 [(match_operand:SI 1 "register_operand" "l,r")
5596 (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5597 (label_ref (match_operand 3 "" ""))
5601 output_asm_insn (\"cmp\\t%1, %2\", operands);
5602 switch (get_attr_length (insn))
5604 case 4: return \"b%d0\\t%l3\";
5605 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5606 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5609 [(set (attr "far_jump")
5611 (eq_attr "length" "8")
5612 (const_string "yes")
5613 (const_string "no")))
5614 (set (attr "length")
5616 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5617 (le (minus (match_dup 3) (pc)) (const_int 256)))
5620 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5621 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5626 (define_insn "*negated_cbranchsi4"
5629 (match_operator 0 "arm_comparison_operator"
5630 [(match_operand:SI 1 "register_operand" "l")
5631 (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5632 (label_ref (match_operand 3 "" ""))
5636 output_asm_insn (\"cmn\\t%1, %2\", operands);
5637 switch (get_attr_length (insn))
5639 case 4: return \"b%d0\\t%l3\";
5640 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5641 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5644 [(set (attr "far_jump")
5646 (eq_attr "length" "8")
5647 (const_string "yes")
5648 (const_string "no")))
5649 (set (attr "length")
5651 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5652 (le (minus (match_dup 3) (pc)) (const_int 256)))
5655 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5656 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5662 ;; Comparison and test insns
5664 (define_expand "cmpsi"
5665 [(match_operand:SI 0 "s_register_operand" "")
5666 (match_operand:SI 1 "arm_add_operand" "")]
5669 arm_compare_op0 = operands[0];
5670 arm_compare_op1 = operands[1];
5675 (define_expand "cmpsf"
5676 [(match_operand:SF 0 "s_register_operand" "")
5677 (match_operand:SF 1 "fpu_rhs_operand" "")]
5678 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5680 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
5681 operands[1] = force_reg (SFmode, operands[1]);
5683 arm_compare_op0 = operands[0];
5684 arm_compare_op1 = operands[1];
5689 (define_expand "cmpdf"
5690 [(match_operand:DF 0 "s_register_operand" "")
5691 (match_operand:DF 1 "fpu_rhs_operand" "")]
5692 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5694 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
5695 operands[1] = force_reg (DFmode, operands[1]);
5697 arm_compare_op0 = operands[0];
5698 arm_compare_op1 = operands[1];
5703 (define_insn "*arm_cmpsi_insn"
5704 [(set (reg:CC CC_REGNUM)
5705 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5706 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
5711 [(set_attr "conds" "set")]
5714 (define_insn "*cmpsi_shiftsi"
5715 [(set (reg:CC CC_REGNUM)
5716 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5717 (match_operator:SI 3 "shift_operator"
5718 [(match_operand:SI 1 "s_register_operand" "r")
5719 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
5722 [(set_attr "conds" "set")
5723 (set_attr "shift" "1")
5727 (define_insn "*cmpsi_shiftsi_swp"
5728 [(set (reg:CC_SWP CC_REGNUM)
5729 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5730 [(match_operand:SI 1 "s_register_operand" "r")
5731 (match_operand:SI 2 "reg_or_int_operand" "rM")])
5732 (match_operand:SI 0 "s_register_operand" "r")))]
5735 [(set_attr "conds" "set")
5736 (set_attr "shift" "1")
5740 (define_insn "*cmpsi_neg_shiftsi"
5741 [(set (reg:CC CC_REGNUM)
5742 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5743 (neg:SI (match_operator:SI 3 "shift_operator"
5744 [(match_operand:SI 1 "s_register_operand" "r")
5745 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5748 [(set_attr "conds" "set")
5749 (set_attr "shift" "1")
5753 (define_insn "*cmpsf_insn"
5754 [(set (reg:CCFP CC_REGNUM)
5755 (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
5756 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5757 "TARGET_ARM && TARGET_HARD_FLOAT"
5761 [(set_attr "conds" "set")
5762 (set_attr "type" "f_2_r")]
5765 (define_insn "*cmpdf_insn"
5766 [(set (reg:CCFP CC_REGNUM)
5767 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
5768 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5769 "TARGET_ARM && TARGET_HARD_FLOAT"
5773 [(set_attr "conds" "set")
5774 (set_attr "type" "f_2_r")]
5777 (define_insn "*cmpesfdf_df"
5778 [(set (reg:CCFP CC_REGNUM)
5779 (compare:CCFP (float_extend:DF
5780 (match_operand:SF 0 "s_register_operand" "f,f"))
5781 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5782 "TARGET_ARM && TARGET_HARD_FLOAT"
5786 [(set_attr "conds" "set")
5787 (set_attr "type" "f_2_r")]
5790 (define_insn "*cmpdf_esfdf"
5791 [(set (reg:CCFP CC_REGNUM)
5792 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5794 (match_operand:SF 1 "s_register_operand" "f"))))]
5795 "TARGET_ARM && TARGET_HARD_FLOAT"
5797 [(set_attr "conds" "set")
5798 (set_attr "type" "f_2_r")]
5801 ;; Cirrus SF compare instruction
5802 (define_insn "*cirrus_cmpsf"
5803 [(set (reg:CCFP CC_REGNUM)
5804 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
5805 (match_operand:SF 1 "cirrus_fp_register" "v")))]
5806 "TARGET_ARM && TARGET_CIRRUS"
5807 "cfcmps%?\\tr15, %V0, %V1"
5808 [(set_attr "type" "mav_farith")
5809 (set_attr "cirrus" "compare")]
5812 ;; Cirrus DF compare instruction
5813 (define_insn "*cirrus_cmpdf"
5814 [(set (reg:CCFP CC_REGNUM)
5815 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
5816 (match_operand:DF 1 "cirrus_fp_register" "v")))]
5817 "TARGET_ARM && TARGET_CIRRUS"
5818 "cfcmpd%?\\tr15, %V0, %V1"
5819 [(set_attr "type" "mav_farith")
5820 (set_attr "cirrus" "compare")]
5823 ;; Cirrus DI compare instruction
5824 (define_expand "cmpdi"
5825 [(match_operand:DI 0 "cirrus_fp_register" "")
5826 (match_operand:DI 1 "cirrus_fp_register" "")]
5827 "TARGET_ARM && TARGET_CIRRUS"
5829 arm_compare_op0 = operands[0];
5830 arm_compare_op1 = operands[1];
5834 (define_insn "*cirrus_cmpdi"
5835 [(set (reg:CC CC_REGNUM)
5836 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
5837 (match_operand:DI 1 "cirrus_fp_register" "v")))]
5838 "TARGET_ARM && TARGET_CIRRUS"
5839 "cfcmp64%?\\tr15, %V0, %V1"
5840 [(set_attr "type" "mav_farith")
5841 (set_attr "cirrus" "compare")]
5844 (define_insn "*cmpsf_trap"
5845 [(set (reg:CCFPE CC_REGNUM)
5846 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
5847 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5848 "TARGET_ARM && TARGET_HARD_FLOAT"
5852 [(set_attr "conds" "set")
5853 (set_attr "type" "f_2_r")]
5856 (define_insn "*cmpdf_trap"
5857 [(set (reg:CCFPE CC_REGNUM)
5858 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
5859 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5860 "TARGET_ARM && TARGET_HARD_FLOAT"
5864 [(set_attr "conds" "set")
5865 (set_attr "type" "f_2_r")]
5868 (define_insn "*cmp_esfdf_df_trap"
5869 [(set (reg:CCFPE CC_REGNUM)
5870 (compare:CCFPE (float_extend:DF
5871 (match_operand:SF 0 "s_register_operand" "f,f"))
5872 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5873 "TARGET_ARM && TARGET_HARD_FLOAT"
5877 [(set_attr "conds" "set")
5878 (set_attr "type" "f_2_r")]
5881 (define_insn "*cmp_df_esfdf_trap"
5882 [(set (reg:CCFPE CC_REGNUM)
5883 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
5885 (match_operand:SF 1 "s_register_operand" "f"))))]
5886 "TARGET_ARM && TARGET_HARD_FLOAT"
5888 [(set_attr "conds" "set")
5889 (set_attr "type" "f_2_r")]
5892 ; This insn allows redundant compares to be removed by cse, nothing should
5893 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5894 ; is deleted later on. The match_dup will match the mode here, so that
5895 ; mode changes of the condition codes aren't lost by this even though we don't
5896 ; specify what they are.
5898 (define_insn "*deleted_compare"
5899 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5901 "\\t%@ deleted compare"
5902 [(set_attr "conds" "set")
5903 (set_attr "length" "0")]
5907 ;; Conditional branch insns
5909 (define_expand "beq"
5911 (if_then_else (eq (match_dup 1) (const_int 0))
5912 (label_ref (match_operand 0 "" ""))
5915 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5918 (define_expand "bne"
5920 (if_then_else (ne (match_dup 1) (const_int 0))
5921 (label_ref (match_operand 0 "" ""))
5924 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5927 (define_expand "bgt"
5929 (if_then_else (gt (match_dup 1) (const_int 0))
5930 (label_ref (match_operand 0 "" ""))
5933 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5936 (define_expand "ble"
5938 (if_then_else (le (match_dup 1) (const_int 0))
5939 (label_ref (match_operand 0 "" ""))
5942 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5945 (define_expand "bge"
5947 (if_then_else (ge (match_dup 1) (const_int 0))
5948 (label_ref (match_operand 0 "" ""))
5951 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5954 (define_expand "blt"
5956 (if_then_else (lt (match_dup 1) (const_int 0))
5957 (label_ref (match_operand 0 "" ""))
5960 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5963 (define_expand "bgtu"
5965 (if_then_else (gtu (match_dup 1) (const_int 0))
5966 (label_ref (match_operand 0 "" ""))
5969 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5972 (define_expand "bleu"
5974 (if_then_else (leu (match_dup 1) (const_int 0))
5975 (label_ref (match_operand 0 "" ""))
5978 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5981 (define_expand "bgeu"
5983 (if_then_else (geu (match_dup 1) (const_int 0))
5984 (label_ref (match_operand 0 "" ""))
5987 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5990 (define_expand "bltu"
5992 (if_then_else (ltu (match_dup 1) (const_int 0))
5993 (label_ref (match_operand 0 "" ""))
5996 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5999 (define_expand "bunordered"
6001 (if_then_else (unordered (match_dup 1) (const_int 0))
6002 (label_ref (match_operand 0 "" ""))
6004 "TARGET_ARM && TARGET_HARD_FLOAT"
6005 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6009 (define_expand "bordered"
6011 (if_then_else (ordered (match_dup 1) (const_int 0))
6012 (label_ref (match_operand 0 "" ""))
6014 "TARGET_ARM && TARGET_HARD_FLOAT"
6015 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6019 (define_expand "bungt"
6021 (if_then_else (ungt (match_dup 1) (const_int 0))
6022 (label_ref (match_operand 0 "" ""))
6024 "TARGET_ARM && TARGET_HARD_FLOAT"
6025 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6028 (define_expand "bunlt"
6030 (if_then_else (unlt (match_dup 1) (const_int 0))
6031 (label_ref (match_operand 0 "" ""))
6033 "TARGET_ARM && TARGET_HARD_FLOAT"
6034 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6037 (define_expand "bunge"
6039 (if_then_else (unge (match_dup 1) (const_int 0))
6040 (label_ref (match_operand 0 "" ""))
6042 "TARGET_ARM && TARGET_HARD_FLOAT"
6043 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6046 (define_expand "bunle"
6048 (if_then_else (unle (match_dup 1) (const_int 0))
6049 (label_ref (match_operand 0 "" ""))
6051 "TARGET_ARM && TARGET_HARD_FLOAT"
6052 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6055 ;; The following two patterns need two branch instructions, since there is
6056 ;; no single instruction that will handle all cases.
6057 (define_expand "buneq"
6059 (if_then_else (uneq (match_dup 1) (const_int 0))
6060 (label_ref (match_operand 0 "" ""))
6062 "TARGET_ARM && TARGET_HARD_FLOAT"
6063 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6066 (define_expand "bltgt"
6068 (if_then_else (ltgt (match_dup 1) (const_int 0))
6069 (label_ref (match_operand 0 "" ""))
6071 "TARGET_ARM && TARGET_HARD_FLOAT"
6072 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6076 ;; Patterns to match conditional branch insns.
6079 ; Special pattern to match UNEQ.
6080 (define_insn "*arm_buneq"
6082 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6083 (label_ref (match_operand 0 "" ""))
6085 "TARGET_ARM && TARGET_HARD_FLOAT"
6087 if (arm_ccfsm_state != 0)
6090 return \"bvs\\t%l0\;beq\\t%l0\";
6092 [(set_attr "conds" "jump_clob")
6093 (set_attr "length" "8")]
6096 ; Special pattern to match LTGT.
6097 (define_insn "*arm_bltgt"
6099 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6100 (label_ref (match_operand 0 "" ""))
6102 "TARGET_ARM && TARGET_HARD_FLOAT"
6104 if (arm_ccfsm_state != 0)
6107 return \"bmi\\t%l0\;bgt\\t%l0\";
6109 [(set_attr "conds" "jump_clob")
6110 (set_attr "length" "8")]
6113 (define_insn "*arm_cond_branch"
6115 (if_then_else (match_operator 1 "arm_comparison_operator"
6116 [(match_operand 2 "cc_register" "") (const_int 0)])
6117 (label_ref (match_operand 0 "" ""))
6121 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6123 arm_ccfsm_state += 2;
6126 return \"b%d1\\t%l0\";
6128 [(set_attr "conds" "use")]
6131 ; Special pattern to match reversed UNEQ.
6132 (define_insn "*arm_buneq_reversed"
6134 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6136 (label_ref (match_operand 0 "" ""))))]
6137 "TARGET_ARM && TARGET_HARD_FLOAT"
6139 if (arm_ccfsm_state != 0)
6142 return \"bmi\\t%l0\;bgt\\t%l0\";
6144 [(set_attr "conds" "jump_clob")
6145 (set_attr "length" "8")]
6148 ; Special pattern to match reversed LTGT.
6149 (define_insn "*arm_bltgt_reversed"
6151 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6153 (label_ref (match_operand 0 "" ""))))]
6154 "TARGET_ARM && TARGET_HARD_FLOAT"
6156 if (arm_ccfsm_state != 0)
6159 return \"bvs\\t%l0\;beq\\t%l0\";
6161 [(set_attr "conds" "jump_clob")
6162 (set_attr "length" "8")]
6165 (define_insn "*arm_cond_branch_reversed"
6167 (if_then_else (match_operator 1 "arm_comparison_operator"
6168 [(match_operand 2 "cc_register" "") (const_int 0)])
6170 (label_ref (match_operand 0 "" ""))))]
6173 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6175 arm_ccfsm_state += 2;
6178 return \"b%D1\\t%l0\";
6180 [(set_attr "conds" "use")]
6187 (define_expand "seq"
6188 [(set (match_operand:SI 0 "s_register_operand" "=r")
6189 (eq:SI (match_dup 1) (const_int 0)))]
6191 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6194 (define_expand "sne"
6195 [(set (match_operand:SI 0 "s_register_operand" "=r")
6196 (ne:SI (match_dup 1) (const_int 0)))]
6198 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6201 (define_expand "sgt"
6202 [(set (match_operand:SI 0 "s_register_operand" "=r")
6203 (gt:SI (match_dup 1) (const_int 0)))]
6205 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6208 (define_expand "sle"
6209 [(set (match_operand:SI 0 "s_register_operand" "=r")
6210 (le:SI (match_dup 1) (const_int 0)))]
6212 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6215 (define_expand "sge"
6216 [(set (match_operand:SI 0 "s_register_operand" "=r")
6217 (ge:SI (match_dup 1) (const_int 0)))]
6219 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6222 (define_expand "slt"
6223 [(set (match_operand:SI 0 "s_register_operand" "=r")
6224 (lt:SI (match_dup 1) (const_int 0)))]
6226 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6229 (define_expand "sgtu"
6230 [(set (match_operand:SI 0 "s_register_operand" "=r")
6231 (gtu:SI (match_dup 1) (const_int 0)))]
6233 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6236 (define_expand "sleu"
6237 [(set (match_operand:SI 0 "s_register_operand" "=r")
6238 (leu:SI (match_dup 1) (const_int 0)))]
6240 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6243 (define_expand "sgeu"
6244 [(set (match_operand:SI 0 "s_register_operand" "=r")
6245 (geu:SI (match_dup 1) (const_int 0)))]
6247 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6250 (define_expand "sltu"
6251 [(set (match_operand:SI 0 "s_register_operand" "=r")
6252 (ltu:SI (match_dup 1) (const_int 0)))]
6254 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6257 (define_expand "sunordered"
6258 [(set (match_operand:SI 0 "s_register_operand" "=r")
6259 (unordered:SI (match_dup 1) (const_int 0)))]
6260 "TARGET_ARM && TARGET_HARD_FLOAT"
6261 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6265 (define_expand "sordered"
6266 [(set (match_operand:SI 0 "s_register_operand" "=r")
6267 (ordered:SI (match_dup 1) (const_int 0)))]
6268 "TARGET_ARM && TARGET_HARD_FLOAT"
6269 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6273 (define_expand "sungt"
6274 [(set (match_operand:SI 0 "s_register_operand" "=r")
6275 (ungt:SI (match_dup 1) (const_int 0)))]
6276 "TARGET_ARM && TARGET_HARD_FLOAT"
6277 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6281 (define_expand "sunge"
6282 [(set (match_operand:SI 0 "s_register_operand" "=r")
6283 (unge:SI (match_dup 1) (const_int 0)))]
6284 "TARGET_ARM && TARGET_HARD_FLOAT"
6285 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6289 (define_expand "sunlt"
6290 [(set (match_operand:SI 0 "s_register_operand" "=r")
6291 (unlt:SI (match_dup 1) (const_int 0)))]
6292 "TARGET_ARM && TARGET_HARD_FLOAT"
6293 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6297 (define_expand "sunle"
6298 [(set (match_operand:SI 0 "s_register_operand" "=r")
6299 (unle:SI (match_dup 1) (const_int 0)))]
6300 "TARGET_ARM && TARGET_HARD_FLOAT"
6301 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6305 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6306 ;;; simple ARM instructions.
6308 ; (define_expand "suneq"
6309 ; [(set (match_operand:SI 0 "s_register_operand" "=r")
6310 ; (uneq:SI (match_dup 1) (const_int 0)))]
6311 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6315 ; (define_expand "sltgt"
6316 ; [(set (match_operand:SI 0 "s_register_operand" "=r")
6317 ; (ltgt:SI (match_dup 1) (const_int 0)))]
6318 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6322 (define_insn "*mov_scc"
6323 [(set (match_operand:SI 0 "s_register_operand" "=r")
6324 (match_operator:SI 1 "arm_comparison_operator"
6325 [(match_operand 2 "cc_register" "") (const_int 0)]))]
6327 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6328 [(set_attr "conds" "use")
6329 (set_attr "length" "8")]
6332 (define_insn "*mov_negscc"
6333 [(set (match_operand:SI 0 "s_register_operand" "=r")
6334 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
6335 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6337 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6338 [(set_attr "conds" "use")
6339 (set_attr "length" "8")]
6342 (define_insn "*mov_notscc"
6343 [(set (match_operand:SI 0 "s_register_operand" "=r")
6344 (not:SI (match_operator:SI 1 "arm_comparison_operator"
6345 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6347 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6348 [(set_attr "conds" "use")
6349 (set_attr "length" "8")]
6353 ;; Conditional move insns
6355 (define_expand "movsicc"
6356 [(set (match_operand:SI 0 "s_register_operand" "")
6357 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6358 (match_operand:SI 2 "arm_not_operand" "")
6359 (match_operand:SI 3 "arm_not_operand" "")))]
6363 enum rtx_code code = GET_CODE (operands[1]);
6366 if (code == UNEQ || code == LTGT)
6369 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6370 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6374 (define_expand "movsfcc"
6375 [(set (match_operand:SF 0 "s_register_operand" "")
6376 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6377 (match_operand:SF 2 "s_register_operand" "")
6378 (match_operand:SF 3 "nonmemory_operand" "")))]
6382 enum rtx_code code = GET_CODE (operands[1]);
6385 if (code == UNEQ || code == LTGT)
6388 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
6389 Otherwise, ensure it is a valid FP add operand */
6390 if ((!TARGET_HARD_FLOAT)
6391 || (!fpu_add_operand (operands[3], SFmode)))
6392 operands[3] = force_reg (SFmode, operands[3]);
6394 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6395 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6399 (define_expand "movdfcc"
6400 [(set (match_operand:DF 0 "s_register_operand" "")
6401 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6402 (match_operand:DF 2 "s_register_operand" "")
6403 (match_operand:DF 3 "fpu_add_operand" "")))]
6404 "TARGET_ARM && TARGET_HARD_FLOAT"
6407 enum rtx_code code = GET_CODE (operands[1]);
6410 if (code == UNEQ || code == LTGT)
6413 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6414 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6418 (define_insn "*movsicc_insn"
6419 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6421 (match_operator 3 "arm_comparison_operator"
6422 [(match_operand 4 "cc_register" "") (const_int 0)])
6423 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6424 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6431 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6432 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6433 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6434 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6435 [(set_attr "length" "4,4,4,4,8,8,8,8")
6436 (set_attr "conds" "use")]
6439 (define_insn "*movsfcc_hard_insn"
6440 [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6442 (match_operator 3 "arm_comparison_operator"
6443 [(match_operand 4 "cc_register" "") (const_int 0)])
6444 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6445 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6446 "TARGET_ARM && TARGET_HARD_FLOAT"
6452 mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
6453 mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
6454 mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
6455 mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
6456 [(set_attr "length" "4,4,4,4,8,8,8,8")
6457 (set_attr "type" "ffarith")
6458 (set_attr "conds" "use")]
6461 (define_insn "*movsfcc_soft_insn"
6462 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6463 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
6464 [(match_operand 4 "cc_register" "") (const_int 0)])
6465 (match_operand:SF 1 "s_register_operand" "0,r")
6466 (match_operand:SF 2 "s_register_operand" "r,0")))]
6467 "TARGET_ARM && TARGET_SOFT_FLOAT"
6471 [(set_attr "conds" "use")]
6474 (define_insn "*movdfcc_insn"
6475 [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6477 (match_operator 3 "arm_comparison_operator"
6478 [(match_operand 4 "cc_register" "") (const_int 0)])
6479 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6480 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6481 "TARGET_ARM && TARGET_HARD_FLOAT"
6487 mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
6488 mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
6489 mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
6490 mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
6491 [(set_attr "length" "4,4,4,4,8,8,8,8")
6492 (set_attr "type" "ffarith")
6493 (set_attr "conds" "use")]
6497 ;; Jump and linkage insns
6499 (define_expand "jump"
6501 (label_ref (match_operand 0 "" "")))]
6506 (define_insn "*arm_jump"
6508 (label_ref (match_operand 0 "" "")))]
6512 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6514 arm_ccfsm_state += 2;
6517 return \"b%?\\t%l0\";
6520 [(set_attr "predicable" "yes")]
6523 (define_insn "*thumb_jump"
6525 (label_ref (match_operand 0 "" "")))]
6528 if (get_attr_length (insn) == 2)
6530 return \"bl\\t%l0\\t%@ far jump\";
6532 [(set (attr "far_jump")
6534 (eq_attr "length" "4")
6535 (const_string "yes")
6536 (const_string "no")))
6537 (set (attr "length")
6539 (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6540 (le (minus (match_dup 0) (pc)) (const_int 2044)))
6545 (define_expand "call"
6546 [(parallel [(call (match_operand 0 "memory_operand" "")
6547 (match_operand 1 "general_operand" ""))
6548 (use (match_operand 2 "" ""))
6549 (clobber (reg:SI LR_REGNUM))])]
6555 /* In an untyped call, we can get NULL for operand 2. */
6556 if (operands[2] == NULL_RTX)
6557 operands[2] = const0_rtx;
6559 /* This is to decide if we should generate indirect calls by loading the
6560 32 bit address of the callee into a register before performing the
6561 branch and link. operand[2] encodes the long_call/short_call
6562 attribute of the function being called. This attribute is set whenever
6563 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6564 is used, and the short_call attribute can also be set if function is
6565 declared as static or if it has already been defined in the current
6566 compilation unit. See arm.c and arm.h for info about this. The third
6567 parameter to arm_is_longcall_p is used to tell it which pattern
6569 callee = XEXP (operands[0], 0);
6571 if (GET_CODE (callee) != REG
6572 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6573 XEXP (operands[0], 0) = force_reg (Pmode, callee);
6577 (define_insn "*call_reg"
6578 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
6579 (match_operand 1 "" ""))
6580 (use (match_operand 2 "" ""))
6581 (clobber (reg:SI LR_REGNUM))]
6584 return output_call (operands);
6586 ;; length is worst case, normally it is only two
6587 [(set_attr "length" "12")
6588 (set_attr "type" "call")]
6591 (define_insn "*call_mem"
6592 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
6593 (match_operand 1 "" ""))
6594 (use (match_operand 2 "" ""))
6595 (clobber (reg:SI LR_REGNUM))]
6598 return output_call_mem (operands);
6600 [(set_attr "length" "12")
6601 (set_attr "type" "call")]
6604 (define_insn "*call_indirect"
6605 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6606 (match_operand 1 "" ""))
6607 (use (match_operand 2 "" ""))
6608 (clobber (reg:SI LR_REGNUM))]
6612 if (TARGET_CALLER_INTERWORKING)
6613 return \"bl\\t%__interwork_call_via_%0\";
6615 return \"bl\\t%__call_via_%0\";
6617 [(set_attr "type" "call")]
6620 (define_insn "*call_value_indirect"
6621 [(set (match_operand 0 "" "=l")
6622 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6623 (match_operand 2 "" "")))
6624 (use (match_operand 3 "" ""))
6625 (clobber (reg:SI LR_REGNUM))]
6629 if (TARGET_CALLER_INTERWORKING)
6630 return \"bl\\t%__interwork_call_via_%1\";
6632 return \"bl\\t%__call_via_%1\";
6634 [(set_attr "type" "call")]
6637 (define_expand "call_value"
6638 [(parallel [(set (match_operand 0 "" "")
6639 (call (match_operand 1 "memory_operand" "")
6640 (match_operand 2 "general_operand" "")))
6641 (use (match_operand 3 "" ""))
6642 (clobber (reg:SI LR_REGNUM))])]
6646 rtx callee = XEXP (operands[1], 0);
6648 /* In an untyped call, we can get NULL for operand 2. */
6649 if (operands[3] == 0)
6650 operands[3] = const0_rtx;
6652 /* See the comment in define_expand \"call\". */
6653 if (GET_CODE (callee) != REG
6654 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6655 XEXP (operands[1], 0) = force_reg (Pmode, callee);
6659 (define_insn "*call_value_reg"
6660 [(set (match_operand 0 "" "=r,f,v")
6661 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r,r"))
6662 (match_operand 2 "" "")))
6663 (use (match_operand 3 "" ""))
6664 (clobber (reg:SI LR_REGNUM))]
6667 return output_call (&operands[1]);
6669 [(set_attr "length" "12")
6670 (set_attr "type" "call")]
6673 (define_insn "*call_value_mem"
6674 [(set (match_operand 0 "" "=r,f,v")
6675 (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m,m"))
6676 (match_operand 2 "" "")))
6677 (use (match_operand 3 "" ""))
6678 (clobber (reg:SI LR_REGNUM))]
6679 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6681 return output_call_mem (&operands[1]);
6683 [(set_attr "length" "12")
6684 (set_attr "type" "call")]
6687 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6688 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6690 (define_insn "*call_symbol"
6691 [(call (mem:SI (match_operand:SI 0 "" "X"))
6692 (match_operand 1 "" ""))
6693 (use (match_operand 2 "" ""))
6694 (clobber (reg:SI LR_REGNUM))]
6696 && (GET_CODE (operands[0]) == SYMBOL_REF)
6697 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6700 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6702 [(set_attr "type" "call")]
6705 (define_insn "*call_value_symbol"
6706 [(set (match_operand 0 "s_register_operand" "=r,f,v")
6707 (call (mem:SI (match_operand:SI 1 "" "X,X,X"))
6708 (match_operand:SI 2 "" "")))
6709 (use (match_operand 3 "" ""))
6710 (clobber (reg:SI LR_REGNUM))]
6712 && (GET_CODE (operands[1]) == SYMBOL_REF)
6713 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6716 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6718 [(set_attr "type" "call")]
6721 (define_insn "*call_insn"
6722 [(call (mem:SI (match_operand:SI 0 "" "X"))
6723 (match_operand:SI 1 "" ""))
6724 (use (match_operand 2 "" ""))
6725 (clobber (reg:SI LR_REGNUM))]
6727 && GET_CODE (operands[0]) == SYMBOL_REF
6728 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6730 [(set_attr "length" "4")
6731 (set_attr "type" "call")]
6734 (define_insn "*call_value_insn"
6735 [(set (match_operand 0 "register_operand" "=l")
6736 (call (mem:SI (match_operand 1 "" "X"))
6737 (match_operand 2 "" "")))
6738 (use (match_operand 3 "" ""))
6739 (clobber (reg:SI LR_REGNUM))]
6741 && GET_CODE (operands[1]) == SYMBOL_REF
6742 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6744 [(set_attr "length" "4")
6745 (set_attr "type" "call")]
6748 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6749 (define_expand "sibcall"
6750 [(parallel [(call (match_operand 0 "memory_operand" "")
6751 (match_operand 1 "general_operand" ""))
6753 (use (match_operand 2 "" ""))])]
6757 if (operands[2] == NULL_RTX)
6758 operands[2] = const0_rtx;
6762 (define_expand "sibcall_value"
6763 [(parallel [(set (match_operand 0 "register_operand" "")
6764 (call (match_operand 1 "memory_operand" "")
6765 (match_operand 2 "general_operand" "")))
6767 (use (match_operand 3 "" ""))])]
6771 if (operands[3] == NULL_RTX)
6772 operands[3] = const0_rtx;
6776 (define_insn "*sibcall_insn"
6777 [(call (mem:SI (match_operand:SI 0 "" "X"))
6778 (match_operand 1 "" ""))
6780 (use (match_operand 2 "" ""))]
6781 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6783 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6785 [(set_attr "type" "call")]
6788 (define_insn "*sibcall_value_insn"
6789 [(set (match_operand 0 "s_register_operand" "=r,f,v")
6790 (call (mem:SI (match_operand:SI 1 "" "X,X,X"))
6791 (match_operand 2 "" "")))
6793 (use (match_operand 3 "" ""))]
6794 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6796 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6798 [(set_attr "type" "call")]
6801 ;; Often the return insn will be the same as loading from memory, so set attr
6802 (define_insn "return"
6804 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6807 if (arm_ccfsm_state == 2)
6809 arm_ccfsm_state += 2;
6812 return output_return_instruction (const_true_rtx, TRUE, FALSE);
6814 [(set_attr "type" "load")
6815 (set_attr "predicable" "yes")]
6818 (define_insn "*cond_return"
6820 (if_then_else (match_operator 0 "arm_comparison_operator"
6821 [(match_operand 1 "cc_register" "") (const_int 0)])
6824 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6827 if (arm_ccfsm_state == 2)
6829 arm_ccfsm_state += 2;
6832 return output_return_instruction (operands[0], TRUE, FALSE);
6834 [(set_attr "conds" "use")
6835 (set_attr "type" "load")]
6838 (define_insn "*cond_return_inverted"
6840 (if_then_else (match_operator 0 "arm_comparison_operator"
6841 [(match_operand 1 "cc_register" "") (const_int 0)])
6844 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6847 if (arm_ccfsm_state == 2)
6849 arm_ccfsm_state += 2;
6852 return output_return_instruction (operands[0], TRUE, TRUE);
6854 [(set_attr "conds" "use")
6855 (set_attr "type" "load")]
6858 ;; Generate a sequence of instructions to determine if the processor is
6859 ;; in 26-bit or 32-bit mode, and return the appropriate return address
6862 (define_expand "return_addr_mask"
6864 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6866 (set (match_operand:SI 0 "s_register_operand" "")
6867 (if_then_else:SI (eq (match_dup 1) (const_int 0))
6869 (const_int 67108860)))] ; 0x03fffffc
6872 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
6875 (define_insn "*check_arch2"
6876 [(set (match_operand:CC_NOOV 0 "cc_register" "")
6877 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6880 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
6881 [(set_attr "length" "8")
6882 (set_attr "conds" "set")]
6885 ;; Call subroutine returning any type.
6887 (define_expand "untyped_call"
6888 [(parallel [(call (match_operand 0 "" "")
6890 (match_operand 1 "" "")
6891 (match_operand 2 "" "")])]
6897 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6899 for (i = 0; i < XVECLEN (operands[2], 0); i++)
6901 rtx set = XVECEXP (operands[2], 0, i);
6903 emit_move_insn (SET_DEST (set), SET_SRC (set));
6906 /* The optimizer does not know that the call sets the function value
6907 registers we stored in the result block. We avoid problems by
6908 claiming that all hard registers are used and clobbered at this
6910 emit_insn (gen_blockage ());
6916 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6917 ;; all of memory. This blocks insns from being moved across this point.
6919 (define_insn "blockage"
6920 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6923 [(set_attr "length" "0")
6924 (set_attr "type" "block")]
6927 (define_expand "casesi"
6928 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6929 (match_operand:SI 1 "const_int_operand" "") ; lower bound
6930 (match_operand:SI 2 "const_int_operand" "") ; total range
6931 (match_operand:SI 3 "" "") ; table label
6932 (match_operand:SI 4 "" "")] ; Out of range label
6937 if (operands[1] != const0_rtx)
6939 reg = gen_reg_rtx (SImode);
6941 emit_insn (gen_addsi3 (reg, operands[0],
6942 GEN_INT (-INTVAL (operands[1]))));
6946 if (!const_ok_for_arm (INTVAL (operands[2])))
6947 operands[2] = force_reg (SImode, operands[2]);
6949 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6955 ;; The USE in this pattern is needed to tell flow analysis that this is
6956 ;; a CASESI insn. It has no other purpose.
6957 (define_insn "casesi_internal"
6958 [(parallel [(set (pc)
6960 (leu (match_operand:SI 0 "s_register_operand" "r")
6961 (match_operand:SI 1 "arm_rhs_operand" "rI"))
6962 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6963 (label_ref (match_operand 2 "" ""))))
6964 (label_ref (match_operand 3 "" ""))))
6965 (clobber (reg:CC CC_REGNUM))
6966 (use (label_ref (match_dup 2)))])]
6970 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6971 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6973 [(set_attr "conds" "clob")
6974 (set_attr "length" "12")]
6977 (define_expand "indirect_jump"
6979 (match_operand:SI 0 "s_register_operand" ""))]
6984 (define_insn "*arm_indirect_jump"
6986 (match_operand:SI 0 "s_register_operand" "r"))]
6988 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6989 [(set_attr "predicable" "yes")]
6992 ;; Although not supported by the define_expand above,
6993 ;; cse/combine may generate this form.
6994 (define_insn "*load_indirect_jump"
6996 (match_operand:SI 0 "memory_operand" "m"))]
6998 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6999 [(set_attr "type" "load")
7000 (set_attr "pool_range" "4096")
7001 (set_attr "neg_pool_range" "4084")
7002 (set_attr "predicable" "yes")]
7005 (define_insn "*thumb_indirect_jump"
7007 (match_operand:SI 0 "register_operand" "l*r"))]
7010 [(set_attr "conds" "clob")
7011 (set_attr "length" "2")]
7022 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
7023 return \"mov\\tr8, r8\";
7025 [(set (attr "length")
7026 (if_then_else (eq_attr "is_thumb" "yes")
7032 ;; Patterns to allow combination of arithmetic, cond code and shifts
7034 (define_insn "*arith_shiftsi"
7035 [(set (match_operand:SI 0 "s_register_operand" "=r")
7036 (match_operator:SI 1 "shiftable_operator"
7037 [(match_operator:SI 3 "shift_operator"
7038 [(match_operand:SI 4 "s_register_operand" "r")
7039 (match_operand:SI 5 "reg_or_int_operand" "rI")])
7040 (match_operand:SI 2 "s_register_operand" "r")]))]
7042 "%i1%?\\t%0, %2, %4%S3"
7043 [(set_attr "predicable" "yes")
7044 (set_attr "shift" "4")
7048 (define_insn "*arith_shiftsi_compare0"
7049 [(set (reg:CC_NOOV CC_REGNUM)
7050 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7051 [(match_operator:SI 3 "shift_operator"
7052 [(match_operand:SI 4 "s_register_operand" "r")
7053 (match_operand:SI 5 "reg_or_int_operand" "rI")])
7054 (match_operand:SI 2 "s_register_operand" "r")])
7056 (set (match_operand:SI 0 "s_register_operand" "=r")
7057 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7060 "%i1%?s\\t%0, %2, %4%S3"
7061 [(set_attr "conds" "set")
7062 (set_attr "shift" "4")
7066 (define_insn "*arith_shiftsi_compare0_scratch"
7067 [(set (reg:CC_NOOV CC_REGNUM)
7068 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7069 [(match_operator:SI 3 "shift_operator"
7070 [(match_operand:SI 4 "s_register_operand" "r")
7071 (match_operand:SI 5 "reg_or_int_operand" "rI")])
7072 (match_operand:SI 2 "s_register_operand" "r")])
7074 (clobber (match_scratch:SI 0 "=r"))]
7076 "%i1%?s\\t%0, %2, %4%S3"
7077 [(set_attr "conds" "set")
7078 (set_attr "shift" "4")
7082 (define_insn "*sub_shiftsi"
7083 [(set (match_operand:SI 0 "s_register_operand" "=r")
7084 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7085 (match_operator:SI 2 "shift_operator"
7086 [(match_operand:SI 3 "s_register_operand" "r")
7087 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7089 "sub%?\\t%0, %1, %3%S2"
7090 [(set_attr "predicable" "yes")
7091 (set_attr "shift" "3")
7095 (define_insn "*sub_shiftsi_compare0"
7096 [(set (reg:CC_NOOV CC_REGNUM)
7098 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7099 (match_operator:SI 2 "shift_operator"
7100 [(match_operand:SI 3 "s_register_operand" "r")
7101 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7103 (set (match_operand:SI 0 "s_register_operand" "=r")
7104 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7107 "sub%?s\\t%0, %1, %3%S2"
7108 [(set_attr "conds" "set")
7109 (set_attr "shift" "3")
7113 (define_insn "*sub_shiftsi_compare0_scratch"
7114 [(set (reg:CC_NOOV CC_REGNUM)
7116 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7117 (match_operator:SI 2 "shift_operator"
7118 [(match_operand:SI 3 "s_register_operand" "r")
7119 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7121 (clobber (match_scratch:SI 0 "=r"))]
7123 "sub%?s\\t%0, %1, %3%S2"
7124 [(set_attr "conds" "set")
7125 (set_attr "shift" "3")
7131 (define_insn "*and_scc"
7132 [(set (match_operand:SI 0 "s_register_operand" "=r")
7133 (and:SI (match_operator:SI 1 "arm_comparison_operator"
7134 [(match_operand 3 "cc_register" "") (const_int 0)])
7135 (match_operand:SI 2 "s_register_operand" "r")))]
7137 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7138 [(set_attr "conds" "use")
7139 (set_attr "length" "8")]
7142 (define_insn "*ior_scc"
7143 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7144 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
7145 [(match_operand 3 "cc_register" "") (const_int 0)])
7146 (match_operand:SI 1 "s_register_operand" "0,?r")))]
7150 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7151 [(set_attr "conds" "use")
7152 (set_attr "length" "4,8")]
7155 (define_insn "*compare_scc"
7156 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7157 (match_operator:SI 1 "arm_comparison_operator"
7158 [(match_operand:SI 2 "s_register_operand" "r,r")
7159 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7160 (clobber (reg:CC CC_REGNUM))]
7163 if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
7164 return \"mov\\t%0, %2, lsr #31\";
7166 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
7167 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7169 if (GET_CODE (operands[1]) == NE)
7171 if (which_alternative == 1)
7172 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7173 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7175 if (which_alternative == 1)
7176 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7178 output_asm_insn (\"cmp\\t%2, %3\", operands);
7179 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7181 [(set_attr "conds" "clob")
7182 (set_attr "length" "12")]
7185 (define_insn "*cond_move"
7186 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7187 (if_then_else:SI (match_operator 3 "equality_operator"
7188 [(match_operator 4 "arm_comparison_operator"
7189 [(match_operand 5 "cc_register" "") (const_int 0)])
7191 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7192 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7195 if (GET_CODE (operands[3]) == NE)
7197 if (which_alternative != 1)
7198 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7199 if (which_alternative != 0)
7200 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7203 if (which_alternative != 0)
7204 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7205 if (which_alternative != 1)
7206 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7209 [(set_attr "conds" "use")
7210 (set_attr "length" "4,4,8")]
7213 (define_insn "*cond_arith"
7214 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7215 (match_operator:SI 5 "shiftable_operator"
7216 [(match_operator:SI 4 "arm_comparison_operator"
7217 [(match_operand:SI 2 "s_register_operand" "r,r")
7218 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7219 (match_operand:SI 1 "s_register_operand" "0,?r")]))
7220 (clobber (reg:CC CC_REGNUM))]
7223 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7224 return \"%i5\\t%0, %1, %2, lsr #31\";
7226 output_asm_insn (\"cmp\\t%2, %3\", operands);
7227 if (GET_CODE (operands[5]) == AND)
7228 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7229 else if (GET_CODE (operands[5]) == MINUS)
7230 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7231 else if (which_alternative != 0)
7232 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7233 return \"%i5%d4\\t%0, %1, #1\";
7235 [(set_attr "conds" "clob")
7236 (set_attr "length" "12")]
7239 (define_insn "*cond_sub"
7240 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7241 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7242 (match_operator:SI 4 "arm_comparison_operator"
7243 [(match_operand:SI 2 "s_register_operand" "r,r")
7244 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7245 (clobber (reg:CC CC_REGNUM))]
7248 output_asm_insn (\"cmp\\t%2, %3\", operands);
7249 if (which_alternative != 0)
7250 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7251 return \"sub%d4\\t%0, %1, #1\";
7253 [(set_attr "conds" "clob")
7254 (set_attr "length" "8,12")]
7257 (define_insn "*cmp_ite0"
7258 [(set (match_operand 6 "dominant_cc_register" "")
7261 (match_operator 4 "arm_comparison_operator"
7262 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7263 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7264 (match_operator:SI 5 "arm_comparison_operator"
7265 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7266 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7272 static const char * const opcodes[4][2] =
7274 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7275 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7276 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7277 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7278 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7279 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7280 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7281 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7284 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7286 return opcodes[which_alternative][swap];
7288 [(set_attr "conds" "set")
7289 (set_attr "length" "8")]
7292 (define_insn "*cmp_ite1"
7293 [(set (match_operand 6 "dominant_cc_register" "")
7296 (match_operator 4 "arm_comparison_operator"
7297 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7298 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7299 (match_operator:SI 5 "arm_comparison_operator"
7300 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7301 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7307 static const char * const opcodes[4][2] =
7309 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7310 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7311 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7312 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7313 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7314 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7315 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7316 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7319 comparison_dominates_p (GET_CODE (operands[5]),
7320 reverse_condition (GET_CODE (operands[4])));
7322 return opcodes[which_alternative][swap];
7324 [(set_attr "conds" "set")
7325 (set_attr "length" "8")]
7328 (define_insn "*cmp_and"
7329 [(set (match_operand 6 "dominant_cc_register" "")
7332 (match_operator 4 "arm_comparison_operator"
7333 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7334 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7335 (match_operator:SI 5 "arm_comparison_operator"
7336 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7337 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7342 static const char *const opcodes[4][2] =
7344 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7345 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7346 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7347 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7348 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7349 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7350 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7351 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7354 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7356 return opcodes[which_alternative][swap];
7358 [(set_attr "conds" "set")
7359 (set_attr "predicable" "no")
7360 (set_attr "length" "8")]
7363 (define_insn "*cmp_ior"
7364 [(set (match_operand 6 "dominant_cc_register" "")
7367 (match_operator 4 "arm_comparison_operator"
7368 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7369 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7370 (match_operator:SI 5 "arm_comparison_operator"
7371 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7372 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7377 static const char *const opcodes[4][2] =
7379 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7380 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7381 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7382 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7383 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7384 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7385 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7386 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7389 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7391 return opcodes[which_alternative][swap];
7394 [(set_attr "conds" "set")
7395 (set_attr "length" "8")]
7398 (define_insn "*negscc"
7399 [(set (match_operand:SI 0 "s_register_operand" "=r")
7400 (neg:SI (match_operator 3 "arm_comparison_operator"
7401 [(match_operand:SI 1 "s_register_operand" "r")
7402 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7403 (clobber (reg:CC CC_REGNUM))]
7406 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7407 return \"mov\\t%0, %1, asr #31\";
7409 if (GET_CODE (operands[3]) == NE)
7410 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7412 if (GET_CODE (operands[3]) == GT)
7413 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7415 output_asm_insn (\"cmp\\t%1, %2\", operands);
7416 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7417 return \"mvn%d3\\t%0, #0\";
7419 [(set_attr "conds" "clob")
7420 (set_attr "length" "12")]
7423 (define_insn "movcond"
7424 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7426 (match_operator 5 "arm_comparison_operator"
7427 [(match_operand:SI 3 "s_register_operand" "r,r,r")
7428 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7429 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7430 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
7431 (clobber (reg:CC CC_REGNUM))]
7434 if (GET_CODE (operands[5]) == LT
7435 && (operands[4] == const0_rtx))
7437 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7439 if (operands[2] == const0_rtx)
7440 return \"and\\t%0, %1, %3, asr #31\";
7441 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
7443 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7445 if (operands[1] == const0_rtx)
7446 return \"bic\\t%0, %2, %3, asr #31\";
7447 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
7449 /* The only case that falls through to here is when both ops 1 & 2
7453 if (GET_CODE (operands[5]) == GE
7454 && (operands[4] == const0_rtx))
7456 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7458 if (operands[2] == const0_rtx)
7459 return \"bic\\t%0, %1, %3, asr #31\";
7460 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7462 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7464 if (operands[1] == const0_rtx)
7465 return \"and\\t%0, %2, %3, asr #31\";
7466 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7468 /* The only case that falls through to here is when both ops 1 & 2
7471 if (GET_CODE (operands[4]) == CONST_INT
7472 && !const_ok_for_arm (INTVAL (operands[4])))
7473 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7475 output_asm_insn (\"cmp\\t%3, %4\", operands);
7476 if (which_alternative != 0)
7477 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7478 if (which_alternative != 1)
7479 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7482 [(set_attr "conds" "clob")
7483 (set_attr "length" "8,8,12")]
7486 (define_insn "*ifcompare_plus_move"
7487 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7488 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7489 [(match_operand:SI 4 "s_register_operand" "r,r")
7490 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7492 (match_operand:SI 2 "s_register_operand" "r,r")
7493 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7494 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7495 (clobber (reg:CC CC_REGNUM))]
7498 [(set_attr "conds" "clob")
7499 (set_attr "length" "8,12")]
7502 (define_insn "*if_plus_move"
7503 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7505 (match_operator 4 "arm_comparison_operator"
7506 [(match_operand 5 "cc_register" "") (const_int 0)])
7508 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7509 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7510 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7514 sub%d4\\t%0, %2, #%n3
7515 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7516 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7517 [(set_attr "conds" "use")
7518 (set_attr "length" "4,4,8,8")
7519 (set_attr "type" "*,*,*,*")]
7522 (define_insn "*ifcompare_move_plus"
7523 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7524 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7525 [(match_operand:SI 4 "s_register_operand" "r,r")
7526 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7527 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7529 (match_operand:SI 2 "s_register_operand" "r,r")
7530 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7531 (clobber (reg:CC CC_REGNUM))]
7534 [(set_attr "conds" "clob")
7535 (set_attr "length" "8,12")]
7538 (define_insn "*if_move_plus"
7539 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7541 (match_operator 4 "arm_comparison_operator"
7542 [(match_operand 5 "cc_register" "") (const_int 0)])
7543 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7545 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7546 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7550 sub%D4\\t%0, %2, #%n3
7551 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7552 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7553 [(set_attr "conds" "use")
7554 (set_attr "length" "4,4,8,8")
7555 (set_attr "type" "*,*,*,*")]
7558 (define_insn "*ifcompare_arith_arith"
7559 [(set (match_operand:SI 0 "s_register_operand" "=r")
7560 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7561 [(match_operand:SI 5 "s_register_operand" "r")
7562 (match_operand:SI 6 "arm_add_operand" "rIL")])
7563 (match_operator:SI 8 "shiftable_operator"
7564 [(match_operand:SI 1 "s_register_operand" "r")
7565 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7566 (match_operator:SI 7 "shiftable_operator"
7567 [(match_operand:SI 3 "s_register_operand" "r")
7568 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7569 (clobber (reg:CC CC_REGNUM))]
7572 [(set_attr "conds" "clob")
7573 (set_attr "length" "12")]
7576 (define_insn "*if_arith_arith"
7577 [(set (match_operand:SI 0 "s_register_operand" "=r")
7578 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7579 [(match_operand 8 "cc_register" "") (const_int 0)])
7580 (match_operator:SI 6 "shiftable_operator"
7581 [(match_operand:SI 1 "s_register_operand" "r")
7582 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7583 (match_operator:SI 7 "shiftable_operator"
7584 [(match_operand:SI 3 "s_register_operand" "r")
7585 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7587 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7588 [(set_attr "conds" "use")
7589 (set_attr "length" "8")]
7592 (define_insn "*ifcompare_arith_move"
7593 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7594 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7595 [(match_operand:SI 2 "s_register_operand" "r,r")
7596 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7597 (match_operator:SI 7 "shiftable_operator"
7598 [(match_operand:SI 4 "s_register_operand" "r,r")
7599 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7600 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7601 (clobber (reg:CC CC_REGNUM))]
7604 /* If we have an operation where (op x 0) is the identity operation and
7605 the conditional operator is LT or GE and we are comparing against zero and
7606 everything is in registers then we can do this in two instructions */
7607 if (operands[3] == const0_rtx
7608 && GET_CODE (operands[7]) != AND
7609 && GET_CODE (operands[5]) == REG
7610 && GET_CODE (operands[1]) == REG
7611 && REGNO (operands[1]) == REGNO (operands[4])
7612 && REGNO (operands[4]) != REGNO (operands[0]))
7614 if (GET_CODE (operands[6]) == LT)
7615 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7616 else if (GET_CODE (operands[6]) == GE)
7617 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7619 if (GET_CODE (operands[3]) == CONST_INT
7620 && !const_ok_for_arm (INTVAL (operands[3])))
7621 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7623 output_asm_insn (\"cmp\\t%2, %3\", operands);
7624 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7625 if (which_alternative != 0)
7626 return \"mov%D6\\t%0, %1\";
7629 [(set_attr "conds" "clob")
7630 (set_attr "length" "8,12")]
7633 (define_insn "*if_arith_move"
7634 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7635 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7636 [(match_operand 6 "cc_register" "") (const_int 0)])
7637 (match_operator:SI 5 "shiftable_operator"
7638 [(match_operand:SI 2 "s_register_operand" "r,r")
7639 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7640 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7644 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7645 [(set_attr "conds" "use")
7646 (set_attr "length" "4,8")
7647 (set_attr "type" "*,*")]
7650 (define_insn "*ifcompare_move_arith"
7651 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7652 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7653 [(match_operand:SI 4 "s_register_operand" "r,r")
7654 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7655 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7656 (match_operator:SI 7 "shiftable_operator"
7657 [(match_operand:SI 2 "s_register_operand" "r,r")
7658 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7659 (clobber (reg:CC CC_REGNUM))]
7662 /* If we have an operation where (op x 0) is the identity operation and
7663 the conditional operator is LT or GE and we are comparing against zero and
7664 everything is in registers then we can do this in two instructions */
7665 if (operands[5] == const0_rtx
7666 && GET_CODE (operands[7]) != AND
7667 && GET_CODE (operands[3]) == REG
7668 && GET_CODE (operands[1]) == REG
7669 && REGNO (operands[1]) == REGNO (operands[2])
7670 && REGNO (operands[2]) != REGNO (operands[0]))
7672 if (GET_CODE (operands[6]) == GE)
7673 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7674 else if (GET_CODE (operands[6]) == LT)
7675 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7678 if (GET_CODE (operands[5]) == CONST_INT
7679 && !const_ok_for_arm (INTVAL (operands[5])))
7680 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7682 output_asm_insn (\"cmp\\t%4, %5\", operands);
7684 if (which_alternative != 0)
7685 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7686 return \"%I7%D6\\t%0, %2, %3\";
7688 [(set_attr "conds" "clob")
7689 (set_attr "length" "8,12")]
7692 (define_insn "*if_move_arith"
7693 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7695 (match_operator 4 "arm_comparison_operator"
7696 [(match_operand 6 "cc_register" "") (const_int 0)])
7697 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7698 (match_operator:SI 5 "shiftable_operator"
7699 [(match_operand:SI 2 "s_register_operand" "r,r")
7700 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7704 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7705 [(set_attr "conds" "use")
7706 (set_attr "length" "4,8")
7707 (set_attr "type" "*,*")]
7710 (define_insn "*ifcompare_move_not"
7711 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7713 (match_operator 5 "arm_comparison_operator"
7714 [(match_operand:SI 3 "s_register_operand" "r,r")
7715 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7716 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7718 (match_operand:SI 2 "s_register_operand" "r,r"))))
7719 (clobber (reg:CC CC_REGNUM))]
7722 [(set_attr "conds" "clob")
7723 (set_attr "length" "8,12")]
7726 (define_insn "*if_move_not"
7727 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7729 (match_operator 4 "arm_comparison_operator"
7730 [(match_operand 3 "cc_register" "") (const_int 0)])
7731 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7732 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7736 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7737 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7738 [(set_attr "conds" "use")
7739 (set_attr "length" "4,8,8")]
7742 (define_insn "*ifcompare_not_move"
7743 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7745 (match_operator 5 "arm_comparison_operator"
7746 [(match_operand:SI 3 "s_register_operand" "r,r")
7747 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7749 (match_operand:SI 2 "s_register_operand" "r,r"))
7750 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7751 (clobber (reg:CC CC_REGNUM))]
7754 [(set_attr "conds" "clob")
7755 (set_attr "length" "8,12")]
7758 (define_insn "*if_not_move"
7759 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7761 (match_operator 4 "arm_comparison_operator"
7762 [(match_operand 3 "cc_register" "") (const_int 0)])
7763 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7764 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7768 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7769 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7770 [(set_attr "conds" "use")
7771 (set_attr "length" "4,8,8")]
7774 (define_insn "*ifcompare_shift_move"
7775 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7777 (match_operator 6 "arm_comparison_operator"
7778 [(match_operand:SI 4 "s_register_operand" "r,r")
7779 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7780 (match_operator:SI 7 "shift_operator"
7781 [(match_operand:SI 2 "s_register_operand" "r,r")
7782 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7783 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7784 (clobber (reg:CC CC_REGNUM))]
7787 [(set_attr "conds" "clob")
7788 (set_attr "length" "8,12")]
7791 (define_insn "*if_shift_move"
7792 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7794 (match_operator 5 "arm_comparison_operator"
7795 [(match_operand 6 "cc_register" "") (const_int 0)])
7796 (match_operator:SI 4 "shift_operator"
7797 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7798 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7799 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7803 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7804 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7805 [(set_attr "conds" "use")
7806 (set_attr "shift" "2")
7807 (set_attr "length" "4,8,8")]
7810 (define_insn "*ifcompare_move_shift"
7811 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7813 (match_operator 6 "arm_comparison_operator"
7814 [(match_operand:SI 4 "s_register_operand" "r,r")
7815 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7816 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7817 (match_operator:SI 7 "shift_operator"
7818 [(match_operand:SI 2 "s_register_operand" "r,r")
7819 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7820 (clobber (reg:CC CC_REGNUM))]
7823 [(set_attr "conds" "clob")
7824 (set_attr "length" "8,12")]
7827 (define_insn "*if_move_shift"
7828 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7830 (match_operator 5 "arm_comparison_operator"
7831 [(match_operand 6 "cc_register" "") (const_int 0)])
7832 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7833 (match_operator:SI 4 "shift_operator"
7834 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7835 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7839 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7840 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7841 [(set_attr "conds" "use")
7842 (set_attr "shift" "2")
7843 (set_attr "length" "4,8,8")]
7846 (define_insn "*ifcompare_shift_shift"
7847 [(set (match_operand:SI 0 "s_register_operand" "=r")
7849 (match_operator 7 "arm_comparison_operator"
7850 [(match_operand:SI 5 "s_register_operand" "r")
7851 (match_operand:SI 6 "arm_add_operand" "rIL")])
7852 (match_operator:SI 8 "shift_operator"
7853 [(match_operand:SI 1 "s_register_operand" "r")
7854 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7855 (match_operator:SI 9 "shift_operator"
7856 [(match_operand:SI 3 "s_register_operand" "r")
7857 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7858 (clobber (reg:CC CC_REGNUM))]
7861 [(set_attr "conds" "clob")
7862 (set_attr "length" "12")]
7865 (define_insn "*if_shift_shift"
7866 [(set (match_operand:SI 0 "s_register_operand" "=r")
7868 (match_operator 5 "arm_comparison_operator"
7869 [(match_operand 8 "cc_register" "") (const_int 0)])
7870 (match_operator:SI 6 "shift_operator"
7871 [(match_operand:SI 1 "s_register_operand" "r")
7872 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7873 (match_operator:SI 7 "shift_operator"
7874 [(match_operand:SI 3 "s_register_operand" "r")
7875 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7877 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7878 [(set_attr "conds" "use")
7879 (set_attr "shift" "1")
7880 (set_attr "length" "8")]
7883 (define_insn "*ifcompare_not_arith"
7884 [(set (match_operand:SI 0 "s_register_operand" "=r")
7886 (match_operator 6 "arm_comparison_operator"
7887 [(match_operand:SI 4 "s_register_operand" "r")
7888 (match_operand:SI 5 "arm_add_operand" "rIL")])
7889 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7890 (match_operator:SI 7 "shiftable_operator"
7891 [(match_operand:SI 2 "s_register_operand" "r")
7892 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7893 (clobber (reg:CC CC_REGNUM))]
7896 [(set_attr "conds" "clob")
7897 (set_attr "length" "12")]
7900 (define_insn "*if_not_arith"
7901 [(set (match_operand:SI 0 "s_register_operand" "=r")
7903 (match_operator 5 "arm_comparison_operator"
7904 [(match_operand 4 "cc_register" "") (const_int 0)])
7905 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7906 (match_operator:SI 6 "shiftable_operator"
7907 [(match_operand:SI 2 "s_register_operand" "r")
7908 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7910 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7911 [(set_attr "conds" "use")
7912 (set_attr "length" "8")]
7915 (define_insn "*ifcompare_arith_not"
7916 [(set (match_operand:SI 0 "s_register_operand" "=r")
7918 (match_operator 6 "arm_comparison_operator"
7919 [(match_operand:SI 4 "s_register_operand" "r")
7920 (match_operand:SI 5 "arm_add_operand" "rIL")])
7921 (match_operator:SI 7 "shiftable_operator"
7922 [(match_operand:SI 2 "s_register_operand" "r")
7923 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7924 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7925 (clobber (reg:CC CC_REGNUM))]
7928 [(set_attr "conds" "clob")
7929 (set_attr "length" "12")]
7932 (define_insn "*if_arith_not"
7933 [(set (match_operand:SI 0 "s_register_operand" "=r")
7935 (match_operator 5 "arm_comparison_operator"
7936 [(match_operand 4 "cc_register" "") (const_int 0)])
7937 (match_operator:SI 6 "shiftable_operator"
7938 [(match_operand:SI 2 "s_register_operand" "r")
7939 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7940 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7942 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7943 [(set_attr "conds" "use")
7944 (set_attr "length" "8")]
7947 (define_insn "*ifcompare_neg_move"
7948 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7950 (match_operator 5 "arm_comparison_operator"
7951 [(match_operand:SI 3 "s_register_operand" "r,r")
7952 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7953 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7954 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7955 (clobber (reg:CC CC_REGNUM))]
7958 [(set_attr "conds" "clob")
7959 (set_attr "length" "8,12")]
7962 (define_insn "*if_neg_move"
7963 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7965 (match_operator 4 "arm_comparison_operator"
7966 [(match_operand 3 "cc_register" "") (const_int 0)])
7967 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7968 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7972 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7973 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
7974 [(set_attr "conds" "use")
7975 (set_attr "length" "4,8,8")]
7978 (define_insn "*ifcompare_move_neg"
7979 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7981 (match_operator 5 "arm_comparison_operator"
7982 [(match_operand:SI 3 "s_register_operand" "r,r")
7983 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7984 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7985 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
7986 (clobber (reg:CC CC_REGNUM))]
7989 [(set_attr "conds" "clob")
7990 (set_attr "length" "8,12")]
7993 (define_insn "*if_move_neg"
7994 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7996 (match_operator 4 "arm_comparison_operator"
7997 [(match_operand 3 "cc_register" "") (const_int 0)])
7998 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7999 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8003 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
8004 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
8005 [(set_attr "conds" "use")
8006 (set_attr "length" "4,8,8")]
8009 (define_insn "*arith_adjacentmem"
8010 [(set (match_operand:SI 0 "s_register_operand" "=r")
8011 (match_operator:SI 1 "shiftable_operator"
8012 [(match_operand:SI 2 "memory_operand" "m")
8013 (match_operand:SI 3 "memory_operand" "m")]))
8014 (clobber (match_scratch:SI 4 "=r"))]
8015 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
8020 int val1 = 0, val2 = 0;
8022 if (REGNO (operands[0]) > REGNO (operands[4]))
8024 ldm[1] = operands[4];
8025 ldm[2] = operands[0];
8029 ldm[1] = operands[0];
8030 ldm[2] = operands[4];
8032 if (GET_CODE (XEXP (operands[2], 0)) != REG)
8033 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
8034 if (GET_CODE (XEXP (operands[3], 0)) != REG)
8035 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
8036 arith[0] = operands[0];
8037 arith[3] = operands[1];
8051 ldm[0] = ops[0] = operands[4];
8052 ops[1] = XEXP (XEXP (operands[2], 0), 0);
8053 ops[2] = XEXP (XEXP (operands[2], 0), 1);
8054 output_add_immediate (ops);
8056 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8058 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8062 ldm[0] = XEXP (operands[3], 0);
8064 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8066 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8070 ldm[0] = XEXP (operands[2], 0);
8072 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8074 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8076 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
8079 [(set_attr "length" "12")
8080 (set_attr "predicable" "yes")
8081 (set_attr "type" "load")]
8084 ;; the arm can support extended pre-inc instructions
8086 ;; In all these cases, we use operands 0 and 1 for the register being
8087 ;; incremented because those are the operands that local-alloc will
8088 ;; tie and these are the pair most likely to be tieable (and the ones
8089 ;; that will benefit the most).
8091 ;; We reject the frame pointer if it occurs anywhere in these patterns since
8092 ;; elimination will cause too many headaches.
8094 (define_insn "*strqi_preinc"
8095 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8096 (match_operand:SI 2 "index_operand" "rJ")))
8097 (match_operand:QI 3 "s_register_operand" "r"))
8098 (set (match_operand:SI 0 "s_register_operand" "=r")
8099 (plus:SI (match_dup 1) (match_dup 2)))]
8101 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8102 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8103 && (GET_CODE (operands[2]) != REG
8104 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8105 "str%?b\\t%3, [%0, %2]!"
8106 [(set_attr "type" "store1")
8107 (set_attr "predicable" "yes")]
8110 (define_insn "*strqi_predec"
8111 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8112 (match_operand:SI 2 "s_register_operand" "r")))
8113 (match_operand:QI 3 "s_register_operand" "r"))
8114 (set (match_operand:SI 0 "s_register_operand" "=r")
8115 (minus:SI (match_dup 1) (match_dup 2)))]
8117 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8118 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8119 && (GET_CODE (operands[2]) != REG
8120 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8121 "str%?b\\t%3, [%0, -%2]!"
8122 [(set_attr "type" "store1")
8123 (set_attr "predicable" "yes")]
8126 (define_insn "*loadqi_preinc"
8127 [(set (match_operand:QI 3 "s_register_operand" "=r")
8128 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8129 (match_operand:SI 2 "index_operand" "rJ"))))
8130 (set (match_operand:SI 0 "s_register_operand" "=r")
8131 (plus:SI (match_dup 1) (match_dup 2)))]
8133 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8134 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8135 && (GET_CODE (operands[2]) != REG
8136 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8137 "ldr%?b\\t%3, [%0, %2]!"
8138 [(set_attr "type" "load")
8139 (set_attr "predicable" "yes")]
8142 (define_insn "*loadqi_predec"
8143 [(set (match_operand:QI 3 "s_register_operand" "=r")
8144 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8145 (match_operand:SI 2 "s_register_operand" "r"))))
8146 (set (match_operand:SI 0 "s_register_operand" "=r")
8147 (minus:SI (match_dup 1) (match_dup 2)))]
8149 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8150 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8151 && (GET_CODE (operands[2]) != REG
8152 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8153 "ldr%?b\\t%3, [%0, -%2]!"
8154 [(set_attr "type" "load")
8155 (set_attr "predicable" "yes")]
8158 (define_insn "*loadqisi_preinc"
8159 [(set (match_operand:SI 3 "s_register_operand" "=r")
8161 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8162 (match_operand:SI 2 "index_operand" "rJ")))))
8163 (set (match_operand:SI 0 "s_register_operand" "=r")
8164 (plus:SI (match_dup 1) (match_dup 2)))]
8166 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8167 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8168 && (GET_CODE (operands[2]) != REG
8169 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8170 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8171 [(set_attr "type" "load")
8172 (set_attr "predicable" "yes")]
8175 (define_insn "*loadqisi_predec"
8176 [(set (match_operand:SI 3 "s_register_operand" "=r")
8178 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8179 (match_operand:SI 2 "s_register_operand" "r")))))
8180 (set (match_operand:SI 0 "s_register_operand" "=r")
8181 (minus:SI (match_dup 1) (match_dup 2)))]
8183 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8184 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8185 && (GET_CODE (operands[2]) != REG
8186 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8187 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8188 [(set_attr "type" "load")
8189 (set_attr "predicable" "yes")]
8192 (define_insn "*strsi_preinc"
8193 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8194 (match_operand:SI 2 "index_operand" "rJ")))
8195 (match_operand:SI 3 "s_register_operand" "r"))
8196 (set (match_operand:SI 0 "s_register_operand" "=r")
8197 (plus:SI (match_dup 1) (match_dup 2)))]
8199 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8200 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8201 && (GET_CODE (operands[2]) != REG
8202 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8203 "str%?\\t%3, [%0, %2]!"
8204 [(set_attr "type" "store1")
8205 (set_attr "predicable" "yes")]
8208 (define_insn "*strsi_predec"
8209 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8210 (match_operand:SI 2 "s_register_operand" "r")))
8211 (match_operand:SI 3 "s_register_operand" "r"))
8212 (set (match_operand:SI 0 "s_register_operand" "=r")
8213 (minus:SI (match_dup 1) (match_dup 2)))]
8215 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8216 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8217 && (GET_CODE (operands[2]) != REG
8218 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8219 "str%?\\t%3, [%0, -%2]!"
8220 [(set_attr "type" "store1")
8221 (set_attr "predicable" "yes")]
8224 (define_insn "*loadsi_preinc"
8225 [(set (match_operand:SI 3 "s_register_operand" "=r")
8226 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8227 (match_operand:SI 2 "index_operand" "rJ"))))
8228 (set (match_operand:SI 0 "s_register_operand" "=r")
8229 (plus:SI (match_dup 1) (match_dup 2)))]
8231 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8232 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8233 && (GET_CODE (operands[2]) != REG
8234 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8235 "ldr%?\\t%3, [%0, %2]!"
8236 [(set_attr "type" "load")
8237 (set_attr "predicable" "yes")]
8240 (define_insn "*loadsi_predec"
8241 [(set (match_operand:SI 3 "s_register_operand" "=r")
8242 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8243 (match_operand:SI 2 "s_register_operand" "r"))))
8244 (set (match_operand:SI 0 "s_register_operand" "=r")
8245 (minus:SI (match_dup 1) (match_dup 2)))]
8247 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8248 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8249 && (GET_CODE (operands[2]) != REG
8250 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8251 "ldr%?\\t%3, [%0, -%2]!"
8252 [(set_attr "type" "load")
8253 (set_attr "predicable" "yes")]
8256 (define_insn "*loadhi_preinc"
8257 [(set (match_operand:HI 3 "s_register_operand" "=r")
8258 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8259 (match_operand:SI 2 "index_operand" "rJ"))))
8260 (set (match_operand:SI 0 "s_register_operand" "=r")
8261 (plus:SI (match_dup 1) (match_dup 2)))]
8263 && !BYTES_BIG_ENDIAN
8264 && !TARGET_MMU_TRAPS
8266 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8267 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8268 && (GET_CODE (operands[2]) != REG
8269 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8270 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8271 [(set_attr "type" "load")
8272 (set_attr "predicable" "yes")]
8275 (define_insn "*loadhi_predec"
8276 [(set (match_operand:HI 3 "s_register_operand" "=r")
8277 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8278 (match_operand:SI 2 "s_register_operand" "r"))))
8279 (set (match_operand:SI 0 "s_register_operand" "=r")
8280 (minus:SI (match_dup 1) (match_dup 2)))]
8282 && !BYTES_BIG_ENDIAN
8283 && !TARGET_MMU_TRAPS
8285 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8286 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8287 && (GET_CODE (operands[2]) != REG
8288 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8289 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8290 [(set_attr "type" "load")
8291 (set_attr "predicable" "yes")]
8294 (define_insn "*strqi_shiftpreinc"
8295 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8296 [(match_operand:SI 3 "s_register_operand" "r")
8297 (match_operand:SI 4 "const_shift_operand" "n")])
8298 (match_operand:SI 1 "s_register_operand" "0")))
8299 (match_operand:QI 5 "s_register_operand" "r"))
8300 (set (match_operand:SI 0 "s_register_operand" "=r")
8301 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8304 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8305 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8306 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8307 "str%?b\\t%5, [%0, %3%S2]!"
8308 [(set_attr "type" "store1")
8309 (set_attr "predicable" "yes")]
8312 (define_insn "*strqi_shiftpredec"
8313 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8314 (match_operator:SI 2 "shift_operator"
8315 [(match_operand:SI 3 "s_register_operand" "r")
8316 (match_operand:SI 4 "const_shift_operand" "n")])))
8317 (match_operand:QI 5 "s_register_operand" "r"))
8318 (set (match_operand:SI 0 "s_register_operand" "=r")
8319 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8322 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8323 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8324 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8325 "str%?b\\t%5, [%0, -%3%S2]!"
8326 [(set_attr "type" "store1")
8327 (set_attr "predicable" "yes")]
8330 (define_insn "*loadqi_shiftpreinc"
8331 [(set (match_operand:QI 5 "s_register_operand" "=r")
8332 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8333 [(match_operand:SI 3 "s_register_operand" "r")
8334 (match_operand:SI 4 "const_shift_operand" "n")])
8335 (match_operand:SI 1 "s_register_operand" "0"))))
8336 (set (match_operand:SI 0 "s_register_operand" "=r")
8337 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8340 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8341 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8342 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8343 "ldr%?b\\t%5, [%0, %3%S2]!"
8344 [(set_attr "type" "load")
8345 (set_attr "predicable" "yes")]
8348 (define_insn "*loadqi_shiftpredec"
8349 [(set (match_operand:QI 5 "s_register_operand" "=r")
8350 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8351 (match_operator:SI 2 "shift_operator"
8352 [(match_operand:SI 3 "s_register_operand" "r")
8353 (match_operand:SI 4 "const_shift_operand" "n")]))))
8354 (set (match_operand:SI 0 "s_register_operand" "=r")
8355 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8358 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8359 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8360 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8361 "ldr%?b\\t%5, [%0, -%3%S2]!"
8362 [(set_attr "type" "load")
8363 (set_attr "predicable" "yes")]
8366 (define_insn "*strsi_shiftpreinc"
8367 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8368 [(match_operand:SI 3 "s_register_operand" "r")
8369 (match_operand:SI 4 "const_shift_operand" "n")])
8370 (match_operand:SI 1 "s_register_operand" "0")))
8371 (match_operand:SI 5 "s_register_operand" "r"))
8372 (set (match_operand:SI 0 "s_register_operand" "=r")
8373 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8376 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8377 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8378 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8379 "str%?\\t%5, [%0, %3%S2]!"
8380 [(set_attr "type" "store1")
8381 (set_attr "predicable" "yes")]
8384 (define_insn "*strsi_shiftpredec"
8385 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8386 (match_operator:SI 2 "shift_operator"
8387 [(match_operand:SI 3 "s_register_operand" "r")
8388 (match_operand:SI 4 "const_shift_operand" "n")])))
8389 (match_operand:SI 5 "s_register_operand" "r"))
8390 (set (match_operand:SI 0 "s_register_operand" "=r")
8391 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8394 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8395 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8396 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8397 "str%?\\t%5, [%0, -%3%S2]!"
8398 [(set_attr "type" "store1")
8399 (set_attr "predicable" "yes")]
8402 (define_insn "*loadsi_shiftpreinc"
8403 [(set (match_operand:SI 5 "s_register_operand" "=r")
8404 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8405 [(match_operand:SI 3 "s_register_operand" "r")
8406 (match_operand:SI 4 "const_shift_operand" "n")])
8407 (match_operand:SI 1 "s_register_operand" "0"))))
8408 (set (match_operand:SI 0 "s_register_operand" "=r")
8409 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8412 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8413 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8414 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8415 "ldr%?\\t%5, [%0, %3%S2]!"
8416 [(set_attr "type" "load")
8417 (set_attr "predicable" "yes")]
8420 (define_insn "*loadsi_shiftpredec"
8421 [(set (match_operand:SI 5 "s_register_operand" "=r")
8422 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8423 (match_operator:SI 2 "shift_operator"
8424 [(match_operand:SI 3 "s_register_operand" "r")
8425 (match_operand:SI 4 "const_shift_operand" "n")]))))
8426 (set (match_operand:SI 0 "s_register_operand" "=r")
8427 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8430 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8431 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8432 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8433 "ldr%?\\t%5, [%0, -%3%S2]!"
8434 [(set_attr "type" "load")
8435 (set_attr "predicable" "yes")])
8437 (define_insn "*loadhi_shiftpreinc"
8438 [(set (match_operand:HI 5 "s_register_operand" "=r")
8439 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8440 [(match_operand:SI 3 "s_register_operand" "r")
8441 (match_operand:SI 4 "const_shift_operand" "n")])
8442 (match_operand:SI 1 "s_register_operand" "0"))))
8443 (set (match_operand:SI 0 "s_register_operand" "=r")
8444 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8447 && !BYTES_BIG_ENDIAN
8448 && !TARGET_MMU_TRAPS
8450 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8451 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8452 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8453 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8454 [(set_attr "type" "load")
8455 (set_attr "predicable" "yes")]
8458 (define_insn "*loadhi_shiftpredec"
8459 [(set (match_operand:HI 5 "s_register_operand" "=r")
8460 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8461 (match_operator:SI 2 "shift_operator"
8462 [(match_operand:SI 3 "s_register_operand" "r")
8463 (match_operand:SI 4 "const_shift_operand" "n")]))))
8464 (set (match_operand:SI 0 "s_register_operand" "=r")
8465 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8468 && !BYTES_BIG_ENDIAN
8469 && !TARGET_MMU_TRAPS
8471 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8472 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8473 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8474 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8475 [(set_attr "type" "load")
8476 (set_attr "predicable" "yes")]
8479 ; It can also support extended post-inc expressions, but combine doesn't
8481 ; It doesn't seem worth adding peepholes for anything but the most common
8482 ; cases since, unlike combine, the increment must immediately follow the load
8483 ; for this pattern to match.
8484 ; We must watch to see that the source/destination register isn't also the
8485 ; same as the base address register, and that if the index is a register,
8486 ; that it is not the same as the base address register. In such cases the
8487 ; instruction that we would generate would have UNPREDICTABLE behavior so
8491 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8492 (match_operand:QI 2 "s_register_operand" "r"))
8494 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8496 && (REGNO (operands[2]) != REGNO (operands[0]))
8497 && (GET_CODE (operands[1]) != REG
8498 || (REGNO (operands[1]) != REGNO (operands[0])))"
8499 "str%?b\\t%2, [%0], %1"
8503 [(set (match_operand:QI 0 "s_register_operand" "=r")
8504 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8506 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8508 && REGNO (operands[0]) != REGNO(operands[1])
8509 && (GET_CODE (operands[2]) != REG
8510 || REGNO(operands[0]) != REGNO (operands[2]))"
8511 "ldr%?b\\t%0, [%1], %2"
8515 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8516 (match_operand:SI 2 "s_register_operand" "r"))
8518 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8520 && (REGNO (operands[2]) != REGNO (operands[0]))
8521 && (GET_CODE (operands[1]) != REG
8522 || (REGNO (operands[1]) != REGNO (operands[0])))"
8523 "str%?\\t%2, [%0], %1"
8527 [(set (match_operand:HI 0 "s_register_operand" "=r")
8528 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8530 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8532 && !BYTES_BIG_ENDIAN
8533 && !TARGET_MMU_TRAPS
8535 && REGNO (operands[0]) != REGNO(operands[1])
8536 && (GET_CODE (operands[2]) != REG
8537 || REGNO(operands[0]) != REGNO (operands[2]))"
8538 "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8542 [(set (match_operand:SI 0 "s_register_operand" "=r")
8543 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8545 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8547 && REGNO (operands[0]) != REGNO(operands[1])
8548 && (GET_CODE (operands[2]) != REG
8549 || REGNO(operands[0]) != REGNO (operands[2]))"
8550 "ldr%?\\t%0, [%1], %2"
8554 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8555 (match_operand:SI 1 "index_operand" "rJ")))
8556 (match_operand:QI 2 "s_register_operand" "r"))
8557 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8559 && (REGNO (operands[2]) != REGNO (operands[0]))
8560 && (GET_CODE (operands[1]) != REG
8561 || (REGNO (operands[1]) != REGNO (operands[0])))"
8562 "str%?b\\t%2, [%0, %1]!"
8566 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8567 [(match_operand:SI 0 "s_register_operand" "r")
8568 (match_operand:SI 1 "const_int_operand" "n")])
8569 (match_operand:SI 2 "s_register_operand" "+r")))
8570 (match_operand:QI 3 "s_register_operand" "r"))
8571 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8574 && (REGNO (operands[3]) != REGNO (operands[2]))
8575 && (REGNO (operands[0]) != REGNO (operands[2]))"
8576 "str%?b\\t%3, [%2, %0%S4]!"
8579 ; This pattern is never tried by combine, so do it as a peephole
8582 [(set (match_operand:SI 0 "s_register_operand" "")
8583 (match_operand:SI 1 "s_register_operand" ""))
8584 (set (reg:CC CC_REGNUM)
8585 (compare:CC (match_dup 1) (const_int 0)))]
8588 || (!cirrus_fp_register (operands[0], SImode)
8589 && !cirrus_fp_register (operands[1], SImode)))
8591 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8592 (set (match_dup 0) (match_dup 1))])]
8596 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8597 ; reversed, check that the memory references aren't volatile.
8600 [(set (match_operand:SI 0 "s_register_operand" "=r")
8601 (match_operand:SI 4 "memory_operand" "m"))
8602 (set (match_operand:SI 1 "s_register_operand" "=r")
8603 (match_operand:SI 5 "memory_operand" "m"))
8604 (set (match_operand:SI 2 "s_register_operand" "=r")
8605 (match_operand:SI 6 "memory_operand" "m"))
8606 (set (match_operand:SI 3 "s_register_operand" "=r")
8607 (match_operand:SI 7 "memory_operand" "m"))]
8608 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8610 return emit_ldm_seq (operands, 4);
8615 [(set (match_operand:SI 0 "s_register_operand" "=r")
8616 (match_operand:SI 3 "memory_operand" "m"))
8617 (set (match_operand:SI 1 "s_register_operand" "=r")
8618 (match_operand:SI 4 "memory_operand" "m"))
8619 (set (match_operand:SI 2 "s_register_operand" "=r")
8620 (match_operand:SI 5 "memory_operand" "m"))]
8621 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8623 return emit_ldm_seq (operands, 3);
8628 [(set (match_operand:SI 0 "s_register_operand" "=r")
8629 (match_operand:SI 2 "memory_operand" "m"))
8630 (set (match_operand:SI 1 "s_register_operand" "=r")
8631 (match_operand:SI 3 "memory_operand" "m"))]
8632 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8634 return emit_ldm_seq (operands, 2);
8639 [(set (match_operand:SI 4 "memory_operand" "=m")
8640 (match_operand:SI 0 "s_register_operand" "r"))
8641 (set (match_operand:SI 5 "memory_operand" "=m")
8642 (match_operand:SI 1 "s_register_operand" "r"))
8643 (set (match_operand:SI 6 "memory_operand" "=m")
8644 (match_operand:SI 2 "s_register_operand" "r"))
8645 (set (match_operand:SI 7 "memory_operand" "=m")
8646 (match_operand:SI 3 "s_register_operand" "r"))]
8647 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8649 return emit_stm_seq (operands, 4);
8654 [(set (match_operand:SI 3 "memory_operand" "=m")
8655 (match_operand:SI 0 "s_register_operand" "r"))
8656 (set (match_operand:SI 4 "memory_operand" "=m")
8657 (match_operand:SI 1 "s_register_operand" "r"))
8658 (set (match_operand:SI 5 "memory_operand" "=m")
8659 (match_operand:SI 2 "s_register_operand" "r"))]
8660 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8662 return emit_stm_seq (operands, 3);
8667 [(set (match_operand:SI 2 "memory_operand" "=m")
8668 (match_operand:SI 0 "s_register_operand" "r"))
8669 (set (match_operand:SI 3 "memory_operand" "=m")
8670 (match_operand:SI 1 "s_register_operand" "r"))]
8671 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8673 return emit_stm_seq (operands, 2);
8678 [(set (match_operand:SI 0 "s_register_operand" "")
8679 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8681 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8682 [(match_operand:SI 3 "s_register_operand" "")
8683 (match_operand:SI 4 "arm_rhs_operand" "")]))))
8684 (clobber (match_operand:SI 5 "s_register_operand" ""))]
8686 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8687 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8692 ;; This split can be used because CC_Z mode implies that the following
8693 ;; branch will be an equality, or an unsigned inequality, so the sign
8694 ;; extension is not needed.
8697 [(set (reg:CC_Z CC_REGNUM)
8699 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8701 (match_operand 1 "const_int_operand" "")))
8702 (clobber (match_scratch:SI 2 ""))]
8704 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8705 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8706 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8707 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8709 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8713 (define_expand "prologue"
8714 [(clobber (const_int 0))]
8717 arm_expand_prologue ();
8719 thumb_expand_prologue ();
8724 (define_expand "epilogue"
8725 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8729 thumb_expand_epilogue ();
8730 else if (USE_RETURN_INSN (FALSE))
8732 emit_jump_insn (gen_return ());
8735 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8737 gen_rtx_RETURN (VOIDmode)),
8743 ;; Note - although unspec_volatile's USE all hard registers,
8744 ;; USEs are ignored after relaod has completed. Thus we need
8745 ;; to add an unspec of the link register to ensure that flow
8746 ;; does not think that it is unused by the sibcall branch that
8747 ;; will replace the standard function epilogue.
8748 (define_insn "sibcall_epilogue"
8749 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
8750 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
8753 if (USE_RETURN_INSN (FALSE))
8754 return output_return_instruction (const_true_rtx, FALSE, FALSE);
8755 return arm_output_epilogue (FALSE);
8757 ;; Length is absolute worst case
8758 [(set_attr "length" "44")
8759 (set_attr "type" "block")
8760 ;; We don't clobber the conditions, but the potential length of this
8761 ;; operation is sufficient to make conditionalizing the sequence
8762 ;; unlikely to be profitable.
8763 (set_attr "conds" "clob")]
8766 (define_insn "*epilogue_insns"
8767 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8771 return arm_output_epilogue (TRUE);
8772 else /* TARGET_THUMB */
8773 return thumb_unexpanded_epilogue ();
8775 ; Length is absolute worst case
8776 [(set_attr "length" "44")
8777 (set_attr "type" "block")
8778 ;; We don't clobber the conditions, but the potential length of this
8779 ;; operation is sufficient to make conditionalizing the sequence
8780 ;; unlikely to be profitable.
8781 (set_attr "conds" "clob")]
8784 (define_expand "eh_epilogue"
8785 [(use (match_operand:SI 0 "register_operand" "r"))
8786 (use (match_operand:SI 1 "register_operand" "r"))
8787 (use (match_operand:SI 2 "register_operand" "r"))]
8791 cfun->machine->eh_epilogue_sp_ofs = operands[1];
8792 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8794 rtx ra = gen_rtx_REG (Pmode, 2);
8796 emit_move_insn (ra, operands[2]);
8799 /* This is a hack -- we may have crystalized the function type too
8801 cfun->machine->func_type = 0;
8805 ;; This split is only used during output to reduce the number of patterns
8806 ;; that need assembler instructions adding to them. We allowed the setting
8807 ;; of the conditions to be implicit during rtl generation so that
8808 ;; the conditional compare patterns would work. However this conflicts to
8809 ;; some extent with the conditional data operations, so we have to split them
8813 [(set (match_operand:SI 0 "s_register_operand" "")
8814 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8815 [(match_operand 2 "" "") (match_operand 3 "" "")])
8817 (match_operand 4 "" "")))
8818 (clobber (reg:CC CC_REGNUM))]
8819 "TARGET_ARM && reload_completed"
8820 [(set (match_dup 5) (match_dup 6))
8821 (cond_exec (match_dup 7)
8822 (set (match_dup 0) (match_dup 4)))]
8825 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8826 operands[2], operands[3]);
8827 enum rtx_code rc = GET_CODE (operands[1]);
8829 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8830 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8831 if (mode == CCFPmode || mode == CCFPEmode)
8832 rc = reverse_condition_maybe_unordered (rc);
8834 rc = reverse_condition (rc);
8836 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8841 [(set (match_operand:SI 0 "s_register_operand" "")
8842 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8843 [(match_operand 2 "" "") (match_operand 3 "" "")])
8844 (match_operand 4 "" "")
8846 (clobber (reg:CC CC_REGNUM))]
8847 "TARGET_ARM && reload_completed"
8848 [(set (match_dup 5) (match_dup 6))
8849 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8850 (set (match_dup 0) (match_dup 4)))]
8853 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8854 operands[2], operands[3]);
8856 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8857 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8862 [(set (match_operand:SI 0 "s_register_operand" "")
8863 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8864 [(match_operand 2 "" "") (match_operand 3 "" "")])
8865 (match_operand 4 "" "")
8866 (match_operand 5 "" "")))
8867 (clobber (reg:CC CC_REGNUM))]
8868 "TARGET_ARM && reload_completed"
8869 [(set (match_dup 6) (match_dup 7))
8870 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8871 (set (match_dup 0) (match_dup 4)))
8872 (cond_exec (match_dup 8)
8873 (set (match_dup 0) (match_dup 5)))]
8876 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8877 operands[2], operands[3]);
8878 enum rtx_code rc = GET_CODE (operands[1]);
8880 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8881 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8882 if (mode == CCFPmode || mode == CCFPEmode)
8883 rc = reverse_condition_maybe_unordered (rc);
8885 rc = reverse_condition (rc);
8887 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8892 [(set (match_operand:SI 0 "s_register_operand" "")
8893 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8894 [(match_operand:SI 2 "s_register_operand" "")
8895 (match_operand:SI 3 "arm_add_operand" "")])
8896 (match_operand:SI 4 "arm_rhs_operand" "")
8898 (match_operand:SI 5 "s_register_operand" ""))))
8899 (clobber (reg:CC CC_REGNUM))]
8900 "TARGET_ARM && reload_completed"
8901 [(set (match_dup 6) (match_dup 7))
8902 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8903 (set (match_dup 0) (match_dup 4)))
8904 (cond_exec (match_dup 8)
8905 (set (match_dup 0) (not:SI (match_dup 5))))]
8908 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8909 operands[2], operands[3]);
8910 enum rtx_code rc = GET_CODE (operands[1]);
8912 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8913 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8914 if (mode == CCFPmode || mode == CCFPEmode)
8915 rc = reverse_condition_maybe_unordered (rc);
8917 rc = reverse_condition (rc);
8919 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8923 (define_insn "*cond_move_not"
8924 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8925 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8926 [(match_operand 3 "cc_register" "") (const_int 0)])
8927 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8929 (match_operand:SI 2 "s_register_operand" "r,r"))))]
8933 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8934 [(set_attr "conds" "use")
8935 (set_attr "length" "4,8")]
8938 ;; The next two patterns occur when an AND operation is followed by a
8939 ;; scc insn sequence
8941 (define_insn "*sign_extract_onebit"
8942 [(set (match_operand:SI 0 "s_register_operand" "=r")
8943 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8945 (match_operand:SI 2 "const_int_operand" "n")))
8946 (clobber (reg:CC CC_REGNUM))]
8949 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8950 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8951 return \"mvnne\\t%0, #0\";
8953 [(set_attr "conds" "clob")
8954 (set_attr "length" "8")]
8957 (define_insn "*not_signextract_onebit"
8958 [(set (match_operand:SI 0 "s_register_operand" "=r")
8960 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8962 (match_operand:SI 2 "const_int_operand" "n"))))
8963 (clobber (reg:CC CC_REGNUM))]
8966 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8967 output_asm_insn (\"tst\\t%1, %2\", operands);
8968 output_asm_insn (\"mvneq\\t%0, #0\", operands);
8969 return \"movne\\t%0, #0\";
8971 [(set_attr "conds" "clob")
8972 (set_attr "length" "12")]
8975 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
8976 ;; expressions. For simplicity, the first register is also in the unspec
8978 (define_insn "*push_multi"
8979 [(match_parallel 2 "multi_register_push"
8980 [(set (match_operand:BLK 0 "memory_operand" "=m")
8981 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8982 UNSPEC_PUSH_MULT))])]
8986 int num_saves = XVECLEN (operands[2], 0);
8988 /* For the StrongARM at least it is faster to
8989 use STR to store only a single register. */
8991 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8997 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
8999 for (i = 1; i < num_saves; i++)
9001 strcat (pattern, \", %|\");
9003 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9006 strcat (pattern, \"}\");
9007 output_asm_insn (pattern, operands);
9012 [(set_attr "type" "store4")]
9015 (define_insn "stack_tie"
9016 [(set (mem:BLK (scratch))
9017 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9018 (match_operand:SI 1 "s_register_operand" "r")]
9022 [(set_attr "length" "0")]
9025 ;; Similarly for the floating point registers
9026 (define_insn "*push_fp_multi"
9027 [(match_parallel 2 "multi_register_push"
9028 [(set (match_operand:BLK 0 "memory_operand" "=m")
9029 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9030 UNSPEC_PUSH_MULT))])]
9036 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9037 output_asm_insn (pattern, operands);
9040 [(set_attr "type" "f_store")]
9043 ;; Special patterns for dealing with the constant pool
9045 (define_insn "align_4"
9046 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9049 assemble_align (32);
9054 (define_insn "consttable_end"
9055 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9058 making_const_table = FALSE;
9063 (define_insn "consttable_1"
9064 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9067 making_const_table = TRUE;
9068 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9072 [(set_attr "length" "4")]
9075 (define_insn "consttable_2"
9076 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9079 making_const_table = TRUE;
9080 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9084 [(set_attr "length" "4")]
9087 (define_insn "consttable_4"
9088 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9092 making_const_table = TRUE;
9093 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9098 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9099 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9103 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9108 [(set_attr "length" "4")]
9111 (define_insn "consttable_8"
9112 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9116 making_const_table = TRUE;
9117 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9122 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9123 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9127 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9132 [(set_attr "length" "8")]
9135 ;; Miscellaneous Thumb patterns
9137 (define_expand "tablejump"
9138 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9139 (use (label_ref (match_operand 1 "" "")))])]
9144 /* Hopefully, CSE will eliminate this copy. */
9145 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
9146 rtx reg2 = gen_reg_rtx (SImode);
9148 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
9154 (define_insn "*thumb_tablejump"
9155 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9156 (use (label_ref (match_operand 1 "" "")))]
9159 [(set_attr "length" "2")]
9164 (define_insn "clzsi2"
9165 [(set (match_operand:SI 0 "s_register_operand" "=r")
9166 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
9167 "TARGET_ARM && arm_arch5"
9170 (define_expand "ffssi2"
9171 [(set (match_operand:SI 0 "s_register_operand" "")
9172 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9173 "TARGET_ARM && arm_arch5"
9178 t1 = gen_reg_rtx (SImode);
9179 t2 = gen_reg_rtx (SImode);
9180 t3 = gen_reg_rtx (SImode);
9182 emit_insn (gen_negsi2 (t1, operands[1]));
9183 emit_insn (gen_andsi3 (t2, operands[1], t1));
9184 emit_insn (gen_clzsi2 (t3, t2));
9185 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
9190 (define_expand "ctzsi2"
9191 [(set (match_operand:SI 0 "s_register_operand" "")
9192 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
9193 "TARGET_ARM && arm_arch5"
9198 t1 = gen_reg_rtx (SImode);
9199 t2 = gen_reg_rtx (SImode);
9200 t3 = gen_reg_rtx (SImode);
9202 emit_insn (gen_negsi2 (t1, operands[1]));
9203 emit_insn (gen_andsi3 (t2, operands[1], t1));
9204 emit_insn (gen_clzsi2 (t3, t2));
9205 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
9210 ;; V5E instructions.
9212 (define_insn "prefetch"
9213 [(prefetch (match_operand:SI 0 "address_operand" "p")
9214 (match_operand:SI 1 "" "")
9215 (match_operand:SI 2 "" ""))]
9216 "TARGET_ARM && arm_arch5e"
9219 ;; General predication pattern
9222 [(match_operator 0 "arm_comparison_operator"
9223 [(match_operand 1 "cc_register" "")
9229 (define_insn "prologue_use"
9230 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
9232 "%@ %0 needed for prologue"