1 ;;- Machine description for ARM for GNU compiler
2 ;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;; 2001, 2002, 2003 Free Software Foundation, Inc.
4 ;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;; and Martin Simmons (@harleqn.co.uk).
6 ;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
8 ;; This file is part of GCC.
10 ;; GCC is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 2, or (at your
13 ;; option) any later version.
15 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
18 ;; License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; see the file COPYING. If not, write to
22 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
28 ;;---------------------------------------------------------------------------
33 [(IP_REGNUM 12) ; Scratch register
34 (SP_REGNUM 13) ; Stack pointer
35 (LR_REGNUM 14) ; Return address register
36 (PC_REGNUM 15) ; Program counter
37 (CC_REGNUM 24) ; Condition code pseudo register
43 ;; Note: sin and cos are no-longer used.
46 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
47 ; operand 0 is the result,
48 ; operand 1 the parameter.
49 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
50 ; operand 0 is the result,
51 ; operand 1 the parameter.
52 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
53 ; operand 0 is the first register,
54 ; subsequent registers are in parallel (use ...)
56 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
57 ; usage, that is, we will add the pic_register
58 ; value to it before trying to dereference it.
59 (UNSPEC_PRLG_STK 4) ; A special barrier that prevents frame accesses
60 ; being scheduled before the stack adjustment insn.
61 (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
62 ; this unspec is used to prevent the deletion of
63 ; instructions setting registers for EH handling
64 ; and stack frame generation. Operand 0 is the
66 (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
70 ;; UNSPEC_VOLATILE Usage:
73 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
75 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
76 ; instruction epilogue sequence that isn't expanded
77 ; into normal RTL. Used for both normal and sibcall
79 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
80 ; for inlined constants.
81 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
83 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
85 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
87 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
89 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
94 ;;---------------------------------------------------------------------------
97 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
98 ; generating ARM code. This is used to control the length of some insn
99 ; patterns that share the same RTL in both ARM and Thumb code.
100 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
102 ; PROG_MODE attribute is used to determine whether condition codes are
103 ; clobbered by a call insn: they are if in prog32 mode. This is controlled
104 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
105 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
107 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
108 ; scheduling decisions for the load unit and the multiplier.
109 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
111 ;; Operand number of an input operand that is shifted. Zero if the
112 ;; given instruction does not shift one of its input operands.
113 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_is_xscale")))
114 (define_attr "shift" "" (const_int 0))
116 ; Floating Point Unit. If we only have floating point emulation, then there
117 ; is no point in scheduling the floating point insns. (Well, for best
118 ; performance we should try and group them together).
119 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
121 ; LENGTH of an instruction (in bytes)
122 (define_attr "length" "" (const_int 4))
124 ; POOL_RANGE is how far away from a constant pool entry that this insn
125 ; can be placed. If the distance is zero, then this insn will never
126 ; reference the pool.
127 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
128 ; before its address.
129 (define_attr "pool_range" "" (const_int 0))
130 (define_attr "neg_pool_range" "" (const_int 0))
132 ; An assembler sequence may clobber the condition codes without us knowing.
133 ; If such an insn references the pool, then we have no way of knowing how,
134 ; so use the most conservative value for pool_range.
135 (define_asm_attributes
136 [(set_attr "conds" "clob")
137 (set_attr "length" "4")
138 (set_attr "pool_range" "250")])
140 ; TYPE attribute is used to detect floating point instructions which, if
141 ; running on a co-processor can run in parallel with other, basic instructions
142 ; If write-buffer scheduling is enabled then it can also be used in the
143 ; scheduling of writes.
145 ; Classification of each insn
146 ; normal any data instruction that doesn't hit memory or fp regs
147 ; mult a multiply instruction
148 ; block blockage insn, this blocks all functional units
149 ; float a floating point arithmetic operation (subject to expansion)
150 ; fdivd DFmode floating point division
151 ; fdivs SFmode floating point division
152 ; fmul Floating point multiply
153 ; ffmul Fast floating point multiply
154 ; farith Floating point arithmetic (4 cycle)
155 ; ffarith Fast floating point arithmetic (2 cycle)
156 ; float_em a floating point arithmetic operation that is normally emulated
157 ; even on a machine with an fpa.
158 ; f_load a floating point load from memory
159 ; f_store a floating point store to memory
160 ; f_mem_r a transfer of a floating point register to a real reg via mem
161 ; r_mem_f the reverse of f_mem_r
162 ; f_2_r fast transfer float to arm (no memory needed)
163 ; r_2_f fast transfer arm to float
164 ; call a subroutine call
165 ; load any load from memory
166 ; store1 store 1 word to memory from arm registers
167 ; store2 store 2 words
168 ; store3 store 3 words
169 ; store4 store 4 words
170 ; Additions for Cirrus Maverick co-processor:
171 ; mav_farith Floating point arithmetic (4 cycle)
172 ; mav_dmult Double multiplies (7 cycle)
175 "normal,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,call,load,store1,store2,store3,store4,mav_farith,mav_dmult"
176 (const_string "normal"))
178 ; Load scheduling, set from the arm_ld_sched variable
179 ; initialized by arm_override_options()
180 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
182 ; condition codes: this one is used by final_prescan_insn to speed up
183 ; conditionalizing instructions. It saves having to scan the rtl to see if
184 ; it uses or alters the condition codes.
186 ; USE means that the condition codes are used by the insn in the process of
187 ; outputting code, this means (at present) that we can't use the insn in
190 ; SET means that the purpose of the insn is to set the condition codes in a
191 ; well defined manner.
193 ; CLOB means that the condition codes are altered in an undefined manner, if
194 ; they are altered at all
196 ; JUMP_CLOB is used when the condition cannot be represented by a single
197 ; instruction (UNEQ and LTGT). These cannot be predicated.
199 ; NOCOND means that the condition codes are neither altered nor affect the
200 ; output of this insn
202 (define_attr "conds" "use,set,clob,jump_clob,nocond"
203 (if_then_else (eq_attr "type" "call")
204 (if_then_else (eq_attr "prog_mode" "prog32")
205 (const_string "clob") (const_string "nocond"))
206 (const_string "nocond")))
208 ; Predicable means that the insn can be conditionally executed based on
209 ; an automatically added predicate (additional patterns are generated by
210 ; gen...). We default to 'no' because no Thumb patterns match this rule
211 ; and not all ARM patterns do.
212 (define_attr "predicable" "no,yes" (const_string "no"))
214 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
215 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
216 ; suffer blockages enough to warrent modelling this (and it can adversely
217 ; affect the schedule).
218 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
220 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
221 ; to stall the processor. Used with model_wbuf above.
222 (define_attr "write_conflict" "no,yes"
223 (if_then_else (eq_attr "type"
224 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
226 (const_string "no")))
228 ; Classify the insns into those that take one cycle and those that take more
229 ; than one on the main cpu execution unit.
230 (define_attr "core_cycles" "single,multi"
231 (if_then_else (eq_attr "type"
232 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
233 (const_string "single")
234 (const_string "multi")))
236 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
237 ;; distant label. Only applicable to Thumb code.
238 (define_attr "far_jump" "yes,no" (const_string "no"))
240 ;; (define_function_unit {name} {num-units} {n-users} {test}
241 ;; {ready-delay} {issue-delay} [{conflict-list}])
243 ;;--------------------------------------------------------------------
244 ;; Floating point unit (FPA)
245 ;;--------------------------------------------------------------------
246 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
247 (eq_attr "type" "fdivx")) 71 69)
249 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
250 (eq_attr "type" "fdivd")) 59 57)
252 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
253 (eq_attr "type" "fdivs")) 31 29)
255 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
256 (eq_attr "type" "fmul")) 9 7)
258 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
259 (eq_attr "type" "ffmul")) 6 4)
261 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
262 (eq_attr "type" "farith")) 4 2)
264 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
265 (eq_attr "type" "ffarith")) 2 2)
267 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
268 (eq_attr "type" "r_2_f")) 5 3)
270 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
271 (eq_attr "type" "f_2_r")) 1 2)
273 ; The fpa10 doesn't really have a memory read unit, but it can start to
274 ; speculatively execute the instruction in the pipeline, provided the data
275 ; is already loaded, so pretend reads have a delay of 2 (and that the
276 ; pipeline is infinite).
278 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
279 (eq_attr "type" "f_load")) 3 1)
281 ;;--------------------------------------------------------------------
283 ;;--------------------------------------------------------------------
284 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
286 ; The write buffer on some of the arm6 processors is hard to model exactly.
287 ; There is room in the buffer for up to two addresses and up to eight words
288 ; of memory, but the two needn't be split evenly. When writing the two
289 ; addresses are fully pipelined. However, a read from memory that is not
290 ; currently in the cache will block until the writes have completed.
291 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
292 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
293 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
294 ; cycle to add as well.
296 (define_function_unit "write_buf" 1 2
297 (and (eq_attr "model_wbuf" "yes")
298 (eq_attr "type" "store1,r_mem_f")) 5 3)
299 (define_function_unit "write_buf" 1 2
300 (and (eq_attr "model_wbuf" "yes")
301 (eq_attr "type" "store2")) 7 4)
302 (define_function_unit "write_buf" 1 2
303 (and (eq_attr "model_wbuf" "yes")
304 (eq_attr "type" "store3")) 9 5)
305 (define_function_unit "write_buf" 1 2
306 (and (eq_attr "model_wbuf" "yes")
307 (eq_attr "type" "store4")) 11 6)
309 ;;--------------------------------------------------------------------
310 ;; Write blockage unit
311 ;;--------------------------------------------------------------------
312 ; The write_blockage unit models (partially), the fact that reads will stall
313 ; until the write buffer empties.
314 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
315 ; so we don't model them here
316 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
317 (eq_attr "type" "store1")) 5 5
318 [(eq_attr "write_conflict" "yes")])
319 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
320 (eq_attr "type" "store2")) 7 7
321 [(eq_attr "write_conflict" "yes")])
322 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
323 (eq_attr "type" "store3")) 9 9
324 [(eq_attr "write_conflict" "yes")])
325 (define_function_unit "write_blockage" 1 0
326 (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
327 [(eq_attr "write_conflict" "yes")])
328 (define_function_unit "write_blockage" 1 0
329 (and (eq_attr "model_wbuf" "yes")
330 (eq_attr "write_conflict" "yes")) 1 1)
332 ;;--------------------------------------------------------------------
334 ;;--------------------------------------------------------------------
335 ; Everything must spend at least one cycle in the core unit
336 (define_function_unit "core" 1 0 (eq_attr "core_cycles" "single") 1 1)
338 (define_function_unit "core" 1 0
339 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
341 (define_function_unit "core" 1 0
342 (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
344 ;; We do not need to conditionalize the define_function_unit immediately
345 ;; above. This one will be ignored for anything other than xscale
346 ;; compiles and for xscale compiles it provides a larger delay
347 ;; and the scheduler will DTRT.
348 ;; FIXME: this test needs to be revamped to not depend on this feature
351 (define_function_unit "core" 1 0
352 (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
353 (eq_attr "is_xscale" "yes"))
356 (define_function_unit "core" 1 0
357 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
359 (define_function_unit "core" 1 0
360 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
362 (define_function_unit "core" 1 0
363 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
365 (define_function_unit "core" 1 0
366 (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
368 (define_function_unit "core" 1 0
369 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
371 (define_function_unit "core" 1 0
372 (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
374 (define_function_unit "core" 1 0
375 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
376 (eq_attr "type" "mult")) 4 4)
378 (define_function_unit "core" 1 0
379 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
380 (eq_attr "type" "mult")) 3 2)
382 (define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
384 (define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
386 (define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
388 (define_function_unit "core" 1 0
389 (and (eq_attr "core_cycles" "multi")
390 (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
392 (include "cirrus.md")
394 ;;---------------------------------------------------------------------------
399 ;; Note: For DImode insns, there is normally no reason why operands should
400 ;; not be in the same register, what we don't want is for something being
401 ;; written to partially overlap something that is an input.
402 ;; Cirrus 64bit additions should not be split because we have a native
403 ;; 64bit addition instructions.
405 (define_expand "adddi3"
407 [(set (match_operand:DI 0 "s_register_operand" "")
408 (plus:DI (match_operand:DI 1 "s_register_operand" "")
409 (match_operand:DI 2 "s_register_operand" "")))
410 (clobber (reg:CC CC_REGNUM))])]
415 if (!cirrus_fp_register (operands[0], DImode))
416 operands[0] = force_reg (DImode, operands[0]);
417 if (!cirrus_fp_register (operands[1], DImode))
418 operands[1] = force_reg (DImode, operands[1]);
419 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
425 if (GET_CODE (operands[1]) != REG)
426 operands[1] = force_reg (SImode, operands[1]);
427 if (GET_CODE (operands[2]) != REG)
428 operands[2] = force_reg (SImode, operands[2]);
433 (define_insn "*thumb_adddi3"
434 [(set (match_operand:DI 0 "register_operand" "=l")
435 (plus:DI (match_operand:DI 1 "register_operand" "%0")
436 (match_operand:DI 2 "register_operand" "l")))
437 (clobber (reg:CC CC_REGNUM))
440 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
441 [(set_attr "length" "4")]
444 (define_insn_and_split "*arm_adddi3"
445 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
446 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
447 (match_operand:DI 2 "s_register_operand" "r, 0")))
448 (clobber (reg:CC CC_REGNUM))]
449 "TARGET_ARM && !TARGET_CIRRUS"
451 "TARGET_ARM && reload_completed"
452 [(parallel [(set (reg:CC_C CC_REGNUM)
453 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
455 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
456 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
457 (plus:SI (match_dup 4) (match_dup 5))))]
460 operands[3] = gen_highpart (SImode, operands[0]);
461 operands[0] = gen_lowpart (SImode, operands[0]);
462 operands[4] = gen_highpart (SImode, operands[1]);
463 operands[1] = gen_lowpart (SImode, operands[1]);
464 operands[5] = gen_highpart (SImode, operands[2]);
465 operands[2] = gen_lowpart (SImode, operands[2]);
467 [(set_attr "conds" "clob")
468 (set_attr "length" "8")]
471 (define_insn_and_split "*adddi_sesidi_di"
472 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
473 (plus:DI (sign_extend:DI
474 (match_operand:SI 2 "s_register_operand" "r,r"))
475 (match_operand:DI 1 "s_register_operand" "r,0")))
476 (clobber (reg:CC CC_REGNUM))]
477 "TARGET_ARM && !TARGET_CIRRUS"
479 "TARGET_ARM && reload_completed"
480 [(parallel [(set (reg:CC_C CC_REGNUM)
481 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
483 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
484 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
485 (plus:SI (ashiftrt:SI (match_dup 2)
490 operands[3] = gen_highpart (SImode, operands[0]);
491 operands[0] = gen_lowpart (SImode, operands[0]);
492 operands[4] = gen_highpart (SImode, operands[1]);
493 operands[1] = gen_lowpart (SImode, operands[1]);
494 operands[2] = gen_lowpart (SImode, operands[2]);
496 [(set_attr "conds" "clob")
497 (set_attr "length" "8")]
500 (define_insn_and_split "*adddi_zesidi_di"
501 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
502 (plus:DI (zero_extend:DI
503 (match_operand:SI 2 "s_register_operand" "r,r"))
504 (match_operand:DI 1 "s_register_operand" "r,0")))
505 (clobber (reg:CC CC_REGNUM))]
506 "TARGET_ARM && !TARGET_CIRRUS"
508 "TARGET_ARM && reload_completed"
509 [(parallel [(set (reg:CC_C CC_REGNUM)
510 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
512 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
513 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
514 (plus:SI (match_dup 4) (const_int 0))))]
517 operands[3] = gen_highpart (SImode, operands[0]);
518 operands[0] = gen_lowpart (SImode, operands[0]);
519 operands[4] = gen_highpart (SImode, operands[1]);
520 operands[1] = gen_lowpart (SImode, operands[1]);
521 operands[2] = gen_lowpart (SImode, operands[2]);
523 [(set_attr "conds" "clob")
524 (set_attr "length" "8")]
527 (define_expand "addsi3"
528 [(set (match_operand:SI 0 "s_register_operand" "")
529 (plus:SI (match_operand:SI 1 "s_register_operand" "")
530 (match_operand:SI 2 "reg_or_int_operand" "")))]
533 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
535 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
537 (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
543 ; If there is a scratch available, this will be faster than synthesising the
546 [(match_scratch:SI 3 "r")
547 (set (match_operand:SI 0 "s_register_operand" "")
548 (plus:SI (match_operand:SI 1 "s_register_operand" "")
549 (match_operand:SI 2 "const_int_operand" "")))]
551 !(const_ok_for_arm (INTVAL (operands[2]))
552 || const_ok_for_arm (-INTVAL (operands[2])))
553 && const_ok_for_arm (~INTVAL (operands[2]))"
554 [(set (match_dup 3) (match_dup 2))
555 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
559 (define_insn_and_split "*arm_addsi3"
560 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
561 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
562 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
569 GET_CODE (operands[2]) == CONST_INT
570 && !(const_ok_for_arm (INTVAL (operands[2]))
571 || const_ok_for_arm (-INTVAL (operands[2])))"
572 [(clobber (const_int 0))]
574 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
578 [(set_attr "length" "4,4,16")
579 (set_attr "predicable" "yes")]
582 ;; Register group 'k' is a single register group containing only the stack
583 ;; register. Trying to reload it will always fail catastrophically,
584 ;; so never allow those alternatives to match if reloading is needed.
586 (define_insn "*thumb_addsi3"
587 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
588 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
589 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
592 static const char * const asms[] =
594 \"add\\t%0, %0, %2\",
595 \"sub\\t%0, %0, #%n2\",
596 \"add\\t%0, %1, %2\",
597 \"add\\t%0, %0, %2\",
598 \"add\\t%0, %0, %2\",
599 \"add\\t%0, %1, %2\",
602 if ((which_alternative == 2 || which_alternative == 6)
603 && GET_CODE (operands[2]) == CONST_INT
604 && INTVAL (operands[2]) < 0)
605 return \"sub\\t%0, %1, #%n2\";
606 return asms[which_alternative];
608 [(set_attr "length" "2")]
611 ;; Reloading and elimination of the frame pointer can
612 ;; sometimes cause this optimization to be missed.
614 [(set (match_operand:SI 0 "register_operand" "")
615 (match_operand:SI 1 "const_int_operand" ""))
617 (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
619 && REGNO (operands[2]) == STACK_POINTER_REGNUM
620 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
621 && (INTVAL (operands[1]) & 3) == 0"
622 [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
626 (define_insn "*addsi3_compare0"
627 [(set (reg:CC_NOOV CC_REGNUM)
629 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
630 (match_operand:SI 2 "arm_add_operand" "rI,L"))
632 (set (match_operand:SI 0 "s_register_operand" "=r,r")
633 (plus:SI (match_dup 1) (match_dup 2)))]
637 sub%?s\\t%0, %1, #%n2"
638 [(set_attr "conds" "set")]
641 (define_insn "*addsi3_compare0_scratch"
642 [(set (reg:CC_NOOV CC_REGNUM)
644 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
645 (match_operand:SI 1 "arm_add_operand" "rI,L"))
651 [(set_attr "conds" "set")]
654 ;; These patterns are the same ones as the two regular addsi3_compare0
655 ;; patterns, except we write them slightly different - the combiner
656 ;; tends to generate them this way.
657 (define_insn "*addsi3_compare0_for_combiner"
658 [(set (reg:CC CC_REGNUM)
660 (match_operand:SI 1 "s_register_operand" "r,r")
661 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
662 (set (match_operand:SI 0 "s_register_operand" "=r,r")
663 (plus:SI (match_dup 1) (match_dup 2)))]
667 sub%?s\\t%0, %1, #%n2"
668 [(set_attr "conds" "set")]
671 (define_insn "*addsi3_compare0_scratch_for_combiner"
672 [(set (reg:CC CC_REGNUM)
674 (match_operand:SI 0 "s_register_operand" "r,r")
675 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
680 [(set_attr "conds" "set")]
683 ;; The next four insns work because they compare the result with one of
684 ;; the operands, and we know that the use of the condition code is
685 ;; either GEU or LTU, so we can use the carry flag from the addition
686 ;; instead of doing the compare a second time.
687 (define_insn "*addsi3_compare_op1"
688 [(set (reg:CC_C CC_REGNUM)
690 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
691 (match_operand:SI 2 "arm_add_operand" "rI,L"))
693 (set (match_operand:SI 0 "s_register_operand" "=r,r")
694 (plus:SI (match_dup 1) (match_dup 2)))]
698 sub%?s\\t%0, %1, #%n2"
699 [(set_attr "conds" "set")]
702 (define_insn "*addsi3_compare_op2"
703 [(set (reg:CC_C CC_REGNUM)
705 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
706 (match_operand:SI 2 "arm_add_operand" "rI,L"))
708 (set (match_operand:SI 0 "s_register_operand" "=r,r")
709 (plus:SI (match_dup 1) (match_dup 2)))]
713 sub%?s\\t%0, %1, #%n2"
714 [(set_attr "conds" "set")]
717 (define_insn "*compare_addsi2_op0"
718 [(set (reg:CC_C CC_REGNUM)
720 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
721 (match_operand:SI 1 "arm_add_operand" "rI,L"))
727 [(set_attr "conds" "set")]
730 (define_insn "*compare_addsi2_op1"
731 [(set (reg:CC_C CC_REGNUM)
733 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
734 (match_operand:SI 1 "arm_add_operand" "rI,L"))
740 [(set_attr "conds" "set")]
743 (define_insn "*addsi3_carryin"
744 [(set (match_operand:SI 0 "s_register_operand" "=r")
745 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
746 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
747 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
750 [(set_attr "conds" "use")]
753 (define_insn "*addsi3_carryin_shift"
754 [(set (match_operand:SI 0 "s_register_operand" "")
755 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
757 (match_operator:SI 2 "shift_operator"
758 [(match_operand:SI 3 "s_register_operand" "")
759 (match_operand:SI 4 "reg_or_int_operand" "")])
760 (match_operand:SI 1 "s_register_operand" ""))))]
762 "adc%?\\t%0, %1, %3%S2"
763 [(set_attr "conds" "use")]
766 (define_insn "*addsi3_carryin_alt1"
767 [(set (match_operand:SI 0 "s_register_operand" "=r")
768 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
769 (match_operand:SI 2 "arm_rhs_operand" "rI"))
770 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
773 [(set_attr "conds" "use")]
776 (define_insn "*addsi3_carryin_alt2"
777 [(set (match_operand:SI 0 "s_register_operand" "=r")
778 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
779 (match_operand:SI 1 "s_register_operand" "r"))
780 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
783 [(set_attr "conds" "use")]
786 (define_insn "*addsi3_carryin_alt3"
787 [(set (match_operand:SI 0 "s_register_operand" "=r")
788 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
789 (match_operand:SI 2 "arm_rhs_operand" "rI"))
790 (match_operand:SI 1 "s_register_operand" "r")))]
793 [(set_attr "conds" "use")]
796 (define_insn "incscc"
797 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
798 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
799 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
800 (match_operand:SI 1 "s_register_operand" "0,?r")))]
804 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
805 [(set_attr "conds" "use")
806 (set_attr "length" "4,8")]
809 (define_insn "*arm_addsf3"
810 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
811 (plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
812 (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
813 "TARGET_ARM && TARGET_HARD_FLOAT"
816 suf%?s\\t%0, %1, #%N2"
817 [(set_attr "type" "farith")
818 (set_attr "predicable" "yes")]
821 (define_insn "*arm_adddf3"
822 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
823 (plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
824 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
825 "TARGET_ARM && TARGET_HARD_FLOAT"
828 suf%?d\\t%0, %1, #%N2"
829 [(set_attr "type" "farith")
830 (set_attr "predicable" "yes")]
833 (define_insn "*adddf_esfdf_df"
834 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
835 (plus:DF (float_extend:DF
836 (match_operand:SF 1 "s_register_operand" "f,f"))
837 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
838 "TARGET_ARM && TARGET_HARD_FLOAT"
841 suf%?d\\t%0, %1, #%N2"
842 [(set_attr "type" "farith")
843 (set_attr "predicable" "yes")]
846 (define_insn "*adddf_df_esfdf"
847 [(set (match_operand:DF 0 "s_register_operand" "=f")
848 (plus:DF (match_operand:DF 1 "s_register_operand" "f")
850 (match_operand:SF 2 "s_register_operand" "f"))))]
851 "TARGET_ARM && TARGET_HARD_FLOAT"
852 "adf%?d\\t%0, %1, %2"
853 [(set_attr "type" "farith")
854 (set_attr "predicable" "yes")]
857 (define_insn "*adddf_esfdf_esfdf"
858 [(set (match_operand:DF 0 "s_register_operand" "=f")
859 (plus:DF (float_extend:DF
860 (match_operand:SF 1 "s_register_operand" "f"))
862 (match_operand:SF 2 "s_register_operand" "f"))))]
863 "TARGET_ARM && TARGET_HARD_FLOAT"
864 "adf%?d\\t%0, %1, %2"
865 [(set_attr "type" "farith")
866 (set_attr "predicable" "yes")]
869 (define_expand "subdi3"
871 [(set (match_operand:DI 0 "s_register_operand" "")
872 (minus:DI (match_operand:DI 1 "s_register_operand" "")
873 (match_operand:DI 2 "s_register_operand" "")))
874 (clobber (reg:CC CC_REGNUM))])]
879 && cirrus_fp_register (operands[0], DImode)
880 && cirrus_fp_register (operands[1], DImode))
882 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
888 if (GET_CODE (operands[1]) != REG)
889 operands[1] = force_reg (SImode, operands[1]);
890 if (GET_CODE (operands[2]) != REG)
891 operands[2] = force_reg (SImode, operands[2]);
896 (define_insn "*arm_subdi3"
897 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
898 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
899 (match_operand:DI 2 "s_register_operand" "r,0,0")))
900 (clobber (reg:CC CC_REGNUM))]
902 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
903 [(set_attr "conds" "clob")
904 (set_attr "length" "8")]
907 (define_insn "*thumb_subdi3"
908 [(set (match_operand:DI 0 "register_operand" "=l")
909 (minus:DI (match_operand:DI 1 "register_operand" "0")
910 (match_operand:DI 2 "register_operand" "l")))
911 (clobber (reg:CC CC_REGNUM))]
913 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
914 [(set_attr "length" "4")]
917 (define_insn "*subdi_di_zesidi"
918 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
919 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
921 (match_operand:SI 2 "s_register_operand" "r,r"))))
922 (clobber (reg:CC CC_REGNUM))]
924 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
925 [(set_attr "conds" "clob")
926 (set_attr "length" "8")]
929 (define_insn "*subdi_di_sesidi"
930 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
931 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
933 (match_operand:SI 2 "s_register_operand" "r,r"))))
934 (clobber (reg:CC CC_REGNUM))]
936 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
937 [(set_attr "conds" "clob")
938 (set_attr "length" "8")]
941 (define_insn "*subdi_zesidi_di"
942 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
943 (minus:DI (zero_extend:DI
944 (match_operand:SI 2 "s_register_operand" "r,r"))
945 (match_operand:DI 1 "s_register_operand" "?r,0")))
946 (clobber (reg:CC CC_REGNUM))]
948 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
949 [(set_attr "conds" "clob")
950 (set_attr "length" "8")]
953 (define_insn "*subdi_sesidi_di"
954 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
955 (minus:DI (sign_extend:DI
956 (match_operand:SI 2 "s_register_operand" "r,r"))
957 (match_operand:DI 1 "s_register_operand" "?r,0")))
958 (clobber (reg:CC CC_REGNUM))]
960 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
961 [(set_attr "conds" "clob")
962 (set_attr "length" "8")]
965 (define_insn "*subdi_zesidi_zesidi"
966 [(set (match_operand:DI 0 "s_register_operand" "=r")
967 (minus:DI (zero_extend:DI
968 (match_operand:SI 1 "s_register_operand" "r"))
970 (match_operand:SI 2 "s_register_operand" "r"))))
971 (clobber (reg:CC CC_REGNUM))]
973 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
974 [(set_attr "conds" "clob")
975 (set_attr "length" "8")]
978 (define_expand "subsi3"
979 [(set (match_operand:SI 0 "s_register_operand" "")
980 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
981 (match_operand:SI 2 "s_register_operand" "")))]
984 if (GET_CODE (operands[1]) == CONST_INT)
988 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
991 : preserve_subexpressions_p ()));
994 else /* TARGET_THUMB */
995 operands[1] = force_reg (SImode, operands[1]);
1000 (define_insn "*thumb_subsi3_insn"
1001 [(set (match_operand:SI 0 "register_operand" "=l")
1002 (minus:SI (match_operand:SI 1 "register_operand" "l")
1003 (match_operand:SI 2 "register_operand" "l")))]
1006 [(set_attr "length" "2")]
1009 (define_insn_and_split "*arm_subsi3_insn"
1010 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1011 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
1012 (match_operand:SI 2 "s_register_operand" "r,r")))]
1018 && GET_CODE (operands[1]) == CONST_INT
1019 && !const_ok_for_arm (INTVAL (operands[1]))"
1020 [(clobber (const_int 0))]
1022 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1026 [(set_attr "length" "4,16")
1027 (set_attr "predicable" "yes")]
1031 [(match_scratch:SI 3 "r")
1032 (set (match_operand:SI 0 "s_register_operand" "")
1033 (minus:SI (match_operand:SI 1 "const_int_operand" "")
1034 (match_operand:SI 2 "s_register_operand" "")))]
1036 && !const_ok_for_arm (INTVAL (operands[1]))
1037 && const_ok_for_arm (~INTVAL (operands[1]))"
1038 [(set (match_dup 3) (match_dup 1))
1039 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1043 (define_insn "*subsi3_compare0"
1044 [(set (reg:CC_NOOV CC_REGNUM)
1046 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1047 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1049 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1050 (minus:SI (match_dup 1) (match_dup 2)))]
1054 rsb%?s\\t%0, %2, %1"
1055 [(set_attr "conds" "set")]
1058 (define_insn "decscc"
1059 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1060 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1061 (match_operator:SI 2 "arm_comparison_operator"
1062 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1066 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1067 [(set_attr "conds" "use")
1068 (set_attr "length" "*,8")]
1071 (define_insn "*arm_subsf3"
1072 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1073 (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1074 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1075 "TARGET_ARM && TARGET_HARD_FLOAT"
1078 rsf%?s\\t%0, %2, %1"
1079 [(set_attr "type" "farith")]
1082 (define_insn "*arm_subdf3"
1083 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1084 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1085 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1086 "TARGET_ARM && TARGET_HARD_FLOAT"
1089 rsf%?d\\t%0, %2, %1"
1090 [(set_attr "type" "farith")
1091 (set_attr "predicable" "yes")]
1094 (define_insn "*subdf_esfdf_df"
1095 [(set (match_operand:DF 0 "s_register_operand" "=f")
1096 (minus:DF (float_extend:DF
1097 (match_operand:SF 1 "s_register_operand" "f"))
1098 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1099 "TARGET_ARM && TARGET_HARD_FLOAT"
1100 "suf%?d\\t%0, %1, %2"
1101 [(set_attr "type" "farith")
1102 (set_attr "predicable" "yes")]
1105 (define_insn "*subdf_df_esfdf"
1106 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1107 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1109 (match_operand:SF 2 "s_register_operand" "f,f"))))]
1110 "TARGET_ARM && TARGET_HARD_FLOAT"
1113 rsf%?d\\t%0, %2, %1"
1114 [(set_attr "type" "farith")
1115 (set_attr "predicable" "yes")]
1118 (define_insn "*subdf_esfdf_esfdf"
1119 [(set (match_operand:DF 0 "s_register_operand" "=f")
1120 (minus:DF (float_extend:DF
1121 (match_operand:SF 1 "s_register_operand" "f"))
1123 (match_operand:SF 2 "s_register_operand" "f"))))]
1124 "TARGET_ARM && TARGET_HARD_FLOAT"
1125 "suf%?d\\t%0, %1, %2"
1126 [(set_attr "type" "farith")
1127 (set_attr "predicable" "yes")]
1130 ;; Multiplication insns
1132 (define_expand "mulsi3"
1133 [(set (match_operand:SI 0 "s_register_operand" "")
1134 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1135 (match_operand:SI 1 "s_register_operand" "")))]
1140 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1141 (define_insn "*arm_mulsi3"
1142 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1143 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1144 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1146 "mul%?\\t%0, %2, %1"
1147 [(set_attr "type" "mult")
1148 (set_attr "predicable" "yes")]
1151 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1152 ; 1 and 2; are the same, because reload will make operand 0 match
1153 ; operand 1 without realizing that this conflicts with operand 2. We fix
1154 ; this by adding another alternative to match this case, and then `reload'
1155 ; it ourselves. This alternative must come first.
1156 (define_insn "*thumb_mulsi3"
1157 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1158 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1159 (match_operand:SI 2 "register_operand" "l,l,l")))]
1162 if (which_alternative < 2)
1163 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1165 return \"mul\\t%0, %0, %2\";
1167 [(set_attr "length" "4,4,2")
1168 (set_attr "type" "mult")]
1171 (define_insn "*mulsi3_compare0"
1172 [(set (reg:CC_NOOV CC_REGNUM)
1173 (compare:CC_NOOV (mult:SI
1174 (match_operand:SI 2 "s_register_operand" "r,r")
1175 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1177 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1178 (mult:SI (match_dup 2) (match_dup 1)))]
1179 "TARGET_ARM && !arm_is_xscale"
1180 "mul%?s\\t%0, %2, %1"
1181 [(set_attr "conds" "set")
1182 (set_attr "type" "mult")]
1185 (define_insn "*mulsi_compare0_scratch"
1186 [(set (reg:CC_NOOV CC_REGNUM)
1187 (compare:CC_NOOV (mult:SI
1188 (match_operand:SI 2 "s_register_operand" "r,r")
1189 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1191 (clobber (match_scratch:SI 0 "=&r,&r"))]
1192 "TARGET_ARM && !arm_is_xscale"
1193 "mul%?s\\t%0, %2, %1"
1194 [(set_attr "conds" "set")
1195 (set_attr "type" "mult")]
1198 ;; Unnamed templates to match MLA instruction.
1200 (define_insn "*mulsi3addsi"
1201 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1203 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1204 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1205 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1207 "mla%?\\t%0, %2, %1, %3"
1208 [(set_attr "type" "mult")
1209 (set_attr "predicable" "yes")]
1212 (define_insn "*mulsi3addsi_compare0"
1213 [(set (reg:CC_NOOV CC_REGNUM)
1216 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1217 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1218 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1220 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1221 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1223 "TARGET_ARM && !arm_is_xscale"
1224 "mla%?s\\t%0, %2, %1, %3"
1225 [(set_attr "conds" "set")
1226 (set_attr "type" "mult")]
1229 (define_insn "*mulsi3addsi_compare0_scratch"
1230 [(set (reg:CC_NOOV CC_REGNUM)
1233 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1234 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1235 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1237 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1238 "TARGET_ARM && !arm_is_xscale"
1239 "mla%?s\\t%0, %2, %1, %3"
1240 [(set_attr "conds" "set")
1241 (set_attr "type" "mult")]
1244 ;; Unnamed template to match long long multiply-accumlate (smlal)
1246 (define_insn "*mulsidi3adddi"
1247 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1250 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1251 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1252 (match_operand:DI 1 "s_register_operand" "0")))]
1253 "TARGET_ARM && arm_fast_multiply"
1254 "smlal%?\\t%Q0, %R0, %3, %2"
1255 [(set_attr "type" "mult")
1256 (set_attr "predicable" "yes")]
1259 (define_insn "mulsidi3"
1260 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1262 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1263 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1264 "TARGET_ARM && arm_fast_multiply"
1265 "smull%?\\t%Q0, %R0, %1, %2"
1266 [(set_attr "type" "mult")
1267 (set_attr "predicable" "yes")]
1270 (define_insn "umulsidi3"
1271 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1273 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1274 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1275 "TARGET_ARM && arm_fast_multiply"
1276 "umull%?\\t%Q0, %R0, %1, %2"
1277 [(set_attr "type" "mult")
1278 (set_attr "predicable" "yes")]
1281 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1283 (define_insn "*umulsidi3adddi"
1284 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1287 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1288 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1289 (match_operand:DI 1 "s_register_operand" "0")))]
1290 "TARGET_ARM && arm_fast_multiply"
1291 "umlal%?\\t%Q0, %R0, %3, %2"
1292 [(set_attr "type" "mult")
1293 (set_attr "predicable" "yes")]
1296 (define_insn "smulsi3_highpart"
1297 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1301 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1302 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1304 (clobber (match_scratch:SI 3 "=&r,&r"))]
1305 "TARGET_ARM && arm_fast_multiply"
1306 "smull%?\\t%3, %0, %2, %1"
1307 [(set_attr "type" "mult")
1308 (set_attr "predicable" "yes")]
1311 (define_insn "umulsi3_highpart"
1312 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1316 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1317 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1319 (clobber (match_scratch:SI 3 "=&r,&r"))]
1320 "TARGET_ARM && arm_fast_multiply"
1321 "umull%?\\t%3, %0, %2, %1"
1322 [(set_attr "type" "mult")
1323 (set_attr "predicable" "yes")]
1326 (define_insn "mulhisi3"
1327 [(set (match_operand:SI 0 "s_register_operand" "=r")
1328 (mult:SI (sign_extend:SI
1329 (match_operand:HI 1 "s_register_operand" "%r"))
1331 (match_operand:HI 2 "s_register_operand" "r"))))]
1332 "TARGET_ARM && arm_arch5e"
1333 "smulbb%?\\t%0, %1, %2"
1334 [(set_attr "type" "mult")
1335 (set_attr "predicable" "yes")]
1338 (define_insn "*mulhisi3tb"
1339 [(set (match_operand:SI 0 "s_register_operand" "=r")
1340 (mult:SI (ashiftrt:SI
1341 (match_operand:SI 1 "s_register_operand" "r")
1344 (match_operand:HI 2 "s_register_operand" "r"))))]
1345 "TARGET_ARM && arm_arch5e"
1346 "smultb%?\\t%0, %1, %2"
1347 [(set_attr "type" "mult")
1348 (set_attr "predicable" "yes")]
1351 (define_insn "*mulhisi3bt"
1352 [(set (match_operand:SI 0 "s_register_operand" "=r")
1353 (mult:SI (sign_extend:SI
1354 (match_operand:HI 1 "s_register_operand" "r"))
1356 (match_operand:SI 2 "s_register_operand" "r")
1358 "TARGET_ARM && arm_arch5e"
1359 "smulbt%?\\t%0, %1, %2"
1360 [(set_attr "type" "mult")
1361 (set_attr "predicable" "yes")]
1364 (define_insn "*mulhisi3tt"
1365 [(set (match_operand:SI 0 "s_register_operand" "=r")
1366 (mult:SI (ashiftrt:SI
1367 (match_operand:SI 1 "s_register_operand" "r")
1370 (match_operand:SI 2 "s_register_operand" "r")
1372 "TARGET_ARM && arm_arch5e"
1373 "smultt%?\\t%0, %1, %2"
1374 [(set_attr "type" "mult")
1375 (set_attr "predicable" "yes")]
1378 (define_insn "*mulhisi3addsi"
1379 [(set (match_operand:SI 0 "s_register_operand" "=r")
1380 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1381 (mult:SI (sign_extend:SI
1382 (match_operand:HI 2 "s_register_operand" "%r"))
1384 (match_operand:HI 3 "s_register_operand" "r")))))]
1385 "TARGET_ARM && arm_arch5e"
1386 "smlabb%?\\t%0, %2, %3, %1"
1387 [(set_attr "type" "mult")
1388 (set_attr "predicable" "yes")]
1391 (define_insn "*mulhidi3adddi"
1392 [(set (match_operand:DI 0 "s_register_operand" "=r")
1394 (match_operand:DI 1 "s_register_operand" "0")
1395 (mult:DI (sign_extend:DI
1396 (match_operand:HI 2 "s_register_operand" "%r"))
1398 (match_operand:HI 3 "s_register_operand" "r")))))]
1399 "TARGET_ARM && arm_arch5e"
1400 "smlalbb%?\\t%Q0, %R0, %2, %3"
1401 [(set_attr "type" "mult")
1402 (set_attr "predicable" "yes")])
1404 (define_insn "*arm_mulsf3"
1405 [(set (match_operand:SF 0 "s_register_operand" "=f")
1406 (mult:SF (match_operand:SF 1 "s_register_operand" "f")
1407 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1408 "TARGET_ARM && TARGET_HARD_FLOAT"
1409 "fml%?s\\t%0, %1, %2"
1410 [(set_attr "type" "ffmul")
1411 (set_attr "predicable" "yes")]
1414 (define_insn "*arm_muldf3"
1415 [(set (match_operand:DF 0 "s_register_operand" "=f")
1416 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1417 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1418 "TARGET_ARM && TARGET_HARD_FLOAT"
1419 "muf%?d\\t%0, %1, %2"
1420 [(set_attr "type" "fmul")
1421 (set_attr "predicable" "yes")]
1424 (define_insn "*muldf_esfdf_df"
1425 [(set (match_operand:DF 0 "s_register_operand" "=f")
1426 (mult:DF (float_extend:DF
1427 (match_operand:SF 1 "s_register_operand" "f"))
1428 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1429 "TARGET_ARM && TARGET_HARD_FLOAT"
1430 "muf%?d\\t%0, %1, %2"
1431 [(set_attr "type" "fmul")
1432 (set_attr "predicable" "yes")]
1435 (define_insn "*muldf_df_esfdf"
1436 [(set (match_operand:DF 0 "s_register_operand" "=f")
1437 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1439 (match_operand:SF 2 "s_register_operand" "f"))))]
1440 "TARGET_ARM && TARGET_HARD_FLOAT"
1441 "muf%?d\\t%0, %1, %2"
1442 [(set_attr "type" "fmul")
1443 (set_attr "predicable" "yes")]
1446 (define_insn "*muldf_esfdf_esfdf"
1447 [(set (match_operand:DF 0 "s_register_operand" "=f")
1449 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f"))
1450 (float_extend:DF (match_operand:SF 2 "s_register_operand" "f"))))]
1451 "TARGET_ARM && TARGET_HARD_FLOAT"
1452 "muf%?d\\t%0, %1, %2"
1453 [(set_attr "type" "fmul")
1454 (set_attr "predicable" "yes")]
1459 (define_insn "divsf3"
1460 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1461 (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1462 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1463 "TARGET_ARM && TARGET_HARD_FLOAT"
1466 frd%?s\\t%0, %2, %1"
1467 [(set_attr "type" "fdivs")
1468 (set_attr "predicable" "yes")]
1471 (define_insn "divdf3"
1472 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1473 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1474 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1475 "TARGET_ARM && TARGET_HARD_FLOAT"
1478 rdf%?d\\t%0, %2, %1"
1479 [(set_attr "type" "fdivd")
1480 (set_attr "predicable" "yes")]
1483 (define_insn "*divdf_esfdf_df"
1484 [(set (match_operand:DF 0 "s_register_operand" "=f")
1485 (div:DF (float_extend:DF
1486 (match_operand:SF 1 "s_register_operand" "f"))
1487 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1488 "TARGET_ARM && TARGET_HARD_FLOAT"
1489 "dvf%?d\\t%0, %1, %2"
1490 [(set_attr "type" "fdivd")
1491 (set_attr "predicable" "yes")]
1494 (define_insn "*divdf_df_esfdf"
1495 [(set (match_operand:DF 0 "s_register_operand" "=f")
1496 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1498 (match_operand:SF 2 "s_register_operand" "f"))))]
1499 "TARGET_ARM && TARGET_HARD_FLOAT"
1500 "rdf%?d\\t%0, %2, %1"
1501 [(set_attr "type" "fdivd")
1502 (set_attr "predicable" "yes")]
1505 (define_insn "*divdf_esfdf_esfdf"
1506 [(set (match_operand:DF 0 "s_register_operand" "=f")
1507 (div:DF (float_extend:DF
1508 (match_operand:SF 1 "s_register_operand" "f"))
1510 (match_operand:SF 2 "s_register_operand" "f"))))]
1511 "TARGET_ARM && TARGET_HARD_FLOAT"
1512 "dvf%?d\\t%0, %1, %2"
1513 [(set_attr "type" "fdivd")
1514 (set_attr "predicable" "yes")]
1519 (define_insn "modsf3"
1520 [(set (match_operand:SF 0 "s_register_operand" "=f")
1521 (mod:SF (match_operand:SF 1 "s_register_operand" "f")
1522 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1523 "TARGET_ARM && TARGET_HARD_FLOAT"
1524 "rmf%?s\\t%0, %1, %2"
1525 [(set_attr "type" "fdivs")
1526 (set_attr "predicable" "yes")]
1529 (define_insn "moddf3"
1530 [(set (match_operand:DF 0 "s_register_operand" "=f")
1531 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1532 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1533 "TARGET_ARM && TARGET_HARD_FLOAT"
1534 "rmf%?d\\t%0, %1, %2"
1535 [(set_attr "type" "fdivd")
1536 (set_attr "predicable" "yes")]
1539 (define_insn "*moddf_esfdf_df"
1540 [(set (match_operand:DF 0 "s_register_operand" "=f")
1541 (mod:DF (float_extend:DF
1542 (match_operand:SF 1 "s_register_operand" "f"))
1543 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1544 "TARGET_ARM && TARGET_HARD_FLOAT"
1545 "rmf%?d\\t%0, %1, %2"
1546 [(set_attr "type" "fdivd")
1547 (set_attr "predicable" "yes")]
1550 (define_insn "*moddf_df_esfdf"
1551 [(set (match_operand:DF 0 "s_register_operand" "=f")
1552 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1554 (match_operand:SF 2 "s_register_operand" "f"))))]
1555 "TARGET_ARM && TARGET_HARD_FLOAT"
1556 "rmf%?d\\t%0, %1, %2"
1557 [(set_attr "type" "fdivd")
1558 (set_attr "predicable" "yes")]
1561 (define_insn "*moddf_esfdf_esfdf"
1562 [(set (match_operand:DF 0 "s_register_operand" "=f")
1563 (mod:DF (float_extend:DF
1564 (match_operand:SF 1 "s_register_operand" "f"))
1566 (match_operand:SF 2 "s_register_operand" "f"))))]
1567 "TARGET_ARM && TARGET_HARD_FLOAT"
1568 "rmf%?d\\t%0, %1, %2"
1569 [(set_attr "type" "fdivd")
1570 (set_attr "predicable" "yes")]
1573 ;; Boolean and,ior,xor insns
1575 ;; Split up double word logical operations
1577 ;; Split up simple DImode logical operations. Simply perform the logical
1578 ;; operation on the upper and lower halves of the registers.
1580 [(set (match_operand:DI 0 "s_register_operand" "")
1581 (match_operator:DI 6 "logical_binary_operator"
1582 [(match_operand:DI 1 "s_register_operand" "")
1583 (match_operand:DI 2 "s_register_operand" "")]))]
1584 "TARGET_ARM && reload_completed"
1585 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1586 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1589 operands[3] = gen_highpart (SImode, operands[0]);
1590 operands[0] = gen_lowpart (SImode, operands[0]);
1591 operands[4] = gen_highpart (SImode, operands[1]);
1592 operands[1] = gen_lowpart (SImode, operands[1]);
1593 operands[5] = gen_highpart (SImode, operands[2]);
1594 operands[2] = gen_lowpart (SImode, operands[2]);
1599 [(set (match_operand:DI 0 "s_register_operand" "")
1600 (match_operator:DI 6 "logical_binary_operator"
1601 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1602 (match_operand:DI 1 "s_register_operand" "")]))]
1603 "TARGET_ARM && reload_completed"
1604 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1605 (set (match_dup 3) (match_op_dup:SI 6
1606 [(ashiftrt:SI (match_dup 2) (const_int 31))
1610 operands[3] = gen_highpart (SImode, operands[0]);
1611 operands[0] = gen_lowpart (SImode, operands[0]);
1612 operands[4] = gen_highpart (SImode, operands[1]);
1613 operands[1] = gen_lowpart (SImode, operands[1]);
1614 operands[5] = gen_highpart (SImode, operands[2]);
1615 operands[2] = gen_lowpart (SImode, operands[2]);
1619 ;; The zero extend of operand 2 means we can just copy the high part of
1620 ;; operand1 into operand0.
1622 [(set (match_operand:DI 0 "s_register_operand" "")
1624 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1625 (match_operand:DI 1 "s_register_operand" "")))]
1626 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1627 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1628 (set (match_dup 3) (match_dup 4))]
1631 operands[4] = gen_highpart (SImode, operands[1]);
1632 operands[3] = gen_highpart (SImode, operands[0]);
1633 operands[0] = gen_lowpart (SImode, operands[0]);
1634 operands[1] = gen_lowpart (SImode, operands[1]);
1638 ;; The zero extend of operand 2 means we can just copy the high part of
1639 ;; operand1 into operand0.
1641 [(set (match_operand:DI 0 "s_register_operand" "")
1643 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1644 (match_operand:DI 1 "s_register_operand" "")))]
1645 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1646 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1647 (set (match_dup 3) (match_dup 4))]
1650 operands[4] = gen_highpart (SImode, operands[1]);
1651 operands[3] = gen_highpart (SImode, operands[0]);
1652 operands[0] = gen_lowpart (SImode, operands[0]);
1653 operands[1] = gen_lowpart (SImode, operands[1]);
1657 (define_insn "anddi3"
1658 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1659 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1660 (match_operand:DI 2 "s_register_operand" "r,r")))]
1663 [(set_attr "length" "8")]
1666 (define_insn_and_split "*anddi_zesidi_di"
1667 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1668 (and:DI (zero_extend:DI
1669 (match_operand:SI 2 "s_register_operand" "r,r"))
1670 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1673 "TARGET_ARM && reload_completed"
1674 ; The zero extend of operand 2 clears the high word of the output
1676 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1677 (set (match_dup 3) (const_int 0))]
1680 operands[3] = gen_highpart (SImode, operands[0]);
1681 operands[0] = gen_lowpart (SImode, operands[0]);
1682 operands[1] = gen_lowpart (SImode, operands[1]);
1684 [(set_attr "length" "8")]
1687 (define_insn "*anddi_sesdi_di"
1688 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1689 (and:DI (sign_extend:DI
1690 (match_operand:SI 2 "s_register_operand" "r,r"))
1691 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1694 [(set_attr "length" "8")]
1697 (define_expand "andsi3"
1698 [(set (match_operand:SI 0 "s_register_operand" "")
1699 (and:SI (match_operand:SI 1 "s_register_operand" "")
1700 (match_operand:SI 2 "reg_or_int_operand" "")))]
1705 if (GET_CODE (operands[2]) == CONST_INT)
1707 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1710 ? 0 : preserve_subexpressions_p ()));
1714 else /* TARGET_THUMB */
1716 if (GET_CODE (operands[2]) != CONST_INT)
1717 operands[2] = force_reg (SImode, operands[2]);
1722 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1724 operands[2] = force_reg (SImode,
1725 GEN_INT (~INTVAL (operands[2])));
1727 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1732 for (i = 9; i <= 31; i++)
1734 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1736 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1740 else if ((((HOST_WIDE_INT) 1) << i) - 1
1741 == ~INTVAL (operands[2]))
1743 rtx shift = GEN_INT (i);
1744 rtx reg = gen_reg_rtx (SImode);
1746 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1747 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1753 operands[2] = force_reg (SImode, operands[2]);
1759 (define_insn_and_split "*arm_andsi3_insn"
1760 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1761 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1762 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1766 bic%?\\t%0, %1, #%B2
1769 && GET_CODE (operands[2]) == CONST_INT
1770 && !(const_ok_for_arm (INTVAL (operands[2]))
1771 || const_ok_for_arm (~INTVAL (operands[2])))"
1772 [(clobber (const_int 0))]
1774 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1778 [(set_attr "length" "4,4,16")
1779 (set_attr "predicable" "yes")]
1782 (define_insn "*thumb_andsi3_insn"
1783 [(set (match_operand:SI 0 "register_operand" "=l")
1784 (and:SI (match_operand:SI 1 "register_operand" "%0")
1785 (match_operand:SI 2 "register_operand" "l")))]
1788 [(set_attr "length" "2")]
1791 (define_insn "*andsi3_compare0"
1792 [(set (reg:CC_NOOV CC_REGNUM)
1794 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1795 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1797 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1798 (and:SI (match_dup 1) (match_dup 2)))]
1802 bic%?s\\t%0, %1, #%B2"
1803 [(set_attr "conds" "set")]
1806 (define_insn "*andsi3_compare0_scratch"
1807 [(set (reg:CC_NOOV CC_REGNUM)
1809 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1810 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1812 (clobber (match_scratch:SI 2 "=X,r"))]
1816 bic%?s\\t%2, %0, #%B1"
1817 [(set_attr "conds" "set")]
1820 (define_insn "*zeroextractsi_compare0_scratch"
1821 [(set (reg:CC_NOOV CC_REGNUM)
1822 (compare:CC_NOOV (zero_extract:SI
1823 (match_operand:SI 0 "s_register_operand" "r")
1824 (match_operand 1 "const_int_operand" "n")
1825 (match_operand 2 "const_int_operand" "n"))
1828 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1829 && INTVAL (operands[1]) > 0
1830 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1831 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1833 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1834 << INTVAL (operands[2]));
1835 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1838 [(set_attr "conds" "set")]
1841 (define_insn "*ne_zeroextractsi"
1842 [(set (match_operand:SI 0 "s_register_operand" "=r")
1843 (ne:SI (zero_extract:SI
1844 (match_operand:SI 1 "s_register_operand" "r")
1845 (match_operand:SI 2 "const_int_operand" "n")
1846 (match_operand:SI 3 "const_int_operand" "n"))
1848 (clobber (reg:CC CC_REGNUM))]
1850 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1851 && INTVAL (operands[2]) > 0
1852 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1853 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1855 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1856 << INTVAL (operands[3]));
1857 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1858 return \"movne\\t%0, #1\";
1860 [(set_attr "conds" "clob")
1861 (set_attr "length" "8")]
1864 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1865 ;;; represented by the bitfield, then this will produce incorrect results.
1866 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1867 ;;; which have a real bit-field insert instruction, the truncation happens
1868 ;;; in the bit-field insert instruction itself. Since arm does not have a
1869 ;;; bit-field insert instruction, we would have to emit code here to truncate
1870 ;;; the value before we insert. This loses some of the advantage of having
1871 ;;; this insv pattern, so this pattern needs to be reevalutated.
1873 (define_expand "insv"
1874 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1875 (match_operand:SI 1 "general_operand" "")
1876 (match_operand:SI 2 "general_operand" ""))
1877 (match_operand:SI 3 "reg_or_int_operand" ""))]
1881 int start_bit = INTVAL (operands[2]);
1882 int width = INTVAL (operands[1]);
1883 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1884 rtx target, subtarget;
1886 target = operands[0];
1887 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1888 subreg as the final target. */
1889 if (GET_CODE (target) == SUBREG)
1891 subtarget = gen_reg_rtx (SImode);
1892 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1893 < GET_MODE_SIZE (SImode))
1894 target = SUBREG_REG (target);
1899 if (GET_CODE (operands[3]) == CONST_INT)
1901 /* Since we are inserting a known constant, we may be able to
1902 reduce the number of bits that we have to clear so that
1903 the mask becomes simple. */
1904 /* ??? This code does not check to see if the new mask is actually
1905 simpler. It may not be. */
1906 rtx op1 = gen_reg_rtx (SImode);
1907 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1908 start of this pattern. */
1909 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1910 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1912 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1913 emit_insn (gen_iorsi3 (subtarget, op1,
1914 GEN_INT (op3_value << start_bit)));
1916 else if (start_bit == 0
1917 && !(const_ok_for_arm (mask)
1918 || const_ok_for_arm (~mask)))
1920 /* A Trick, since we are setting the bottom bits in the word,
1921 we can shift operand[3] up, operand[0] down, OR them together
1922 and rotate the result back again. This takes 3 insns, and
1923 the third might be mergable into another op. */
1924 /* The shift up copes with the possibility that operand[3] is
1925 wider than the bitfield. */
1926 rtx op0 = gen_reg_rtx (SImode);
1927 rtx op1 = gen_reg_rtx (SImode);
1929 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1930 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1931 emit_insn (gen_iorsi3 (op1, op1, op0));
1932 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1934 else if ((width + start_bit == 32)
1935 && !(const_ok_for_arm (mask)
1936 || const_ok_for_arm (~mask)))
1938 /* Similar trick, but slightly less efficient. */
1940 rtx op0 = gen_reg_rtx (SImode);
1941 rtx op1 = gen_reg_rtx (SImode);
1943 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1944 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1945 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1946 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1950 rtx op0 = GEN_INT (mask);
1951 rtx op1 = gen_reg_rtx (SImode);
1952 rtx op2 = gen_reg_rtx (SImode);
1954 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1956 rtx tmp = gen_reg_rtx (SImode);
1958 emit_insn (gen_movsi (tmp, op0));
1962 /* Mask out any bits in operand[3] that are not needed. */
1963 emit_insn (gen_andsi3 (op1, operands[3], op0));
1965 if (GET_CODE (op0) == CONST_INT
1966 && (const_ok_for_arm (mask << start_bit)
1967 || const_ok_for_arm (~(mask << start_bit))))
1969 op0 = GEN_INT (~(mask << start_bit));
1970 emit_insn (gen_andsi3 (op2, operands[0], op0));
1974 if (GET_CODE (op0) == CONST_INT)
1976 rtx tmp = gen_reg_rtx (SImode);
1978 emit_insn (gen_movsi (tmp, op0));
1983 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1985 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1989 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1991 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1994 if (subtarget != target)
1996 /* If TARGET is still a SUBREG, then it must be wider than a word,
1997 so we must be careful only to set the subword we were asked to. */
1998 if (GET_CODE (target) == SUBREG)
1999 emit_move_insn (target, subtarget);
2001 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2008 ; constants for op 2 will never be given to these patterns.
2009 (define_insn_and_split "*anddi_notdi_di"
2010 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2011 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2012 (match_operand:DI 2 "s_register_operand" "0,r")))]
2015 "TARGET_ARM && reload_completed"
2016 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2017 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2020 operands[3] = gen_highpart (SImode, operands[0]);
2021 operands[0] = gen_lowpart (SImode, operands[0]);
2022 operands[4] = gen_highpart (SImode, operands[1]);
2023 operands[1] = gen_lowpart (SImode, operands[1]);
2024 operands[5] = gen_highpart (SImode, operands[2]);
2025 operands[2] = gen_lowpart (SImode, operands[2]);
2027 [(set_attr "length" "8")
2028 (set_attr "predicable" "yes")]
2031 (define_insn_and_split "*anddi_notzesidi_di"
2032 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2033 (and:DI (not:DI (zero_extend:DI
2034 (match_operand:SI 2 "s_register_operand" "r,r")))
2035 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2038 bic%?\\t%Q0, %Q1, %2
2040 ; (not (zero_extend ...)) allows us to just copy the high word from
2041 ; operand1 to operand0.
2044 && operands[0] != operands[1]"
2045 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2046 (set (match_dup 3) (match_dup 4))]
2049 operands[3] = gen_highpart (SImode, operands[0]);
2050 operands[0] = gen_lowpart (SImode, operands[0]);
2051 operands[4] = gen_highpart (SImode, operands[1]);
2052 operands[1] = gen_lowpart (SImode, operands[1]);
2054 [(set_attr "length" "4,8")
2055 (set_attr "predicable" "yes")]
2058 (define_insn_and_split "*anddi_notsesidi_di"
2059 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2060 (and:DI (not:DI (sign_extend:DI
2061 (match_operand:SI 2 "s_register_operand" "r,r")))
2062 (match_operand:DI 1 "s_register_operand" "0,r")))]
2065 "TARGET_ARM && reload_completed"
2066 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2067 (set (match_dup 3) (and:SI (not:SI
2068 (ashiftrt:SI (match_dup 2) (const_int 31)))
2072 operands[3] = gen_highpart (SImode, operands[0]);
2073 operands[0] = gen_lowpart (SImode, operands[0]);
2074 operands[4] = gen_highpart (SImode, operands[1]);
2075 operands[1] = gen_lowpart (SImode, operands[1]);
2077 [(set_attr "length" "8")
2078 (set_attr "predicable" "yes")]
2081 (define_insn "andsi_notsi_si"
2082 [(set (match_operand:SI 0 "s_register_operand" "=r")
2083 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2084 (match_operand:SI 1 "s_register_operand" "r")))]
2086 "bic%?\\t%0, %1, %2"
2087 [(set_attr "predicable" "yes")]
2090 (define_insn "bicsi3"
2091 [(set (match_operand:SI 0 "register_operand" "=l")
2092 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2093 (match_operand:SI 2 "register_operand" "0")))]
2096 [(set_attr "length" "2")]
2099 (define_insn "andsi_not_shiftsi_si"
2100 [(set (match_operand:SI 0 "s_register_operand" "=r")
2101 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2102 [(match_operand:SI 2 "s_register_operand" "r")
2103 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2104 (match_operand:SI 1 "s_register_operand" "r")))]
2106 "bic%?\\t%0, %1, %2%S4"
2107 [(set_attr "predicable" "yes")
2108 (set_attr "shift" "2")
2112 (define_insn "*andsi_notsi_si_compare0"
2113 [(set (reg:CC_NOOV CC_REGNUM)
2115 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2116 (match_operand:SI 1 "s_register_operand" "r"))
2118 (set (match_operand:SI 0 "s_register_operand" "=r")
2119 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2121 "bic%?s\\t%0, %1, %2"
2122 [(set_attr "conds" "set")]
2125 (define_insn "*andsi_notsi_si_compare0_scratch"
2126 [(set (reg:CC_NOOV CC_REGNUM)
2128 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2129 (match_operand:SI 1 "s_register_operand" "r"))
2131 (clobber (match_scratch:SI 0 "=r"))]
2133 "bic%?s\\t%0, %1, %2"
2134 [(set_attr "conds" "set")]
2137 (define_insn "iordi3"
2138 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2139 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2140 (match_operand:DI 2 "s_register_operand" "r,r")))]
2143 [(set_attr "length" "8")
2144 (set_attr "predicable" "yes")]
2147 (define_insn "*iordi_zesidi_di"
2148 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2149 (ior:DI (zero_extend:DI
2150 (match_operand:SI 2 "s_register_operand" "r,r"))
2151 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2154 orr%?\\t%Q0, %Q1, %2
2156 [(set_attr "length" "4,8")
2157 (set_attr "predicable" "yes")]
2160 (define_insn "*iordi_sesidi_di"
2161 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2162 (ior:DI (sign_extend:DI
2163 (match_operand:SI 2 "s_register_operand" "r,r"))
2164 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2167 [(set_attr "length" "8")
2168 (set_attr "predicable" "yes")]
2171 (define_expand "iorsi3"
2172 [(set (match_operand:SI 0 "s_register_operand" "")
2173 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2174 (match_operand:SI 2 "reg_or_int_operand" "")))]
2177 if (GET_CODE (operands[2]) == CONST_INT)
2181 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2184 ? 0 : preserve_subexpressions_p ()));
2187 else /* TARGET_THUMB */
2188 operands [2] = force_reg (SImode, operands [2]);
2193 (define_insn_and_split "*arm_iorsi3"
2194 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2195 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2196 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2202 && GET_CODE (operands[2]) == CONST_INT
2203 && !const_ok_for_arm (INTVAL (operands[2]))"
2204 [(clobber (const_int 0))]
2206 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2210 [(set_attr "length" "4,16")
2211 (set_attr "predicable" "yes")]
2214 (define_insn "*thumb_iorsi3"
2215 [(set (match_operand:SI 0 "register_operand" "=l")
2216 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2217 (match_operand:SI 2 "register_operand" "l")))]
2220 [(set_attr "length" "2")]
2224 [(match_scratch:SI 3 "r")
2225 (set (match_operand:SI 0 "s_register_operand" "")
2226 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2227 (match_operand:SI 2 "const_int_operand" "")))]
2229 && !const_ok_for_arm (INTVAL (operands[2]))
2230 && const_ok_for_arm (~INTVAL (operands[2]))"
2231 [(set (match_dup 3) (match_dup 2))
2232 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2236 (define_insn "*iorsi3_compare0"
2237 [(set (reg:CC_NOOV CC_REGNUM)
2238 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2239 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2241 (set (match_operand:SI 0 "s_register_operand" "=r")
2242 (ior:SI (match_dup 1) (match_dup 2)))]
2244 "orr%?s\\t%0, %1, %2"
2245 [(set_attr "conds" "set")]
2248 (define_insn "*iorsi3_compare0_scratch"
2249 [(set (reg:CC_NOOV CC_REGNUM)
2250 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2251 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2253 (clobber (match_scratch:SI 0 "=r"))]
2255 "orr%?s\\t%0, %1, %2"
2256 [(set_attr "conds" "set")]
2259 (define_insn "xordi3"
2260 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2261 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2262 (match_operand:DI 2 "s_register_operand" "r,r")))]
2265 [(set_attr "length" "8")
2266 (set_attr "predicable" "yes")]
2269 (define_insn "*xordi_zesidi_di"
2270 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2271 (xor:DI (zero_extend:DI
2272 (match_operand:SI 2 "s_register_operand" "r,r"))
2273 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2276 eor%?\\t%Q0, %Q1, %2
2278 [(set_attr "length" "4,8")
2279 (set_attr "predicable" "yes")]
2282 (define_insn "*xordi_sesidi_di"
2283 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2284 (xor:DI (sign_extend:DI
2285 (match_operand:SI 2 "s_register_operand" "r,r"))
2286 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2289 [(set_attr "length" "8")
2290 (set_attr "predicable" "yes")]
2293 (define_expand "xorsi3"
2294 [(set (match_operand:SI 0 "s_register_operand" "")
2295 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2296 (match_operand:SI 2 "arm_rhs_operand" "")))]
2299 if (GET_CODE (operands[2]) == CONST_INT)
2300 operands[2] = force_reg (SImode, operands[2]);
2304 (define_insn "*arm_xorsi3"
2305 [(set (match_operand:SI 0 "s_register_operand" "=r")
2306 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2307 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2309 "eor%?\\t%0, %1, %2"
2310 [(set_attr "predicable" "yes")]
2313 (define_insn "*thumb_xorsi3"
2314 [(set (match_operand:SI 0 "register_operand" "=l")
2315 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2316 (match_operand:SI 2 "register_operand" "l")))]
2319 [(set_attr "length" "2")]
2322 (define_insn "*xorsi3_compare0"
2323 [(set (reg:CC_NOOV CC_REGNUM)
2324 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2325 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2327 (set (match_operand:SI 0 "s_register_operand" "=r")
2328 (xor:SI (match_dup 1) (match_dup 2)))]
2330 "eor%?s\\t%0, %1, %2"
2331 [(set_attr "conds" "set")]
2334 (define_insn "*xorsi3_compare0_scratch"
2335 [(set (reg:CC_NOOV CC_REGNUM)
2336 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2337 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2341 [(set_attr "conds" "set")]
2344 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2345 ; (NOT D) we can sometimes merge the final NOT into one of the following
2349 [(set (match_operand:SI 0 "s_register_operand" "")
2350 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2351 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2352 (match_operand:SI 3 "arm_rhs_operand" "")))
2353 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2355 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2356 (not:SI (match_dup 3))))
2357 (set (match_dup 0) (not:SI (match_dup 4)))]
2361 (define_insn "*andsi_iorsi3_notsi"
2362 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2363 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2364 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2365 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2367 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2368 [(set_attr "length" "8")
2369 (set_attr "predicable" "yes")]
2374 ;; Minimum and maximum insns
2376 (define_insn "smaxsi3"
2377 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2378 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2379 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2380 (clobber (reg:CC CC_REGNUM))]
2383 cmp\\t%1, %2\;movlt\\t%0, %2
2384 cmp\\t%1, %2\;movge\\t%0, %1
2385 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2386 [(set_attr "conds" "clob")
2387 (set_attr "length" "8,8,12")]
2390 (define_insn "sminsi3"
2391 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2392 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2393 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2394 (clobber (reg:CC CC_REGNUM))]
2397 cmp\\t%1, %2\;movge\\t%0, %2
2398 cmp\\t%1, %2\;movlt\\t%0, %1
2399 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2400 [(set_attr "conds" "clob")
2401 (set_attr "length" "8,8,12")]
2404 (define_insn "umaxsi3"
2405 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2406 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2407 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2408 (clobber (reg:CC CC_REGNUM))]
2411 cmp\\t%1, %2\;movcc\\t%0, %2
2412 cmp\\t%1, %2\;movcs\\t%0, %1
2413 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2414 [(set_attr "conds" "clob")
2415 (set_attr "length" "8,8,12")]
2418 (define_insn "uminsi3"
2419 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2420 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2421 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2422 (clobber (reg:CC CC_REGNUM))]
2425 cmp\\t%1, %2\;movcs\\t%0, %2
2426 cmp\\t%1, %2\;movcc\\t%0, %1
2427 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2428 [(set_attr "conds" "clob")
2429 (set_attr "length" "8,8,12")]
2432 (define_insn "*store_minmaxsi"
2433 [(set (match_operand:SI 0 "memory_operand" "=m")
2434 (match_operator:SI 3 "minmax_operator"
2435 [(match_operand:SI 1 "s_register_operand" "r")
2436 (match_operand:SI 2 "s_register_operand" "r")]))
2437 (clobber (reg:CC CC_REGNUM))]
2440 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2442 output_asm_insn (\"cmp\\t%1, %2\", operands);
2443 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2444 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2447 [(set_attr "conds" "clob")
2448 (set_attr "length" "12")
2449 (set_attr "type" "store1")]
2452 ; Reject the frame pointer in operand[1], since reloading this after
2453 ; it has been eliminated can cause carnage.
2454 (define_insn "*minmax_arithsi"
2455 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2456 (match_operator:SI 4 "shiftable_operator"
2457 [(match_operator:SI 5 "minmax_operator"
2458 [(match_operand:SI 2 "s_register_operand" "r,r")
2459 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2460 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2461 (clobber (reg:CC CC_REGNUM))]
2463 && (GET_CODE (operands[1]) != REG
2464 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2465 && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2468 enum rtx_code code = GET_CODE (operands[4]);
2470 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2472 output_asm_insn (\"cmp\\t%2, %3\", operands);
2473 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2474 if (which_alternative != 0 || operands[3] != const0_rtx
2475 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2476 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2479 [(set_attr "conds" "clob")
2480 (set_attr "length" "12")]
2484 ;; Shift and rotation insns
2486 (define_expand "ashlsi3"
2487 [(set (match_operand:SI 0 "s_register_operand" "")
2488 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2489 (match_operand:SI 2 "arm_rhs_operand" "")))]
2492 if (GET_CODE (operands[2]) == CONST_INT
2493 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2495 emit_insn (gen_movsi (operands[0], const0_rtx));
2501 (define_insn "*thumb_ashlsi3"
2502 [(set (match_operand:SI 0 "register_operand" "=l,l")
2503 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2504 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2507 [(set_attr "length" "2")]
2510 (define_expand "ashrsi3"
2511 [(set (match_operand:SI 0 "s_register_operand" "")
2512 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2513 (match_operand:SI 2 "arm_rhs_operand" "")))]
2516 if (GET_CODE (operands[2]) == CONST_INT
2517 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2518 operands[2] = GEN_INT (31);
2522 (define_insn "*thumb_ashrsi3"
2523 [(set (match_operand:SI 0 "register_operand" "=l,l")
2524 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2525 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2528 [(set_attr "length" "2")]
2531 (define_expand "lshrsi3"
2532 [(set (match_operand:SI 0 "s_register_operand" "")
2533 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2534 (match_operand:SI 2 "arm_rhs_operand" "")))]
2537 if (GET_CODE (operands[2]) == CONST_INT
2538 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2540 emit_insn (gen_movsi (operands[0], const0_rtx));
2546 (define_insn "*thumb_lshrsi3"
2547 [(set (match_operand:SI 0 "register_operand" "=l,l")
2548 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2549 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2552 [(set_attr "length" "2")]
2555 (define_expand "rotlsi3"
2556 [(set (match_operand:SI 0 "s_register_operand" "")
2557 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2558 (match_operand:SI 2 "reg_or_int_operand" "")))]
2561 if (GET_CODE (operands[2]) == CONST_INT)
2562 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2565 rtx reg = gen_reg_rtx (SImode);
2566 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2572 (define_expand "rotrsi3"
2573 [(set (match_operand:SI 0 "s_register_operand" "")
2574 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2575 (match_operand:SI 2 "arm_rhs_operand" "")))]
2580 if (GET_CODE (operands[2]) == CONST_INT
2581 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2582 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2584 else /* TARGET_THUMB */
2586 if (GET_CODE (operands [2]) == CONST_INT)
2587 operands [2] = force_reg (SImode, operands[2]);
2592 (define_insn "*thumb_rotrsi3"
2593 [(set (match_operand:SI 0 "register_operand" "=l")
2594 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2595 (match_operand:SI 2 "register_operand" "l")))]
2598 [(set_attr "length" "2")]
2601 (define_expand "ashldi3"
2602 [(set (match_operand:DI 0 "s_register_operand" "")
2603 (ashift:DI (match_operand:DI 1 "general_operand" "")
2604 (match_operand:SI 2 "general_operand" "")))]
2605 "TARGET_ARM && (TARGET_CIRRUS)"
2607 if (! s_register_operand (operands[1], DImode))
2608 operands[1] = copy_to_mode_reg (DImode, operands[1]);
2609 if (! s_register_operand (operands[2], SImode))
2610 operands[2] = copy_to_mode_reg (SImode, operands[2]);
2614 (define_insn "*arm_shiftsi3"
2615 [(set (match_operand:SI 0 "s_register_operand" "=r")
2616 (match_operator:SI 3 "shift_operator"
2617 [(match_operand:SI 1 "s_register_operand" "r")
2618 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2621 [(set_attr "predicable" "yes")
2622 (set_attr "shift" "1")
2626 (define_insn "*shiftsi3_compare0"
2627 [(set (reg:CC_NOOV CC_REGNUM)
2628 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2629 [(match_operand:SI 1 "s_register_operand" "r")
2630 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2632 (set (match_operand:SI 0 "s_register_operand" "=r")
2633 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2635 "mov%?s\\t%0, %1%S3"
2636 [(set_attr "conds" "set")
2637 (set_attr "shift" "1")
2641 (define_insn "*shiftsi3_compare0_scratch"
2642 [(set (reg:CC_NOOV CC_REGNUM)
2643 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2644 [(match_operand:SI 1 "s_register_operand" "r")
2645 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2647 (clobber (match_scratch:SI 0 "=r"))]
2649 "mov%?s\\t%0, %1%S3"
2650 [(set_attr "conds" "set")
2651 (set_attr "shift" "1")
2655 (define_insn "*notsi_shiftsi"
2656 [(set (match_operand:SI 0 "s_register_operand" "=r")
2657 (not:SI (match_operator:SI 3 "shift_operator"
2658 [(match_operand:SI 1 "s_register_operand" "r")
2659 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2662 [(set_attr "predicable" "yes")
2663 (set_attr "shift" "1")
2667 (define_insn "*notsi_shiftsi_compare0"
2668 [(set (reg:CC_NOOV CC_REGNUM)
2669 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2670 [(match_operand:SI 1 "s_register_operand" "r")
2671 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2673 (set (match_operand:SI 0 "s_register_operand" "=r")
2674 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2676 "mvn%?s\\t%0, %1%S3"
2677 [(set_attr "conds" "set")
2678 (set_attr "shift" "1")
2682 (define_insn "*not_shiftsi_compare0_scratch"
2683 [(set (reg:CC_NOOV CC_REGNUM)
2684 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2685 [(match_operand:SI 1 "s_register_operand" "r")
2686 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2688 (clobber (match_scratch:SI 0 "=r"))]
2690 "mvn%?s\\t%0, %1%S3"
2691 [(set_attr "conds" "set")
2692 (set_attr "shift" "1")
2696 ;; We don't really have extzv, but defining this using shifts helps
2697 ;; to reduce register pressure later on.
2699 (define_expand "extzv"
2701 (ashift:SI (match_operand:SI 1 "register_operand" "")
2702 (match_operand:SI 2 "const_int_operand" "")))
2703 (set (match_operand:SI 0 "register_operand" "")
2704 (lshiftrt:SI (match_dup 4)
2705 (match_operand:SI 3 "const_int_operand" "")))]
2709 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2710 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2712 operands[3] = GEN_INT (rshift);
2716 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2720 operands[2] = GEN_INT (lshift);
2721 operands[4] = gen_reg_rtx (SImode);
2726 ;; Unary arithmetic insns
2728 (define_expand "negdi2"
2730 [(set (match_operand:DI 0 "s_register_operand" "")
2731 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2732 (clobber (reg:CC CC_REGNUM))])]
2737 if (GET_CODE (operands[1]) != REG)
2738 operands[1] = force_reg (SImode, operands[1]);
2743 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2744 ;; The second alternative is to allow the common case of a *full* overlap.
2745 (define_insn "*arm_negdi2"
2746 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2747 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2748 (clobber (reg:CC CC_REGNUM))]
2750 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2751 [(set_attr "conds" "clob")
2752 (set_attr "length" "8")]
2755 (define_insn "*thumb_negdi2"
2756 [(set (match_operand:DI 0 "register_operand" "=&l")
2757 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2758 (clobber (reg:CC CC_REGNUM))]
2760 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2761 [(set_attr "length" "6")]
2764 (define_expand "negsi2"
2765 [(set (match_operand:SI 0 "s_register_operand" "")
2766 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2771 (define_insn "*arm_negsi2"
2772 [(set (match_operand:SI 0 "s_register_operand" "=r")
2773 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2775 "rsb%?\\t%0, %1, #0"
2776 [(set_attr "predicable" "yes")]
2779 (define_insn "*thumb_negsi2"
2780 [(set (match_operand:SI 0 "register_operand" "=l")
2781 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2784 [(set_attr "length" "2")]
2787 (define_insn "*arm_negsf2"
2788 [(set (match_operand:SF 0 "s_register_operand" "=f")
2789 (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
2790 "TARGET_ARM && TARGET_HARD_FLOAT"
2792 [(set_attr "type" "ffarith")
2793 (set_attr "predicable" "yes")]
2796 (define_insn "*arm_negdf2"
2797 [(set (match_operand:DF 0 "s_register_operand" "=f")
2798 (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
2799 "TARGET_ARM && TARGET_HARD_FLOAT"
2801 [(set_attr "type" "ffarith")
2802 (set_attr "predicable" "yes")]
2805 (define_insn "*negdf_esfdf"
2806 [(set (match_operand:DF 0 "s_register_operand" "=f")
2807 (neg:DF (float_extend:DF
2808 (match_operand:SF 1 "s_register_operand" "f"))))]
2809 "TARGET_ARM && TARGET_HARD_FLOAT"
2811 [(set_attr "type" "ffarith")
2812 (set_attr "predicable" "yes")]
2815 ;; abssi2 doesn't really clobber the condition codes if a different register
2816 ;; is being set. To keep things simple, assume during rtl manipulations that
2817 ;; it does, but tell the final scan operator the truth. Similarly for
2820 (define_insn "*arm_abssi2"
2821 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2822 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2823 (clobber (reg:CC CC_REGNUM))]
2826 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2827 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2828 [(set_attr "conds" "clob,*")
2829 (set_attr "shift" "1")
2830 ;; predicable can't be set based on the variant, so left as no
2831 (set_attr "length" "8")]
2834 (define_insn "*neg_abssi2"
2835 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2836 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2837 (clobber (reg:CC CC_REGNUM))]
2840 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2841 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2842 [(set_attr "conds" "clob,*")
2843 (set_attr "shift" "1")
2844 ;; predicable can't be set based on the variant, so left as no
2845 (set_attr "length" "8")]
2848 (define_insn "*arm_abssf2"
2849 [(set (match_operand:SF 0 "s_register_operand" "=f")
2850 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
2851 "TARGET_ARM && TARGET_HARD_FLOAT"
2853 [(set_attr "type" "ffarith")
2854 (set_attr "predicable" "yes")]
2857 (define_insn "*arm_absdf2"
2858 [(set (match_operand:DF 0 "s_register_operand" "=f")
2859 (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
2860 "TARGET_ARM && TARGET_HARD_FLOAT"
2862 [(set_attr "type" "ffarith")
2863 (set_attr "predicable" "yes")]
2866 (define_insn "*absdf_esfdf"
2867 [(set (match_operand:DF 0 "s_register_operand" "=f")
2868 (abs:DF (float_extend:DF
2869 (match_operand:SF 1 "s_register_operand" "f"))))]
2870 "TARGET_ARM && TARGET_HARD_FLOAT"
2872 [(set_attr "type" "ffarith")
2873 (set_attr "predicable" "yes")]
2876 (define_insn "sqrtsf2"
2877 [(set (match_operand:SF 0 "s_register_operand" "=f")
2878 (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
2879 "TARGET_ARM && TARGET_HARD_FLOAT"
2881 [(set_attr "type" "float_em")
2882 (set_attr "predicable" "yes")]
2885 (define_insn "sqrtdf2"
2886 [(set (match_operand:DF 0 "s_register_operand" "=f")
2887 (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
2888 "TARGET_ARM && TARGET_HARD_FLOAT"
2890 [(set_attr "type" "float_em")
2891 (set_attr "predicable" "yes")]
2894 (define_insn "*sqrtdf_esfdf"
2895 [(set (match_operand:DF 0 "s_register_operand" "=f")
2896 (sqrt:DF (float_extend:DF
2897 (match_operand:SF 1 "s_register_operand" "f"))))]
2898 "TARGET_ARM && TARGET_HARD_FLOAT"
2900 [(set_attr "type" "float_em")
2901 (set_attr "predicable" "yes")]
2904 (define_insn_and_split "one_cmpldi2"
2905 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2906 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2909 "TARGET_ARM && reload_completed"
2910 [(set (match_dup 0) (not:SI (match_dup 1)))
2911 (set (match_dup 2) (not:SI (match_dup 3)))]
2914 operands[2] = gen_highpart (SImode, operands[0]);
2915 operands[0] = gen_lowpart (SImode, operands[0]);
2916 operands[3] = gen_highpart (SImode, operands[1]);
2917 operands[1] = gen_lowpart (SImode, operands[1]);
2919 [(set_attr "length" "8")
2920 (set_attr "predicable" "yes")]
2923 (define_expand "one_cmplsi2"
2924 [(set (match_operand:SI 0 "s_register_operand" "")
2925 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2930 (define_insn "*arm_one_cmplsi2"
2931 [(set (match_operand:SI 0 "s_register_operand" "=r")
2932 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
2935 [(set_attr "predicable" "yes")]
2938 (define_insn "*thumb_one_cmplsi2"
2939 [(set (match_operand:SI 0 "register_operand" "=l")
2940 (not:SI (match_operand:SI 1 "register_operand" "l")))]
2943 [(set_attr "length" "2")]
2946 (define_insn "*notsi_compare0"
2947 [(set (reg:CC_NOOV CC_REGNUM)
2948 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2950 (set (match_operand:SI 0 "s_register_operand" "=r")
2951 (not:SI (match_dup 1)))]
2954 [(set_attr "conds" "set")]
2957 (define_insn "*notsi_compare0_scratch"
2958 [(set (reg:CC_NOOV CC_REGNUM)
2959 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2961 (clobber (match_scratch:SI 0 "=r"))]
2964 [(set_attr "conds" "set")]
2967 ;; Fixed <--> Floating conversion insns
2969 (define_insn "*arm_floatsisf2"
2970 [(set (match_operand:SF 0 "s_register_operand" "=f")
2971 (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
2972 "TARGET_ARM && TARGET_HARD_FLOAT"
2974 [(set_attr "type" "r_2_f")
2975 (set_attr "predicable" "yes")]
2978 (define_insn "*arm_floatsidf2"
2979 [(set (match_operand:DF 0 "s_register_operand" "=f")
2980 (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
2981 "TARGET_ARM && TARGET_HARD_FLOAT"
2983 [(set_attr "type" "r_2_f")
2984 (set_attr "predicable" "yes")]
2987 (define_insn "*arm_fix_truncsfsi2"
2988 [(set (match_operand:SI 0 "s_register_operand" "=r")
2989 (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
2990 "TARGET_ARM && TARGET_HARD_FLOAT"
2992 [(set_attr "type" "f_2_r")
2993 (set_attr "predicable" "yes")]
2996 (define_insn "*arm_fix_truncdfsi2"
2997 [(set (match_operand:SI 0 "s_register_operand" "=r")
2998 (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
2999 "TARGET_ARM && TARGET_HARD_FLOAT"
3001 [(set_attr "type" "f_2_r")
3002 (set_attr "predicable" "yes")]
3007 (define_insn "*arm_truncdfsf2"
3008 [(set (match_operand:SF 0 "s_register_operand" "=f")
3010 (match_operand:DF 1 "s_register_operand" "f")))]
3011 "TARGET_ARM && TARGET_HARD_FLOAT"
3013 [(set_attr "type" "ffarith")
3014 (set_attr "predicable" "yes")]
3017 ;; Zero and sign extension instructions.
3019 (define_insn "zero_extendsidi2"
3020 [(set (match_operand:DI 0 "s_register_operand" "=r")
3021 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3024 if (REGNO (operands[1])
3025 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3026 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3027 return \"mov%?\\t%R0, #0\";
3029 [(set_attr "length" "8")
3030 (set_attr "predicable" "yes")]
3033 (define_insn "zero_extendqidi2"
3034 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
3035 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3038 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3039 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3040 [(set_attr "length" "8")
3041 (set_attr "predicable" "yes")
3042 (set_attr "type" "*,load")
3043 (set_attr "pool_range" "*,4092")
3044 (set_attr "neg_pool_range" "*,4084")]
3047 (define_insn "extendsidi2"
3048 [(set (match_operand:DI 0 "s_register_operand" "=r")
3049 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3052 if (REGNO (operands[1])
3053 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3054 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3055 return \"mov%?\\t%R0, %Q0, asr #31\";
3057 [(set_attr "length" "8")
3058 (set_attr "shift" "1")
3059 (set_attr "predicable" "yes")]
3062 (define_expand "zero_extendhisi2"
3064 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3066 (set (match_operand:SI 0 "s_register_operand" "")
3067 (lshiftrt:SI (match_dup 2) (const_int 16)))]
3073 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3075 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3076 here because the insn below will generate an LDRH instruction
3077 rather than an LDR instruction, so we cannot get an unaligned
3079 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3080 gen_rtx_ZERO_EXTEND (SImode,
3084 if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3086 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3089 if (!s_register_operand (operands[1], HImode))
3090 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3091 operands[1] = gen_lowpart (SImode, operands[1]);
3092 operands[2] = gen_reg_rtx (SImode);
3094 else /* TARGET_THUMB */
3096 if (GET_CODE (operands[1]) == MEM)
3100 tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3101 tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3108 if (!s_register_operand (operands[1], HImode))
3109 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3110 operands[1] = gen_lowpart (SImode, operands[1]);
3111 operands[2] = gen_reg_rtx (SImode);
3113 ops[0] = operands[2];
3114 ops[1] = operands[1];
3115 ops[2] = GEN_INT (16);
3117 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3118 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3120 ops[0] = operands[0];
3121 ops[1] = operands[2];
3122 ops[2] = GEN_INT (16);
3124 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3125 gen_rtx_LSHIFTRT (SImode, ops[1],
3133 (define_insn "*thumb_zero_extendhisi2"
3134 [(set (match_operand:SI 0 "register_operand" "=l")
3135 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3138 rtx mem = XEXP (operands[1], 0);
3140 if (GET_CODE (mem) == CONST)
3141 mem = XEXP (mem, 0);
3143 if (GET_CODE (mem) == LABEL_REF)
3144 return \"ldr\\t%0, %1\";
3146 if (GET_CODE (mem) == PLUS)
3148 rtx a = XEXP (mem, 0);
3149 rtx b = XEXP (mem, 1);
3151 /* This can happen due to bugs in reload. */
3152 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3155 ops[0] = operands[0];
3158 output_asm_insn (\"mov %0, %1\", ops);
3160 XEXP (mem, 0) = operands[0];
3163 else if ( GET_CODE (a) == LABEL_REF
3164 && GET_CODE (b) == CONST_INT)
3165 return \"ldr\\t%0, %1\";
3168 return \"ldrh\\t%0, %1\";
3170 [(set_attr "length" "4")
3171 (set_attr "type" "load")
3172 (set_attr "pool_range" "60")]
3175 (define_insn "*arm_zero_extendhisi2"
3176 [(set (match_operand:SI 0 "s_register_operand" "=r")
3177 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3178 "TARGET_ARM && arm_arch4"
3180 [(set_attr "type" "load")
3181 (set_attr "predicable" "yes")
3182 (set_attr "pool_range" "256")
3183 (set_attr "neg_pool_range" "244")]
3187 [(set (match_operand:SI 0 "s_register_operand" "")
3188 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3189 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3190 "TARGET_ARM && (!arm_arch4)"
3191 [(set (match_dup 2) (match_dup 1))
3192 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3194 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3200 [(set (match_operand:SI 0 "s_register_operand" "")
3201 (match_operator:SI 3 "shiftable_operator"
3202 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3203 (match_operand:SI 4 "s_register_operand" "")]))
3204 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3205 "TARGET_ARM && (!arm_arch4)"
3206 [(set (match_dup 2) (match_dup 1))
3209 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3211 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3216 (define_expand "zero_extendqisi2"
3217 [(set (match_operand:SI 0 "s_register_operand" "")
3218 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3221 if (GET_CODE (operands[1]) != MEM)
3225 emit_insn (gen_andsi3 (operands[0],
3226 gen_lowpart (SImode, operands[1]),
3229 else /* TARGET_THUMB */
3231 rtx temp = gen_reg_rtx (SImode);
3234 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3235 operands[1] = gen_lowpart (SImode, operands[1]);
3238 ops[1] = operands[1];
3239 ops[2] = GEN_INT (24);
3241 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3242 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3244 ops[0] = operands[0];
3246 ops[2] = GEN_INT (24);
3248 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3249 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3256 (define_insn "*thumb_zero_extendqisi2"
3257 [(set (match_operand:SI 0 "register_operand" "=l")
3258 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3261 [(set_attr "length" "2")
3262 (set_attr "type" "load")
3263 (set_attr "pool_range" "32")]
3266 (define_insn "*arm_zero_extendqisi2"
3267 [(set (match_operand:SI 0 "s_register_operand" "=r")
3268 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3270 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3271 [(set_attr "type" "load")
3272 (set_attr "predicable" "yes")
3273 (set_attr "pool_range" "4096")
3274 (set_attr "neg_pool_range" "4084")]
3278 [(set (match_operand:SI 0 "s_register_operand" "")
3279 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3280 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3281 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3282 [(set (match_dup 2) (match_dup 1))
3283 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3287 (define_insn "*compareqi_eq0"
3288 [(set (reg:CC_Z CC_REGNUM)
3289 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3293 [(set_attr "conds" "set")]
3296 (define_expand "extendhisi2"
3298 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3300 (set (match_operand:SI 0 "s_register_operand" "")
3301 (ashiftrt:SI (match_dup 2)
3306 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3308 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3309 here because the insn below will generate an LDRH instruction
3310 rather than an LDR instruction, so we cannot get an unaligned
3312 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3313 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3317 if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3319 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3322 if (!s_register_operand (operands[1], HImode))
3323 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3324 operands[1] = gen_lowpart (SImode, operands[1]);
3325 operands[2] = gen_reg_rtx (SImode);
3331 ops[0] = operands[2];
3332 ops[1] = operands[1];
3333 ops[2] = GEN_INT (16);
3335 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3336 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3338 ops[0] = operands[0];
3339 ops[1] = operands[2];
3340 ops[2] = GEN_INT (16);
3342 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3343 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3350 (define_insn "*thumb_extendhisi2_insn"
3351 [(set (match_operand:SI 0 "register_operand" "=l")
3352 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3353 (clobber (match_scratch:SI 2 "=&l"))]
3358 rtx mem = XEXP (operands[1], 0);
3360 /* This code used to try to use 'V', and fix the address only if it was
3361 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3362 range of QImode offsets, and offsettable_address_p does a QImode
3365 if (GET_CODE (mem) == CONST)
3366 mem = XEXP (mem, 0);
3368 if (GET_CODE (mem) == LABEL_REF)
3369 return \"ldr\\t%0, %1\";
3371 if (GET_CODE (mem) == PLUS)
3373 rtx a = XEXP (mem, 0);
3374 rtx b = XEXP (mem, 1);
3376 if (GET_CODE (a) == LABEL_REF
3377 && GET_CODE (b) == CONST_INT)
3378 return \"ldr\\t%0, %1\";
3380 if (GET_CODE (b) == REG)
3381 return \"ldrsh\\t%0, %1\";
3389 ops[2] = const0_rtx;
3392 if (GET_CODE (ops[1]) != REG)
3398 ops[0] = operands[0];
3399 ops[3] = operands[2];
3400 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3403 [(set_attr "length" "4")
3404 (set_attr "type" "load")
3405 (set_attr "pool_range" "1020")]
3408 (define_expand "extendhisi2_mem"
3409 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3411 (zero_extend:SI (match_dup 7)))
3412 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3413 (set (match_operand:SI 0 "" "")
3414 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3419 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3421 mem1 = gen_rtx_MEM (QImode, addr);
3422 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3423 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3424 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3425 operands[0] = gen_lowpart (SImode, operands[0]);
3427 operands[2] = gen_reg_rtx (SImode);
3428 operands[3] = gen_reg_rtx (SImode);
3429 operands[6] = gen_reg_rtx (SImode);
3432 if (BYTES_BIG_ENDIAN)
3434 operands[4] = operands[2];
3435 operands[5] = operands[3];
3439 operands[4] = operands[3];
3440 operands[5] = operands[2];
3445 (define_insn "*arm_extendhisi_insn"
3446 [(set (match_operand:SI 0 "s_register_operand" "=r")
3447 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3448 "TARGET_ARM && arm_arch4"
3450 [(set_attr "type" "load")
3451 (set_attr "predicable" "yes")
3452 (set_attr "pool_range" "256")
3453 (set_attr "neg_pool_range" "244")]
3457 [(set (match_operand:SI 0 "s_register_operand" "")
3458 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3459 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3460 "TARGET_ARM && (!arm_arch4)"
3461 [(set (match_dup 2) (match_dup 1))
3462 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3464 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3470 [(set (match_operand:SI 0 "s_register_operand" "")
3471 (match_operator:SI 3 "shiftable_operator"
3472 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3473 (match_operand:SI 4 "s_register_operand" "")]))
3474 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3475 "TARGET_ARM && (!arm_arch4)"
3476 [(set (match_dup 2) (match_dup 1))
3479 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3480 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3485 (define_expand "extendqihi2"
3487 (ashift:SI (match_operand:QI 1 "general_operand" "")
3489 (set (match_operand:HI 0 "s_register_operand" "")
3490 (ashiftrt:SI (match_dup 2)
3495 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3497 emit_insn (gen_rtx_SET (VOIDmode,
3499 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3502 if (!s_register_operand (operands[1], QImode))
3503 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3504 operands[0] = gen_lowpart (SImode, operands[0]);
3505 operands[1] = gen_lowpart (SImode, operands[1]);
3506 operands[2] = gen_reg_rtx (SImode);
3510 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3511 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3512 (define_insn "*extendqihi_insn"
3513 [(set (match_operand:HI 0 "s_register_operand" "=r")
3514 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3515 "TARGET_ARM && arm_arch4"
3517 /* If the address is invalid, this will split the instruction into two. */
3518 if (bad_signed_byte_operand (operands[1], VOIDmode))
3520 return \"ldr%?sb\\t%0, %1\";
3522 [(set_attr "type" "load")
3523 (set_attr "predicable" "yes")
3524 (set_attr "length" "8")
3525 (set_attr "pool_range" "256")
3526 (set_attr "neg_pool_range" "244")]
3530 [(set (match_operand:HI 0 "s_register_operand" "")
3531 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3532 "TARGET_ARM && arm_arch4 && reload_completed"
3533 [(set (match_dup 3) (match_dup 1))
3534 (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3537 HOST_WIDE_INT offset;
3539 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3540 operands[2] = gen_rtx_MEM (QImode, operands[3]);
3541 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3542 operands[1] = XEXP (operands[1], 0);
3543 if (GET_CODE (operands[1]) == PLUS
3544 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3545 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3546 || const_ok_for_arm (-offset)))
3548 HOST_WIDE_INT low = (offset > 0
3549 ? (offset & 0xff) : -((-offset) & 0xff));
3550 XEXP (operands[2], 0) = plus_constant (operands[3], low);
3551 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3553 /* Ensure the sum is in correct canonical form */
3554 else if (GET_CODE (operands[1]) == PLUS
3555 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3556 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3557 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3558 XEXP (operands[1], 1),
3559 XEXP (operands[1], 0));
3563 (define_expand "extendqisi2"
3565 (ashift:SI (match_operand:QI 1 "general_operand" "")
3567 (set (match_operand:SI 0 "s_register_operand" "")
3568 (ashiftrt:SI (match_dup 2)
3573 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3575 emit_insn (gen_rtx_SET (VOIDmode,
3577 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3580 if (!s_register_operand (operands[1], QImode))
3581 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3582 operands[1] = gen_lowpart (SImode, operands[1]);
3583 operands[2] = gen_reg_rtx (SImode);
3589 ops[0] = operands[2];
3590 ops[1] = operands[1];
3591 ops[2] = GEN_INT (24);
3593 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3594 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3596 ops[0] = operands[0];
3597 ops[1] = operands[2];
3598 ops[2] = GEN_INT (24);
3600 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3601 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3608 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3609 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3610 (define_insn "*arm_extendqisi_insn"
3611 [(set (match_operand:SI 0 "s_register_operand" "=r")
3612 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3613 "TARGET_ARM && arm_arch4"
3615 /* If the address is invalid, this will split the instruction into two. */
3616 if (bad_signed_byte_operand (operands[1], VOIDmode))
3618 return \"ldr%?sb\\t%0, %1\";
3620 [(set_attr "type" "load")
3621 (set_attr "predicable" "yes")
3622 (set_attr "length" "8")
3623 (set_attr "pool_range" "256")
3624 (set_attr "neg_pool_range" "244")]
3628 [(set (match_operand:SI 0 "s_register_operand" "")
3629 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3630 "TARGET_ARM && arm_arch4 && reload_completed"
3631 [(set (match_dup 0) (match_dup 1))
3632 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3635 HOST_WIDE_INT offset;
3637 operands[2] = gen_rtx_MEM (QImode, operands[0]);
3638 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3639 operands[1] = XEXP (operands[1], 0);
3640 if (GET_CODE (operands[1]) == PLUS
3641 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3642 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3643 || const_ok_for_arm (-offset)))
3645 HOST_WIDE_INT low = (offset > 0
3646 ? (offset & 0xff) : -((-offset) & 0xff));
3647 XEXP (operands[2], 0) = plus_constant (operands[0], low);
3648 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3650 /* Ensure the sum is in correct canonical form */
3651 else if (GET_CODE (operands[1]) == PLUS
3652 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3653 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3654 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3655 XEXP (operands[1], 1),
3656 XEXP (operands[1], 0));
3660 (define_insn "*thumb_extendqisi2_insn"
3661 [(set (match_operand:SI 0 "register_operand" "=l,l")
3662 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3667 rtx mem = XEXP (operands[1], 0);
3669 if (GET_CODE (mem) == CONST)
3670 mem = XEXP (mem, 0);
3672 if (GET_CODE (mem) == LABEL_REF)
3673 return \"ldr\\t%0, %1\";
3675 if (GET_CODE (mem) == PLUS
3676 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3677 return \"ldr\\t%0, %1\";
3679 if (which_alternative == 0)
3680 return \"ldrsb\\t%0, %1\";
3682 ops[0] = operands[0];
3684 if (GET_CODE (mem) == PLUS)
3686 rtx a = XEXP (mem, 0);
3687 rtx b = XEXP (mem, 1);
3692 if (GET_CODE (a) == REG)
3694 if (GET_CODE (b) == REG)
3695 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3696 else if (REGNO (a) == REGNO (ops[0]))
3698 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3699 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3700 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3703 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3705 else if (GET_CODE (b) != REG)
3709 if (REGNO (b) == REGNO (ops[0]))
3711 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3712 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3713 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3716 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3719 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3721 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3722 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3723 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3728 ops[2] = const0_rtx;
3730 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3734 [(set_attr "length" "2,6")
3735 (set_attr "type" "load,load")
3736 (set_attr "pool_range" "32,32")]
3739 (define_expand "extendsfdf2"
3740 [(set (match_operand:DF 0 "s_register_operand" "")
3741 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
3742 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3746 (define_insn "*arm_extendsfdf2"
3747 [(set (match_operand:DF 0 "s_register_operand" "=f")
3748 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
3749 "TARGET_ARM && TARGET_HARD_FLOAT"
3751 [(set_attr "type" "ffarith")
3752 (set_attr "predicable" "yes")]
3755 ;; Move insns (including loads and stores)
3757 ;; XXX Just some ideas about movti.
3758 ;; I don't think these are a good idea on the arm, there just aren't enough
3760 ;;(define_expand "loadti"
3761 ;; [(set (match_operand:TI 0 "s_register_operand" "")
3762 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
3765 ;;(define_expand "storeti"
3766 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3767 ;; (match_operand:TI 1 "s_register_operand" ""))]
3770 ;;(define_expand "movti"
3771 ;; [(set (match_operand:TI 0 "general_operand" "")
3772 ;; (match_operand:TI 1 "general_operand" ""))]
3778 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3779 ;; operands[1] = copy_to_reg (operands[1]);
3780 ;; if (GET_CODE (operands[0]) == MEM)
3781 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3782 ;; else if (GET_CODE (operands[1]) == MEM)
3783 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3787 ;; emit_insn (insn);
3791 ;; Recognize garbage generated above.
3794 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3795 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3799 ;; register mem = (which_alternative < 3);
3800 ;; register const char *template;
3802 ;; operands[mem] = XEXP (operands[mem], 0);
3803 ;; switch (which_alternative)
3805 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3806 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
3807 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
3808 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
3809 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
3810 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
3812 ;; output_asm_insn (template, operands);
3816 (define_expand "movdi"
3817 [(set (match_operand:DI 0 "general_operand" "")
3818 (match_operand:DI 1 "general_operand" ""))]
3823 if (!no_new_pseudos)
3825 if (GET_CODE (operands[0]) != REG)
3826 operands[1] = force_reg (DImode, operands[1]);
3832 (define_insn "*arm_movdi"
3833 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3834 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
3835 "TARGET_ARM && !TARGET_CIRRUS"
3837 return (output_move_double (operands));
3839 [(set_attr "length" "8")
3840 (set_attr "type" "*,load,store2")
3841 (set_attr "pool_range" "*,1020,*")
3842 (set_attr "neg_pool_range" "*,1008,*")]
3845 ;;; ??? This should have alternatives for constants.
3846 ;;; ??? This was originally identical to the movdf_insn pattern.
3847 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3848 ;;; thumb_reorg with a memory reference.
3849 (define_insn "*thumb_movdi_insn"
3850 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3851 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
3854 && ( register_operand (operands[0], DImode)
3855 || register_operand (operands[1], DImode))"
3858 switch (which_alternative)
3862 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3863 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
3864 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
3866 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3868 operands[1] = GEN_INT (- INTVAL (operands[1]));
3869 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3871 return \"ldmia\\t%1, {%0, %H0}\";
3873 return \"stmia\\t%0, {%1, %H1}\";
3875 return thumb_load_double_from_address (operands);
3877 operands[2] = gen_rtx (MEM, SImode,
3878 plus_constant (XEXP (operands[0], 0), 4));
3879 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3882 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3883 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
3884 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
3887 [(set_attr "length" "4,4,6,2,2,6,4,4")
3888 (set_attr "type" "*,*,*,load,store2,load,store2,*")
3889 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
3892 (define_expand "movsi"
3893 [(set (match_operand:SI 0 "general_operand" "")
3894 (match_operand:SI 1 "general_operand" ""))]
3899 /* Everything except mem = const or mem = mem can be done easily */
3900 if (GET_CODE (operands[0]) == MEM)
3901 operands[1] = force_reg (SImode, operands[1]);
3902 if (GET_CODE (operands[1]) == CONST_INT
3903 && !(const_ok_for_arm (INTVAL (operands[1]))
3904 || const_ok_for_arm (~INTVAL (operands[1]))))
3906 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3909 : preserve_subexpressions_p ()));
3913 else /* TARGET_THUMB.... */
3915 if (!no_new_pseudos)
3917 if (GET_CODE (operands[0]) != REG)
3918 operands[1] = force_reg (SImode, operands[1]);
3923 && (CONSTANT_P (operands[1])
3924 || symbol_mentioned_p (operands[1])
3925 || label_mentioned_p (operands[1])))
3926 operands[1] = legitimize_pic_address (operands[1], SImode,
3927 (no_new_pseudos ? operands[0] : 0));
3931 (define_insn "*arm_movsi_insn"
3932 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
3933 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
3935 && ( register_operand (operands[0], SImode)
3936 || register_operand (operands[1], SImode))"
3942 [(set_attr "type" "*,*,load,store1")
3943 (set_attr "predicable" "yes")
3944 (set_attr "pool_range" "*,*,4096,*")
3945 (set_attr "neg_pool_range" "*,*,4084,*")]
3949 [(set (match_operand:SI 0 "s_register_operand" "")
3950 (match_operand:SI 1 "const_int_operand" ""))]
3952 && (!(const_ok_for_arm (INTVAL (operands[1]))
3953 || const_ok_for_arm (~INTVAL (operands[1]))))"
3954 [(clobber (const_int 0))]
3956 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3962 (define_insn "*thumb_movsi_insn"
3963 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
3964 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
3966 && ( register_operand (operands[0], SImode)
3967 || register_operand (operands[1], SImode))"
3978 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
3979 (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
3980 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
3984 [(set (match_operand:SI 0 "register_operand" "")
3985 (match_operand:SI 1 "const_int_operand" ""))]
3986 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
3987 [(set (match_dup 0) (match_dup 1))
3988 (set (match_dup 0) (neg:SI (match_dup 0)))]
3989 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
3993 [(set (match_operand:SI 0 "register_operand" "")
3994 (match_operand:SI 1 "const_int_operand" ""))]
3995 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
3996 [(set (match_dup 0) (match_dup 1))
3997 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4000 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4001 unsigned HOST_WIDE_INT mask = 0xff;
4004 for (i = 0; i < 25; i++)
4005 if ((val & (mask << i)) == val)
4008 /* Shouldn't happen, but we don't want to split if the shift is zero. */
4012 operands[1] = GEN_INT (val >> i);
4013 operands[2] = GEN_INT (i);
4017 ;; When generating pic, we need to load the symbol offset into a register.
4018 ;; So that the optimizer does not confuse this with a normal symbol load
4019 ;; we use an unspec. The offset will be loaded from a constant pool entry,
4020 ;; since that is the only type of relocation we can use.
4022 ;; The rather odd constraints on the following are to force reload to leave
4023 ;; the insn alone, and to force the minipool generation pass to then move
4024 ;; the GOT symbol to memory.
4026 (define_insn "pic_load_addr_arm"
4027 [(set (match_operand:SI 0 "s_register_operand" "=r")
4028 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4029 "TARGET_ARM && flag_pic"
4031 [(set_attr "type" "load")
4032 (set (attr "pool_range") (const_int 4096))
4033 (set (attr "neg_pool_range") (const_int 4084))]
4036 (define_insn "pic_load_addr_thumb"
4037 [(set (match_operand:SI 0 "s_register_operand" "=l")
4038 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4039 "TARGET_THUMB && flag_pic"
4041 [(set_attr "type" "load")
4042 (set (attr "pool_range") (const_int 1024))]
4045 ;; This variant is used for AOF assembly, since it needs to mention the
4046 ;; pic register in the rtl.
4047 (define_expand "pic_load_addr_based"
4048 [(set (match_operand:SI 0 "s_register_operand" "=r")
4049 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4050 "TARGET_ARM && flag_pic"
4051 "operands[2] = pic_offset_table_rtx;"
4054 (define_insn "*pic_load_addr_based_insn"
4055 [(set (match_operand:SI 0 "s_register_operand" "=r")
4056 (unspec:SI [(match_operand 1 "" "")
4057 (match_operand 2 "s_register_operand" "r")]
4059 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4061 #ifdef AOF_ASSEMBLER
4062 operands[1] = aof_pic_entry (operands[1]);
4064 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4067 [(set_attr "type" "load")
4068 (set (attr "pool_range")
4069 (if_then_else (eq_attr "is_thumb" "yes")
4072 (set (attr "neg_pool_range")
4073 (if_then_else (eq_attr "is_thumb" "yes")
4078 (define_insn "pic_add_dot_plus_four"
4079 [(set (match_operand:SI 0 "register_operand" "+r")
4080 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
4081 (use (label_ref (match_operand 1 "" "")))]
4082 "TARGET_THUMB && flag_pic"
4084 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4085 CODE_LABEL_NUMBER (operands[1]));
4086 return \"add\\t%0, %|pc\";
4088 [(set_attr "length" "2")]
4091 (define_insn "pic_add_dot_plus_eight"
4092 [(set (match_operand:SI 0 "register_operand" "+r")
4093 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
4094 (use (label_ref (match_operand 1 "" "")))]
4095 "TARGET_ARM && flag_pic"
4097 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4098 CODE_LABEL_NUMBER (operands[1]));
4099 return \"add%?\\t%0, %|pc, %0\";
4101 [(set_attr "predicable" "yes")]
4104 (define_expand "builtin_setjmp_receiver"
4105 [(label_ref (match_operand 0 "" ""))]
4109 arm_finalize_pic (0);
4113 ;; If copying one reg to another we can set the condition codes according to
4114 ;; its value. Such a move is common after a return from subroutine and the
4115 ;; result is being tested against zero.
4117 (define_insn "*movsi_compare0"
4118 [(set (reg:CC CC_REGNUM)
4119 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4121 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4126 sub%?s\\t%0, %1, #0"
4127 [(set_attr "conds" "set")]
4130 ;; Subroutine to store a half word from a register into memory.
4131 ;; Operand 0 is the source register (HImode)
4132 ;; Operand 1 is the destination address in a register (SImode)
4134 ;; In both this routine and the next, we must be careful not to spill
4135 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4136 ;; can generate unrecognizable rtl.
4138 (define_expand "storehi"
4139 [;; store the low byte
4140 (set (match_operand 1 "" "") (match_dup 3))
4141 ;; extract the high byte
4143 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4144 ;; store the high byte
4145 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
4149 rtx op1 = operands[1];
4150 rtx addr = XEXP (op1, 0);
4151 enum rtx_code code = GET_CODE (addr);
4153 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4155 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4157 operands[4] = adjust_address (op1, QImode, 1);
4158 operands[1] = adjust_address (operands[1], QImode, 0);
4159 operands[3] = gen_lowpart (QImode, operands[0]);
4160 operands[0] = gen_lowpart (SImode, operands[0]);
4161 operands[2] = gen_reg_rtx (SImode);
4165 (define_expand "storehi_bigend"
4166 [(set (match_dup 4) (match_dup 3))
4168 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4169 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 3))]
4173 rtx op1 = operands[1];
4174 rtx addr = XEXP (op1, 0);
4175 enum rtx_code code = GET_CODE (addr);
4177 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4179 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4181 operands[4] = adjust_address (op1, QImode, 1);
4182 operands[1] = adjust_address (operands[1], QImode, 0);
4183 operands[3] = gen_lowpart (QImode, operands[0]);
4184 operands[0] = gen_lowpart (SImode, operands[0]);
4185 operands[2] = gen_reg_rtx (SImode);
4189 ;; Subroutine to store a half word integer constant into memory.
4190 (define_expand "storeinthi"
4191 [(set (match_operand 0 "" "")
4192 (subreg:QI (match_operand 1 "" "") 0))
4193 (set (match_dup 3) (match_dup 2))]
4197 HOST_WIDE_INT value = INTVAL (operands[1]);
4198 rtx addr = XEXP (operands[0], 0);
4199 rtx op0 = operands[0];
4200 enum rtx_code code = GET_CODE (addr);
4202 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4204 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4206 operands[1] = gen_reg_rtx (SImode);
4207 if (BYTES_BIG_ENDIAN)
4209 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4210 if ((value & 255) == ((value >> 8) & 255))
4211 operands[2] = operands[1];
4214 operands[2] = gen_reg_rtx (SImode);
4215 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4220 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4221 if ((value & 255) == ((value >> 8) & 255))
4222 operands[2] = operands[1];
4225 operands[2] = gen_reg_rtx (SImode);
4226 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4230 operands[3] = adjust_address (op0, QImode, 1);
4231 operands[0] = adjust_address (operands[0], QImode, 0);
4232 operands[2] = gen_lowpart (QImode, operands[2]);
4236 (define_expand "storehi_single_op"
4237 [(set (match_operand:HI 0 "memory_operand" "")
4238 (match_operand:HI 1 "general_operand" ""))]
4239 "TARGET_ARM && arm_arch4"
4241 if (!s_register_operand (operands[1], HImode))
4242 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4246 (define_expand "movhi"
4247 [(set (match_operand:HI 0 "general_operand" "")
4248 (match_operand:HI 1 "general_operand" ""))]
4253 if (!no_new_pseudos)
4255 if (GET_CODE (operands[0]) == MEM)
4259 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4262 if (GET_CODE (operands[1]) == CONST_INT)
4263 emit_insn (gen_storeinthi (operands[0], operands[1]));
4266 if (GET_CODE (operands[1]) == MEM)
4267 operands[1] = force_reg (HImode, operands[1]);
4268 if (BYTES_BIG_ENDIAN)
4269 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4271 emit_insn (gen_storehi (operands[1], operands[0]));
4275 /* Sign extend a constant, and keep it in an SImode reg. */
4276 else if (GET_CODE (operands[1]) == CONST_INT)
4278 rtx reg = gen_reg_rtx (SImode);
4279 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4281 /* If the constant is already valid, leave it alone. */
4282 if (!const_ok_for_arm (val))
4284 /* If setting all the top bits will make the constant
4285 loadable in a single instruction, then set them.
4286 Otherwise, sign extend the number. */
4288 if (const_ok_for_arm (~(val | ~0xffff)))
4290 else if (val & 0x8000)
4294 emit_insn (gen_movsi (reg, GEN_INT (val)));
4295 operands[1] = gen_lowpart (HImode, reg);
4297 else if (arm_arch4 && !no_new_pseudos && optimize > 0
4298 && GET_CODE (operands[1]) == MEM)
4300 rtx reg = gen_reg_rtx (SImode);
4302 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4303 operands[1] = gen_lowpart (HImode, reg);
4305 else if (!arm_arch4)
4307 /* Note: We do not have to worry about TARGET_MMU_TRAPS
4308 for v4 and up architectures because LDRH instructions will
4309 be used to access the HI values, and these cannot generate
4310 unaligned word access faults in the MMU. */
4311 if (GET_CODE (operands[1]) == MEM)
4313 if (TARGET_MMU_TRAPS)
4316 rtx offset = const0_rtx;
4317 rtx reg = gen_reg_rtx (SImode);
4319 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4320 || (GET_CODE (base) == PLUS
4321 && (GET_CODE (offset = XEXP (base, 1))
4323 && ((INTVAL(offset) & 1) != 1)
4324 && GET_CODE (base = XEXP (base, 0)) == REG))
4325 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4327 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4330 new = gen_rtx_MEM (SImode,
4331 plus_constant (base, new_offset));
4332 MEM_COPY_ATTRIBUTES (new, operands[1]);
4333 emit_insn (gen_movsi (reg, new));
4334 if (((INTVAL (offset) & 2) != 0)
4335 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4337 rtx reg2 = gen_reg_rtx (SImode);
4339 emit_insn (gen_lshrsi3 (reg2, reg,
4345 emit_insn (gen_movhi_bytes (reg, operands[1]));
4347 operands[1] = gen_lowpart (HImode, reg);
4349 else if (BYTES_BIG_ENDIAN)
4352 rtx offset = const0_rtx;
4354 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4355 || (GET_CODE (base) == PLUS
4356 && (GET_CODE (offset = XEXP (base, 1))
4358 && GET_CODE (base = XEXP (base, 0)) == REG))
4359 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4361 rtx reg = gen_reg_rtx (SImode);
4364 if ((INTVAL (offset) & 2) == 2)
4366 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4367 new = gen_rtx_MEM (SImode,
4368 plus_constant (base,
4370 MEM_COPY_ATTRIBUTES (new, operands[1]);
4371 emit_insn (gen_movsi (reg, new));
4375 new = gen_rtx_MEM (SImode,
4376 XEXP (operands[1], 0));
4377 MEM_COPY_ATTRIBUTES (new, operands[1]);
4378 emit_insn (gen_rotated_loadsi (reg, new));
4381 operands[1] = gen_lowpart (HImode, reg);
4385 emit_insn (gen_movhi_bigend (operands[0],
4393 /* Handle loading a large integer during reload */
4394 else if (GET_CODE (operands[1]) == CONST_INT
4395 && !const_ok_for_arm (INTVAL (operands[1]))
4396 && !const_ok_for_arm (~INTVAL (operands[1])))
4398 /* Writing a constant to memory needs a scratch, which should
4399 be handled with SECONDARY_RELOADs. */
4400 if (GET_CODE (operands[0]) != REG)
4403 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4404 emit_insn (gen_movsi (operands[0], operands[1]));
4408 else /* TARGET_THUMB */
4410 if (!no_new_pseudos)
4412 if (GET_CODE (operands[0]) != REG)
4413 operands[1] = force_reg (HImode, operands[1]);
4415 /* ??? We shouldn't really get invalid addresses here, but this can
4416 happen if we are passed a SP (never OK for HImode/QImode) or
4417 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4418 HImode/QImode) relative address. */
4419 /* ??? This should perhaps be fixed elsewhere, for instance, in
4420 fixup_stack_1, by checking for other kinds of invalid addresses,
4421 e.g. a bare reference to a virtual register. This may confuse the
4422 alpha though, which must handle this case differently. */
4423 if (GET_CODE (operands[0]) == MEM
4424 && !memory_address_p (GET_MODE (operands[0]),
4425 XEXP (operands[0], 0)))
4427 = replace_equiv_address (operands[0],
4428 copy_to_reg (XEXP (operands[0], 0)));
4430 if (GET_CODE (operands[1]) == MEM
4431 && !memory_address_p (GET_MODE (operands[1]),
4432 XEXP (operands[1], 0)))
4434 = replace_equiv_address (operands[1],
4435 copy_to_reg (XEXP (operands[1], 0)));
4437 /* Handle loading a large integer during reload */
4438 else if (GET_CODE (operands[1]) == CONST_INT
4439 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4441 /* Writing a constant to memory needs a scratch, which should
4442 be handled with SECONDARY_RELOADs. */
4443 if (GET_CODE (operands[0]) != REG)
4446 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4447 emit_insn (gen_movsi (operands[0], operands[1]));
4454 (define_insn "*thumb_movhi_insn"
4455 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4456 (match_operand:HI 1 "general_operand" "l,mn,l,*h,*r,I"))]
4458 && ( register_operand (operands[0], HImode)
4459 || register_operand (operands[1], HImode))"
4461 switch (which_alternative)
4463 case 0: return \"add %0, %1, #0\";
4464 case 2: return \"strh %1, %0\";
4465 case 3: return \"mov %0, %1\";
4466 case 4: return \"mov %0, %1\";
4467 case 5: return \"mov %0, %1\";
4470 /* The stack pointer can end up being taken as an index register.
4471 Catch this case here and deal with it. */
4472 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4473 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4474 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4477 ops[0] = operands[0];
4478 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4480 output_asm_insn (\"mov %0, %1\", ops);
4482 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4485 return \"ldrh %0, %1\";
4487 [(set_attr "length" "2,4,2,2,2,2")
4488 (set_attr "type" "*,load,store1,*,*,*")
4489 (set_attr "pool_range" "*,64,*,*,*,*")]
4493 (define_insn "rotated_loadsi"
4494 [(set (match_operand:SI 0 "s_register_operand" "=r")
4495 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4497 "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4502 ops[0] = operands[0];
4503 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4504 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4507 [(set_attr "type" "load")
4508 (set_attr "predicable" "yes")]
4511 (define_expand "movhi_bytes"
4512 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4514 (zero_extend:SI (match_dup 6)))
4515 (set (match_operand:SI 0 "" "")
4516 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4521 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4523 mem1 = gen_rtx_MEM (QImode, addr);
4524 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4525 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4526 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4527 operands[0] = gen_lowpart (SImode, operands[0]);
4529 operands[2] = gen_reg_rtx (SImode);
4530 operands[3] = gen_reg_rtx (SImode);
4533 if (BYTES_BIG_ENDIAN)
4535 operands[4] = operands[2];
4536 operands[5] = operands[3];
4540 operands[4] = operands[3];
4541 operands[5] = operands[2];
4546 (define_expand "movhi_bigend"
4548 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4551 (ashiftrt:SI (match_dup 2) (const_int 16)))
4552 (set (match_operand:HI 0 "s_register_operand" "")
4553 (subreg:HI (match_dup 3) 0))]
4556 operands[2] = gen_reg_rtx (SImode);
4557 operands[3] = gen_reg_rtx (SImode);
4561 ;; Pattern to recognize insn generated default case above
4562 (define_insn "*movhi_insn_arch4"
4563 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4564 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4567 && (GET_CODE (operands[1]) != CONST_INT
4568 || const_ok_for_arm (INTVAL (operands[1]))
4569 || const_ok_for_arm (~INTVAL (operands[1])))"
4571 mov%?\\t%0, %1\\t%@ movhi
4572 mvn%?\\t%0, #%B1\\t%@ movhi
4573 str%?h\\t%1, %0\\t%@ movhi
4574 ldr%?h\\t%0, %1\\t%@ movhi"
4575 [(set_attr "type" "*,*,store1,load")
4576 (set_attr "predicable" "yes")
4577 (set_attr "pool_range" "*,*,*,256")
4578 (set_attr "neg_pool_range" "*,*,*,244")]
4581 (define_insn "*movhi_insn_littleend"
4582 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4583 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4586 && !BYTES_BIG_ENDIAN
4587 && !TARGET_MMU_TRAPS
4588 && (GET_CODE (operands[1]) != CONST_INT
4589 || const_ok_for_arm (INTVAL (operands[1]))
4590 || const_ok_for_arm (~INTVAL (operands[1])))"
4592 mov%?\\t%0, %1\\t%@ movhi
4593 mvn%?\\t%0, #%B1\\t%@ movhi
4594 ldr%?\\t%0, %1\\t%@ movhi"
4595 [(set_attr "type" "*,*,load")
4596 (set_attr "predicable" "yes")
4597 (set_attr "pool_range" "4096")
4598 (set_attr "neg_pool_range" "4084")]
4601 (define_insn "*movhi_insn_bigend"
4602 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4603 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4607 && !TARGET_MMU_TRAPS
4608 && (GET_CODE (operands[1]) != CONST_INT
4609 || const_ok_for_arm (INTVAL (operands[1]))
4610 || const_ok_for_arm (~INTVAL (operands[1])))"
4612 mov%?\\t%0, %1\\t%@ movhi
4613 mvn%?\\t%0, #%B1\\t%@ movhi
4614 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4615 [(set_attr "type" "*,*,load")
4616 (set_attr "predicable" "yes")
4617 (set_attr "length" "4,4,8")
4618 (set_attr "pool_range" "*,*,4092")
4619 (set_attr "neg_pool_range" "*,*,4084")]
4622 (define_insn "*loadhi_si_bigend"
4623 [(set (match_operand:SI 0 "s_register_operand" "=r")
4624 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
4628 && !TARGET_MMU_TRAPS"
4629 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4630 [(set_attr "type" "load")
4631 (set_attr "predicable" "yes")
4632 (set_attr "pool_range" "4096")
4633 (set_attr "neg_pool_range" "4084")]
4636 (define_insn "*movhi_bytes"
4637 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4638 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4639 "TARGET_ARM && TARGET_MMU_TRAPS"
4641 mov%?\\t%0, %1\\t%@ movhi
4642 mvn%?\\t%0, #%B1\\t%@ movhi"
4643 [(set_attr "predicable" "yes")]
4646 (define_insn "thumb_movhi_clobber"
4647 [(set (match_operand:HI 0 "memory_operand" "=m")
4648 (match_operand:HI 1 "register_operand" "l"))
4649 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4655 ;; We use a DImode scratch because we may occasionally need an additional
4656 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4657 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4658 (define_expand "reload_outhi"
4659 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4660 (match_operand:HI 1 "s_register_operand" "r")
4661 (match_operand:DI 2 "s_register_operand" "=&l")])]
4664 arm_reload_out_hi (operands);
4666 thumb_reload_out_hi (operands);
4671 (define_expand "reload_inhi"
4672 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4673 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4674 (match_operand:DI 2 "s_register_operand" "=&r")])]
4675 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4678 arm_reload_in_hi (operands);
4680 thumb_reload_out_hi (operands);
4684 (define_expand "movqi"
4685 [(set (match_operand:QI 0 "general_operand" "")
4686 (match_operand:QI 1 "general_operand" ""))]
4691 /* Everything except mem = const or mem = mem can be done easily */
4693 if (!no_new_pseudos)
4695 if (GET_CODE (operands[1]) == CONST_INT)
4697 rtx reg = gen_reg_rtx (SImode);
4699 emit_insn (gen_movsi (reg, operands[1]));
4700 operands[1] = gen_lowpart (QImode, reg);
4702 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4704 rtx reg = gen_reg_rtx (SImode);
4706 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4707 operands[1] = gen_lowpart (QImode, reg);
4709 if (GET_CODE (operands[0]) == MEM)
4710 operands[1] = force_reg (QImode, operands[1]);
4713 else /* TARGET_THUMB */
4715 if (!no_new_pseudos)
4717 if (GET_CODE (operands[0]) != REG)
4718 operands[1] = force_reg (QImode, operands[1]);
4720 /* ??? We shouldn't really get invalid addresses here, but this can
4721 happen if we are passed a SP (never OK for HImode/QImode) or
4722 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4723 HImode/QImode) relative address. */
4724 /* ??? This should perhaps be fixed elsewhere, for instance, in
4725 fixup_stack_1, by checking for other kinds of invalid addresses,
4726 e.g. a bare reference to a virtual register. This may confuse the
4727 alpha though, which must handle this case differently. */
4728 if (GET_CODE (operands[0]) == MEM
4729 && !memory_address_p (GET_MODE (operands[0]),
4730 XEXP (operands[0], 0)))
4732 = replace_equiv_address (operands[0],
4733 copy_to_reg (XEXP (operands[0], 0)));
4734 if (GET_CODE (operands[1]) == MEM
4735 && !memory_address_p (GET_MODE (operands[1]),
4736 XEXP (operands[1], 0)))
4738 = replace_equiv_address (operands[1],
4739 copy_to_reg (XEXP (operands[1], 0)));
4741 /* Handle loading a large integer during reload */
4742 else if (GET_CODE (operands[1]) == CONST_INT
4743 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4745 /* Writing a constant to memory needs a scratch, which should
4746 be handled with SECONDARY_RELOADs. */
4747 if (GET_CODE (operands[0]) != REG)
4750 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4751 emit_insn (gen_movsi (operands[0], operands[1]));
4759 (define_insn "*arm_movqi_insn"
4760 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4761 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4763 && ( register_operand (operands[0], QImode)
4764 || register_operand (operands[1], QImode))"
4770 [(set_attr "type" "*,*,load,store1")
4771 (set_attr "predicable" "yes")]
4774 (define_insn "*thumb_movqi_insn"
4775 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4776 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
4778 && ( register_operand (operands[0], QImode)
4779 || register_operand (operands[1], QImode))"
4787 [(set_attr "length" "2")
4788 (set_attr "type" "*,load,store1,*,*,*")
4789 (set_attr "pool_range" "*,32,*,*,*,*")]
4792 (define_expand "movsf"
4793 [(set (match_operand:SF 0 "general_operand" "")
4794 (match_operand:SF 1 "general_operand" ""))]
4799 if (GET_CODE (operands[0]) == MEM)
4800 operands[1] = force_reg (SFmode, operands[1]);
4802 else /* TARGET_THUMB */
4804 if (!no_new_pseudos)
4806 if (GET_CODE (operands[0]) != REG)
4807 operands[1] = force_reg (SFmode, operands[1]);
4814 [(set (match_operand:SF 0 "nonimmediate_operand" "")
4815 (match_operand:SF 1 "immediate_operand" ""))]
4817 && !TARGET_HARD_FLOAT
4819 && GET_CODE (operands[1]) == CONST_DOUBLE"
4820 [(set (match_dup 2) (match_dup 3))]
4822 operands[2] = gen_lowpart (SImode, operands[0]);
4823 operands[3] = gen_lowpart (SImode, operands[1]);
4824 if (operands[2] == 0 || operands[3] == 0)
4829 (define_insn "*arm_movsf_hard_insn"
4830 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
4831 (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
4833 && TARGET_HARD_FLOAT
4834 && (GET_CODE (operands[0]) != MEM
4835 || register_operand (operands[1], SFmode))"
4841 str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
4842 stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
4844 ldr%?\\t%0, %1\\t%@ float
4845 str%?\\t%1, %0\\t%@ float"
4846 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
4847 (set_attr "predicable" "yes")
4849 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
4850 (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
4851 (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
4854 ;; Exactly the same as above, except that all `f' cases are deleted.
4855 ;; This is necessary to prevent reload from ever trying to use a `f' reg
4856 ;; when -msoft-float.
4858 (define_insn "*arm_movsf_soft_insn"
4859 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4860 (match_operand:SF 1 "general_operand" "r,mE,r"))]
4863 && TARGET_SOFT_FLOAT
4864 && (GET_CODE (operands[0]) != MEM
4865 || register_operand (operands[1], SFmode))"
4868 ldr%?\\t%0, %1\\t%@ float
4869 str%?\\t%1, %0\\t%@ float"
4870 [(set_attr "length" "4,4,4")
4871 (set_attr "predicable" "yes")
4872 (set_attr "type" "*,load,store1")
4873 (set_attr "pool_range" "*,4096,*")
4874 (set_attr "neg_pool_range" "*,4084,*")]
4877 ;;; ??? This should have alternatives for constants.
4878 (define_insn "*thumb_movsf_insn"
4879 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4880 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
4882 && ( register_operand (operands[0], SFmode)
4883 || register_operand (operands[1], SFmode))"
4892 [(set_attr "length" "2")
4893 (set_attr "type" "*,load,store1,load,store1,*,*")
4894 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
4897 (define_expand "movdf"
4898 [(set (match_operand:DF 0 "general_operand" "")
4899 (match_operand:DF 1 "general_operand" ""))]
4904 if (GET_CODE (operands[0]) == MEM)
4905 operands[1] = force_reg (DFmode, operands[1]);
4907 else /* TARGET_THUMB */
4909 if (!no_new_pseudos)
4911 if (GET_CODE (operands[0]) != REG)
4912 operands[1] = force_reg (DFmode, operands[1]);
4918 ;; Reloading a df mode value stored in integer regs to memory can require a
4920 (define_expand "reload_outdf"
4921 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
4922 (match_operand:DF 1 "s_register_operand" "r")
4923 (match_operand:SI 2 "s_register_operand" "=&r")]
4927 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
4930 operands[2] = XEXP (operands[0], 0);
4931 else if (code == POST_INC || code == PRE_DEC)
4933 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
4934 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
4935 emit_insn (gen_movdi (operands[0], operands[1]));
4938 else if (code == PRE_INC)
4940 rtx reg = XEXP (XEXP (operands[0], 0), 0);
4942 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
4945 else if (code == POST_DEC)
4946 operands[2] = XEXP (XEXP (operands[0], 0), 0);
4948 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
4949 XEXP (XEXP (operands[0], 0), 1)));
4951 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
4954 if (code == POST_DEC)
4955 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
4961 (define_insn "*movdf_hard_insn"
4962 [(set (match_operand:DF 0 "nonimmediate_operand"
4963 "=r,Q,r,m,r, f, f,f, m,!f,!r")
4964 (match_operand:DF 1 "general_operand"
4965 "Q, r,r,r,mF,fG,H,mF,f,r, f"))]
4967 && TARGET_HARD_FLOAT
4968 && (GET_CODE (operands[0]) != MEM
4969 || register_operand (operands[1], DFmode))"
4972 switch (which_alternative)
4975 case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
4976 case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
4977 case 2: case 3: case 4: return output_move_double (operands);
4978 case 5: return \"mvf%?d\\t%0, %1\";
4979 case 6: return \"mnf%?d\\t%0, #%N1\";
4980 case 7: return \"ldf%?d\\t%0, %1\";
4981 case 8: return \"stf%?d\\t%1, %0\";
4982 case 9: return output_mov_double_fpu_from_arm (operands);
4983 case 10: return output_mov_double_arm_from_fpu (operands);
4987 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
4988 (set_attr "predicable" "yes")
4990 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
4991 (set_attr "pool_range" "*,*,*,*,1020,*,*,1024,*,*,*")
4992 (set_attr "neg_pool_range" "*,*,*,*,1008,*,*,1008,*,*,*")]
4995 ;; Software floating point version. This is essentially the same as movdi.
4996 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
4999 (define_insn "*movdf_soft_insn"
5000 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5001 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5002 "TARGET_ARM && TARGET_SOFT_FLOAT
5005 "* return output_move_double (operands);"
5006 [(set_attr "length" "8,8,8")
5007 (set_attr "type" "*,load,store2")
5008 (set_attr "pool_range" "1020")
5009 (set_attr "neg_pool_range" "1008")]
5012 ;;; ??? This should have alternatives for constants.
5013 ;;; ??? This was originally identical to the movdi_insn pattern.
5014 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5015 ;;; thumb_reorg with a memory reference.
5016 (define_insn "*thumb_movdf_insn"
5017 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5018 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
5020 && ( register_operand (operands[0], DFmode)
5021 || register_operand (operands[1], DFmode))"
5023 switch (which_alternative)
5027 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5028 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5029 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5031 return \"ldmia\\t%1, {%0, %H0}\";
5033 return \"stmia\\t%0, {%1, %H1}\";
5035 return thumb_load_double_from_address (operands);
5037 operands[2] = gen_rtx (MEM, SImode,
5038 plus_constant (XEXP (operands[0], 0), 4));
5039 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5042 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5043 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5044 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5047 [(set_attr "length" "4,2,2,6,4,4")
5048 (set_attr "type" "*,load,store2,load,store2,*")
5049 (set_attr "pool_range" "*,*,*,1020,*,*")]
5053 ;; Saving and restoring the floating point registers in the prologue should
5054 ;; be done in XFmode, even though we don't support that for anything else
5055 ;; (Well, strictly it's 'internal representation', but that's effectively
5058 (define_insn "*movxf_hard_insn"
5059 [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
5060 (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
5061 "TARGET_ARM && TARGET_HARD_FLOAT && reload_completed"
5063 switch (which_alternative)
5066 case 0: return \"mvf%?e\\t%0, %1\";
5067 case 1: return \"mnf%?e\\t%0, #%N1\";
5068 case 2: return \"ldf%?e\\t%0, %1\";
5069 case 3: return \"stf%?e\\t%1, %0\";
5070 case 4: return output_mov_long_double_fpu_from_arm (operands);
5071 case 5: return output_mov_long_double_arm_from_fpu (operands);
5072 case 6: return output_mov_long_double_arm_from_arm (operands);
5075 [(set_attr "length" "4,4,4,4,8,8,12")
5076 (set_attr "predicable" "yes")
5077 (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
5078 (set_attr "pool_range" "*,*,1024,*,*,*,*")
5079 (set_attr "neg_pool_range" "*,*,1004,*,*,*,*")]
5083 ;; load- and store-multiple insns
5084 ;; The arm can load/store any set of registers, provided that they are in
5085 ;; ascending order; but that is beyond GCC so stick with what it knows.
5087 (define_expand "load_multiple"
5088 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5089 (match_operand:SI 1 "" ""))
5090 (use (match_operand:SI 2 "" ""))])]
5093 /* Support only fixed point registers. */
5094 if (GET_CODE (operands[2]) != CONST_INT
5095 || INTVAL (operands[2]) > 14
5096 || INTVAL (operands[2]) < 2
5097 || GET_CODE (operands[1]) != MEM
5098 || GET_CODE (operands[0]) != REG
5099 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5100 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5104 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5105 force_reg (SImode, XEXP (operands[1], 0)),
5106 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5107 MEM_IN_STRUCT_P(operands[1]),
5108 MEM_SCALAR_P (operands[1]));
5112 ;; Load multiple with write-back
5114 (define_insn "*ldmsi_postinc4"
5115 [(match_parallel 0 "load_multiple_operation"
5116 [(set (match_operand:SI 1 "s_register_operand" "=r")
5117 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5119 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5120 (mem:SI (match_dup 2)))
5121 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5122 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5123 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5124 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5125 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5126 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5127 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5128 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5129 [(set_attr "type" "load")
5130 (set_attr "predicable" "yes")]
5133 (define_insn "*ldmsi_postinc3"
5134 [(match_parallel 0 "load_multiple_operation"
5135 [(set (match_operand:SI 1 "s_register_operand" "=r")
5136 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5138 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5139 (mem:SI (match_dup 2)))
5140 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5141 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5142 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5143 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5144 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5145 "ldm%?ia\\t%1!, {%3, %4, %5}"
5146 [(set_attr "type" "load")
5147 (set_attr "predicable" "yes")]
5150 (define_insn "*ldmsi_postinc2"
5151 [(match_parallel 0 "load_multiple_operation"
5152 [(set (match_operand:SI 1 "s_register_operand" "=r")
5153 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5155 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5156 (mem:SI (match_dup 2)))
5157 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5158 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5159 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5160 "ldm%?ia\\t%1!, {%3, %4}"
5161 [(set_attr "type" "load")
5162 (set_attr "predicable" "yes")]
5165 ;; Ordinary load multiple
5167 (define_insn "*ldmsi4"
5168 [(match_parallel 0 "load_multiple_operation"
5169 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5170 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5171 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5172 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5173 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5174 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5175 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5176 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5177 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5178 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5179 [(set_attr "type" "load")
5180 (set_attr "predicable" "yes")]
5183 (define_insn "*ldmsi3"
5184 [(match_parallel 0 "load_multiple_operation"
5185 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5186 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5187 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5188 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5189 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5190 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5191 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5192 "ldm%?ia\\t%1, {%2, %3, %4}"
5193 [(set_attr "type" "load")
5194 (set_attr "predicable" "yes")]
5197 (define_insn "*ldmsi2"
5198 [(match_parallel 0 "load_multiple_operation"
5199 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5200 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5201 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5202 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5203 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5204 "ldm%?ia\\t%1, {%2, %3}"
5205 [(set_attr "type" "load")
5206 (set_attr "predicable" "yes")]
5209 (define_expand "store_multiple"
5210 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5211 (match_operand:SI 1 "" ""))
5212 (use (match_operand:SI 2 "" ""))])]
5215 /* Support only fixed point registers */
5216 if (GET_CODE (operands[2]) != CONST_INT
5217 || INTVAL (operands[2]) > 14
5218 || INTVAL (operands[2]) < 2
5219 || GET_CODE (operands[1]) != REG
5220 || GET_CODE (operands[0]) != MEM
5221 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5222 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5226 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5227 force_reg (SImode, XEXP (operands[0], 0)),
5228 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5229 MEM_IN_STRUCT_P(operands[0]),
5230 MEM_SCALAR_P (operands[0]));
5234 ;; Store multiple with write-back
5236 (define_insn "*stmsi_postinc4"
5237 [(match_parallel 0 "store_multiple_operation"
5238 [(set (match_operand:SI 1 "s_register_operand" "=r")
5239 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5241 (set (mem:SI (match_dup 2))
5242 (match_operand:SI 3 "arm_hard_register_operand" ""))
5243 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5244 (match_operand:SI 4 "arm_hard_register_operand" ""))
5245 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5246 (match_operand:SI 5 "arm_hard_register_operand" ""))
5247 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5248 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5249 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5250 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5251 [(set_attr "predicable" "yes")
5252 (set_attr "type" "store4")]
5255 (define_insn "*stmsi_postinc3"
5256 [(match_parallel 0 "store_multiple_operation"
5257 [(set (match_operand:SI 1 "s_register_operand" "=r")
5258 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5260 (set (mem:SI (match_dup 2))
5261 (match_operand:SI 3 "arm_hard_register_operand" ""))
5262 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5263 (match_operand:SI 4 "arm_hard_register_operand" ""))
5264 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5265 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5266 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5267 "stm%?ia\\t%1!, {%3, %4, %5}"
5268 [(set_attr "predicable" "yes")
5269 (set_attr "type" "store3")]
5272 (define_insn "*stmsi_postinc2"
5273 [(match_parallel 0 "store_multiple_operation"
5274 [(set (match_operand:SI 1 "s_register_operand" "=r")
5275 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5277 (set (mem:SI (match_dup 2))
5278 (match_operand:SI 3 "arm_hard_register_operand" ""))
5279 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5280 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5281 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5282 "stm%?ia\\t%1!, {%3, %4}"
5283 [(set_attr "predicable" "yes")
5284 (set_attr "type" "store2")]
5287 ;; Ordinary store multiple
5289 (define_insn "*stmsi4"
5290 [(match_parallel 0 "store_multiple_operation"
5291 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5292 (match_operand:SI 2 "arm_hard_register_operand" ""))
5293 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5294 (match_operand:SI 3 "arm_hard_register_operand" ""))
5295 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5296 (match_operand:SI 4 "arm_hard_register_operand" ""))
5297 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5298 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5299 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5300 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5301 [(set_attr "predicable" "yes")
5302 (set_attr "type" "store4")]
5305 (define_insn "*stmsi3"
5306 [(match_parallel 0 "store_multiple_operation"
5307 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5308 (match_operand:SI 2 "arm_hard_register_operand" ""))
5309 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5310 (match_operand:SI 3 "arm_hard_register_operand" ""))
5311 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5312 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5313 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5314 "stm%?ia\\t%1, {%2, %3, %4}"
5315 [(set_attr "predicable" "yes")
5316 (set_attr "type" "store3")]
5319 (define_insn "*stmsi2"
5320 [(match_parallel 0 "store_multiple_operation"
5321 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5322 (match_operand:SI 2 "arm_hard_register_operand" ""))
5323 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5324 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5325 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5326 "stm%?ia\\t%1, {%2, %3}"
5327 [(set_attr "predicable" "yes")
5328 (set_attr "type" "store2")]
5331 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5332 ;; We could let this apply for blocks of less than this, but it clobbers so
5333 ;; many registers that there is then probably a better way.
5335 (define_expand "movstrqi"
5336 [(match_operand:BLK 0 "general_operand" "")
5337 (match_operand:BLK 1 "general_operand" "")
5338 (match_operand:SI 2 "const_int_operand" "")
5339 (match_operand:SI 3 "const_int_operand" "")]
5344 if (arm_gen_movstrqi (operands))
5348 else /* TARGET_THUMB */
5350 if ( INTVAL (operands[3]) != 4
5351 || INTVAL (operands[2]) > 48)
5354 thumb_expand_movstrqi (operands);
5360 ;; Thumb block-move insns
5362 (define_insn "movmem12b"
5363 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5364 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5365 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5366 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5367 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5368 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5369 (set (match_operand:SI 0 "register_operand" "=l")
5370 (plus:SI (match_dup 2) (const_int 12)))
5371 (set (match_operand:SI 1 "register_operand" "=l")
5372 (plus:SI (match_dup 3) (const_int 12)))
5373 (clobber (match_scratch:SI 4 "=&l"))
5374 (clobber (match_scratch:SI 5 "=&l"))
5375 (clobber (match_scratch:SI 6 "=&l"))]
5377 "* return thumb_output_move_mem_multiple (3, operands);"
5378 [(set_attr "length" "4")
5379 ; This isn't entirely accurate... It loads as well, but in terms of
5380 ; scheduling the following insn it is better to consider it as a store
5381 (set_attr "type" "store3")]
5384 (define_insn "movmem8b"
5385 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5386 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5387 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5388 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5389 (set (match_operand:SI 0 "register_operand" "=l")
5390 (plus:SI (match_dup 2) (const_int 8)))
5391 (set (match_operand:SI 1 "register_operand" "=l")
5392 (plus:SI (match_dup 3) (const_int 8)))
5393 (clobber (match_scratch:SI 4 "=&l"))
5394 (clobber (match_scratch:SI 5 "=&l"))]
5396 "* return thumb_output_move_mem_multiple (2, operands);"
5397 [(set_attr "length" "4")
5398 ; This isn't entirely accurate... It loads as well, but in terms of
5399 ; scheduling the following insn it is better to consider it as a store
5400 (set_attr "type" "store2")]
5405 ;; Compare & branch insns
5406 ;; The range calcualations are based as follows:
5407 ;; For forward branches, the address calculation returns the address of
5408 ;; the next instruction. This is 2 beyond the branch instruction.
5409 ;; For backward branches, the address calculation returns the address of
5410 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5411 ;; instruction for the shortest sequence, and 4 before the branch instruction
5412 ;; if we have to jump around an unconditional branch.
5413 ;; To the basic branch range the PC offset must be added (this is +4).
5414 ;; So for forward branches we have
5415 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5416 ;; And for backward branches we have
5417 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5419 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5420 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5422 (define_insn "cbranchsi4"
5425 (match_operator 0 "arm_comparison_operator"
5426 [(match_operand:SI 1 "register_operand" "l,r")
5427 (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5428 (label_ref (match_operand 3 "" ""))
5432 output_asm_insn (\"cmp\\t%1, %2\", operands);
5433 switch (get_attr_length (insn))
5435 case 4: return \"b%d0\\t%l3\";
5436 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5437 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5440 [(set (attr "far_jump")
5442 (eq_attr "length" "8")
5443 (const_string "yes")
5444 (const_string "no")))
5445 (set (attr "length")
5447 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5448 (le (minus (match_dup 3) (pc)) (const_int 256)))
5451 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5452 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5457 (define_insn "*negated_cbranchsi4"
5460 (match_operator 0 "arm_comparison_operator"
5461 [(match_operand:SI 1 "register_operand" "l")
5462 (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5463 (label_ref (match_operand 3 "" ""))
5467 output_asm_insn (\"cmn\\t%1, %2\", operands);
5468 switch (get_attr_length (insn))
5470 case 4: return \"b%d0\\t%l3\";
5471 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5472 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5475 [(set (attr "far_jump")
5477 (eq_attr "length" "8")
5478 (const_string "yes")
5479 (const_string "no")))
5480 (set (attr "length")
5482 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5483 (le (minus (match_dup 3) (pc)) (const_int 256)))
5486 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5487 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5493 ;; Comparison and test insns
5495 (define_expand "cmpsi"
5496 [(match_operand:SI 0 "s_register_operand" "")
5497 (match_operand:SI 1 "arm_add_operand" "")]
5500 arm_compare_op0 = operands[0];
5501 arm_compare_op1 = operands[1];
5506 (define_expand "cmpsf"
5507 [(match_operand:SF 0 "s_register_operand" "")
5508 (match_operand:SF 1 "fpu_rhs_operand" "")]
5509 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5511 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
5512 operands[1] = force_reg (SFmode, operands[1]);
5514 arm_compare_op0 = operands[0];
5515 arm_compare_op1 = operands[1];
5520 (define_expand "cmpdf"
5521 [(match_operand:DF 0 "s_register_operand" "")
5522 (match_operand:DF 1 "fpu_rhs_operand" "")]
5523 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5525 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
5526 operands[1] = force_reg (DFmode, operands[1]);
5528 arm_compare_op0 = operands[0];
5529 arm_compare_op1 = operands[1];
5534 (define_insn "*arm_cmpsi_insn"
5535 [(set (reg:CC CC_REGNUM)
5536 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5537 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
5542 [(set_attr "conds" "set")]
5545 (define_insn "*cmpsi_shiftsi"
5546 [(set (reg:CC CC_REGNUM)
5547 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5548 (match_operator:SI 3 "shift_operator"
5549 [(match_operand:SI 1 "s_register_operand" "r")
5550 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
5553 [(set_attr "conds" "set")
5554 (set_attr "shift" "1")
5558 (define_insn "*cmpsi_shiftsi_swp"
5559 [(set (reg:CC_SWP CC_REGNUM)
5560 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5561 [(match_operand:SI 1 "s_register_operand" "r")
5562 (match_operand:SI 2 "reg_or_int_operand" "rM")])
5563 (match_operand:SI 0 "s_register_operand" "r")))]
5566 [(set_attr "conds" "set")
5567 (set_attr "shift" "1")
5571 (define_insn "*cmpsi_neg_shiftsi"
5572 [(set (reg:CC CC_REGNUM)
5573 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5574 (neg:SI (match_operator:SI 3 "shift_operator"
5575 [(match_operand:SI 1 "s_register_operand" "r")
5576 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5579 [(set_attr "conds" "set")
5580 (set_attr "shift" "1")
5584 (define_insn "*cmpsf_insn"
5585 [(set (reg:CCFP CC_REGNUM)
5586 (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
5587 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5588 "TARGET_ARM && TARGET_HARD_FLOAT"
5592 [(set_attr "conds" "set")
5593 (set_attr "type" "f_2_r")]
5596 (define_insn "*cmpdf_insn"
5597 [(set (reg:CCFP CC_REGNUM)
5598 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
5599 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5600 "TARGET_ARM && TARGET_HARD_FLOAT"
5604 [(set_attr "conds" "set")
5605 (set_attr "type" "f_2_r")]
5608 (define_insn "*cmpesfdf_df"
5609 [(set (reg:CCFP CC_REGNUM)
5610 (compare:CCFP (float_extend:DF
5611 (match_operand:SF 0 "s_register_operand" "f,f"))
5612 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5613 "TARGET_ARM && TARGET_HARD_FLOAT"
5617 [(set_attr "conds" "set")
5618 (set_attr "type" "f_2_r")]
5621 (define_insn "*cmpdf_esfdf"
5622 [(set (reg:CCFP CC_REGNUM)
5623 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5625 (match_operand:SF 1 "s_register_operand" "f"))))]
5626 "TARGET_ARM && TARGET_HARD_FLOAT"
5628 [(set_attr "conds" "set")
5629 (set_attr "type" "f_2_r")]
5632 ;; Cirrus SF compare instruction
5633 (define_insn "*cirrus_cmpsf"
5634 [(set (reg:CCFP CC_REGNUM)
5635 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
5636 (match_operand:SF 1 "cirrus_fp_register" "v")))]
5637 "TARGET_ARM && TARGET_CIRRUS"
5638 "cfcmps%?\\tr15, %V0, %V1"
5639 [(set_attr "type" "mav_farith")
5640 (set_attr "cirrus" "compare")]
5643 ;; Cirrus DF compare instruction
5644 (define_insn "*cirrus_cmpdf"
5645 [(set (reg:CCFP CC_REGNUM)
5646 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
5647 (match_operand:DF 1 "cirrus_fp_register" "v")))]
5648 "TARGET_ARM && TARGET_CIRRUS"
5649 "cfcmpd%?\\tr15, %V0, %V1"
5650 [(set_attr "type" "mav_farith")
5651 (set_attr "cirrus" "compare")]
5654 ;; Cirrus DI compare instruction
5655 (define_expand "cmpdi"
5656 [(match_operand:DI 0 "cirrus_fp_register" "")
5657 (match_operand:DI 1 "cirrus_fp_register" "")]
5658 "TARGET_ARM && TARGET_CIRRUS"
5660 arm_compare_op0 = operands[0];
5661 arm_compare_op1 = operands[1];
5665 (define_insn "*cirrus_cmpdi"
5666 [(set (reg:CC CC_REGNUM)
5667 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
5668 (match_operand:DI 1 "cirrus_fp_register" "v")))]
5669 "TARGET_ARM && TARGET_CIRRUS"
5670 "cfcmp64%?\\tr15, %V0, %V1"
5671 [(set_attr "type" "mav_farith")
5672 (set_attr "cirrus" "compare")]
5675 (define_insn "*cmpsf_trap"
5676 [(set (reg:CCFPE CC_REGNUM)
5677 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
5678 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5679 "TARGET_ARM && TARGET_HARD_FLOAT"
5683 [(set_attr "conds" "set")
5684 (set_attr "type" "f_2_r")]
5687 (define_insn "*cmpdf_trap"
5688 [(set (reg:CCFPE CC_REGNUM)
5689 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
5690 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5691 "TARGET_ARM && TARGET_HARD_FLOAT"
5695 [(set_attr "conds" "set")
5696 (set_attr "type" "f_2_r")]
5699 (define_insn "*cmp_esfdf_df_trap"
5700 [(set (reg:CCFPE CC_REGNUM)
5701 (compare:CCFPE (float_extend:DF
5702 (match_operand:SF 0 "s_register_operand" "f,f"))
5703 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5704 "TARGET_ARM && TARGET_HARD_FLOAT"
5708 [(set_attr "conds" "set")
5709 (set_attr "type" "f_2_r")]
5712 (define_insn "*cmp_df_esfdf_trap"
5713 [(set (reg:CCFPE CC_REGNUM)
5714 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
5716 (match_operand:SF 1 "s_register_operand" "f"))))]
5717 "TARGET_ARM && TARGET_HARD_FLOAT"
5719 [(set_attr "conds" "set")
5720 (set_attr "type" "f_2_r")]
5723 ; This insn allows redundant compares to be removed by cse, nothing should
5724 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5725 ; is deleted later on. The match_dup will match the mode here, so that
5726 ; mode changes of the condition codes aren't lost by this even though we don't
5727 ; specify what they are.
5729 (define_insn "*deleted_compare"
5730 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5732 "\\t%@ deleted compare"
5733 [(set_attr "conds" "set")
5734 (set_attr "length" "0")]
5738 ;; Conditional branch insns
5740 (define_expand "beq"
5742 (if_then_else (eq (match_dup 1) (const_int 0))
5743 (label_ref (match_operand 0 "" ""))
5746 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5749 (define_expand "bne"
5751 (if_then_else (ne (match_dup 1) (const_int 0))
5752 (label_ref (match_operand 0 "" ""))
5755 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5758 (define_expand "bgt"
5760 (if_then_else (gt (match_dup 1) (const_int 0))
5761 (label_ref (match_operand 0 "" ""))
5764 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5767 (define_expand "ble"
5769 (if_then_else (le (match_dup 1) (const_int 0))
5770 (label_ref (match_operand 0 "" ""))
5773 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5776 (define_expand "bge"
5778 (if_then_else (ge (match_dup 1) (const_int 0))
5779 (label_ref (match_operand 0 "" ""))
5782 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5785 (define_expand "blt"
5787 (if_then_else (lt (match_dup 1) (const_int 0))
5788 (label_ref (match_operand 0 "" ""))
5791 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5794 (define_expand "bgtu"
5796 (if_then_else (gtu (match_dup 1) (const_int 0))
5797 (label_ref (match_operand 0 "" ""))
5800 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5803 (define_expand "bleu"
5805 (if_then_else (leu (match_dup 1) (const_int 0))
5806 (label_ref (match_operand 0 "" ""))
5809 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5812 (define_expand "bgeu"
5814 (if_then_else (geu (match_dup 1) (const_int 0))
5815 (label_ref (match_operand 0 "" ""))
5818 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5821 (define_expand "bltu"
5823 (if_then_else (ltu (match_dup 1) (const_int 0))
5824 (label_ref (match_operand 0 "" ""))
5827 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5830 (define_expand "bunordered"
5832 (if_then_else (unordered (match_dup 1) (const_int 0))
5833 (label_ref (match_operand 0 "" ""))
5835 "TARGET_ARM && TARGET_HARD_FLOAT"
5836 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5840 (define_expand "bordered"
5842 (if_then_else (ordered (match_dup 1) (const_int 0))
5843 (label_ref (match_operand 0 "" ""))
5845 "TARGET_ARM && TARGET_HARD_FLOAT"
5846 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5850 (define_expand "bungt"
5852 (if_then_else (ungt (match_dup 1) (const_int 0))
5853 (label_ref (match_operand 0 "" ""))
5855 "TARGET_ARM && TARGET_HARD_FLOAT"
5856 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5859 (define_expand "bunlt"
5861 (if_then_else (unlt (match_dup 1) (const_int 0))
5862 (label_ref (match_operand 0 "" ""))
5864 "TARGET_ARM && TARGET_HARD_FLOAT"
5865 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5868 (define_expand "bunge"
5870 (if_then_else (unge (match_dup 1) (const_int 0))
5871 (label_ref (match_operand 0 "" ""))
5873 "TARGET_ARM && TARGET_HARD_FLOAT"
5874 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5877 (define_expand "bunle"
5879 (if_then_else (unle (match_dup 1) (const_int 0))
5880 (label_ref (match_operand 0 "" ""))
5882 "TARGET_ARM && TARGET_HARD_FLOAT"
5883 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5886 ;; The following two patterns need two branch instructions, since there is
5887 ;; no single instruction that will handle all cases.
5888 (define_expand "buneq"
5890 (if_then_else (uneq (match_dup 1) (const_int 0))
5891 (label_ref (match_operand 0 "" ""))
5893 "TARGET_ARM && TARGET_HARD_FLOAT"
5894 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
5897 (define_expand "bltgt"
5899 (if_then_else (ltgt (match_dup 1) (const_int 0))
5900 (label_ref (match_operand 0 "" ""))
5902 "TARGET_ARM && TARGET_HARD_FLOAT"
5903 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
5907 ;; Patterns to match conditional branch insns.
5910 ; Special pattern to match UNEQ.
5911 (define_insn "*arm_buneq"
5913 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5914 (label_ref (match_operand 0 "" ""))
5916 "TARGET_ARM && TARGET_HARD_FLOAT"
5918 if (arm_ccfsm_state != 0)
5921 return \"bvs\\t%l0\;beq\\t%l0\";
5923 [(set_attr "conds" "jump_clob")
5924 (set_attr "length" "8")]
5927 ; Special pattern to match LTGT.
5928 (define_insn "*arm_bltgt"
5930 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5931 (label_ref (match_operand 0 "" ""))
5933 "TARGET_ARM && TARGET_HARD_FLOAT"
5935 if (arm_ccfsm_state != 0)
5938 return \"bmi\\t%l0\;bgt\\t%l0\";
5940 [(set_attr "conds" "jump_clob")
5941 (set_attr "length" "8")]
5944 (define_insn "*arm_cond_branch"
5946 (if_then_else (match_operator 1 "arm_comparison_operator"
5947 [(match_operand 2 "cc_register" "") (const_int 0)])
5948 (label_ref (match_operand 0 "" ""))
5952 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5954 arm_ccfsm_state += 2;
5957 return \"b%d1\\t%l0\";
5959 [(set_attr "conds" "use")]
5962 ; Special pattern to match reversed UNEQ.
5963 (define_insn "*arm_buneq_reversed"
5965 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5967 (label_ref (match_operand 0 "" ""))))]
5968 "TARGET_ARM && TARGET_HARD_FLOAT"
5970 if (arm_ccfsm_state != 0)
5973 return \"bmi\\t%l0\;bgt\\t%l0\";
5975 [(set_attr "conds" "jump_clob")
5976 (set_attr "length" "8")]
5979 ; Special pattern to match reversed LTGT.
5980 (define_insn "*arm_bltgt_reversed"
5982 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5984 (label_ref (match_operand 0 "" ""))))]
5985 "TARGET_ARM && TARGET_HARD_FLOAT"
5987 if (arm_ccfsm_state != 0)
5990 return \"bvs\\t%l0\;beq\\t%l0\";
5992 [(set_attr "conds" "jump_clob")
5993 (set_attr "length" "8")]
5996 (define_insn "*arm_cond_branch_reversed"
5998 (if_then_else (match_operator 1 "arm_comparison_operator"
5999 [(match_operand 2 "cc_register" "") (const_int 0)])
6001 (label_ref (match_operand 0 "" ""))))]
6004 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6006 arm_ccfsm_state += 2;
6009 return \"b%D1\\t%l0\";
6011 [(set_attr "conds" "use")]
6018 (define_expand "seq"
6019 [(set (match_operand:SI 0 "s_register_operand" "=r")
6020 (eq:SI (match_dup 1) (const_int 0)))]
6022 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6025 (define_expand "sne"
6026 [(set (match_operand:SI 0 "s_register_operand" "=r")
6027 (ne:SI (match_dup 1) (const_int 0)))]
6029 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6032 (define_expand "sgt"
6033 [(set (match_operand:SI 0 "s_register_operand" "=r")
6034 (gt:SI (match_dup 1) (const_int 0)))]
6036 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6039 (define_expand "sle"
6040 [(set (match_operand:SI 0 "s_register_operand" "=r")
6041 (le:SI (match_dup 1) (const_int 0)))]
6043 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6046 (define_expand "sge"
6047 [(set (match_operand:SI 0 "s_register_operand" "=r")
6048 (ge:SI (match_dup 1) (const_int 0)))]
6050 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6053 (define_expand "slt"
6054 [(set (match_operand:SI 0 "s_register_operand" "=r")
6055 (lt:SI (match_dup 1) (const_int 0)))]
6057 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6060 (define_expand "sgtu"
6061 [(set (match_operand:SI 0 "s_register_operand" "=r")
6062 (gtu:SI (match_dup 1) (const_int 0)))]
6064 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6067 (define_expand "sleu"
6068 [(set (match_operand:SI 0 "s_register_operand" "=r")
6069 (leu:SI (match_dup 1) (const_int 0)))]
6071 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6074 (define_expand "sgeu"
6075 [(set (match_operand:SI 0 "s_register_operand" "=r")
6076 (geu:SI (match_dup 1) (const_int 0)))]
6078 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6081 (define_expand "sltu"
6082 [(set (match_operand:SI 0 "s_register_operand" "=r")
6083 (ltu:SI (match_dup 1) (const_int 0)))]
6085 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6088 (define_expand "sunordered"
6089 [(set (match_operand:SI 0 "s_register_operand" "=r")
6090 (unordered:SI (match_dup 1) (const_int 0)))]
6091 "TARGET_ARM && TARGET_HARD_FLOAT"
6092 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6096 (define_expand "sordered"
6097 [(set (match_operand:SI 0 "s_register_operand" "=r")
6098 (ordered:SI (match_dup 1) (const_int 0)))]
6099 "TARGET_ARM && TARGET_HARD_FLOAT"
6100 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6104 (define_expand "sungt"
6105 [(set (match_operand:SI 0 "s_register_operand" "=r")
6106 (ungt:SI (match_dup 1) (const_int 0)))]
6107 "TARGET_ARM && TARGET_HARD_FLOAT"
6108 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6112 (define_expand "sunge"
6113 [(set (match_operand:SI 0 "s_register_operand" "=r")
6114 (unge:SI (match_dup 1) (const_int 0)))]
6115 "TARGET_ARM && TARGET_HARD_FLOAT"
6116 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6120 (define_expand "sunlt"
6121 [(set (match_operand:SI 0 "s_register_operand" "=r")
6122 (unlt:SI (match_dup 1) (const_int 0)))]
6123 "TARGET_ARM && TARGET_HARD_FLOAT"
6124 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6128 (define_expand "sunle"
6129 [(set (match_operand:SI 0 "s_register_operand" "=r")
6130 (unle:SI (match_dup 1) (const_int 0)))]
6131 "TARGET_ARM && TARGET_HARD_FLOAT"
6132 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6136 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6137 ;;; simple ARM instructions.
6139 ; (define_expand "suneq"
6140 ; [(set (match_operand:SI 0 "s_register_operand" "=r")
6141 ; (uneq:SI (match_dup 1) (const_int 0)))]
6142 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6146 ; (define_expand "sltgt"
6147 ; [(set (match_operand:SI 0 "s_register_operand" "=r")
6148 ; (ltgt:SI (match_dup 1) (const_int 0)))]
6149 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6153 (define_insn "*mov_scc"
6154 [(set (match_operand:SI 0 "s_register_operand" "=r")
6155 (match_operator:SI 1 "arm_comparison_operator"
6156 [(match_operand 2 "cc_register" "") (const_int 0)]))]
6158 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6159 [(set_attr "conds" "use")
6160 (set_attr "length" "8")]
6163 (define_insn "*mov_negscc"
6164 [(set (match_operand:SI 0 "s_register_operand" "=r")
6165 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
6166 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6168 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6169 [(set_attr "conds" "use")
6170 (set_attr "length" "8")]
6173 (define_insn "*mov_notscc"
6174 [(set (match_operand:SI 0 "s_register_operand" "=r")
6175 (not:SI (match_operator:SI 1 "arm_comparison_operator"
6176 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6178 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6179 [(set_attr "conds" "use")
6180 (set_attr "length" "8")]
6184 ;; Conditional move insns
6186 (define_expand "movsicc"
6187 [(set (match_operand:SI 0 "s_register_operand" "")
6188 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6189 (match_operand:SI 2 "arm_not_operand" "")
6190 (match_operand:SI 3 "arm_not_operand" "")))]
6194 enum rtx_code code = GET_CODE (operands[1]);
6197 if (code == UNEQ || code == LTGT)
6200 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6201 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6205 (define_expand "movsfcc"
6206 [(set (match_operand:SF 0 "s_register_operand" "")
6207 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6208 (match_operand:SF 2 "s_register_operand" "")
6209 (match_operand:SF 3 "nonmemory_operand" "")))]
6213 enum rtx_code code = GET_CODE (operands[1]);
6216 if (code == UNEQ || code == LTGT)
6219 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
6220 Otherwise, ensure it is a valid FP add operand */
6221 if ((!TARGET_HARD_FLOAT)
6222 || (!fpu_add_operand (operands[3], SFmode)))
6223 operands[3] = force_reg (SFmode, operands[3]);
6225 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6226 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6230 (define_expand "movdfcc"
6231 [(set (match_operand:DF 0 "s_register_operand" "")
6232 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6233 (match_operand:DF 2 "s_register_operand" "")
6234 (match_operand:DF 3 "fpu_add_operand" "")))]
6235 "TARGET_ARM && TARGET_HARD_FLOAT"
6238 enum rtx_code code = GET_CODE (operands[1]);
6241 if (code == UNEQ || code == LTGT)
6244 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6245 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6249 (define_insn "*movsicc_insn"
6250 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6252 (match_operator 3 "arm_comparison_operator"
6253 [(match_operand 4 "cc_register" "") (const_int 0)])
6254 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6255 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6262 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6263 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6264 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6265 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6266 [(set_attr "length" "4,4,4,4,8,8,8,8")
6267 (set_attr "conds" "use")]
6270 (define_insn "*movsfcc_hard_insn"
6271 [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6273 (match_operator 3 "arm_comparison_operator"
6274 [(match_operand 4 "cc_register" "") (const_int 0)])
6275 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6276 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6277 "TARGET_ARM && TARGET_HARD_FLOAT"
6283 mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
6284 mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
6285 mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
6286 mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
6287 [(set_attr "length" "4,4,4,4,8,8,8,8")
6288 (set_attr "type" "ffarith")
6289 (set_attr "conds" "use")]
6292 (define_insn "*movsfcc_soft_insn"
6293 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6294 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
6295 [(match_operand 4 "cc_register" "") (const_int 0)])
6296 (match_operand:SF 1 "s_register_operand" "0,r")
6297 (match_operand:SF 2 "s_register_operand" "r,0")))]
6298 "TARGET_ARM && TARGET_SOFT_FLOAT"
6302 [(set_attr "conds" "use")]
6305 (define_insn "*movdfcc_insn"
6306 [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6308 (match_operator 3 "arm_comparison_operator"
6309 [(match_operand 4 "cc_register" "") (const_int 0)])
6310 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6311 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6312 "TARGET_ARM && TARGET_HARD_FLOAT"
6318 mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
6319 mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
6320 mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
6321 mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
6322 [(set_attr "length" "4,4,4,4,8,8,8,8")
6323 (set_attr "type" "ffarith")
6324 (set_attr "conds" "use")]
6328 ;; Jump and linkage insns
6330 (define_expand "jump"
6332 (label_ref (match_operand 0 "" "")))]
6337 (define_insn "*arm_jump"
6339 (label_ref (match_operand 0 "" "")))]
6343 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6345 arm_ccfsm_state += 2;
6348 return \"b%?\\t%l0\";
6351 [(set_attr "predicable" "yes")]
6354 (define_insn "*thumb_jump"
6356 (label_ref (match_operand 0 "" "")))]
6359 if (get_attr_length (insn) == 2)
6361 return \"bl\\t%l0\\t%@ far jump\";
6363 [(set (attr "far_jump")
6365 (eq_attr "length" "4")
6366 (const_string "yes")
6367 (const_string "no")))
6368 (set (attr "length")
6370 (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6371 (le (minus (match_dup 0) (pc)) (const_int 2044)))
6376 (define_expand "call"
6377 [(parallel [(call (match_operand 0 "memory_operand" "")
6378 (match_operand 1 "general_operand" ""))
6379 (use (match_operand 2 "" ""))
6380 (clobber (reg:SI LR_REGNUM))])]
6386 /* In an untyped call, we can get NULL for operand 2. */
6387 if (operands[2] == NULL_RTX)
6388 operands[2] = const0_rtx;
6390 /* This is to decide if we should generate indirect calls by loading the
6391 32 bit address of the callee into a register before performing the
6392 branch and link. operand[2] encodes the long_call/short_call
6393 attribute of the function being called. This attribute is set whenever
6394 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6395 is used, and the short_call attribute can also be set if function is
6396 declared as static or if it has already been defined in the current
6397 compilation unit. See arm.c and arm.h for info about this. The third
6398 parameter to arm_is_longcall_p is used to tell it which pattern
6400 callee = XEXP (operands[0], 0);
6402 if (GET_CODE (callee) != REG
6403 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6404 XEXP (operands[0], 0) = force_reg (Pmode, callee);
6408 (define_insn "*call_reg"
6409 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
6410 (match_operand 1 "" ""))
6411 (use (match_operand 2 "" ""))
6412 (clobber (reg:SI LR_REGNUM))]
6415 return output_call (operands);
6417 ;; length is worst case, normally it is only two
6418 [(set_attr "length" "12")
6419 (set_attr "type" "call")]
6422 (define_insn "*call_mem"
6423 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
6424 (match_operand 1 "" ""))
6425 (use (match_operand 2 "" ""))
6426 (clobber (reg:SI LR_REGNUM))]
6429 return output_call_mem (operands);
6431 [(set_attr "length" "12")
6432 (set_attr "type" "call")]
6435 (define_insn "*call_indirect"
6436 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6437 (match_operand 1 "" ""))
6438 (use (match_operand 2 "" ""))
6439 (clobber (reg:SI LR_REGNUM))]
6443 if (TARGET_CALLER_INTERWORKING)
6444 return \"bl\\t%__interwork_call_via_%0\";
6446 return \"bl\\t%__call_via_%0\";
6448 [(set_attr "type" "call")]
6451 (define_insn "*call_value_indirect"
6452 [(set (match_operand 0 "" "=l")
6453 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6454 (match_operand 2 "" "")))
6455 (use (match_operand 3 "" ""))
6456 (clobber (reg:SI LR_REGNUM))]
6460 if (TARGET_CALLER_INTERWORKING)
6461 return \"bl\\t%__interwork_call_via_%1\";
6463 return \"bl\\t%__call_via_%1\";
6465 [(set_attr "type" "call")]
6468 (define_expand "call_value"
6469 [(parallel [(set (match_operand 0 "" "")
6470 (call (match_operand 1 "memory_operand" "")
6471 (match_operand 2 "general_operand" "")))
6472 (use (match_operand 3 "" ""))
6473 (clobber (reg:SI LR_REGNUM))])]
6477 rtx callee = XEXP (operands[1], 0);
6479 /* In an untyped call, we can get NULL for operand 2. */
6480 if (operands[3] == 0)
6481 operands[3] = const0_rtx;
6483 /* See the comment in define_expand \"call\". */
6484 if (GET_CODE (callee) != REG
6485 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6486 XEXP (operands[1], 0) = force_reg (Pmode, callee);
6490 (define_insn "*call_value_reg"
6491 [(set (match_operand 0 "" "=r,f,v")
6492 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r,r"))
6493 (match_operand 2 "" "")))
6494 (use (match_operand 3 "" ""))
6495 (clobber (reg:SI LR_REGNUM))]
6498 return output_call (&operands[1]);
6500 [(set_attr "length" "12")
6501 (set_attr "type" "call")]
6504 (define_insn "*call_value_mem"
6505 [(set (match_operand 0 "" "=r,f,v")
6506 (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m,m"))
6507 (match_operand 2 "" "")))
6508 (use (match_operand 3 "" ""))
6509 (clobber (reg:SI LR_REGNUM))]
6510 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6512 return output_call_mem (&operands[1]);
6514 [(set_attr "length" "12")
6515 (set_attr "type" "call")]
6518 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6519 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6521 (define_insn "*call_symbol"
6522 [(call (mem:SI (match_operand:SI 0 "" "X"))
6523 (match_operand 1 "" ""))
6524 (use (match_operand 2 "" ""))
6525 (clobber (reg:SI LR_REGNUM))]
6527 && (GET_CODE (operands[0]) == SYMBOL_REF)
6528 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6531 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6533 [(set_attr "type" "call")]
6536 (define_insn "*call_value_symbol"
6537 [(set (match_operand 0 "s_register_operand" "=r,f,v")
6538 (call (mem:SI (match_operand:SI 1 "" "X,X,X"))
6539 (match_operand:SI 2 "" "")))
6540 (use (match_operand 3 "" ""))
6541 (clobber (reg:SI LR_REGNUM))]
6543 && (GET_CODE (operands[1]) == SYMBOL_REF)
6544 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6547 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6549 [(set_attr "type" "call")]
6552 (define_insn "*call_insn"
6553 [(call (mem:SI (match_operand:SI 0 "" "X"))
6554 (match_operand:SI 1 "" ""))
6555 (use (match_operand 2 "" ""))
6556 (clobber (reg:SI LR_REGNUM))]
6558 && GET_CODE (operands[0]) == SYMBOL_REF
6559 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6561 [(set_attr "length" "4")
6562 (set_attr "type" "call")]
6565 (define_insn "*call_value_insn"
6566 [(set (match_operand 0 "register_operand" "=l")
6567 (call (mem:SI (match_operand 1 "" "X"))
6568 (match_operand 2 "" "")))
6569 (use (match_operand 3 "" ""))
6570 (clobber (reg:SI LR_REGNUM))]
6572 && GET_CODE (operands[1]) == SYMBOL_REF
6573 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6575 [(set_attr "length" "4")
6576 (set_attr "type" "call")]
6579 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6580 (define_expand "sibcall"
6581 [(parallel [(call (match_operand 0 "memory_operand" "")
6582 (match_operand 1 "general_operand" ""))
6584 (use (match_operand 2 "" ""))])]
6588 if (operands[2] == NULL_RTX)
6589 operands[2] = const0_rtx;
6593 (define_expand "sibcall_value"
6594 [(parallel [(set (match_operand 0 "register_operand" "")
6595 (call (match_operand 1 "memory_operand" "")
6596 (match_operand 2 "general_operand" "")))
6598 (use (match_operand 3 "" ""))])]
6602 if (operands[3] == NULL_RTX)
6603 operands[3] = const0_rtx;
6607 (define_insn "*sibcall_insn"
6608 [(call (mem:SI (match_operand:SI 0 "" "X"))
6609 (match_operand 1 "" ""))
6611 (use (match_operand 2 "" ""))]
6612 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6614 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6616 [(set_attr "type" "call")]
6619 (define_insn "*sibcall_value_insn"
6620 [(set (match_operand 0 "s_register_operand" "=r,f,v")
6621 (call (mem:SI (match_operand:SI 1 "" "X,X,X"))
6622 (match_operand 2 "" "")))
6624 (use (match_operand 3 "" ""))]
6625 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6627 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6629 [(set_attr "type" "call")]
6632 ;; Often the return insn will be the same as loading from memory, so set attr
6633 (define_insn "return"
6635 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6638 if (arm_ccfsm_state == 2)
6640 arm_ccfsm_state += 2;
6643 return output_return_instruction (const_true_rtx, TRUE, FALSE);
6645 [(set_attr "type" "load")
6646 (set_attr "predicable" "yes")]
6649 (define_insn "*cond_return"
6651 (if_then_else (match_operator 0 "arm_comparison_operator"
6652 [(match_operand 1 "cc_register" "") (const_int 0)])
6655 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6658 if (arm_ccfsm_state == 2)
6660 arm_ccfsm_state += 2;
6663 return output_return_instruction (operands[0], TRUE, FALSE);
6665 [(set_attr "conds" "use")
6666 (set_attr "type" "load")]
6669 (define_insn "*cond_return_inverted"
6671 (if_then_else (match_operator 0 "arm_comparison_operator"
6672 [(match_operand 1 "cc_register" "") (const_int 0)])
6675 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6678 if (arm_ccfsm_state == 2)
6680 arm_ccfsm_state += 2;
6683 return output_return_instruction (operands[0], TRUE, TRUE);
6685 [(set_attr "conds" "use")
6686 (set_attr "type" "load")]
6689 ;; Generate a sequence of instructions to determine if the processor is
6690 ;; in 26-bit or 32-bit mode, and return the appropriate return address
6693 (define_expand "return_addr_mask"
6695 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6697 (set (match_operand:SI 0 "s_register_operand" "")
6698 (if_then_else:SI (eq (match_dup 1) (const_int 0))
6700 (const_int 67108860)))] ; 0x03fffffc
6703 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
6706 (define_insn "*check_arch2"
6707 [(set (match_operand:CC_NOOV 0 "cc_register" "")
6708 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6711 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
6712 [(set_attr "length" "8")
6713 (set_attr "conds" "set")]
6716 ;; Call subroutine returning any type.
6718 (define_expand "untyped_call"
6719 [(parallel [(call (match_operand 0 "" "")
6721 (match_operand 1 "" "")
6722 (match_operand 2 "" "")])]
6728 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6730 for (i = 0; i < XVECLEN (operands[2], 0); i++)
6732 rtx set = XVECEXP (operands[2], 0, i);
6734 emit_move_insn (SET_DEST (set), SET_SRC (set));
6737 /* The optimizer does not know that the call sets the function value
6738 registers we stored in the result block. We avoid problems by
6739 claiming that all hard registers are used and clobbered at this
6741 emit_insn (gen_blockage ());
6747 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6748 ;; all of memory. This blocks insns from being moved across this point.
6750 (define_insn "blockage"
6751 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6754 [(set_attr "length" "0")
6755 (set_attr "type" "block")]
6758 (define_expand "casesi"
6759 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6760 (match_operand:SI 1 "const_int_operand" "") ; lower bound
6761 (match_operand:SI 2 "const_int_operand" "") ; total range
6762 (match_operand:SI 3 "" "") ; table label
6763 (match_operand:SI 4 "" "")] ; Out of range label
6768 if (operands[1] != const0_rtx)
6770 reg = gen_reg_rtx (SImode);
6772 emit_insn (gen_addsi3 (reg, operands[0],
6773 GEN_INT (-INTVAL (operands[1]))));
6777 if (!const_ok_for_arm (INTVAL (operands[2])))
6778 operands[2] = force_reg (SImode, operands[2]);
6780 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6786 ;; The USE in this pattern is needed to tell flow analysis that this is
6787 ;; a CASESI insn. It has no other purpose.
6788 (define_insn "casesi_internal"
6789 [(parallel [(set (pc)
6791 (leu (match_operand:SI 0 "s_register_operand" "r")
6792 (match_operand:SI 1 "arm_rhs_operand" "rI"))
6793 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6794 (label_ref (match_operand 2 "" ""))))
6795 (label_ref (match_operand 3 "" ""))))
6796 (clobber (reg:CC CC_REGNUM))
6797 (use (label_ref (match_dup 2)))])]
6801 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6802 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6804 [(set_attr "conds" "clob")
6805 (set_attr "length" "12")]
6808 (define_expand "indirect_jump"
6810 (match_operand:SI 0 "s_register_operand" ""))]
6815 (define_insn "*arm_indirect_jump"
6817 (match_operand:SI 0 "s_register_operand" "r"))]
6819 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6820 [(set_attr "predicable" "yes")]
6823 ;; Although not supported by the define_expand above,
6824 ;; cse/combine may generate this form.
6825 (define_insn "*load_indirect_jump"
6827 (match_operand:SI 0 "memory_operand" "m"))]
6829 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6830 [(set_attr "type" "load")
6831 (set_attr "pool_range" "4096")
6832 (set_attr "neg_pool_range" "4084")
6833 (set_attr "predicable" "yes")]
6836 (define_insn "*thumb_indirect_jump"
6838 (match_operand:SI 0 "register_operand" "l*r"))]
6841 [(set_attr "conds" "clob")
6842 (set_attr "length" "2")]
6853 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6854 return \"mov\\tr8, r8\";
6856 [(set (attr "length")
6857 (if_then_else (eq_attr "is_thumb" "yes")
6863 ;; Patterns to allow combination of arithmetic, cond code and shifts
6865 (define_insn "*arith_shiftsi"
6866 [(set (match_operand:SI 0 "s_register_operand" "=r")
6867 (match_operator:SI 1 "shiftable_operator"
6868 [(match_operator:SI 3 "shift_operator"
6869 [(match_operand:SI 4 "s_register_operand" "r")
6870 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6871 (match_operand:SI 2 "s_register_operand" "r")]))]
6873 "%i1%?\\t%0, %2, %4%S3"
6874 [(set_attr "predicable" "yes")
6875 (set_attr "shift" "4")
6879 (define_insn "*arith_shiftsi_compare0"
6880 [(set (reg:CC_NOOV CC_REGNUM)
6881 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6882 [(match_operator:SI 3 "shift_operator"
6883 [(match_operand:SI 4 "s_register_operand" "r")
6884 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6885 (match_operand:SI 2 "s_register_operand" "r")])
6887 (set (match_operand:SI 0 "s_register_operand" "=r")
6888 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6891 "%i1%?s\\t%0, %2, %4%S3"
6892 [(set_attr "conds" "set")
6893 (set_attr "shift" "4")
6897 (define_insn "*arith_shiftsi_compare0_scratch"
6898 [(set (reg:CC_NOOV CC_REGNUM)
6899 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6900 [(match_operator:SI 3 "shift_operator"
6901 [(match_operand:SI 4 "s_register_operand" "r")
6902 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6903 (match_operand:SI 2 "s_register_operand" "r")])
6905 (clobber (match_scratch:SI 0 "=r"))]
6907 "%i1%?s\\t%0, %2, %4%S3"
6908 [(set_attr "conds" "set")
6909 (set_attr "shift" "4")
6913 (define_insn "*sub_shiftsi"
6914 [(set (match_operand:SI 0 "s_register_operand" "=r")
6915 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6916 (match_operator:SI 2 "shift_operator"
6917 [(match_operand:SI 3 "s_register_operand" "r")
6918 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
6920 "sub%?\\t%0, %1, %3%S2"
6921 [(set_attr "predicable" "yes")
6922 (set_attr "shift" "3")
6926 (define_insn "*sub_shiftsi_compare0"
6927 [(set (reg:CC_NOOV CC_REGNUM)
6929 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6930 (match_operator:SI 2 "shift_operator"
6931 [(match_operand:SI 3 "s_register_operand" "r")
6932 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6934 (set (match_operand:SI 0 "s_register_operand" "=r")
6935 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6938 "sub%?s\\t%0, %1, %3%S2"
6939 [(set_attr "conds" "set")
6940 (set_attr "shift" "3")
6944 (define_insn "*sub_shiftsi_compare0_scratch"
6945 [(set (reg:CC_NOOV CC_REGNUM)
6947 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6948 (match_operator:SI 2 "shift_operator"
6949 [(match_operand:SI 3 "s_register_operand" "r")
6950 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6952 (clobber (match_scratch:SI 0 "=r"))]
6954 "sub%?s\\t%0, %1, %3%S2"
6955 [(set_attr "conds" "set")
6956 (set_attr "shift" "3")
6962 (define_insn "*and_scc"
6963 [(set (match_operand:SI 0 "s_register_operand" "=r")
6964 (and:SI (match_operator:SI 1 "arm_comparison_operator"
6965 [(match_operand 3 "cc_register" "") (const_int 0)])
6966 (match_operand:SI 2 "s_register_operand" "r")))]
6968 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
6969 [(set_attr "conds" "use")
6970 (set_attr "length" "8")]
6973 (define_insn "*ior_scc"
6974 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6975 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
6976 [(match_operand 3 "cc_register" "") (const_int 0)])
6977 (match_operand:SI 1 "s_register_operand" "0,?r")))]
6981 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
6982 [(set_attr "conds" "use")
6983 (set_attr "length" "4,8")]
6986 (define_insn "*compare_scc"
6987 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6988 (match_operator:SI 1 "arm_comparison_operator"
6989 [(match_operand:SI 2 "s_register_operand" "r,r")
6990 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
6991 (clobber (reg:CC CC_REGNUM))]
6994 if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
6995 return \"mov\\t%0, %2, lsr #31\";
6997 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
6998 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7000 if (GET_CODE (operands[1]) == NE)
7002 if (which_alternative == 1)
7003 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7004 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7006 if (which_alternative == 1)
7007 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7009 output_asm_insn (\"cmp\\t%2, %3\", operands);
7010 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7012 [(set_attr "conds" "clob")
7013 (set_attr "length" "12")]
7016 (define_insn "*cond_move"
7017 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7018 (if_then_else:SI (match_operator 3 "equality_operator"
7019 [(match_operator 4 "arm_comparison_operator"
7020 [(match_operand 5 "cc_register" "") (const_int 0)])
7022 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7023 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7026 if (GET_CODE (operands[3]) == NE)
7028 if (which_alternative != 1)
7029 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7030 if (which_alternative != 0)
7031 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7034 if (which_alternative != 0)
7035 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7036 if (which_alternative != 1)
7037 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7040 [(set_attr "conds" "use")
7041 (set_attr "length" "4,4,8")]
7044 (define_insn "*cond_arith"
7045 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7046 (match_operator:SI 5 "shiftable_operator"
7047 [(match_operator:SI 4 "arm_comparison_operator"
7048 [(match_operand:SI 2 "s_register_operand" "r,r")
7049 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7050 (match_operand:SI 1 "s_register_operand" "0,?r")]))
7051 (clobber (reg:CC CC_REGNUM))]
7054 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7055 return \"%i5\\t%0, %1, %2, lsr #31\";
7057 output_asm_insn (\"cmp\\t%2, %3\", operands);
7058 if (GET_CODE (operands[5]) == AND)
7059 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7060 else if (GET_CODE (operands[5]) == MINUS)
7061 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7062 else if (which_alternative != 0)
7063 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7064 return \"%i5%d4\\t%0, %1, #1\";
7066 [(set_attr "conds" "clob")
7067 (set_attr "length" "12")]
7070 (define_insn "*cond_sub"
7071 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7072 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7073 (match_operator:SI 4 "arm_comparison_operator"
7074 [(match_operand:SI 2 "s_register_operand" "r,r")
7075 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7076 (clobber (reg:CC CC_REGNUM))]
7079 output_asm_insn (\"cmp\\t%2, %3\", operands);
7080 if (which_alternative != 0)
7081 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7082 return \"sub%d4\\t%0, %1, #1\";
7084 [(set_attr "conds" "clob")
7085 (set_attr "length" "8,12")]
7088 (define_insn "*cmp_ite0"
7089 [(set (match_operand 6 "dominant_cc_register" "")
7092 (match_operator 4 "arm_comparison_operator"
7093 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7094 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7095 (match_operator:SI 5 "arm_comparison_operator"
7096 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7097 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7103 static const char * const opcodes[4][2] =
7105 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7106 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7107 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7108 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7109 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7110 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7111 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7112 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7115 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7117 return opcodes[which_alternative][swap];
7119 [(set_attr "conds" "set")
7120 (set_attr "length" "8")]
7123 (define_insn "*cmp_ite1"
7124 [(set (match_operand 6 "dominant_cc_register" "")
7127 (match_operator 4 "arm_comparison_operator"
7128 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7129 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7130 (match_operator:SI 5 "arm_comparison_operator"
7131 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7132 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7138 static const char * const opcodes[4][2] =
7140 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7141 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7142 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7143 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7144 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7145 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7146 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7147 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7150 comparison_dominates_p (GET_CODE (operands[5]),
7151 reverse_condition (GET_CODE (operands[4])));
7153 return opcodes[which_alternative][swap];
7155 [(set_attr "conds" "set")
7156 (set_attr "length" "8")]
7159 (define_insn "*cmp_and"
7160 [(set (match_operand 6 "dominant_cc_register" "")
7163 (match_operator 4 "arm_comparison_operator"
7164 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7165 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7166 (match_operator:SI 5 "arm_comparison_operator"
7167 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7168 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7173 static const char *const opcodes[4][2] =
7175 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7176 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7177 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7178 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7179 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7180 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7181 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7182 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7185 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7187 return opcodes[which_alternative][swap];
7189 [(set_attr "conds" "set")
7190 (set_attr "predicable" "no")
7191 (set_attr "length" "8")]
7194 (define_insn "*cmp_ior"
7195 [(set (match_operand 6 "dominant_cc_register" "")
7198 (match_operator 4 "arm_comparison_operator"
7199 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7200 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7201 (match_operator:SI 5 "arm_comparison_operator"
7202 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7203 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7208 static const char *const opcodes[4][2] =
7210 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7211 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7212 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7213 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7214 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7215 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7216 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7217 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7220 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7222 return opcodes[which_alternative][swap];
7225 [(set_attr "conds" "set")
7226 (set_attr "length" "8")]
7229 (define_insn "*negscc"
7230 [(set (match_operand:SI 0 "s_register_operand" "=r")
7231 (neg:SI (match_operator 3 "arm_comparison_operator"
7232 [(match_operand:SI 1 "s_register_operand" "r")
7233 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7234 (clobber (reg:CC CC_REGNUM))]
7237 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7238 return \"mov\\t%0, %1, asr #31\";
7240 if (GET_CODE (operands[3]) == NE)
7241 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7243 if (GET_CODE (operands[3]) == GT)
7244 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7246 output_asm_insn (\"cmp\\t%1, %2\", operands);
7247 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7248 return \"mvn%d3\\t%0, #0\";
7250 [(set_attr "conds" "clob")
7251 (set_attr "length" "12")]
7254 (define_insn "movcond"
7255 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7257 (match_operator 5 "arm_comparison_operator"
7258 [(match_operand:SI 3 "s_register_operand" "r,r,r")
7259 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7260 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7261 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
7262 (clobber (reg:CC CC_REGNUM))]
7265 if (GET_CODE (operands[5]) == LT
7266 && (operands[4] == const0_rtx))
7268 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7270 if (operands[2] == const0_rtx)
7271 return \"and\\t%0, %1, %3, asr #31\";
7272 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
7274 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7276 if (operands[1] == const0_rtx)
7277 return \"bic\\t%0, %2, %3, asr #31\";
7278 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
7280 /* The only case that falls through to here is when both ops 1 & 2
7284 if (GET_CODE (operands[5]) == GE
7285 && (operands[4] == const0_rtx))
7287 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7289 if (operands[2] == const0_rtx)
7290 return \"bic\\t%0, %1, %3, asr #31\";
7291 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7293 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7295 if (operands[1] == const0_rtx)
7296 return \"and\\t%0, %2, %3, asr #31\";
7297 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7299 /* The only case that falls through to here is when both ops 1 & 2
7302 if (GET_CODE (operands[4]) == CONST_INT
7303 && !const_ok_for_arm (INTVAL (operands[4])))
7304 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7306 output_asm_insn (\"cmp\\t%3, %4\", operands);
7307 if (which_alternative != 0)
7308 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7309 if (which_alternative != 1)
7310 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7313 [(set_attr "conds" "clob")
7314 (set_attr "length" "8,8,12")]
7317 (define_insn "*ifcompare_plus_move"
7318 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7319 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7320 [(match_operand:SI 4 "s_register_operand" "r,r")
7321 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7323 (match_operand:SI 2 "s_register_operand" "r,r")
7324 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7325 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7326 (clobber (reg:CC CC_REGNUM))]
7329 [(set_attr "conds" "clob")
7330 (set_attr "length" "8,12")]
7333 (define_insn "*if_plus_move"
7334 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7336 (match_operator 4 "arm_comparison_operator"
7337 [(match_operand 5 "cc_register" "") (const_int 0)])
7339 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7340 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7341 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7345 sub%d4\\t%0, %2, #%n3
7346 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7347 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7348 [(set_attr "conds" "use")
7349 (set_attr "length" "4,4,8,8")
7350 (set_attr "type" "*,*,*,*")]
7353 (define_insn "*ifcompare_move_plus"
7354 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7355 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7356 [(match_operand:SI 4 "s_register_operand" "r,r")
7357 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7358 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7360 (match_operand:SI 2 "s_register_operand" "r,r")
7361 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7362 (clobber (reg:CC CC_REGNUM))]
7365 [(set_attr "conds" "clob")
7366 (set_attr "length" "8,12")]
7369 (define_insn "*if_move_plus"
7370 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7372 (match_operator 4 "arm_comparison_operator"
7373 [(match_operand 5 "cc_register" "") (const_int 0)])
7374 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7376 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7377 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7381 sub%D4\\t%0, %2, #%n3
7382 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7383 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7384 [(set_attr "conds" "use")
7385 (set_attr "length" "4,4,8,8")
7386 (set_attr "type" "*,*,*,*")]
7389 (define_insn "*ifcompare_arith_arith"
7390 [(set (match_operand:SI 0 "s_register_operand" "=r")
7391 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7392 [(match_operand:SI 5 "s_register_operand" "r")
7393 (match_operand:SI 6 "arm_add_operand" "rIL")])
7394 (match_operator:SI 8 "shiftable_operator"
7395 [(match_operand:SI 1 "s_register_operand" "r")
7396 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7397 (match_operator:SI 7 "shiftable_operator"
7398 [(match_operand:SI 3 "s_register_operand" "r")
7399 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7400 (clobber (reg:CC CC_REGNUM))]
7403 [(set_attr "conds" "clob")
7404 (set_attr "length" "12")]
7407 (define_insn "*if_arith_arith"
7408 [(set (match_operand:SI 0 "s_register_operand" "=r")
7409 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7410 [(match_operand 8 "cc_register" "") (const_int 0)])
7411 (match_operator:SI 6 "shiftable_operator"
7412 [(match_operand:SI 1 "s_register_operand" "r")
7413 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7414 (match_operator:SI 7 "shiftable_operator"
7415 [(match_operand:SI 3 "s_register_operand" "r")
7416 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7418 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7419 [(set_attr "conds" "use")
7420 (set_attr "length" "8")]
7423 (define_insn "*ifcompare_arith_move"
7424 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7425 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7426 [(match_operand:SI 2 "s_register_operand" "r,r")
7427 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7428 (match_operator:SI 7 "shiftable_operator"
7429 [(match_operand:SI 4 "s_register_operand" "r,r")
7430 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7431 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7432 (clobber (reg:CC CC_REGNUM))]
7435 /* If we have an operation where (op x 0) is the identity operation and
7436 the conditional operator is LT or GE and we are comparing against zero and
7437 everything is in registers then we can do this in two instructions */
7438 if (operands[3] == const0_rtx
7439 && GET_CODE (operands[7]) != AND
7440 && GET_CODE (operands[5]) == REG
7441 && GET_CODE (operands[1]) == REG
7442 && REGNO (operands[1]) == REGNO (operands[4])
7443 && REGNO (operands[4]) != REGNO (operands[0]))
7445 if (GET_CODE (operands[6]) == LT)
7446 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7447 else if (GET_CODE (operands[6]) == GE)
7448 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7450 if (GET_CODE (operands[3]) == CONST_INT
7451 && !const_ok_for_arm (INTVAL (operands[3])))
7452 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7454 output_asm_insn (\"cmp\\t%2, %3\", operands);
7455 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7456 if (which_alternative != 0)
7457 return \"mov%D6\\t%0, %1\";
7460 [(set_attr "conds" "clob")
7461 (set_attr "length" "8,12")]
7464 (define_insn "*if_arith_move"
7465 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7466 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7467 [(match_operand 6 "cc_register" "") (const_int 0)])
7468 (match_operator:SI 5 "shiftable_operator"
7469 [(match_operand:SI 2 "s_register_operand" "r,r")
7470 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7471 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7475 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7476 [(set_attr "conds" "use")
7477 (set_attr "length" "4,8")
7478 (set_attr "type" "*,*")]
7481 (define_insn "*ifcompare_move_arith"
7482 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7483 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7484 [(match_operand:SI 4 "s_register_operand" "r,r")
7485 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7486 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7487 (match_operator:SI 7 "shiftable_operator"
7488 [(match_operand:SI 2 "s_register_operand" "r,r")
7489 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7490 (clobber (reg:CC CC_REGNUM))]
7493 /* If we have an operation where (op x 0) is the identity operation and
7494 the conditional operator is LT or GE and we are comparing against zero and
7495 everything is in registers then we can do this in two instructions */
7496 if (operands[5] == const0_rtx
7497 && GET_CODE (operands[7]) != AND
7498 && GET_CODE (operands[3]) == REG
7499 && GET_CODE (operands[1]) == REG
7500 && REGNO (operands[1]) == REGNO (operands[2])
7501 && REGNO (operands[2]) != REGNO (operands[0]))
7503 if (GET_CODE (operands[6]) == GE)
7504 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7505 else if (GET_CODE (operands[6]) == LT)
7506 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7509 if (GET_CODE (operands[5]) == CONST_INT
7510 && !const_ok_for_arm (INTVAL (operands[5])))
7511 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7513 output_asm_insn (\"cmp\\t%4, %5\", operands);
7515 if (which_alternative != 0)
7516 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7517 return \"%I7%D6\\t%0, %2, %3\";
7519 [(set_attr "conds" "clob")
7520 (set_attr "length" "8,12")]
7523 (define_insn "*if_move_arith"
7524 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7526 (match_operator 4 "arm_comparison_operator"
7527 [(match_operand 6 "cc_register" "") (const_int 0)])
7528 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7529 (match_operator:SI 5 "shiftable_operator"
7530 [(match_operand:SI 2 "s_register_operand" "r,r")
7531 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7535 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7536 [(set_attr "conds" "use")
7537 (set_attr "length" "4,8")
7538 (set_attr "type" "*,*")]
7541 (define_insn "*ifcompare_move_not"
7542 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7544 (match_operator 5 "arm_comparison_operator"
7545 [(match_operand:SI 3 "s_register_operand" "r,r")
7546 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7547 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7549 (match_operand:SI 2 "s_register_operand" "r,r"))))
7550 (clobber (reg:CC CC_REGNUM))]
7553 [(set_attr "conds" "clob")
7554 (set_attr "length" "8,12")]
7557 (define_insn "*if_move_not"
7558 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7560 (match_operator 4 "arm_comparison_operator"
7561 [(match_operand 3 "cc_register" "") (const_int 0)])
7562 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7563 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7567 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7568 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7569 [(set_attr "conds" "use")
7570 (set_attr "length" "4,8,8")]
7573 (define_insn "*ifcompare_not_move"
7574 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7576 (match_operator 5 "arm_comparison_operator"
7577 [(match_operand:SI 3 "s_register_operand" "r,r")
7578 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7580 (match_operand:SI 2 "s_register_operand" "r,r"))
7581 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7582 (clobber (reg:CC CC_REGNUM))]
7585 [(set_attr "conds" "clob")
7586 (set_attr "length" "8,12")]
7589 (define_insn "*if_not_move"
7590 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7592 (match_operator 4 "arm_comparison_operator"
7593 [(match_operand 3 "cc_register" "") (const_int 0)])
7594 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7595 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7599 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7600 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7601 [(set_attr "conds" "use")
7602 (set_attr "length" "4,8,8")]
7605 (define_insn "*ifcompare_shift_move"
7606 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7608 (match_operator 6 "arm_comparison_operator"
7609 [(match_operand:SI 4 "s_register_operand" "r,r")
7610 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7611 (match_operator:SI 7 "shift_operator"
7612 [(match_operand:SI 2 "s_register_operand" "r,r")
7613 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7614 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7615 (clobber (reg:CC CC_REGNUM))]
7618 [(set_attr "conds" "clob")
7619 (set_attr "length" "8,12")]
7622 (define_insn "*if_shift_move"
7623 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7625 (match_operator 5 "arm_comparison_operator"
7626 [(match_operand 6 "cc_register" "") (const_int 0)])
7627 (match_operator:SI 4 "shift_operator"
7628 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7629 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7630 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7634 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7635 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7636 [(set_attr "conds" "use")
7637 (set_attr "shift" "2")
7638 (set_attr "length" "4,8,8")]
7641 (define_insn "*ifcompare_move_shift"
7642 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7644 (match_operator 6 "arm_comparison_operator"
7645 [(match_operand:SI 4 "s_register_operand" "r,r")
7646 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7647 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7648 (match_operator:SI 7 "shift_operator"
7649 [(match_operand:SI 2 "s_register_operand" "r,r")
7650 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7651 (clobber (reg:CC CC_REGNUM))]
7654 [(set_attr "conds" "clob")
7655 (set_attr "length" "8,12")]
7658 (define_insn "*if_move_shift"
7659 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7661 (match_operator 5 "arm_comparison_operator"
7662 [(match_operand 6 "cc_register" "") (const_int 0)])
7663 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7664 (match_operator:SI 4 "shift_operator"
7665 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7666 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7670 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7671 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7672 [(set_attr "conds" "use")
7673 (set_attr "shift" "2")
7674 (set_attr "length" "4,8,8")]
7677 (define_insn "*ifcompare_shift_shift"
7678 [(set (match_operand:SI 0 "s_register_operand" "=r")
7680 (match_operator 7 "arm_comparison_operator"
7681 [(match_operand:SI 5 "s_register_operand" "r")
7682 (match_operand:SI 6 "arm_add_operand" "rIL")])
7683 (match_operator:SI 8 "shift_operator"
7684 [(match_operand:SI 1 "s_register_operand" "r")
7685 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7686 (match_operator:SI 9 "shift_operator"
7687 [(match_operand:SI 3 "s_register_operand" "r")
7688 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7689 (clobber (reg:CC CC_REGNUM))]
7692 [(set_attr "conds" "clob")
7693 (set_attr "length" "12")]
7696 (define_insn "*if_shift_shift"
7697 [(set (match_operand:SI 0 "s_register_operand" "=r")
7699 (match_operator 5 "arm_comparison_operator"
7700 [(match_operand 8 "cc_register" "") (const_int 0)])
7701 (match_operator:SI 6 "shift_operator"
7702 [(match_operand:SI 1 "s_register_operand" "r")
7703 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7704 (match_operator:SI 7 "shift_operator"
7705 [(match_operand:SI 3 "s_register_operand" "r")
7706 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7708 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7709 [(set_attr "conds" "use")
7710 (set_attr "shift" "1")
7711 (set_attr "length" "8")]
7714 (define_insn "*ifcompare_not_arith"
7715 [(set (match_operand:SI 0 "s_register_operand" "=r")
7717 (match_operator 6 "arm_comparison_operator"
7718 [(match_operand:SI 4 "s_register_operand" "r")
7719 (match_operand:SI 5 "arm_add_operand" "rIL")])
7720 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7721 (match_operator:SI 7 "shiftable_operator"
7722 [(match_operand:SI 2 "s_register_operand" "r")
7723 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7724 (clobber (reg:CC CC_REGNUM))]
7727 [(set_attr "conds" "clob")
7728 (set_attr "length" "12")]
7731 (define_insn "*if_not_arith"
7732 [(set (match_operand:SI 0 "s_register_operand" "=r")
7734 (match_operator 5 "arm_comparison_operator"
7735 [(match_operand 4 "cc_register" "") (const_int 0)])
7736 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7737 (match_operator:SI 6 "shiftable_operator"
7738 [(match_operand:SI 2 "s_register_operand" "r")
7739 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7741 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7742 [(set_attr "conds" "use")
7743 (set_attr "length" "8")]
7746 (define_insn "*ifcompare_arith_not"
7747 [(set (match_operand:SI 0 "s_register_operand" "=r")
7749 (match_operator 6 "arm_comparison_operator"
7750 [(match_operand:SI 4 "s_register_operand" "r")
7751 (match_operand:SI 5 "arm_add_operand" "rIL")])
7752 (match_operator:SI 7 "shiftable_operator"
7753 [(match_operand:SI 2 "s_register_operand" "r")
7754 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7755 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7756 (clobber (reg:CC CC_REGNUM))]
7759 [(set_attr "conds" "clob")
7760 (set_attr "length" "12")]
7763 (define_insn "*if_arith_not"
7764 [(set (match_operand:SI 0 "s_register_operand" "=r")
7766 (match_operator 5 "arm_comparison_operator"
7767 [(match_operand 4 "cc_register" "") (const_int 0)])
7768 (match_operator:SI 6 "shiftable_operator"
7769 [(match_operand:SI 2 "s_register_operand" "r")
7770 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7771 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7773 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7774 [(set_attr "conds" "use")
7775 (set_attr "length" "8")]
7778 (define_insn "*ifcompare_neg_move"
7779 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7781 (match_operator 5 "arm_comparison_operator"
7782 [(match_operand:SI 3 "s_register_operand" "r,r")
7783 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7784 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7785 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7786 (clobber (reg:CC CC_REGNUM))]
7789 [(set_attr "conds" "clob")
7790 (set_attr "length" "8,12")]
7793 (define_insn "*if_neg_move"
7794 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7796 (match_operator 4 "arm_comparison_operator"
7797 [(match_operand 3 "cc_register" "") (const_int 0)])
7798 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7799 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7803 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7804 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
7805 [(set_attr "conds" "use")
7806 (set_attr "length" "4,8,8")]
7809 (define_insn "*ifcompare_move_neg"
7810 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7812 (match_operator 5 "arm_comparison_operator"
7813 [(match_operand:SI 3 "s_register_operand" "r,r")
7814 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7815 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7816 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
7817 (clobber (reg:CC CC_REGNUM))]
7820 [(set_attr "conds" "clob")
7821 (set_attr "length" "8,12")]
7824 (define_insn "*if_move_neg"
7825 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7827 (match_operator 4 "arm_comparison_operator"
7828 [(match_operand 3 "cc_register" "") (const_int 0)])
7829 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7830 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7834 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
7835 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
7836 [(set_attr "conds" "use")
7837 (set_attr "length" "4,8,8")]
7840 (define_insn "*arith_adjacentmem"
7841 [(set (match_operand:SI 0 "s_register_operand" "=r")
7842 (match_operator:SI 1 "shiftable_operator"
7843 [(match_operand:SI 2 "memory_operand" "m")
7844 (match_operand:SI 3 "memory_operand" "m")]))
7845 (clobber (match_scratch:SI 4 "=r"))]
7846 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
7851 int val1 = 0, val2 = 0;
7853 if (REGNO (operands[0]) > REGNO (operands[4]))
7855 ldm[1] = operands[4];
7856 ldm[2] = operands[0];
7860 ldm[1] = operands[0];
7861 ldm[2] = operands[4];
7863 if (GET_CODE (XEXP (operands[2], 0)) != REG)
7864 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
7865 if (GET_CODE (XEXP (operands[3], 0)) != REG)
7866 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
7867 arith[0] = operands[0];
7868 arith[3] = operands[1];
7882 ldm[0] = ops[0] = operands[4];
7883 ops[1] = XEXP (XEXP (operands[2], 0), 0);
7884 ops[2] = XEXP (XEXP (operands[2], 0), 1);
7885 output_add_immediate (ops);
7887 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7889 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7893 ldm[0] = XEXP (operands[3], 0);
7895 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7897 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7901 ldm[0] = XEXP (operands[2], 0);
7903 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7905 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7907 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
7910 [(set_attr "length" "12")
7911 (set_attr "predicable" "yes")
7912 (set_attr "type" "load")]
7915 ;; the arm can support extended pre-inc instructions
7917 ;; In all these cases, we use operands 0 and 1 for the register being
7918 ;; incremented because those are the operands that local-alloc will
7919 ;; tie and these are the pair most likely to be tieable (and the ones
7920 ;; that will benefit the most).
7922 ;; We reject the frame pointer if it occurs anywhere in these patterns since
7923 ;; elimination will cause too many headaches.
7925 (define_insn "*strqi_preinc"
7926 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7927 (match_operand:SI 2 "index_operand" "rJ")))
7928 (match_operand:QI 3 "s_register_operand" "r"))
7929 (set (match_operand:SI 0 "s_register_operand" "=r")
7930 (plus:SI (match_dup 1) (match_dup 2)))]
7932 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7933 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7934 && (GET_CODE (operands[2]) != REG
7935 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7936 "str%?b\\t%3, [%0, %2]!"
7937 [(set_attr "type" "store1")
7938 (set_attr "predicable" "yes")]
7941 (define_insn "*strqi_predec"
7942 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7943 (match_operand:SI 2 "s_register_operand" "r")))
7944 (match_operand:QI 3 "s_register_operand" "r"))
7945 (set (match_operand:SI 0 "s_register_operand" "=r")
7946 (minus:SI (match_dup 1) (match_dup 2)))]
7948 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7949 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7950 && (GET_CODE (operands[2]) != REG
7951 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7952 "str%?b\\t%3, [%0, -%2]!"
7953 [(set_attr "type" "store1")
7954 (set_attr "predicable" "yes")]
7957 (define_insn "*loadqi_preinc"
7958 [(set (match_operand:QI 3 "s_register_operand" "=r")
7959 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7960 (match_operand:SI 2 "index_operand" "rJ"))))
7961 (set (match_operand:SI 0 "s_register_operand" "=r")
7962 (plus:SI (match_dup 1) (match_dup 2)))]
7964 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7965 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7966 && (GET_CODE (operands[2]) != REG
7967 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7968 "ldr%?b\\t%3, [%0, %2]!"
7969 [(set_attr "type" "load")
7970 (set_attr "predicable" "yes")]
7973 (define_insn "*loadqi_predec"
7974 [(set (match_operand:QI 3 "s_register_operand" "=r")
7975 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7976 (match_operand:SI 2 "s_register_operand" "r"))))
7977 (set (match_operand:SI 0 "s_register_operand" "=r")
7978 (minus:SI (match_dup 1) (match_dup 2)))]
7980 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7981 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7982 && (GET_CODE (operands[2]) != REG
7983 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7984 "ldr%?b\\t%3, [%0, -%2]!"
7985 [(set_attr "type" "load")
7986 (set_attr "predicable" "yes")]
7989 (define_insn "*loadqisi_preinc"
7990 [(set (match_operand:SI 3 "s_register_operand" "=r")
7992 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7993 (match_operand:SI 2 "index_operand" "rJ")))))
7994 (set (match_operand:SI 0 "s_register_operand" "=r")
7995 (plus:SI (match_dup 1) (match_dup 2)))]
7997 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7998 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7999 && (GET_CODE (operands[2]) != REG
8000 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8001 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8002 [(set_attr "type" "load")
8003 (set_attr "predicable" "yes")]
8006 (define_insn "*loadqisi_predec"
8007 [(set (match_operand:SI 3 "s_register_operand" "=r")
8009 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8010 (match_operand:SI 2 "s_register_operand" "r")))))
8011 (set (match_operand:SI 0 "s_register_operand" "=r")
8012 (minus:SI (match_dup 1) (match_dup 2)))]
8014 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8015 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8016 && (GET_CODE (operands[2]) != REG
8017 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8018 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8019 [(set_attr "type" "load")
8020 (set_attr "predicable" "yes")]
8023 (define_insn "*strsi_preinc"
8024 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8025 (match_operand:SI 2 "index_operand" "rJ")))
8026 (match_operand:SI 3 "s_register_operand" "r"))
8027 (set (match_operand:SI 0 "s_register_operand" "=r")
8028 (plus:SI (match_dup 1) (match_dup 2)))]
8030 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8031 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8032 && (GET_CODE (operands[2]) != REG
8033 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8034 "str%?\\t%3, [%0, %2]!"
8035 [(set_attr "type" "store1")
8036 (set_attr "predicable" "yes")]
8039 (define_insn "*strsi_predec"
8040 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8041 (match_operand:SI 2 "s_register_operand" "r")))
8042 (match_operand:SI 3 "s_register_operand" "r"))
8043 (set (match_operand:SI 0 "s_register_operand" "=r")
8044 (minus:SI (match_dup 1) (match_dup 2)))]
8046 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8047 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8048 && (GET_CODE (operands[2]) != REG
8049 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8050 "str%?\\t%3, [%0, -%2]!"
8051 [(set_attr "type" "store1")
8052 (set_attr "predicable" "yes")]
8055 (define_insn "*loadsi_preinc"
8056 [(set (match_operand:SI 3 "s_register_operand" "=r")
8057 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8058 (match_operand:SI 2 "index_operand" "rJ"))))
8059 (set (match_operand:SI 0 "s_register_operand" "=r")
8060 (plus:SI (match_dup 1) (match_dup 2)))]
8062 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8063 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8064 && (GET_CODE (operands[2]) != REG
8065 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8066 "ldr%?\\t%3, [%0, %2]!"
8067 [(set_attr "type" "load")
8068 (set_attr "predicable" "yes")]
8071 (define_insn "*loadsi_predec"
8072 [(set (match_operand:SI 3 "s_register_operand" "=r")
8073 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8074 (match_operand:SI 2 "s_register_operand" "r"))))
8075 (set (match_operand:SI 0 "s_register_operand" "=r")
8076 (minus:SI (match_dup 1) (match_dup 2)))]
8078 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8079 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8080 && (GET_CODE (operands[2]) != REG
8081 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8082 "ldr%?\\t%3, [%0, -%2]!"
8083 [(set_attr "type" "load")
8084 (set_attr "predicable" "yes")]
8087 (define_insn "*loadhi_preinc"
8088 [(set (match_operand:HI 3 "s_register_operand" "=r")
8089 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8090 (match_operand:SI 2 "index_operand" "rJ"))))
8091 (set (match_operand:SI 0 "s_register_operand" "=r")
8092 (plus:SI (match_dup 1) (match_dup 2)))]
8094 && !BYTES_BIG_ENDIAN
8095 && !TARGET_MMU_TRAPS
8097 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8098 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8099 && (GET_CODE (operands[2]) != REG
8100 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8101 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8102 [(set_attr "type" "load")
8103 (set_attr "predicable" "yes")]
8106 (define_insn "*loadhi_predec"
8107 [(set (match_operand:HI 3 "s_register_operand" "=r")
8108 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8109 (match_operand:SI 2 "s_register_operand" "r"))))
8110 (set (match_operand:SI 0 "s_register_operand" "=r")
8111 (minus:SI (match_dup 1) (match_dup 2)))]
8113 && !BYTES_BIG_ENDIAN
8114 && !TARGET_MMU_TRAPS
8116 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8117 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8118 && (GET_CODE (operands[2]) != REG
8119 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8120 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8121 [(set_attr "type" "load")
8122 (set_attr "predicable" "yes")]
8125 (define_insn "*strqi_shiftpreinc"
8126 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8127 [(match_operand:SI 3 "s_register_operand" "r")
8128 (match_operand:SI 4 "const_shift_operand" "n")])
8129 (match_operand:SI 1 "s_register_operand" "0")))
8130 (match_operand:QI 5 "s_register_operand" "r"))
8131 (set (match_operand:SI 0 "s_register_operand" "=r")
8132 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8135 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8136 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8137 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8138 "str%?b\\t%5, [%0, %3%S2]!"
8139 [(set_attr "type" "store1")
8140 (set_attr "predicable" "yes")]
8143 (define_insn "*strqi_shiftpredec"
8144 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8145 (match_operator:SI 2 "shift_operator"
8146 [(match_operand:SI 3 "s_register_operand" "r")
8147 (match_operand:SI 4 "const_shift_operand" "n")])))
8148 (match_operand:QI 5 "s_register_operand" "r"))
8149 (set (match_operand:SI 0 "s_register_operand" "=r")
8150 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8153 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8154 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8155 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8156 "str%?b\\t%5, [%0, -%3%S2]!"
8157 [(set_attr "type" "store1")
8158 (set_attr "predicable" "yes")]
8161 (define_insn "*loadqi_shiftpreinc"
8162 [(set (match_operand:QI 5 "s_register_operand" "=r")
8163 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8164 [(match_operand:SI 3 "s_register_operand" "r")
8165 (match_operand:SI 4 "const_shift_operand" "n")])
8166 (match_operand:SI 1 "s_register_operand" "0"))))
8167 (set (match_operand:SI 0 "s_register_operand" "=r")
8168 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8171 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8172 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8173 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8174 "ldr%?b\\t%5, [%0, %3%S2]!"
8175 [(set_attr "type" "load")
8176 (set_attr "predicable" "yes")]
8179 (define_insn "*loadqi_shiftpredec"
8180 [(set (match_operand:QI 5 "s_register_operand" "=r")
8181 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8182 (match_operator:SI 2 "shift_operator"
8183 [(match_operand:SI 3 "s_register_operand" "r")
8184 (match_operand:SI 4 "const_shift_operand" "n")]))))
8185 (set (match_operand:SI 0 "s_register_operand" "=r")
8186 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8189 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8190 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8191 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8192 "ldr%?b\\t%5, [%0, -%3%S2]!"
8193 [(set_attr "type" "load")
8194 (set_attr "predicable" "yes")]
8197 (define_insn "*strsi_shiftpreinc"
8198 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8199 [(match_operand:SI 3 "s_register_operand" "r")
8200 (match_operand:SI 4 "const_shift_operand" "n")])
8201 (match_operand:SI 1 "s_register_operand" "0")))
8202 (match_operand:SI 5 "s_register_operand" "r"))
8203 (set (match_operand:SI 0 "s_register_operand" "=r")
8204 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8207 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8208 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8209 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8210 "str%?\\t%5, [%0, %3%S2]!"
8211 [(set_attr "type" "store1")
8212 (set_attr "predicable" "yes")]
8215 (define_insn "*strsi_shiftpredec"
8216 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8217 (match_operator:SI 2 "shift_operator"
8218 [(match_operand:SI 3 "s_register_operand" "r")
8219 (match_operand:SI 4 "const_shift_operand" "n")])))
8220 (match_operand:SI 5 "s_register_operand" "r"))
8221 (set (match_operand:SI 0 "s_register_operand" "=r")
8222 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8225 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8226 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8227 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8228 "str%?\\t%5, [%0, -%3%S2]!"
8229 [(set_attr "type" "store1")
8230 (set_attr "predicable" "yes")]
8233 (define_insn "*loadsi_shiftpreinc"
8234 [(set (match_operand:SI 5 "s_register_operand" "=r")
8235 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8236 [(match_operand:SI 3 "s_register_operand" "r")
8237 (match_operand:SI 4 "const_shift_operand" "n")])
8238 (match_operand:SI 1 "s_register_operand" "0"))))
8239 (set (match_operand:SI 0 "s_register_operand" "=r")
8240 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8243 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8244 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8245 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8246 "ldr%?\\t%5, [%0, %3%S2]!"
8247 [(set_attr "type" "load")
8248 (set_attr "predicable" "yes")]
8251 (define_insn "*loadsi_shiftpredec"
8252 [(set (match_operand:SI 5 "s_register_operand" "=r")
8253 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8254 (match_operator:SI 2 "shift_operator"
8255 [(match_operand:SI 3 "s_register_operand" "r")
8256 (match_operand:SI 4 "const_shift_operand" "n")]))))
8257 (set (match_operand:SI 0 "s_register_operand" "=r")
8258 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8261 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8262 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8263 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8264 "ldr%?\\t%5, [%0, -%3%S2]!"
8265 [(set_attr "type" "load")
8266 (set_attr "predicable" "yes")])
8268 (define_insn "*loadhi_shiftpreinc"
8269 [(set (match_operand:HI 5 "s_register_operand" "=r")
8270 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8271 [(match_operand:SI 3 "s_register_operand" "r")
8272 (match_operand:SI 4 "const_shift_operand" "n")])
8273 (match_operand:SI 1 "s_register_operand" "0"))))
8274 (set (match_operand:SI 0 "s_register_operand" "=r")
8275 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8278 && !BYTES_BIG_ENDIAN
8279 && !TARGET_MMU_TRAPS
8281 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8282 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8283 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8284 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8285 [(set_attr "type" "load")
8286 (set_attr "predicable" "yes")]
8289 (define_insn "*loadhi_shiftpredec"
8290 [(set (match_operand:HI 5 "s_register_operand" "=r")
8291 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8292 (match_operator:SI 2 "shift_operator"
8293 [(match_operand:SI 3 "s_register_operand" "r")
8294 (match_operand:SI 4 "const_shift_operand" "n")]))))
8295 (set (match_operand:SI 0 "s_register_operand" "=r")
8296 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8299 && !BYTES_BIG_ENDIAN
8300 && !TARGET_MMU_TRAPS
8302 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8303 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8304 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8305 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8306 [(set_attr "type" "load")
8307 (set_attr "predicable" "yes")]
8310 ; It can also support extended post-inc expressions, but combine doesn't
8312 ; It doesn't seem worth adding peepholes for anything but the most common
8313 ; cases since, unlike combine, the increment must immediately follow the load
8314 ; for this pattern to match.
8315 ; We must watch to see that the source/destination register isn't also the
8316 ; same as the base address register, and that if the index is a register,
8317 ; that it is not the same as the base address register. In such cases the
8318 ; instruction that we would generate would have UNPREDICTABLE behavior so
8322 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8323 (match_operand:QI 2 "s_register_operand" "r"))
8325 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8327 && (REGNO (operands[2]) != REGNO (operands[0]))
8328 && (GET_CODE (operands[1]) != REG
8329 || (REGNO (operands[1]) != REGNO (operands[0])))"
8330 "str%?b\\t%2, [%0], %1"
8334 [(set (match_operand:QI 0 "s_register_operand" "=r")
8335 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8337 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8339 && REGNO (operands[0]) != REGNO(operands[1])
8340 && (GET_CODE (operands[2]) != REG
8341 || REGNO(operands[0]) != REGNO (operands[2]))"
8342 "ldr%?b\\t%0, [%1], %2"
8346 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8347 (match_operand:SI 2 "s_register_operand" "r"))
8349 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8351 && (REGNO (operands[2]) != REGNO (operands[0]))
8352 && (GET_CODE (operands[1]) != REG
8353 || (REGNO (operands[1]) != REGNO (operands[0])))"
8354 "str%?\\t%2, [%0], %1"
8358 [(set (match_operand:HI 0 "s_register_operand" "=r")
8359 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8361 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8363 && !BYTES_BIG_ENDIAN
8364 && !TARGET_MMU_TRAPS
8366 && REGNO (operands[0]) != REGNO(operands[1])
8367 && (GET_CODE (operands[2]) != REG
8368 || REGNO(operands[0]) != REGNO (operands[2]))"
8369 "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8373 [(set (match_operand:SI 0 "s_register_operand" "=r")
8374 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8376 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8378 && REGNO (operands[0]) != REGNO(operands[1])
8379 && (GET_CODE (operands[2]) != REG
8380 || REGNO(operands[0]) != REGNO (operands[2]))"
8381 "ldr%?\\t%0, [%1], %2"
8385 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8386 (match_operand:SI 1 "index_operand" "rJ")))
8387 (match_operand:QI 2 "s_register_operand" "r"))
8388 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8390 && (REGNO (operands[2]) != REGNO (operands[0]))
8391 && (GET_CODE (operands[1]) != REG
8392 || (REGNO (operands[1]) != REGNO (operands[0])))"
8393 "str%?b\\t%2, [%0, %1]!"
8397 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8398 [(match_operand:SI 0 "s_register_operand" "r")
8399 (match_operand:SI 1 "const_int_operand" "n")])
8400 (match_operand:SI 2 "s_register_operand" "+r")))
8401 (match_operand:QI 3 "s_register_operand" "r"))
8402 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8405 && (REGNO (operands[3]) != REGNO (operands[2]))
8406 && (REGNO (operands[0]) != REGNO (operands[2]))"
8407 "str%?b\\t%3, [%2, %0%S4]!"
8410 ; This pattern is never tried by combine, so do it as a peephole
8413 [(set (match_operand:SI 0 "s_register_operand" "")
8414 (match_operand:SI 1 "s_register_operand" ""))
8415 (set (reg:CC CC_REGNUM)
8416 (compare:CC (match_dup 1) (const_int 0)))]
8419 || (!cirrus_fp_register (operands[0], SImode)
8420 && !cirrus_fp_register (operands[1], SImode)))
8422 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8423 (set (match_dup 0) (match_dup 1))])]
8427 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8428 ; reversed, check that the memory references aren't volatile.
8431 [(set (match_operand:SI 0 "s_register_operand" "=r")
8432 (match_operand:SI 4 "memory_operand" "m"))
8433 (set (match_operand:SI 1 "s_register_operand" "=r")
8434 (match_operand:SI 5 "memory_operand" "m"))
8435 (set (match_operand:SI 2 "s_register_operand" "=r")
8436 (match_operand:SI 6 "memory_operand" "m"))
8437 (set (match_operand:SI 3 "s_register_operand" "=r")
8438 (match_operand:SI 7 "memory_operand" "m"))]
8439 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8441 return emit_ldm_seq (operands, 4);
8446 [(set (match_operand:SI 0 "s_register_operand" "=r")
8447 (match_operand:SI 3 "memory_operand" "m"))
8448 (set (match_operand:SI 1 "s_register_operand" "=r")
8449 (match_operand:SI 4 "memory_operand" "m"))
8450 (set (match_operand:SI 2 "s_register_operand" "=r")
8451 (match_operand:SI 5 "memory_operand" "m"))]
8452 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8454 return emit_ldm_seq (operands, 3);
8459 [(set (match_operand:SI 0 "s_register_operand" "=r")
8460 (match_operand:SI 2 "memory_operand" "m"))
8461 (set (match_operand:SI 1 "s_register_operand" "=r")
8462 (match_operand:SI 3 "memory_operand" "m"))]
8463 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8465 return emit_ldm_seq (operands, 2);
8470 [(set (match_operand:SI 4 "memory_operand" "=m")
8471 (match_operand:SI 0 "s_register_operand" "r"))
8472 (set (match_operand:SI 5 "memory_operand" "=m")
8473 (match_operand:SI 1 "s_register_operand" "r"))
8474 (set (match_operand:SI 6 "memory_operand" "=m")
8475 (match_operand:SI 2 "s_register_operand" "r"))
8476 (set (match_operand:SI 7 "memory_operand" "=m")
8477 (match_operand:SI 3 "s_register_operand" "r"))]
8478 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8480 return emit_stm_seq (operands, 4);
8485 [(set (match_operand:SI 3 "memory_operand" "=m")
8486 (match_operand:SI 0 "s_register_operand" "r"))
8487 (set (match_operand:SI 4 "memory_operand" "=m")
8488 (match_operand:SI 1 "s_register_operand" "r"))
8489 (set (match_operand:SI 5 "memory_operand" "=m")
8490 (match_operand:SI 2 "s_register_operand" "r"))]
8491 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8493 return emit_stm_seq (operands, 3);
8498 [(set (match_operand:SI 2 "memory_operand" "=m")
8499 (match_operand:SI 0 "s_register_operand" "r"))
8500 (set (match_operand:SI 3 "memory_operand" "=m")
8501 (match_operand:SI 1 "s_register_operand" "r"))]
8502 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8504 return emit_stm_seq (operands, 2);
8509 [(set (match_operand:SI 0 "s_register_operand" "")
8510 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8512 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8513 [(match_operand:SI 3 "s_register_operand" "")
8514 (match_operand:SI 4 "arm_rhs_operand" "")]))))
8515 (clobber (match_operand:SI 5 "s_register_operand" ""))]
8517 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8518 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8523 ;; This split can be used because CC_Z mode implies that the following
8524 ;; branch will be an equality, or an unsigned inequality, so the sign
8525 ;; extension is not needed.
8528 [(set (reg:CC_Z CC_REGNUM)
8530 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8532 (match_operand 1 "const_int_operand" "")))
8533 (clobber (match_scratch:SI 2 ""))]
8535 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8536 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8537 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8538 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8540 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8544 (define_expand "prologue"
8545 [(clobber (const_int 0))]
8548 arm_expand_prologue ();
8550 thumb_expand_prologue ();
8555 (define_expand "epilogue"
8556 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8560 thumb_expand_epilogue ();
8561 else if (USE_RETURN_INSN (FALSE))
8563 emit_jump_insn (gen_return ());
8566 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8568 gen_rtx_RETURN (VOIDmode)),
8574 ;; Note - although unspec_volatile's USE all hard registers,
8575 ;; USEs are ignored after relaod has completed. Thus we need
8576 ;; to add an unspec of the link register to ensure that flow
8577 ;; does not think that it is unused by the sibcall branch that
8578 ;; will replace the standard function epilogue.
8579 (define_insn "sibcall_epilogue"
8580 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
8581 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
8584 if (USE_RETURN_INSN (FALSE))
8585 return output_return_instruction (const_true_rtx, FALSE, FALSE);
8586 return arm_output_epilogue (FALSE);
8588 ;; Length is absolute worst case
8589 [(set_attr "length" "44")
8590 (set_attr "type" "block")
8591 ;; We don't clobber the conditions, but the potential length of this
8592 ;; operation is sufficient to make conditionalizing the sequence
8593 ;; unlikely to be profitable.
8594 (set_attr "conds" "clob")]
8597 (define_insn "*epilogue_insns"
8598 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8602 return arm_output_epilogue (TRUE);
8603 else /* TARGET_THUMB */
8604 return thumb_unexpanded_epilogue ();
8606 ; Length is absolute worst case
8607 [(set_attr "length" "44")
8608 (set_attr "type" "block")
8609 ;; We don't clobber the conditions, but the potential length of this
8610 ;; operation is sufficient to make conditionalizing the sequence
8611 ;; unlikely to be profitable.
8612 (set_attr "conds" "clob")]
8615 (define_expand "eh_epilogue"
8616 [(use (match_operand:SI 0 "register_operand" "r"))
8617 (use (match_operand:SI 1 "register_operand" "r"))
8618 (use (match_operand:SI 2 "register_operand" "r"))]
8622 cfun->machine->eh_epilogue_sp_ofs = operands[1];
8623 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8625 rtx ra = gen_rtx_REG (Pmode, 2);
8627 emit_move_insn (ra, operands[2]);
8630 /* This is a hack -- we may have crystalized the function type too
8632 cfun->machine->func_type = 0;
8636 ;; This split is only used during output to reduce the number of patterns
8637 ;; that need assembler instructions adding to them. We allowed the setting
8638 ;; of the conditions to be implicit during rtl generation so that
8639 ;; the conditional compare patterns would work. However this conflicts to
8640 ;; some extent with the conditional data operations, so we have to split them
8644 [(set (match_operand:SI 0 "s_register_operand" "")
8645 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8646 [(match_operand 2 "" "") (match_operand 3 "" "")])
8648 (match_operand 4 "" "")))
8649 (clobber (reg:CC CC_REGNUM))]
8650 "TARGET_ARM && reload_completed"
8651 [(set (match_dup 5) (match_dup 6))
8652 (cond_exec (match_dup 7)
8653 (set (match_dup 0) (match_dup 4)))]
8656 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8657 operands[2], operands[3]);
8658 enum rtx_code rc = GET_CODE (operands[1]);
8660 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8661 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8662 if (mode == CCFPmode || mode == CCFPEmode)
8663 rc = reverse_condition_maybe_unordered (rc);
8665 rc = reverse_condition (rc);
8667 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8672 [(set (match_operand:SI 0 "s_register_operand" "")
8673 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8674 [(match_operand 2 "" "") (match_operand 3 "" "")])
8675 (match_operand 4 "" "")
8677 (clobber (reg:CC CC_REGNUM))]
8678 "TARGET_ARM && reload_completed"
8679 [(set (match_dup 5) (match_dup 6))
8680 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8681 (set (match_dup 0) (match_dup 4)))]
8684 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8685 operands[2], operands[3]);
8687 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8688 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8693 [(set (match_operand:SI 0 "s_register_operand" "")
8694 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8695 [(match_operand 2 "" "") (match_operand 3 "" "")])
8696 (match_operand 4 "" "")
8697 (match_operand 5 "" "")))
8698 (clobber (reg:CC CC_REGNUM))]
8699 "TARGET_ARM && reload_completed"
8700 [(set (match_dup 6) (match_dup 7))
8701 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8702 (set (match_dup 0) (match_dup 4)))
8703 (cond_exec (match_dup 8)
8704 (set (match_dup 0) (match_dup 5)))]
8707 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8708 operands[2], operands[3]);
8709 enum rtx_code rc = GET_CODE (operands[1]);
8711 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8712 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8713 if (mode == CCFPmode || mode == CCFPEmode)
8714 rc = reverse_condition_maybe_unordered (rc);
8716 rc = reverse_condition (rc);
8718 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8723 [(set (match_operand:SI 0 "s_register_operand" "")
8724 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8725 [(match_operand:SI 2 "s_register_operand" "")
8726 (match_operand:SI 3 "arm_add_operand" "")])
8727 (match_operand:SI 4 "arm_rhs_operand" "")
8729 (match_operand:SI 5 "s_register_operand" ""))))
8730 (clobber (reg:CC CC_REGNUM))]
8731 "TARGET_ARM && reload_completed"
8732 [(set (match_dup 6) (match_dup 7))
8733 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8734 (set (match_dup 0) (match_dup 4)))
8735 (cond_exec (match_dup 8)
8736 (set (match_dup 0) (not:SI (match_dup 5))))]
8739 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8740 operands[2], operands[3]);
8741 enum rtx_code rc = GET_CODE (operands[1]);
8743 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8744 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8745 if (mode == CCFPmode || mode == CCFPEmode)
8746 rc = reverse_condition_maybe_unordered (rc);
8748 rc = reverse_condition (rc);
8750 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8754 (define_insn "*cond_move_not"
8755 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8756 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8757 [(match_operand 3 "cc_register" "") (const_int 0)])
8758 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8760 (match_operand:SI 2 "s_register_operand" "r,r"))))]
8764 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8765 [(set_attr "conds" "use")
8766 (set_attr "length" "4,8")]
8769 ;; The next two patterns occur when an AND operation is followed by a
8770 ;; scc insn sequence
8772 (define_insn "*sign_extract_onebit"
8773 [(set (match_operand:SI 0 "s_register_operand" "=r")
8774 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8776 (match_operand:SI 2 "const_int_operand" "n")))
8777 (clobber (reg:CC CC_REGNUM))]
8780 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8781 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8782 return \"mvnne\\t%0, #0\";
8784 [(set_attr "conds" "clob")
8785 (set_attr "length" "8")]
8788 (define_insn "*not_signextract_onebit"
8789 [(set (match_operand:SI 0 "s_register_operand" "=r")
8791 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8793 (match_operand:SI 2 "const_int_operand" "n"))))
8794 (clobber (reg:CC CC_REGNUM))]
8797 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8798 output_asm_insn (\"tst\\t%1, %2\", operands);
8799 output_asm_insn (\"mvneq\\t%0, #0\", operands);
8800 return \"movne\\t%0, #0\";
8802 [(set_attr "conds" "clob")
8803 (set_attr "length" "12")]
8806 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
8807 ;; expressions. For simplicity, the first register is also in the unspec
8809 (define_insn "*push_multi"
8810 [(match_parallel 2 "multi_register_push"
8811 [(set (match_operand:BLK 0 "memory_operand" "=m")
8812 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8813 UNSPEC_PUSH_MULT))])]
8817 int num_saves = XVECLEN (operands[2], 0);
8819 /* For the StrongARM at least it is faster to
8820 use STR to store only a single register. */
8822 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8828 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
8830 for (i = 1; i < num_saves; i++)
8832 strcat (pattern, \", %|\");
8834 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
8837 strcat (pattern, \"}\");
8838 output_asm_insn (pattern, operands);
8843 [(set_attr "type" "store4")]
8846 (define_insn "stack_tie"
8847 [(set (mem:BLK (scratch))
8848 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
8849 (match_operand:SI 1 "s_register_operand" "r")]
8853 [(set_attr "length" "0")]
8856 ;; Similarly for the floating point registers
8857 (define_insn "*push_fp_multi"
8858 [(match_parallel 2 "multi_register_push"
8859 [(set (match_operand:BLK 0 "memory_operand" "=m")
8860 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
8861 UNSPEC_PUSH_MULT))])]
8867 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
8868 output_asm_insn (pattern, operands);
8871 [(set_attr "type" "f_store")]
8874 ;; Special patterns for dealing with the constant pool
8876 (define_insn "align_4"
8877 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
8880 assemble_align (32);
8885 (define_insn "consttable_end"
8886 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
8889 making_const_table = FALSE;
8894 (define_insn "consttable_1"
8895 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
8898 making_const_table = TRUE;
8899 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
8903 [(set_attr "length" "4")]
8906 (define_insn "consttable_2"
8907 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
8910 making_const_table = TRUE;
8911 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
8915 [(set_attr "length" "4")]
8918 (define_insn "consttable_4"
8919 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
8923 making_const_table = TRUE;
8924 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8929 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8930 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8934 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
8939 [(set_attr "length" "4")]
8942 (define_insn "consttable_8"
8943 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
8947 making_const_table = TRUE;
8948 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8953 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8954 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8958 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
8963 [(set_attr "length" "8")]
8966 ;; Miscellaneous Thumb patterns
8968 (define_expand "tablejump"
8969 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
8970 (use (label_ref (match_operand 1 "" "")))])]
8975 /* Hopefully, CSE will eliminate this copy. */
8976 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
8977 rtx reg2 = gen_reg_rtx (SImode);
8979 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
8985 (define_insn "*thumb_tablejump"
8986 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
8987 (use (label_ref (match_operand 1 "" "")))]
8990 [(set_attr "length" "2")]
8995 (define_insn "clzsi2"
8996 [(set (match_operand:SI 0 "s_register_operand" "=r")
8997 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
8998 "TARGET_ARM && arm_arch5"
9001 (define_expand "ffssi2"
9002 [(set (match_operand:SI 0 "s_register_operand" "")
9003 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9004 "TARGET_ARM && arm_arch5"
9009 t1 = gen_reg_rtx (SImode);
9010 t2 = gen_reg_rtx (SImode);
9011 t3 = gen_reg_rtx (SImode);
9013 emit_insn (gen_negsi2 (t1, operands[1]));
9014 emit_insn (gen_andsi3 (t2, operands[1], t1));
9015 emit_insn (gen_clzsi2 (t3, t2));
9016 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
9021 (define_expand "ctzsi2"
9022 [(set (match_operand:SI 0 "s_register_operand" "")
9023 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
9024 "TARGET_ARM && arm_arch5"
9029 t1 = gen_reg_rtx (SImode);
9030 t2 = gen_reg_rtx (SImode);
9031 t3 = gen_reg_rtx (SImode);
9033 emit_insn (gen_negsi2 (t1, operands[1]));
9034 emit_insn (gen_andsi3 (t2, operands[1], t1));
9035 emit_insn (gen_clzsi2 (t3, t2));
9036 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
9041 ;; V5E instructions.
9043 (define_insn "prefetch"
9044 [(prefetch (match_operand:SI 0 "address_operand" "p")
9045 (match_operand:SI 1 "" "")
9046 (match_operand:SI 2 "" ""))]
9047 "TARGET_ARM && arm_arch5e"
9050 ;; General predication pattern
9053 [(match_operator 0 "arm_comparison_operator"
9054 [(match_operand 1 "cc_register" "")
9060 (define_insn "prologue_use"
9061 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
9063 "%@ %0 needed for prologue"