1 ;;- Machine description for ARM for GNU compiler
2 ;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000
3 ;; Free Software Foundation, Inc.
4 ;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;; and Martin Simmons (@harleqn.co.uk).
6 ;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
8 ;; This file is part of GNU CC.
10 ;; GNU CC is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; GNU CC is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU CC; see the file COPYING. If not, write to
22 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
27 ;; There are patterns in this file to support XFmode arithmetic.
28 ;; Unfortunately RISC iX doesn't work well with these so they are disabled.
32 ;; 0 `sin' operation: operand 0 is the result, operand 1 the parameter,
33 ;; the mode is MODE_FLOAT
34 ;; 1 `cos' operation: operand 0 is the result, operand 1 the parameter,
35 ;; the mode is MODE_FLOAT
36 ;; 2 `push multiple' operation: operand 0 is the first register. Subsequent
37 ;; registers are in parallel (use...) expressions.
38 ;; 3 A symbol that has been treated properly for pic usage, that is, we
39 ;; will add the pic_register value to it before trying to dereference it.
40 ;; Note: sin and cos are no-longer used.
42 ;; UNSPEC_VOLATILE Usage:
43 ;; 0 `blockage' insn to prevent scheduling across an insn in the code.
44 ;; 1 `epilogue' insn, used to represent any part of the instruction epilogue
45 ;; sequence that isn't expanded into normal RTL. Used for both normal
46 ;; and sibcall epilogues.
47 ;; 2 `align' insn. Used at the head of a minipool table for inlined
49 ;; 3 `end-of-table'. Used to mark the end of a minipool table.
50 ;; 4 `pool-entry(1)'. An entry in the constant pool for an 8-bit object.
51 ;; 5 `pool-entry(2)'. An entry in the constant pool for a 16-bit object.
52 ;; 6 `pool-entry(4)'. An entry in the constant pool for a 32-bit object.
53 ;; 7 `pool-entry(8)'. An entry in the constant pool for a 64-bit object.
58 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
59 ; generating ARM code. This is used to control the length of some insn
60 ; patterns that share the same RTL in both ARM and Thumb code.
61 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
63 ; PROG_MODE attribute is used to determine whether condition codes are
64 ; clobbered by a call insn: they are if in prog32 mode. This is controlled
65 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
66 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
68 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
69 ; scheduling decisions for the load unit and the multiplier.
70 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
72 ;; Operand number of an input operand that is shifted. Zero if the
73 ;; given instruction does not shift one of its input operands.
74 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_is_xscale")))
75 (define_attr "shift" "" (const_int 0))
77 ; Floating Point Unit. If we only have floating point emulation, then there
78 ; is no point in scheduling the floating point insns. (Well, for best
79 ; performance we should try and group them together).
80 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
82 ; LENGTH of an instruction (in bytes)
83 (define_attr "length" "" (const_int 4))
85 ; POOL_RANGE is how far away from a constant pool entry that this insn
86 ; can be placed. If the distance is zero, then this insn will never
88 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
90 (define_attr "pool_range" "" (const_int 0))
91 (define_attr "neg_pool_range" "" (const_int 0))
93 ; An assembler sequence may clobber the condition codes without us knowing.
94 (define_asm_attributes
95 [(set_attr "conds" "clob")])
97 ; TYPE attribute is used to detect floating point instructions which, if
98 ; running on a co-processor can run in parallel with other, basic instructions
99 ; If write-buffer scheduling is enabled then it can also be used in the
100 ; scheduling of writes.
102 ; Classification of each insn
103 ; normal any data instruction that doesn't hit memory or fp regs
104 ; mult a multiply instruction
105 ; block blockage insn, this blocks all functional units
106 ; float a floating point arithmetic operation (subject to expansion)
107 ; fdivx XFmode floating point division
108 ; fdivd DFmode floating point division
109 ; fdivs SFmode floating point division
110 ; fmul Floating point multiply
111 ; ffmul Fast floating point multiply
112 ; farith Floating point arithmetic (4 cycle)
113 ; ffarith Fast floating point arithmetic (2 cycle)
114 ; float_em a floating point arithmetic operation that is normally emulated
115 ; even on a machine with an fpa.
116 ; f_load a floating point load from memory
117 ; f_store a floating point store to memory
118 ; f_mem_r a transfer of a floating point register to a real reg via mem
119 ; r_mem_f the reverse of f_mem_r
120 ; f_2_r fast transfer float to arm (no memory needed)
121 ; r_2_f fast transfer arm to float
122 ; call a subroutine call
123 ; load any load from memory
124 ; store1 store 1 word to memory from arm registers
125 ; store2 store 2 words
126 ; store3 store 3 words
127 ; store4 store 4 words
130 "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"
131 (const_string "normal"))
133 ; Load scheduling, set from the arm_ld_sched variable
134 ; initialised by arm_override_options()
135 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
137 ; condition codes: this one is used by final_prescan_insn to speed up
138 ; conditionalizing instructions. It saves having to scan the rtl to see if
139 ; it uses or alters the condition codes.
141 ; USE means that the condition codes are used by the insn in the process of
142 ; outputting code, this means (at present) that we can't use the insn in
145 ; SET means that the purpose of the insn is to set the condition codes in a
146 ; well defined manner.
148 ; CLOB means that the condition codes are altered in an undefined manner, if
149 ; they are altered at all
151 ; JUMP_CLOB is used when the condition cannot be represented by a single
152 ; instruction (UNEQ and LTGT). These cannot be predicated.
154 ; NOCOND means that the condition codes are neither altered nor affect the
155 ; output of this insn
157 (define_attr "conds" "use,set,clob,jump_clob,nocond"
158 (if_then_else (eq_attr "type" "call")
159 (if_then_else (eq_attr "prog_mode" "prog32")
160 (const_string "clob") (const_string "nocond"))
161 (const_string "nocond")))
163 ; Predicable means that the insn can be conditionally executed based on
164 ; an automatically added predicate (additional patterns are generated by
165 ; gen...). We default to 'no' because no Thumb patterns match this rule
166 ; and not all ARM patterns do.
167 (define_attr "predicable" "no,yes" (const_string "no"))
169 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
170 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
171 ; suffer blockages enough to warrent modelling this (and it can adversely
172 ; affect the schedule).
173 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
175 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
176 ; to stall the processor. Used with model_wbuf above.
177 (define_attr "write_conflict" "no,yes"
178 (if_then_else (eq_attr "type"
179 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
181 (const_string "no")))
183 ; Classify the insns into those that take one cycle and those that take more
184 ; than one on the main cpu execution unit.
185 (define_attr "core_cycles" "single,multi"
186 (if_then_else (eq_attr "type"
187 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
188 (const_string "single")
189 (const_string "multi")))
191 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
192 ;; distant label. Only applicable to Thumb code.
193 (define_attr "far_jump" "yes,no" (const_string "no"))
195 ;; (define_function_unit {name} {num-units} {n-users} {test}
196 ;; {ready-delay} {issue-delay} [{conflict-list}])
198 ;;--------------------------------------------------------------------
199 ;; Floating point unit (FPA)
200 ;;--------------------------------------------------------------------
201 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
202 (eq_attr "type" "fdivx")) 71 69)
204 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
205 (eq_attr "type" "fdivd")) 59 57)
207 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
208 (eq_attr "type" "fdivs")) 31 29)
210 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
211 (eq_attr "type" "fmul")) 9 7)
213 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
214 (eq_attr "type" "ffmul")) 6 4)
216 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
217 (eq_attr "type" "farith")) 4 2)
219 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
220 (eq_attr "type" "ffarith")) 2 2)
222 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
223 (eq_attr "type" "r_2_f")) 5 3)
225 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
226 (eq_attr "type" "f_2_r")) 1 2)
228 ; The fpa10 doesn't really have a memory read unit, but it can start to
229 ; speculatively execute the instruction in the pipeline, provided the data
230 ; is already loaded, so pretend reads have a delay of 2 (and that the
231 ; pipeline is infinite).
233 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
234 (eq_attr "type" "f_load")) 3 1)
236 ;;--------------------------------------------------------------------
238 ;;--------------------------------------------------------------------
239 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
241 ; The write buffer on some of the arm6 processors is hard to model exactly.
242 ; There is room in the buffer for up to two addresses and up to eight words
243 ; of memory, but the two needn't be split evenly. When writing the two
244 ; addresses are fully pipelined. However, a read from memory that is not
245 ; currently in the cache will block until the writes have completed.
246 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
247 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
248 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
249 ; cycle to add as well.
251 (define_function_unit "write_buf" 1 2
252 (and (eq_attr "model_wbuf" "yes")
253 (eq_attr "type" "store1,r_mem_f")) 5 3)
254 (define_function_unit "write_buf" 1 2
255 (and (eq_attr "model_wbuf" "yes")
256 (eq_attr "type" "store2")) 7 4)
257 (define_function_unit "write_buf" 1 2
258 (and (eq_attr "model_wbuf" "yes")
259 (eq_attr "type" "store3")) 9 5)
260 (define_function_unit "write_buf" 1 2
261 (and (eq_attr "model_wbuf" "yes")
262 (eq_attr "type" "store4")) 11 6)
264 ;;--------------------------------------------------------------------
265 ;; Write blockage unit
266 ;;--------------------------------------------------------------------
267 ; The write_blockage unit models (partially), the fact that reads will stall
268 ; until the write buffer empties.
269 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
270 ; so we don't model them here
271 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
272 (eq_attr "type" "store1")) 5 5
273 [(eq_attr "write_conflict" "yes")])
274 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
275 (eq_attr "type" "store2")) 7 7
276 [(eq_attr "write_conflict" "yes")])
277 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
278 (eq_attr "type" "store3")) 9 9
279 [(eq_attr "write_conflict" "yes")])
280 (define_function_unit "write_blockage" 1 0
281 (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
282 [(eq_attr "write_conflict" "yes")])
283 (define_function_unit "write_blockage" 1 0
284 (and (eq_attr "model_wbuf" "yes")
285 (eq_attr "write_conflict" "yes")) 1 1)
287 ;;--------------------------------------------------------------------
289 ;;--------------------------------------------------------------------
290 ; Everything must spend at least one cycle in the core unit
291 (define_function_unit "core" 1 0 (eq_attr "core_cycles" "single") 1 1)
293 (define_function_unit "core" 1 0
294 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
296 (define_function_unit "core" 1 0
297 (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
299 ;; We do not need to conditionalize the define_function_unit immediately
300 ;; above. This one will be ignored for anything other than xscale
301 ;; compiles and for xscale compiles it provides a larger delay
302 ;; and the scheduler will DTRT.
303 ;; FIXME: this test needs to be revamped to not depend on this feature
306 (define_function_unit "core" 1 0
307 (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
308 (eq_attr "is_xscale" "yes"))
311 (define_function_unit "core" 1 0
312 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
314 (define_function_unit "core" 1 0
315 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
317 (define_function_unit "core" 1 0
318 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
320 (define_function_unit "core" 1 0
321 (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
323 (define_function_unit "core" 1 0
324 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
326 (define_function_unit "core" 1 0
327 (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
329 (define_function_unit "core" 1 0
330 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
331 (eq_attr "type" "mult")) 4 4)
333 (define_function_unit "core" 1 0
334 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
335 (eq_attr "type" "mult")) 3 2)
337 (define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
339 (define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
341 (define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
343 (define_function_unit "core" 1 0
344 (and (eq_attr "core_cycles" "multi")
345 (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
347 ;;---------------------------------------------------------------------------
348 ;; Make code more maintainable by using names for fixed registers.
358 ;; Note: For DImode insns, there is normally no reason why operands should
359 ;; not be in the same register, what we don't want is for something being
360 ;; written to partially overlap something that is an input.
362 (define_expand "adddi3"
364 [(set (match_operand:DI 0 "s_register_operand" "")
365 (plus:DI (match_operand:DI 1 "s_register_operand" "")
366 (match_operand:DI 2 "s_register_operand" "")))
367 (clobber (reg:CC CC_REGNUM))])]
372 if (GET_CODE (operands[1]) != REG)
373 operands[1] = force_reg (SImode, operands[1]);
374 if (GET_CODE (operands[2]) != REG)
375 operands[2] = force_reg (SImode, operands[2]);
380 (define_insn "*thumb_adddi3"
381 [(set (match_operand:DI 0 "register_operand" "=l")
382 (plus:DI (match_operand:DI 1 "register_operand" "%0")
383 (match_operand:DI 2 "register_operand" "l")))
384 (clobber (reg:CC CC_REGNUM))
387 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
388 [(set_attr "length" "4")]
391 (define_insn_and_split "*arm_adddi3"
392 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
393 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
394 (match_operand:DI 2 "s_register_operand" "r, 0")))
395 (clobber (reg:CC CC_REGNUM))]
398 "TARGET_ARM && reload_completed"
399 [(parallel [(set (reg:CC_C CC_REGNUM)
400 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
402 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
403 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
404 (plus:SI (match_dup 4) (match_dup 5))))]
407 operands[3] = gen_highpart (SImode, operands[0]);
408 operands[0] = gen_lowpart (SImode, operands[0]);
409 operands[4] = gen_highpart (SImode, operands[1]);
410 operands[1] = gen_lowpart (SImode, operands[1]);
411 operands[5] = gen_highpart (SImode, operands[2]);
412 operands[2] = gen_lowpart (SImode, operands[2]);
414 [(set_attr "conds" "clob")
415 (set_attr "length" "8")]
418 (define_insn_and_split "*adddi_sesidi_di"
419 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
420 (plus:DI (sign_extend:DI
421 (match_operand:SI 2 "s_register_operand" "r,r"))
422 (match_operand:DI 1 "s_register_operand" "r,0")))
423 (clobber (reg:CC CC_REGNUM))]
426 "TARGET_ARM && reload_completed"
427 [(parallel [(set (reg:CC_C CC_REGNUM)
428 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
430 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
431 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
432 (plus:SI (ashiftrt:SI (match_dup 2)
437 operands[3] = gen_highpart (SImode, operands[0]);
438 operands[0] = gen_lowpart (SImode, operands[0]);
439 operands[4] = gen_highpart (SImode, operands[1]);
440 operands[1] = gen_lowpart (SImode, operands[1]);
441 operands[2] = gen_lowpart (SImode, operands[2]);
443 [(set_attr "conds" "clob")
444 (set_attr "length" "8")]
447 (define_insn_and_split "*adddi_zesidi_di"
448 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
449 (plus:DI (zero_extend:DI
450 (match_operand:SI 2 "s_register_operand" "r,r"))
451 (match_operand:DI 1 "s_register_operand" "r,0")))
452 (clobber (reg:CC CC_REGNUM))]
455 "TARGET_ARM && reload_completed"
456 [(parallel [(set (reg:CC_C CC_REGNUM)
457 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
459 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
460 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
461 (plus:SI (match_dup 4) (const_int 0))))]
464 operands[3] = gen_highpart (SImode, operands[0]);
465 operands[0] = gen_lowpart (SImode, operands[0]);
466 operands[4] = gen_highpart (SImode, operands[1]);
467 operands[1] = gen_lowpart (SImode, operands[1]);
468 operands[2] = gen_lowpart (SImode, operands[2]);
470 [(set_attr "conds" "clob")
471 (set_attr "length" "8")]
474 (define_expand "addsi3"
475 [(set (match_operand:SI 0 "s_register_operand" "")
476 (plus:SI (match_operand:SI 1 "s_register_operand" "")
477 (match_operand:SI 2 "reg_or_int_operand" "")))]
480 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
482 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
484 (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
490 ; If there is a scratch available, this will be faster than synthesising the
493 [(match_scratch:SI 3 "r")
494 (set (match_operand:SI 0 "s_register_operand" "")
495 (plus:SI (match_operand:SI 1 "s_register_operand" "")
496 (match_operand:SI 2 "const_int_operand" "")))]
498 !(const_ok_for_arm (INTVAL (operands[2]))
499 || const_ok_for_arm (-INTVAL (operands[2])))
500 && const_ok_for_arm (~INTVAL (operands[2]))"
501 [(set (match_dup 3) (match_dup 2))
502 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
506 (define_insn_and_split "*arm_addsi3"
507 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
508 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
509 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
516 GET_CODE (operands[2]) == CONST_INT
517 && !(const_ok_for_arm (INTVAL (operands[2]))
518 || const_ok_for_arm (-INTVAL (operands[2])))"
519 [(clobber (const_int 0))]
521 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
525 [(set_attr "length" "4,4,16")
526 (set_attr "predicable" "yes")]
529 ;; Register group 'k' is a single register group containing only the stack
530 ;; register. Trying to reload it will always fail catastrophically,
531 ;; so never allow those alternatives to match if reloading is needed.
533 (define_insn "*thumb_addsi3"
534 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
535 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
536 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
539 static const char * const asms[] =
541 \"add\\t%0, %0, %2\",
542 \"sub\\t%0, %0, #%n2\",
543 \"add\\t%0, %1, %2\",
544 \"add\\t%0, %0, %2\",
545 \"add\\t%0, %0, %2\",
546 \"add\\t%0, %1, %2\",
549 if ((which_alternative == 2 || which_alternative == 6)
550 && GET_CODE (operands[2]) == CONST_INT
551 && INTVAL (operands[2]) < 0)
552 return \"sub\\t%0, %1, #%n2\";
553 return asms[which_alternative];
555 [(set_attr "length" "2")]
558 ;; Reloading and elimination of the frame pointer can
559 ;; sometimes cause this optimization to be missed.
561 [(set (match_operand:SI 0 "register_operand" "=l")
562 (match_operand:SI 1 "const_int_operand" "M"))
564 (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "k")))]
566 && REGNO (operands[2]) == STACK_POINTER_REGNUM
567 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
568 && (INTVAL (operands[1]) & 3) == 0"
569 [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
573 (define_insn "*addsi3_compare0"
574 [(set (reg:CC_NOOV CC_REGNUM)
576 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
577 (match_operand:SI 2 "arm_add_operand" "rI,L"))
579 (set (match_operand:SI 0 "s_register_operand" "=r,r")
580 (plus:SI (match_dup 1) (match_dup 2)))]
584 sub%?s\\t%0, %1, #%n2"
585 [(set_attr "conds" "set")]
588 (define_insn "*addsi3_compare0_scratch"
589 [(set (reg:CC_NOOV CC_REGNUM)
591 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
592 (match_operand:SI 1 "arm_add_operand" "rI,L"))
598 [(set_attr "conds" "set")]
601 ;; These patterns are the same ones as the two regular addsi3_compare0
602 ;; patterns, except we write them slightly different - the combiner
603 ;; tends to generate them this way.
604 (define_insn "*addsi3_compare0_for_combiner"
605 [(set (reg:CC CC_REGNUM)
607 (match_operand:SI 1 "s_register_operand" "r,r")
608 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
609 (set (match_operand:SI 0 "s_register_operand" "=r,r")
610 (plus:SI (match_dup 1) (match_dup 2)))]
614 sub%?s\\t%0, %1, #%n2"
615 [(set_attr "conds" "set")]
618 (define_insn "*addsi3_compare0_scratch_for_combiner"
619 [(set (reg:CC CC_REGNUM)
621 (match_operand:SI 0 "s_register_operand" "r,r")
622 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
627 [(set_attr "conds" "set")]
630 ;; The next four insns work because they compare the result with one of
631 ;; the operands, and we know that the use of the condition code is
632 ;; either GEU or LTU, so we can use the carry flag from the addition
633 ;; instead of doing the compare a second time.
634 (define_insn "*addsi3_compare_op1"
635 [(set (reg:CC_C CC_REGNUM)
637 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
638 (match_operand:SI 2 "arm_add_operand" "rI,L"))
640 (set (match_operand:SI 0 "s_register_operand" "=r,r")
641 (plus:SI (match_dup 1) (match_dup 2)))]
645 sub%?s\\t%0, %1, #%n2"
646 [(set_attr "conds" "set")]
649 (define_insn "*addsi3_compare_op2"
650 [(set (reg:CC_C CC_REGNUM)
652 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
653 (match_operand:SI 2 "arm_add_operand" "rI,L"))
655 (set (match_operand:SI 0 "s_register_operand" "=r,r")
656 (plus:SI (match_dup 1) (match_dup 2)))]
660 sub%?s\\t%0, %1, #%n2"
661 [(set_attr "conds" "set")]
664 (define_insn "*compare_addsi2_op0"
665 [(set (reg:CC_C CC_REGNUM)
667 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
668 (match_operand:SI 1 "arm_add_operand" "rI,L"))
674 [(set_attr "conds" "set")]
677 (define_insn "*compare_addsi2_op1"
678 [(set (reg:CC_C CC_REGNUM)
680 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
681 (match_operand:SI 1 "arm_add_operand" "rI,L"))
687 [(set_attr "conds" "set")]
690 (define_insn "*addsi3_carryin"
691 [(set (match_operand:SI 0 "s_register_operand" "=r")
692 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
693 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
694 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
697 [(set_attr "conds" "use")]
700 (define_insn "*addsi3_carryin_shift"
701 [(set (match_operand:SI 0 "s_register_operand" "")
702 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
704 (match_operator:SI 2 "shift_operator"
705 [(match_operand:SI 3 "s_register_operand" "")
706 (match_operand:SI 4 "reg_or_int_operand" "")])
707 (match_operand:SI 1 "s_register_operand" ""))))]
709 "adc%?\\t%0, %1, %3%S2"
710 [(set_attr "conds" "use")]
713 (define_insn "*addsi3_carryin_alt1"
714 [(set (match_operand:SI 0 "s_register_operand" "=r")
715 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
716 (match_operand:SI 2 "arm_rhs_operand" "rI"))
717 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
720 [(set_attr "conds" "use")]
723 (define_insn "*addsi3_carryin_alt2"
724 [(set (match_operand:SI 0 "s_register_operand" "=r")
725 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
726 (match_operand:SI 1 "s_register_operand" "r"))
727 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
730 [(set_attr "conds" "use")]
733 (define_insn "*addsi3_carryin_alt3"
734 [(set (match_operand:SI 0 "s_register_operand" "=r")
735 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
736 (match_operand:SI 2 "arm_rhs_operand" "rI"))
737 (match_operand:SI 1 "s_register_operand" "r")))]
740 [(set_attr "conds" "use")]
743 (define_insn "incscc"
744 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
745 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
746 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
747 (match_operand:SI 1 "s_register_operand" "0,?r")))]
751 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
752 [(set_attr "conds" "use")
753 (set_attr "length" "4,8")]
756 (define_insn "addsf3"
757 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
758 (plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
759 (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
760 "TARGET_ARM && TARGET_HARD_FLOAT"
763 suf%?s\\t%0, %1, #%N2"
764 [(set_attr "type" "farith")
765 (set_attr "predicable" "yes")]
768 (define_insn "adddf3"
769 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
770 (plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
771 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
772 "TARGET_ARM && TARGET_HARD_FLOAT"
775 suf%?d\\t%0, %1, #%N2"
776 [(set_attr "type" "farith")
777 (set_attr "predicable" "yes")]
780 (define_insn "*adddf_esfdf_df"
781 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
782 (plus:DF (float_extend:DF
783 (match_operand:SF 1 "s_register_operand" "f,f"))
784 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
785 "TARGET_ARM && TARGET_HARD_FLOAT"
788 suf%?d\\t%0, %1, #%N2"
789 [(set_attr "type" "farith")
790 (set_attr "predicable" "yes")]
793 (define_insn "*adddf_df_esfdf"
794 [(set (match_operand:DF 0 "s_register_operand" "=f")
795 (plus:DF (match_operand:DF 1 "s_register_operand" "f")
797 (match_operand:SF 2 "s_register_operand" "f"))))]
798 "TARGET_ARM && TARGET_HARD_FLOAT"
799 "adf%?d\\t%0, %1, %2"
800 [(set_attr "type" "farith")
801 (set_attr "predicable" "yes")]
804 (define_insn "*adddf_esfdf_esfdf"
805 [(set (match_operand:DF 0 "s_register_operand" "=f")
806 (plus:DF (float_extend:DF
807 (match_operand:SF 1 "s_register_operand" "f"))
809 (match_operand:SF 2 "s_register_operand" "f"))))]
810 "TARGET_ARM && TARGET_HARD_FLOAT"
811 "adf%?d\\t%0, %1, %2"
812 [(set_attr "type" "farith")
813 (set_attr "predicable" "yes")]
816 (define_insn "addxf3"
817 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
818 (plus:XF (match_operand:XF 1 "s_register_operand" "f,f")
819 (match_operand:XF 2 "fpu_add_operand" "fG,H")))]
820 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
823 suf%?e\\t%0, %1, #%N2"
824 [(set_attr "type" "farith")
825 (set_attr "predicable" "yes")]
828 (define_expand "subdi3"
830 [(set (match_operand:DI 0 "s_register_operand" "")
831 (minus:DI (match_operand:DI 1 "s_register_operand" "")
832 (match_operand:DI 2 "s_register_operand" "")))
833 (clobber (reg:CC CC_REGNUM))])]
838 if (GET_CODE (operands[1]) != REG)
839 operands[1] = force_reg (SImode, operands[1]);
840 if (GET_CODE (operands[2]) != REG)
841 operands[2] = force_reg (SImode, operands[2]);
846 (define_insn "*arm_subdi3"
847 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
848 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
849 (match_operand:DI 2 "s_register_operand" "r,0,0")))
850 (clobber (reg:CC CC_REGNUM))]
852 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
853 [(set_attr "conds" "clob")
854 (set_attr "length" "8")]
857 (define_insn "*thumb_subdi3"
858 [(set (match_operand:DI 0 "register_operand" "=l")
859 (minus:DI (match_operand:DI 1 "register_operand" "0")
860 (match_operand:DI 2 "register_operand" "l")))
861 (clobber (reg:CC CC_REGNUM))]
863 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
864 [(set_attr "length" "4")]
867 (define_insn "*subdi_di_zesidi"
868 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
869 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
871 (match_operand:SI 2 "s_register_operand" "r,r"))))
872 (clobber (reg:CC CC_REGNUM))]
874 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
875 [(set_attr "conds" "clob")
876 (set_attr "length" "8")]
879 (define_insn "*subdi_di_sesidi"
880 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
881 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
883 (match_operand:SI 2 "s_register_operand" "r,r"))))
884 (clobber (reg:CC CC_REGNUM))]
886 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
887 [(set_attr "conds" "clob")
888 (set_attr "length" "8")]
891 (define_insn "*subdi_zesidi_di"
892 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
893 (minus:DI (zero_extend:DI
894 (match_operand:SI 2 "s_register_operand" "r,r"))
895 (match_operand:DI 1 "s_register_operand" "?r,0")))
896 (clobber (reg:CC CC_REGNUM))]
898 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
899 [(set_attr "conds" "clob")
900 (set_attr "length" "8")]
903 (define_insn "*subdi_sesidi_di"
904 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
905 (minus:DI (sign_extend:DI
906 (match_operand:SI 2 "s_register_operand" "r,r"))
907 (match_operand:DI 1 "s_register_operand" "?r,0")))
908 (clobber (reg:CC CC_REGNUM))]
910 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
911 [(set_attr "conds" "clob")
912 (set_attr "length" "8")]
915 (define_insn "*subdi_zesidi_zesidi"
916 [(set (match_operand:DI 0 "s_register_operand" "=r")
917 (minus:DI (zero_extend:DI
918 (match_operand:SI 1 "s_register_operand" "r"))
920 (match_operand:SI 2 "s_register_operand" "r"))))
921 (clobber (reg:CC CC_REGNUM))]
923 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
924 [(set_attr "conds" "clob")
925 (set_attr "length" "8")]
928 (define_expand "subsi3"
929 [(set (match_operand:SI 0 "s_register_operand" "")
930 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
931 (match_operand:SI 2 "s_register_operand" "")))]
934 if (GET_CODE (operands[1]) == CONST_INT)
938 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
941 : preserve_subexpressions_p ()));
944 else /* TARGET_THUMB */
945 operands[1] = force_reg (SImode, operands[1]);
950 (define_insn "*thumb_subsi3_insn"
951 [(set (match_operand:SI 0 "register_operand" "=l")
952 (minus:SI (match_operand:SI 1 "register_operand" "l")
953 (match_operand:SI 2 "register_operand" "l")))]
956 [(set_attr "length" "2")]
959 (define_insn_and_split "*arm_subsi3_insn"
960 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
961 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
962 (match_operand:SI 2 "s_register_operand" "r,r")))]
968 && GET_CODE (operands[1]) == CONST_INT
969 && !const_ok_for_arm (INTVAL (operands[1]))"
970 [(clobber (const_int 0))]
972 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
976 [(set_attr "length" "4,16")
977 (set_attr "predicable" "yes")]
981 [(match_scratch:SI 3 "r")
982 (set (match_operand:SI 0 "s_register_operand" "")
983 (minus:SI (match_operand:SI 1 "const_int_operand" "")
984 (match_operand:SI 2 "s_register_operand" "")))]
986 && !const_ok_for_arm (INTVAL (operands[1]))
987 && const_ok_for_arm (~INTVAL (operands[1]))"
988 [(set (match_dup 3) (match_dup 1))
989 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
993 (define_insn "*subsi3_compare0"
994 [(set (reg:CC_NOOV CC_REGNUM)
996 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
997 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
999 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1000 (minus:SI (match_dup 1) (match_dup 2)))]
1004 rsb%?s\\t%0, %2, %1"
1005 [(set_attr "conds" "set")]
1008 (define_insn "decscc"
1009 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1010 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1011 (match_operator:SI 2 "arm_comparison_operator"
1012 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1016 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1017 [(set_attr "conds" "use")
1018 (set_attr "length" "*,8")]
1021 (define_insn "subsf3"
1022 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1023 (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1024 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1025 "TARGET_ARM && TARGET_HARD_FLOAT"
1028 rsf%?s\\t%0, %2, %1"
1029 [(set_attr "type" "farith")]
1032 (define_insn "subdf3"
1033 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1034 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1035 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1036 "TARGET_ARM && TARGET_HARD_FLOAT"
1039 rsf%?d\\t%0, %2, %1"
1040 [(set_attr "type" "farith")
1041 (set_attr "predicable" "yes")]
1044 (define_insn "*subdf_esfdf_df"
1045 [(set (match_operand:DF 0 "s_register_operand" "=f")
1046 (minus:DF (float_extend:DF
1047 (match_operand:SF 1 "s_register_operand" "f"))
1048 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1049 "TARGET_ARM && TARGET_HARD_FLOAT"
1050 "suf%?d\\t%0, %1, %2"
1051 [(set_attr "type" "farith")
1052 (set_attr "predicable" "yes")]
1055 (define_insn "*subdf_df_esfdf"
1056 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1057 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1059 (match_operand:SF 2 "s_register_operand" "f,f"))))]
1060 "TARGET_ARM && TARGET_HARD_FLOAT"
1063 rsf%?d\\t%0, %2, %1"
1064 [(set_attr "type" "farith")
1065 (set_attr "predicable" "yes")]
1068 (define_insn "*subdf_esfdf_esfdf"
1069 [(set (match_operand:DF 0 "s_register_operand" "=f")
1070 (minus:DF (float_extend:DF
1071 (match_operand:SF 1 "s_register_operand" "f"))
1073 (match_operand:SF 2 "s_register_operand" "f"))))]
1074 "TARGET_ARM && TARGET_HARD_FLOAT"
1075 "suf%?d\\t%0, %1, %2"
1076 [(set_attr "type" "farith")
1077 (set_attr "predicable" "yes")]
1080 (define_insn "subxf3"
1081 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1082 (minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1083 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1084 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1087 rsf%?e\\t%0, %2, %1"
1088 [(set_attr "type" "farith")
1089 (set_attr "predicable" "yes")]
1092 ;; Multiplication insns
1094 (define_expand "mulsi3"
1095 [(set (match_operand:SI 0 "s_register_operand" "")
1096 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1097 (match_operand:SI 1 "s_register_operand" "")))]
1102 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1103 (define_insn "*arm_mulsi3"
1104 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1105 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1106 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1108 "mul%?\\t%0, %2, %1"
1109 [(set_attr "type" "mult")
1110 (set_attr "predicable" "yes")]
1113 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1114 ; 1 and 2; are the same, because reload will make operand 0 match
1115 ; operand 1 without realizing that this conflicts with operand 2. We fix
1116 ; this by adding another alternative to match this case, and then `reload'
1117 ; it ourselves. This alternative must come first.
1118 (define_insn "*thumb_mulsi3"
1119 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1120 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1121 (match_operand:SI 2 "register_operand" "l,l,l")))]
1124 if (which_alternative < 2)
1125 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1127 return \"mul\\t%0, %0, %2\";
1129 [(set_attr "length" "4,4,2")
1130 (set_attr "type" "mult")]
1133 (define_insn "*mulsi3_compare0"
1134 [(set (reg:CC_NOOV CC_REGNUM)
1135 (compare:CC_NOOV (mult:SI
1136 (match_operand:SI 2 "s_register_operand" "r,r")
1137 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1139 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1140 (mult:SI (match_dup 2) (match_dup 1)))]
1141 "TARGET_ARM && !arm_is_xscale"
1142 "mul%?s\\t%0, %2, %1"
1143 [(set_attr "conds" "set")
1144 (set_attr "type" "mult")]
1147 (define_insn "*mulsi_compare0_scratch"
1148 [(set (reg:CC_NOOV CC_REGNUM)
1149 (compare:CC_NOOV (mult:SI
1150 (match_operand:SI 2 "s_register_operand" "r,r")
1151 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1153 (clobber (match_scratch:SI 0 "=&r,&r"))]
1154 "TARGET_ARM && !arm_is_xscale"
1155 "mul%?s\\t%0, %2, %1"
1156 [(set_attr "conds" "set")
1157 (set_attr "type" "mult")]
1160 ;; Unnamed templates to match MLA instruction.
1162 (define_insn "*mulsi3addsi"
1163 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1165 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1166 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1167 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1169 "mla%?\\t%0, %2, %1, %3"
1170 [(set_attr "type" "mult")
1171 (set_attr "predicable" "yes")]
1174 (define_insn "*mulsi3addsi_compare0"
1175 [(set (reg:CC_NOOV CC_REGNUM)
1178 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1179 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1180 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1182 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1183 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1185 "TARGET_ARM && !arm_is_xscale"
1186 "mla%?s\\t%0, %2, %1, %3"
1187 [(set_attr "conds" "set")
1188 (set_attr "type" "mult")]
1191 (define_insn "*mulsi3addsi_compare0_scratch"
1192 [(set (reg:CC_NOOV CC_REGNUM)
1195 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1196 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1197 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1199 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1200 "TARGET_ARM && !arm_is_xscale"
1201 "mla%?s\\t%0, %2, %1, %3"
1202 [(set_attr "conds" "set")
1203 (set_attr "type" "mult")]
1206 ;; Unnamed template to match long long multiply-accumlate (smlal)
1208 (define_insn "*mulsidi3adddi"
1209 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1212 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1213 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1214 (match_operand:DI 1 "s_register_operand" "0")))]
1215 "TARGET_ARM && arm_fast_multiply"
1216 "smlal%?\\t%Q0, %R0, %3, %2"
1217 [(set_attr "type" "mult")
1218 (set_attr "predicable" "yes")]
1221 (define_insn "mulsidi3"
1222 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1224 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1225 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1226 "TARGET_ARM && arm_fast_multiply"
1227 "smull%?\\t%Q0, %R0, %1, %2"
1228 [(set_attr "type" "mult")
1229 (set_attr "predicable" "yes")]
1232 (define_insn "umulsidi3"
1233 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1235 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1236 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1237 "TARGET_ARM && arm_fast_multiply"
1238 "umull%?\\t%Q0, %R0, %1, %2"
1239 [(set_attr "type" "mult")
1240 (set_attr "predicable" "yes")]
1243 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1245 (define_insn "*umulsidi3adddi"
1246 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1249 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1250 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1251 (match_operand:DI 1 "s_register_operand" "0")))]
1252 "TARGET_ARM && arm_fast_multiply"
1253 "umlal%?\\t%Q0, %R0, %3, %2"
1254 [(set_attr "type" "mult")
1255 (set_attr "predicable" "yes")]
1258 (define_insn "smulsi3_highpart"
1259 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1263 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1264 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1266 (clobber (match_scratch:SI 3 "=&r,&r"))]
1267 "TARGET_ARM && arm_fast_multiply"
1268 "smull%?\\t%3, %0, %2, %1"
1269 [(set_attr "type" "mult")
1270 (set_attr "predicable" "yes")]
1273 (define_insn "umulsi3_highpart"
1274 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1278 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1279 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1281 (clobber (match_scratch:SI 3 "=&r,&r"))]
1282 "TARGET_ARM && arm_fast_multiply"
1283 "umull%?\\t%3, %0, %2, %1"
1284 [(set_attr "type" "mult")
1285 (set_attr "predicable" "yes")]
1288 (define_insn "mulhisi3"
1289 [(set (match_operand:SI 0 "s_register_operand" "=r")
1290 (mult:SI (sign_extend:SI
1291 (match_operand:HI 1 "s_register_operand" "%r"))
1293 (match_operand:HI 2 "s_register_operand" "r"))))]
1294 "TARGET_ARM && arm_is_xscale"
1295 "smulbb%?\\t%0,%1,%2"
1296 [(set_attr "type" "mult")]
1299 (define_insn "*mulhisi3addsi"
1300 [(set (match_operand:SI 0 "s_register_operand" "=r")
1301 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1302 (mult:SI (sign_extend:SI
1303 (match_operand:HI 2 "s_register_operand" "%r"))
1305 (match_operand:HI 3 "s_register_operand" "r")))))]
1306 "TARGET_ARM && arm_is_xscale"
1307 "smlabb%?\\t%0,%2,%3,%1"
1308 [(set_attr "type" "mult")]
1311 (define_insn "*mulhidi3adddi"
1312 [(set (match_operand:DI 0 "s_register_operand" "=r")
1314 (match_operand:DI 1 "s_register_operand" "0")
1315 (mult:DI (sign_extend:DI
1316 (match_operand:HI 2 "s_register_operand" "%r"))
1318 (match_operand:HI 3 "s_register_operand" "r")))))]
1319 "TARGET_ARM && arm_is_xscale"
1320 "smlalbb%?\\t%Q0, %R0, %2, %3"
1321 [(set_attr "type" "mult")])
1323 (define_insn "mulsf3"
1324 [(set (match_operand:SF 0 "s_register_operand" "=f")
1325 (mult:SF (match_operand:SF 1 "s_register_operand" "f")
1326 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1327 "TARGET_ARM && TARGET_HARD_FLOAT"
1328 "fml%?s\\t%0, %1, %2"
1329 [(set_attr "type" "ffmul")
1330 (set_attr "predicable" "yes")]
1333 (define_insn "muldf3"
1334 [(set (match_operand:DF 0 "s_register_operand" "=f")
1335 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1336 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1337 "TARGET_ARM && TARGET_HARD_FLOAT"
1338 "muf%?d\\t%0, %1, %2"
1339 [(set_attr "type" "fmul")
1340 (set_attr "predicable" "yes")]
1343 (define_insn "*muldf_esfdf_df"
1344 [(set (match_operand:DF 0 "s_register_operand" "=f")
1345 (mult:DF (float_extend:DF
1346 (match_operand:SF 1 "s_register_operand" "f"))
1347 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1348 "TARGET_ARM && TARGET_HARD_FLOAT"
1349 "muf%?d\\t%0, %1, %2"
1350 [(set_attr "type" "fmul")
1351 (set_attr "predicable" "yes")]
1354 (define_insn "*muldf_df_esfdf"
1355 [(set (match_operand:DF 0 "s_register_operand" "=f")
1356 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1358 (match_operand:SF 2 "s_register_operand" "f"))))]
1359 "TARGET_ARM && TARGET_HARD_FLOAT"
1360 "muf%?d\\t%0, %1, %2"
1361 [(set_attr "type" "fmul")
1362 (set_attr "predicable" "yes")]
1365 (define_insn "*muldf_esfdf_esfdf"
1366 [(set (match_operand:DF 0 "s_register_operand" "=f")
1368 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f"))
1369 (float_extend:DF (match_operand:SF 2 "s_register_operand" "f"))))]
1370 "TARGET_ARM && TARGET_HARD_FLOAT"
1371 "muf%?d\\t%0, %1, %2"
1372 [(set_attr "type" "fmul")
1373 (set_attr "predicable" "yes")]
1376 (define_insn "mulxf3"
1377 [(set (match_operand:XF 0 "s_register_operand" "=f")
1378 (mult:XF (match_operand:XF 1 "s_register_operand" "f")
1379 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1380 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1381 "muf%?e\\t%0, %1, %2"
1382 [(set_attr "type" "fmul")
1383 (set_attr "predicable" "yes")]
1388 (define_insn "divsf3"
1389 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1390 (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1391 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1392 "TARGET_ARM && TARGET_HARD_FLOAT"
1395 frd%?s\\t%0, %2, %1"
1396 [(set_attr "type" "fdivs")
1397 (set_attr "predicable" "yes")]
1400 (define_insn "divdf3"
1401 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1402 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1403 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1404 "TARGET_ARM && TARGET_HARD_FLOAT"
1407 rdf%?d\\t%0, %2, %1"
1408 [(set_attr "type" "fdivd")
1409 (set_attr "predicable" "yes")]
1412 (define_insn "*divdf_esfdf_df"
1413 [(set (match_operand:DF 0 "s_register_operand" "=f")
1414 (div:DF (float_extend:DF
1415 (match_operand:SF 1 "s_register_operand" "f"))
1416 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1417 "TARGET_ARM && TARGET_HARD_FLOAT"
1418 "dvf%?d\\t%0, %1, %2"
1419 [(set_attr "type" "fdivd")
1420 (set_attr "predicable" "yes")]
1423 (define_insn "*divdf_df_esfdf"
1424 [(set (match_operand:DF 0 "s_register_operand" "=f")
1425 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1427 (match_operand:SF 2 "s_register_operand" "f"))))]
1428 "TARGET_ARM && TARGET_HARD_FLOAT"
1429 "rdf%?d\\t%0, %2, %1"
1430 [(set_attr "type" "fdivd")
1431 (set_attr "predicable" "yes")]
1434 (define_insn "*divdf_esfdf_esfdf"
1435 [(set (match_operand:DF 0 "s_register_operand" "=f")
1436 (div:DF (float_extend:DF
1437 (match_operand:SF 1 "s_register_operand" "f"))
1439 (match_operand:SF 2 "s_register_operand" "f"))))]
1440 "TARGET_ARM && TARGET_HARD_FLOAT"
1441 "dvf%?d\\t%0, %1, %2"
1442 [(set_attr "type" "fdivd")
1443 (set_attr "predicable" "yes")]
1446 (define_insn "divxf3"
1447 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1448 (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1449 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1450 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1453 rdf%?e\\t%0, %2, %1"
1454 [(set_attr "type" "fdivx")
1455 (set_attr "predicable" "yes")]
1460 (define_insn "modsf3"
1461 [(set (match_operand:SF 0 "s_register_operand" "=f")
1462 (mod:SF (match_operand:SF 1 "s_register_operand" "f")
1463 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1464 "TARGET_ARM && TARGET_HARD_FLOAT"
1465 "rmf%?s\\t%0, %1, %2"
1466 [(set_attr "type" "fdivs")
1467 (set_attr "predicable" "yes")]
1470 (define_insn "moddf3"
1471 [(set (match_operand:DF 0 "s_register_operand" "=f")
1472 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1473 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1474 "TARGET_ARM && TARGET_HARD_FLOAT"
1475 "rmf%?d\\t%0, %1, %2"
1476 [(set_attr "type" "fdivd")
1477 (set_attr "predicable" "yes")]
1480 (define_insn "*moddf_esfdf_df"
1481 [(set (match_operand:DF 0 "s_register_operand" "=f")
1482 (mod:DF (float_extend:DF
1483 (match_operand:SF 1 "s_register_operand" "f"))
1484 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1485 "TARGET_ARM && TARGET_HARD_FLOAT"
1486 "rmf%?d\\t%0, %1, %2"
1487 [(set_attr "type" "fdivd")
1488 (set_attr "predicable" "yes")]
1491 (define_insn "*moddf_df_esfdf"
1492 [(set (match_operand:DF 0 "s_register_operand" "=f")
1493 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1495 (match_operand:SF 2 "s_register_operand" "f"))))]
1496 "TARGET_ARM && TARGET_HARD_FLOAT"
1497 "rmf%?d\\t%0, %1, %2"
1498 [(set_attr "type" "fdivd")
1499 (set_attr "predicable" "yes")]
1502 (define_insn "*moddf_esfdf_esfdf"
1503 [(set (match_operand:DF 0 "s_register_operand" "=f")
1504 (mod:DF (float_extend:DF
1505 (match_operand:SF 1 "s_register_operand" "f"))
1507 (match_operand:SF 2 "s_register_operand" "f"))))]
1508 "TARGET_ARM && TARGET_HARD_FLOAT"
1509 "rmf%?d\\t%0, %1, %2"
1510 [(set_attr "type" "fdivd")
1511 (set_attr "predicable" "yes")]
1514 (define_insn "modxf3"
1515 [(set (match_operand:XF 0 "s_register_operand" "=f")
1516 (mod:XF (match_operand:XF 1 "s_register_operand" "f")
1517 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1518 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1519 "rmf%?e\\t%0, %1, %2"
1520 [(set_attr "type" "fdivx")
1521 (set_attr "predicable" "yes")]
1524 ;; Boolean and,ior,xor insns
1526 ;; Split up double word logical operations
1528 ;; Split up simple DImode logical operations. Simply perform the logical
1529 ;; operation on the upper and lower halves of the registers.
1531 [(set (match_operand:DI 0 "s_register_operand" "")
1532 (match_operator:DI 6 "logical_binary_operator"
1533 [(match_operand:DI 1 "s_register_operand" "")
1534 (match_operand:DI 2 "s_register_operand" "")]))]
1535 "TARGET_ARM && reload_completed"
1536 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1537 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1540 operands[3] = gen_highpart (SImode, operands[0]);
1541 operands[0] = gen_lowpart (SImode, operands[0]);
1542 operands[4] = gen_highpart (SImode, operands[1]);
1543 operands[1] = gen_lowpart (SImode, operands[1]);
1544 operands[5] = gen_highpart (SImode, operands[2]);
1545 operands[2] = gen_lowpart (SImode, operands[2]);
1550 [(set (match_operand:DI 0 "s_register_operand" "")
1551 (match_operator:DI 6 "logical_binary_operator"
1552 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1553 (match_operand:DI 1 "s_register_operand" "")]))]
1554 "TARGET_ARM && reload_completed"
1555 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1556 (set (match_dup 3) (match_op_dup:SI 6
1557 [(ashiftrt:SI (match_dup 2) (const_int 31))
1561 operands[3] = gen_highpart (SImode, operands[0]);
1562 operands[0] = gen_lowpart (SImode, operands[0]);
1563 operands[4] = gen_highpart (SImode, operands[1]);
1564 operands[1] = gen_lowpart (SImode, operands[1]);
1565 operands[5] = gen_highpart (SImode, operands[2]);
1566 operands[2] = gen_lowpart (SImode, operands[2]);
1570 ;; The zero extend of operand 2 means we can just copy the high part of
1571 ;; operand1 into operand0.
1573 [(set (match_operand:DI 0 "s_register_operand" "")
1575 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1576 (match_operand:DI 1 "s_register_operand" "")))]
1577 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1578 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1579 (set (match_dup 3) (match_dup 4))]
1582 operands[4] = gen_highpart (SImode, operands[1]);
1583 operands[3] = gen_highpart (SImode, operands[0]);
1584 operands[0] = gen_lowpart (SImode, operands[0]);
1585 operands[1] = gen_lowpart (SImode, operands[1]);
1589 ;; The zero extend of operand 2 means we can just copy the high part of
1590 ;; operand1 into operand0.
1592 [(set (match_operand:DI 0 "s_register_operand" "")
1594 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1595 (match_operand:DI 1 "s_register_operand" "")))]
1596 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1597 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1598 (set (match_dup 3) (match_dup 4))]
1601 operands[4] = gen_highpart (SImode, operands[1]);
1602 operands[3] = gen_highpart (SImode, operands[0]);
1603 operands[0] = gen_lowpart (SImode, operands[0]);
1604 operands[1] = gen_lowpart (SImode, operands[1]);
1608 (define_insn "anddi3"
1609 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1610 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1611 (match_operand:DI 2 "s_register_operand" "r,r")))]
1614 [(set_attr "length" "8")]
1617 (define_insn_and_split "*anddi_zesidi_di"
1618 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1619 (and:DI (zero_extend:DI
1620 (match_operand:SI 2 "s_register_operand" "r,r"))
1621 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1624 "TARGET_ARM && reload_completed"
1625 ; The zero extend of operand 2 clears the high word of the output
1627 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1628 (set (match_dup 3) (const_int 0))]
1631 operands[3] = gen_highpart (SImode, operands[0]);
1632 operands[0] = gen_lowpart (SImode, operands[0]);
1633 operands[1] = gen_lowpart (SImode, operands[1]);
1635 [(set_attr "length" "8")]
1638 (define_insn "*anddi_sesdi_di"
1639 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1640 (and:DI (sign_extend:DI
1641 (match_operand:SI 2 "s_register_operand" "r,r"))
1642 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1645 [(set_attr "length" "8")]
1648 (define_expand "andsi3"
1649 [(set (match_operand:SI 0 "s_register_operand" "")
1650 (and:SI (match_operand:SI 1 "s_register_operand" "")
1651 (match_operand:SI 2 "reg_or_int_operand" "")))]
1656 if (GET_CODE (operands[2]) == CONST_INT)
1658 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1661 ? 0 : preserve_subexpressions_p ()));
1665 else /* TARGET_THUMB */
1667 if (GET_CODE (operands[2]) != CONST_INT)
1668 operands[2] = force_reg (SImode, operands[2]);
1673 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1675 operands[2] = force_reg (SImode,
1676 GEN_INT (~INTVAL (operands[2])));
1678 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1683 for (i = 9; i <= 31; i++)
1685 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1687 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1691 else if ((((HOST_WIDE_INT) 1) << i) - 1
1692 == ~INTVAL (operands[2]))
1694 rtx shift = GEN_INT (i);
1695 rtx reg = gen_reg_rtx (SImode);
1697 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1698 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1704 operands[2] = force_reg (SImode, operands[2]);
1710 (define_insn_and_split "*arm_andsi3_insn"
1711 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1712 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1713 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1717 bic%?\\t%0, %1, #%B2
1720 && GET_CODE (operands[2]) == CONST_INT
1721 && !(const_ok_for_arm (INTVAL (operands[2]))
1722 || const_ok_for_arm (~INTVAL (operands[2])))"
1723 [(clobber (const_int 0))]
1725 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1729 [(set_attr "length" "4,4,16")
1730 (set_attr "predicable" "yes")]
1733 (define_insn "*thumb_andsi3_insn"
1734 [(set (match_operand:SI 0 "register_operand" "=l")
1735 (and:SI (match_operand:SI 1 "register_operand" "%0")
1736 (match_operand:SI 2 "register_operand" "l")))]
1739 [(set_attr "length" "2")]
1742 (define_insn "*andsi3_compare0"
1743 [(set (reg:CC_NOOV CC_REGNUM)
1745 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1746 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1748 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1749 (and:SI (match_dup 1) (match_dup 2)))]
1753 bic%?s\\t%0, %1, #%B2"
1754 [(set_attr "conds" "set")]
1757 (define_insn "*andsi3_compare0_scratch"
1758 [(set (reg:CC_NOOV CC_REGNUM)
1760 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1761 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1763 (clobber (match_scratch:SI 2 "=X,r"))]
1767 bic%?s\\t%2, %0, #%B1"
1768 [(set_attr "conds" "set")]
1771 (define_insn "*zeroextractsi_compare0_scratch"
1772 [(set (reg:CC_NOOV CC_REGNUM)
1773 (compare:CC_NOOV (zero_extract:SI
1774 (match_operand:SI 0 "s_register_operand" "r")
1775 (match_operand 1 "const_int_operand" "n")
1776 (match_operand 2 "const_int_operand" "n"))
1779 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1780 && INTVAL (operands[1]) > 0
1781 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1782 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1784 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1785 << INTVAL (operands[2]));
1786 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1789 [(set_attr "conds" "set")]
1792 (define_insn "*ne_zeroextractsi"
1793 [(set (match_operand:SI 0 "s_register_operand" "=r")
1794 (ne:SI (zero_extract:SI
1795 (match_operand:SI 1 "s_register_operand" "r")
1796 (match_operand:SI 2 "const_int_operand" "n")
1797 (match_operand:SI 3 "const_int_operand" "n"))
1800 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1801 && INTVAL (operands[2]) > 0
1802 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1803 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1805 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1806 << INTVAL (operands[3]));
1807 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1808 return \"movne\\t%0, #1\";
1810 [(set_attr "conds" "clob")
1811 (set_attr "length" "8")]
1814 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1815 ;;; represented by the bitfield, then this will produce incorrect results.
1816 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1817 ;;; which have a real bitfield insert instruction, the truncation happens
1818 ;;; in the bitfield insert instruction itself. Since arm does not have a
1819 ;;; bitfield insert instruction, we would have to emit code here to truncate
1820 ;;; the value before we insert. This loses some of the advantage of having
1821 ;;; this insv pattern, so this pattern needs to be reevalutated.
1823 (define_expand "insv"
1824 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1825 (match_operand:SI 1 "general_operand" "")
1826 (match_operand:SI 2 "general_operand" ""))
1827 (match_operand:SI 3 "nonmemory_operand" ""))]
1831 int start_bit = INTVAL (operands[2]);
1832 int width = INTVAL (operands[1]);
1833 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1834 rtx target, subtarget;
1836 target = operands[0];
1837 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1838 subreg as the final target. */
1839 if (GET_CODE (target) == SUBREG)
1841 subtarget = gen_reg_rtx (SImode);
1842 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1843 < GET_MODE_SIZE (SImode))
1844 target = SUBREG_REG (target);
1849 if (GET_CODE (operands[3]) == CONST_INT)
1851 /* Since we are inserting a known constant, we may be able to
1852 reduce the number of bits that we have to clear so that
1853 the mask becomes simple. */
1854 /* ??? This code does not check to see if the new mask is actually
1855 simpler. It may not be. */
1856 rtx op1 = gen_reg_rtx (SImode);
1857 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1858 start of this pattern. */
1859 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1860 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1862 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1863 emit_insn (gen_iorsi3 (subtarget, op1,
1864 GEN_INT (op3_value << start_bit)));
1866 else if (start_bit == 0
1867 && !(const_ok_for_arm (mask)
1868 || const_ok_for_arm (~mask)))
1870 /* A Trick, since we are setting the bottom bits in the word,
1871 we can shift operand[3] up, operand[0] down, OR them together
1872 and rotate the result back again. This takes 3 insns, and
1873 the third might be mergable into another op. */
1874 /* The shift up copes with the possibility that operand[3] is
1875 wider than the bitfield. */
1876 rtx op0 = gen_reg_rtx (SImode);
1877 rtx op1 = gen_reg_rtx (SImode);
1879 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1880 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1881 emit_insn (gen_iorsi3 (op1, op1, op0));
1882 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1884 else if ((width + start_bit == 32)
1885 && !(const_ok_for_arm (mask)
1886 || const_ok_for_arm (~mask)))
1888 /* Similar trick, but slightly less efficient. */
1890 rtx op0 = gen_reg_rtx (SImode);
1891 rtx op1 = gen_reg_rtx (SImode);
1893 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1894 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1895 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1896 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1900 rtx op0 = GEN_INT (mask);
1901 rtx op1 = gen_reg_rtx (SImode);
1902 rtx op2 = gen_reg_rtx (SImode);
1904 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1906 rtx tmp = gen_reg_rtx (SImode);
1908 emit_insn (gen_movsi (tmp, op0));
1912 /* Mask out any bits in operand[3] that are not needed. */
1913 emit_insn (gen_andsi3 (op1, operands[3], op0));
1915 if (GET_CODE (op0) == CONST_INT
1916 && (const_ok_for_arm (mask << start_bit)
1917 || const_ok_for_arm (~(mask << start_bit))))
1919 op0 = GEN_INT (~(mask << start_bit));
1920 emit_insn (gen_andsi3 (op2, operands[0], op0));
1924 if (GET_CODE (op0) == CONST_INT)
1926 rtx tmp = gen_reg_rtx (SImode);
1928 emit_insn (gen_movsi (tmp, op0));
1933 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1935 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1939 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1941 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1944 if (subtarget != target)
1946 /* If TARGET is still a SUBREG, then it must be wider than a word,
1947 so we must be careful only to set the subword we were asked to. */
1948 if (GET_CODE (target) == SUBREG)
1949 emit_move_insn (target, subtarget);
1951 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1958 ; constants for op 2 will never be given to these patterns.
1959 (define_insn_and_split "*anddi_notdi_di"
1960 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1961 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1962 (match_operand:DI 2 "s_register_operand" "0,r")))]
1965 "TARGET_ARM && reload_completed"
1966 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1967 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1970 operands[3] = gen_highpart (SImode, operands[0]);
1971 operands[0] = gen_lowpart (SImode, operands[0]);
1972 operands[4] = gen_highpart (SImode, operands[1]);
1973 operands[1] = gen_lowpart (SImode, operands[1]);
1974 operands[5] = gen_highpart (SImode, operands[2]);
1975 operands[2] = gen_lowpart (SImode, operands[2]);
1977 [(set_attr "length" "8")
1978 (set_attr "predicable" "yes")]
1981 (define_insn_and_split "*anddi_notzesidi_di"
1982 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1983 (and:DI (not:DI (zero_extend:DI
1984 (match_operand:SI 2 "s_register_operand" "r,r")))
1985 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1988 bic%?\\t%Q0, %Q1, %2
1990 ; (not (zero_extend ...)) allows us to just copy the high word from
1991 ; operand1 to operand0.
1994 && operands[0] != operands[1]"
1995 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1996 (set (match_dup 3) (match_dup 4))]
1999 operands[3] = gen_highpart (SImode, operands[0]);
2000 operands[0] = gen_lowpart (SImode, operands[0]);
2001 operands[4] = gen_highpart (SImode, operands[1]);
2002 operands[1] = gen_lowpart (SImode, operands[1]);
2004 [(set_attr "length" "4,8")
2005 (set_attr "predicable" "yes")]
2008 (define_insn_and_split "*anddi_notsesidi_di"
2009 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2010 (and:DI (not:DI (sign_extend:DI
2011 (match_operand:SI 2 "s_register_operand" "r,r")))
2012 (match_operand:DI 1 "s_register_operand" "?r,0")))]
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
2018 (ashiftrt:SI (match_dup 2) (const_int 31)))
2022 operands[3] = gen_highpart (SImode, operands[0]);
2023 operands[0] = gen_lowpart (SImode, operands[0]);
2024 operands[4] = gen_highpart (SImode, operands[1]);
2025 operands[1] = gen_lowpart (SImode, operands[1]);
2027 [(set_attr "length" "8")
2028 (set_attr "predicable" "yes")]
2031 (define_insn "andsi_notsi_si"
2032 [(set (match_operand:SI 0 "s_register_operand" "=r")
2033 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2034 (match_operand:SI 1 "s_register_operand" "r")))]
2036 "bic%?\\t%0, %1, %2"
2037 [(set_attr "predicable" "yes")]
2040 (define_insn "bicsi3"
2041 [(set (match_operand:SI 0 "register_operand" "=l")
2042 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2043 (match_operand:SI 2 "register_operand" "0")))]
2046 [(set_attr "length" "2")]
2049 (define_insn "andsi_not_shiftsi_si"
2050 [(set (match_operand:SI 0 "s_register_operand" "=r")
2051 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2052 [(match_operand:SI 2 "s_register_operand" "r")
2053 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2054 (match_operand:SI 1 "s_register_operand" "r")))]
2056 "bic%?\\t%0, %1, %2%S4"
2057 [(set_attr "predicable" "yes")
2058 (set_attr "shift" "2")
2062 (define_insn "*andsi_notsi_si_compare0"
2063 [(set (reg:CC_NOOV CC_REGNUM)
2065 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2066 (match_operand:SI 1 "s_register_operand" "r"))
2068 (set (match_operand:SI 0 "s_register_operand" "=r")
2069 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2071 "bic%?s\\t%0, %1, %2"
2072 [(set_attr "conds" "set")]
2075 (define_insn "*andsi_notsi_si_compare0_scratch"
2076 [(set (reg:CC_NOOV CC_REGNUM)
2078 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2079 (match_operand:SI 1 "s_register_operand" "r"))
2081 (clobber (match_scratch:SI 0 "=r"))]
2083 "bic%?s\\t%0, %1, %2"
2084 [(set_attr "conds" "set")]
2087 (define_insn "iordi3"
2088 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2089 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2090 (match_operand:DI 2 "s_register_operand" "r,r")))]
2093 [(set_attr "length" "8")
2094 (set_attr "predicable" "yes")]
2097 (define_insn "*iordi_zesidi_di"
2098 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2099 (ior:DI (zero_extend:DI
2100 (match_operand:SI 2 "s_register_operand" "r,r"))
2101 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2104 orr%?\\t%Q0, %Q1, %2
2106 [(set_attr "length" "4,8")
2107 (set_attr "predicable" "yes")]
2110 (define_insn "*iordi_sesidi_di"
2111 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2112 (ior:DI (sign_extend:DI
2113 (match_operand:SI 2 "s_register_operand" "r,r"))
2114 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2117 [(set_attr "length" "8")
2118 (set_attr "predicable" "yes")]
2121 (define_expand "iorsi3"
2122 [(set (match_operand:SI 0 "s_register_operand" "")
2123 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2124 (match_operand:SI 2 "reg_or_int_operand" "")))]
2127 if (GET_CODE (operands[2]) == CONST_INT)
2131 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2134 ? 0 : preserve_subexpressions_p ()));
2137 else /* TARGET_THUMB */
2138 operands [2] = force_reg (SImode, operands [2]);
2143 (define_insn_and_split "*arm_iorsi3"
2144 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2145 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2146 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2152 && GET_CODE (operands[2]) == CONST_INT
2153 && !const_ok_for_arm (INTVAL (operands[2]))"
2154 [(clobber (const_int 0))]
2156 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2160 [(set_attr "length" "4,16")
2161 (set_attr "predicable" "yes")]
2164 (define_insn "*thumb_iorsi3"
2165 [(set (match_operand:SI 0 "register_operand" "=l")
2166 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2167 (match_operand:SI 2 "register_operand" "l")))]
2170 [(set_attr "length" "2")]
2174 [(match_scratch:SI 3 "r")
2175 (set (match_operand:SI 0 "s_register_operand" "")
2176 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2177 (match_operand:SI 2 "const_int_operand" "")))]
2179 && !const_ok_for_arm (INTVAL (operands[2]))
2180 && const_ok_for_arm (~INTVAL (operands[2]))"
2181 [(set (match_dup 3) (match_dup 2))
2182 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2186 (define_insn "*iorsi3_compare0"
2187 [(set (reg:CC_NOOV CC_REGNUM)
2188 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2189 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2191 (set (match_operand:SI 0 "s_register_operand" "=r")
2192 (ior:SI (match_dup 1) (match_dup 2)))]
2194 "orr%?s\\t%0, %1, %2"
2195 [(set_attr "conds" "set")]
2198 (define_insn "*iorsi3_compare0_scratch"
2199 [(set (reg:CC_NOOV CC_REGNUM)
2200 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2201 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2203 (clobber (match_scratch:SI 0 "=r"))]
2205 "orr%?s\\t%0, %1, %2"
2206 [(set_attr "conds" "set")]
2209 (define_insn "xordi3"
2210 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2211 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2212 (match_operand:DI 2 "s_register_operand" "r,r")))]
2215 [(set_attr "length" "8")
2216 (set_attr "predicable" "yes")]
2219 (define_insn "*xordi_zesidi_di"
2220 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2221 (xor:DI (zero_extend:DI
2222 (match_operand:SI 2 "s_register_operand" "r,r"))
2223 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2226 eor%?\\t%Q0, %Q1, %2
2228 [(set_attr "length" "4,8")
2229 (set_attr "predicable" "yes")]
2232 (define_insn "*xordi_sesidi_di"
2233 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2234 (xor:DI (sign_extend:DI
2235 (match_operand:SI 2 "s_register_operand" "r,r"))
2236 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2239 [(set_attr "length" "8")
2240 (set_attr "predicable" "yes")]
2243 (define_expand "xorsi3"
2244 [(set (match_operand:SI 0 "s_register_operand" "")
2245 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2246 (match_operand:SI 2 "arm_rhs_operand" "")))]
2249 if (GET_CODE (operands[2]) == CONST_INT)
2250 operands[2] = force_reg (SImode, operands[2]);
2254 (define_insn "*arm_xorsi3"
2255 [(set (match_operand:SI 0 "s_register_operand" "=r")
2256 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2257 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2259 "eor%?\\t%0, %1, %2"
2260 [(set_attr "predicable" "yes")]
2263 (define_insn "*thumb_xorsi3"
2264 [(set (match_operand:SI 0 "register_operand" "=l")
2265 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2266 (match_operand:SI 2 "register_operand" "l")))]
2269 [(set_attr "length" "2")]
2272 (define_insn "*xorsi3_compare0"
2273 [(set (reg:CC_NOOV CC_REGNUM)
2274 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2275 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2277 (set (match_operand:SI 0 "s_register_operand" "=r")
2278 (xor:SI (match_dup 1) (match_dup 2)))]
2280 "eor%?s\\t%0, %1, %2"
2281 [(set_attr "conds" "set")]
2284 (define_insn "*xorsi3_compare0_scratch"
2285 [(set (reg:CC_NOOV CC_REGNUM)
2286 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2287 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2291 [(set_attr "conds" "set")]
2294 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2295 ; (NOT D) we can sometimes merge the final NOT into one of the following
2299 [(set (match_operand:SI 0 "s_register_operand" "=r")
2300 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2301 (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
2302 (match_operand:SI 3 "arm_rhs_operand" "rI")))
2303 (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
2305 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2306 (not:SI (match_dup 3))))
2307 (set (match_dup 0) (not:SI (match_dup 4)))]
2311 (define_insn "*andsi_iorsi3_notsi"
2312 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2313 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2314 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2315 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2317 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2318 [(set_attr "length" "8")
2319 (set_attr "predicable" "yes")]
2324 ;; Minimum and maximum insns
2326 (define_insn "smaxsi3"
2327 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2328 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2329 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2330 (clobber (reg:CC CC_REGNUM))]
2333 cmp\\t%1, %2\;movlt\\t%0, %2
2334 cmp\\t%1, %2\;movge\\t%0, %1
2335 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2336 [(set_attr "conds" "clob")
2337 (set_attr "length" "8,8,12")]
2340 (define_insn "sminsi3"
2341 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2342 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2343 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2344 (clobber (reg:CC CC_REGNUM))]
2347 cmp\\t%1, %2\;movge\\t%0, %2
2348 cmp\\t%1, %2\;movlt\\t%0, %1
2349 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2350 [(set_attr "conds" "clob")
2351 (set_attr "length" "8,8,12")]
2354 (define_insn "umaxsi3"
2355 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2356 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2357 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2358 (clobber (reg:CC CC_REGNUM))]
2361 cmp\\t%1, %2\;movcc\\t%0, %2
2362 cmp\\t%1, %2\;movcs\\t%0, %1
2363 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2364 [(set_attr "conds" "clob")
2365 (set_attr "length" "8,8,12")]
2368 (define_insn "uminsi3"
2369 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2370 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2371 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2372 (clobber (reg:CC CC_REGNUM))]
2375 cmp\\t%1, %2\;movcs\\t%0, %2
2376 cmp\\t%1, %2\;movcc\\t%0, %1
2377 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2378 [(set_attr "conds" "clob")
2379 (set_attr "length" "8,8,12")]
2382 (define_insn "*store_minmaxsi"
2383 [(set (match_operand:SI 0 "memory_operand" "=m")
2384 (match_operator:SI 3 "minmax_operator"
2385 [(match_operand:SI 1 "s_register_operand" "r")
2386 (match_operand:SI 2 "s_register_operand" "r")]))
2387 (clobber (reg:CC CC_REGNUM))]
2390 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2392 output_asm_insn (\"cmp\\t%1, %2\", operands);
2393 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2394 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2397 [(set_attr "conds" "clob")
2398 (set_attr "length" "12")
2399 (set_attr "type" "store1")]
2402 ; Reject the frame pointer in operand[1], since reloading this after
2403 ; it has been eliminated can cause carnage.
2404 (define_insn "*minmax_arithsi"
2405 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2406 (match_operator:SI 4 "shiftable_operator"
2407 [(match_operator:SI 5 "minmax_operator"
2408 [(match_operand:SI 2 "s_register_operand" "r,r")
2409 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2410 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2411 (clobber (reg:CC CC_REGNUM))]
2413 && (GET_CODE (operands[1]) != REG
2414 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2415 && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2418 enum rtx_code code = GET_CODE (operands[4]);
2420 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2422 output_asm_insn (\"cmp\\t%2, %3\", operands);
2423 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2424 if (which_alternative != 0 || operands[3] != const0_rtx
2425 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2426 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2429 [(set_attr "conds" "clob")
2430 (set_attr "length" "12")]
2434 ;; Shift and rotation insns
2436 (define_expand "ashlsi3"
2437 [(set (match_operand:SI 0 "s_register_operand" "")
2438 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2439 (match_operand:SI 2 "arm_rhs_operand" "")))]
2442 if (GET_CODE (operands[2]) == CONST_INT
2443 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2445 emit_insn (gen_movsi (operands[0], const0_rtx));
2451 (define_insn "*thumb_ashlsi3"
2452 [(set (match_operand:SI 0 "register_operand" "=l,l")
2453 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2454 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2457 [(set_attr "length" "2")]
2460 (define_expand "ashrsi3"
2461 [(set (match_operand:SI 0 "s_register_operand" "")
2462 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2463 (match_operand:SI 2 "arm_rhs_operand" "")))]
2466 if (GET_CODE (operands[2]) == CONST_INT
2467 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2468 operands[2] = GEN_INT (31);
2472 (define_insn "*thumb_ashrsi3"
2473 [(set (match_operand:SI 0 "register_operand" "=l,l")
2474 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2475 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2478 [(set_attr "length" "2")]
2481 (define_expand "lshrsi3"
2482 [(set (match_operand:SI 0 "s_register_operand" "")
2483 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2484 (match_operand:SI 2 "arm_rhs_operand" "")))]
2487 if (GET_CODE (operands[2]) == CONST_INT
2488 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2490 emit_insn (gen_movsi (operands[0], const0_rtx));
2496 (define_insn "*thumb_lshrsi3"
2497 [(set (match_operand:SI 0 "register_operand" "=l,l")
2498 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2499 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2502 [(set_attr "length" "2")]
2505 (define_expand "rotlsi3"
2506 [(set (match_operand:SI 0 "s_register_operand" "")
2507 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2508 (match_operand:SI 2 "reg_or_int_operand" "")))]
2511 if (GET_CODE (operands[2]) == CONST_INT)
2512 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2515 rtx reg = gen_reg_rtx (SImode);
2516 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2522 (define_expand "rotrsi3"
2523 [(set (match_operand:SI 0 "s_register_operand" "")
2524 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2525 (match_operand:SI 2 "arm_rhs_operand" "")))]
2530 if (GET_CODE (operands[2]) == CONST_INT
2531 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2532 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2534 else /* TARGET_THUMB */
2536 if (GET_CODE (operands [2]) == CONST_INT)
2537 operands [2] = force_reg (SImode, operands[2]);
2542 (define_insn "*thumb_rotrsi3"
2543 [(set (match_operand:SI 0 "register_operand" "=l")
2544 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2545 (match_operand:SI 2 "register_operand" "l")))]
2548 [(set_attr "length" "2")]
2551 (define_insn "*arm_shiftsi3"
2552 [(set (match_operand:SI 0 "s_register_operand" "=r")
2553 (match_operator:SI 3 "shift_operator"
2554 [(match_operand:SI 1 "s_register_operand" "r")
2555 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2558 [(set_attr "predicable" "yes")
2559 (set_attr "shift" "1")
2563 (define_insn "*shiftsi3_compare0"
2564 [(set (reg:CC_NOOV CC_REGNUM)
2565 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2566 [(match_operand:SI 1 "s_register_operand" "r")
2567 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2569 (set (match_operand:SI 0 "s_register_operand" "=r")
2570 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2572 "mov%?s\\t%0, %1%S3"
2573 [(set_attr "conds" "set")
2574 (set_attr "shift" "1")
2578 (define_insn "*shiftsi3_compare0_scratch"
2579 [(set (reg:CC_NOOV CC_REGNUM)
2580 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2581 [(match_operand:SI 1 "s_register_operand" "r")
2582 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2584 (clobber (match_scratch:SI 0 "=r"))]
2586 "mov%?s\\t%0, %1%S3"
2587 [(set_attr "conds" "set")
2588 (set_attr "shift" "1")
2592 (define_insn "*notsi_shiftsi"
2593 [(set (match_operand:SI 0 "s_register_operand" "=r")
2594 (not:SI (match_operator:SI 3 "shift_operator"
2595 [(match_operand:SI 1 "s_register_operand" "r")
2596 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2599 [(set_attr "predicable" "yes")
2600 (set_attr "shift" "1")
2604 (define_insn "*notsi_shiftsi_compare0"
2605 [(set (reg:CC_NOOV CC_REGNUM)
2606 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2607 [(match_operand:SI 1 "s_register_operand" "r")
2608 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2610 (set (match_operand:SI 0 "s_register_operand" "=r")
2611 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2613 "mvn%?s\\t%0, %1%S3"
2614 [(set_attr "conds" "set")
2615 (set_attr "shift" "1")
2619 (define_insn "*not_shiftsi_compare0_scratch"
2620 [(set (reg:CC_NOOV CC_REGNUM)
2621 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2622 [(match_operand:SI 1 "s_register_operand" "r")
2623 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2625 (clobber (match_scratch:SI 0 "=r"))]
2627 "mvn%?s\\t%0, %1%S3"
2628 [(set_attr "conds" "set")
2629 (set_attr "shift" "1")
2633 ;; We don't really have extzv, but defining this using shifts helps
2634 ;; to reduce register pressure later on.
2636 (define_expand "extzv"
2638 (ashift:SI (match_operand:SI 1 "register_operand" "")
2639 (match_operand:SI 2 "const_int_operand" "")))
2640 (set (match_operand:SI 0 "register_operand" "")
2641 (lshiftrt:SI (match_dup 4)
2642 (match_operand:SI 3 "const_int_operand" "")))]
2646 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2647 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2649 operands[3] = GEN_INT (rshift);
2653 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2657 operands[2] = GEN_INT (lshift);
2658 operands[4] = gen_reg_rtx (SImode);
2663 ;; Unary arithmetic insns
2665 (define_expand "negdi2"
2667 [(set (match_operand:DI 0 "s_register_operand" "")
2668 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2669 (clobber (reg:CC CC_REGNUM))])]
2674 if (GET_CODE (operands[1]) != REG)
2675 operands[1] = force_reg (SImode, operands[1]);
2680 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2681 ;; The second alternative is to allow the common case of a *full* overlap.
2682 (define_insn "*arm_negdi2"
2683 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2684 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2685 (clobber (reg:CC CC_REGNUM))]
2687 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2688 [(set_attr "conds" "clob")
2689 (set_attr "length" "8")]
2692 (define_insn "*thumb_negdi2"
2693 [(set (match_operand:DI 0 "register_operand" "=&l")
2694 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2695 (clobber (reg:CC CC_REGNUM))]
2697 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2698 [(set_attr "length" "6")]
2701 (define_expand "negsi2"
2702 [(set (match_operand:SI 0 "s_register_operand" "")
2703 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2708 (define_insn "*arm_negsi2"
2709 [(set (match_operand:SI 0 "s_register_operand" "=r")
2710 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2712 "rsb%?\\t%0, %1, #0"
2713 [(set_attr "predicable" "yes")]
2716 (define_insn "*thumb_negsi2"
2717 [(set (match_operand:SI 0 "register_operand" "=l")
2718 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2721 [(set_attr "length" "2")]
2724 (define_insn "negsf2"
2725 [(set (match_operand:SF 0 "s_register_operand" "=f")
2726 (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
2727 "TARGET_ARM && TARGET_HARD_FLOAT"
2729 [(set_attr "type" "ffarith")
2730 (set_attr "predicable" "yes")]
2733 (define_insn "negdf2"
2734 [(set (match_operand:DF 0 "s_register_operand" "=f")
2735 (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
2736 "TARGET_ARM && TARGET_HARD_FLOAT"
2738 [(set_attr "type" "ffarith")
2739 (set_attr "predicable" "yes")]
2742 (define_insn "*negdf_esfdf"
2743 [(set (match_operand:DF 0 "s_register_operand" "=f")
2744 (neg:DF (float_extend:DF
2745 (match_operand:SF 1 "s_register_operand" "f"))))]
2746 "TARGET_ARM && TARGET_HARD_FLOAT"
2748 [(set_attr "type" "ffarith")
2749 (set_attr "predicable" "yes")]
2752 (define_insn "negxf2"
2753 [(set (match_operand:XF 0 "s_register_operand" "=f")
2754 (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
2755 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2757 [(set_attr "type" "ffarith")
2758 (set_attr "predicable" "yes")]
2761 ;; abssi2 doesn't really clobber the condition codes if a different register
2762 ;; is being set. To keep things simple, assume during rtl manipulations that
2763 ;; it does, but tell the final scan operator the truth. Similarly for
2766 (define_insn "abssi2"
2767 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2768 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2769 (clobber (reg:CC CC_REGNUM))]
2772 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2773 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2774 [(set_attr "conds" "clob,*")
2775 (set_attr "shift" "1")
2776 ;; predicable can't be set based on the variant, so left as no
2777 (set_attr "length" "8")]
2780 (define_insn "*neg_abssi2"
2781 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2782 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2783 (clobber (reg:CC CC_REGNUM))]
2786 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2787 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2788 [(set_attr "conds" "clob,*")
2789 (set_attr "shift" "1")
2790 ;; predicable can't be set based on the variant, so left as no
2791 (set_attr "length" "8")]
2794 (define_insn "abssf2"
2795 [(set (match_operand:SF 0 "s_register_operand" "=f")
2796 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
2797 "TARGET_ARM && TARGET_HARD_FLOAT"
2799 [(set_attr "type" "ffarith")
2800 (set_attr "predicable" "yes")]
2803 (define_insn "absdf2"
2804 [(set (match_operand:DF 0 "s_register_operand" "=f")
2805 (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
2806 "TARGET_ARM && TARGET_HARD_FLOAT"
2808 [(set_attr "type" "ffarith")
2809 (set_attr "predicable" "yes")]
2812 (define_insn "*absdf_esfdf"
2813 [(set (match_operand:DF 0 "s_register_operand" "=f")
2814 (abs:DF (float_extend:DF
2815 (match_operand:SF 1 "s_register_operand" "f"))))]
2816 "TARGET_ARM && TARGET_HARD_FLOAT"
2818 [(set_attr "type" "ffarith")
2819 (set_attr "predicable" "yes")]
2822 (define_insn "absxf2"
2823 [(set (match_operand:XF 0 "s_register_operand" "=f")
2824 (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
2825 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2827 [(set_attr "type" "ffarith")
2828 (set_attr "predicable" "yes")]
2831 (define_insn "sqrtsf2"
2832 [(set (match_operand:SF 0 "s_register_operand" "=f")
2833 (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
2834 "TARGET_ARM && TARGET_HARD_FLOAT"
2836 [(set_attr "type" "float_em")
2837 (set_attr "predicable" "yes")]
2840 (define_insn "sqrtdf2"
2841 [(set (match_operand:DF 0 "s_register_operand" "=f")
2842 (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
2843 "TARGET_ARM && TARGET_HARD_FLOAT"
2845 [(set_attr "type" "float_em")
2846 (set_attr "predicable" "yes")]
2849 (define_insn "*sqrtdf_esfdf"
2850 [(set (match_operand:DF 0 "s_register_operand" "=f")
2851 (sqrt:DF (float_extend:DF
2852 (match_operand:SF 1 "s_register_operand" "f"))))]
2853 "TARGET_ARM && TARGET_HARD_FLOAT"
2855 [(set_attr "type" "float_em")
2856 (set_attr "predicable" "yes")]
2859 (define_insn "sqrtxf2"
2860 [(set (match_operand:XF 0 "s_register_operand" "=f")
2861 (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
2862 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2864 [(set_attr "type" "float_em")
2865 (set_attr "predicable" "yes")]
2868 ;; SIN COS TAN and family are always emulated, so it's probably better
2869 ;; to always call a library function.
2870 ;(define_insn "sinsf2"
2871 ; [(set (match_operand:SF 0 "s_register_operand" "=f")
2872 ; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 0))]
2873 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2875 ;[(set_attr "type" "float_em")])
2877 ;(define_insn "sindf2"
2878 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2879 ; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 0))]
2880 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2882 ;[(set_attr "type" "float_em")])
2884 ;(define_insn "*sindf_esfdf"
2885 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2886 ; (unspec:DF [(float_extend:DF
2887 ; (match_operand:SF 1 "s_register_operand" "f"))] 0))]
2888 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2890 ;[(set_attr "type" "float_em")])
2892 ;(define_insn "sinxf2"
2893 ; [(set (match_operand:XF 0 "s_register_operand" "=f")
2894 ; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 0))]
2895 ; "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2897 ;[(set_attr "type" "float_em")])
2899 ;(define_insn "cossf2"
2900 ; [(set (match_operand:SF 0 "s_register_operand" "=f")
2901 ; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 1))]
2902 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2904 ;[(set_attr "type" "float_em")])
2906 ;(define_insn "cosdf2"
2907 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2908 ; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 1))]
2909 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2911 ;[(set_attr "type" "float_em")])
2913 ;(define_insn "*cosdf_esfdf"
2914 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2915 ; (unspec:DF [(float_extend:DF
2916 ; (match_operand:SF 1 "s_register_operand" "f"))] 1))]
2917 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2919 ;[(set_attr "type" "float_em")])
2921 ;(define_insn "cosxf2"
2922 ; [(set (match_operand:XF 0 "s_register_operand" "=f")
2923 ; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 1))]
2924 ; "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2926 ;[(set_attr "type" "float_em")])
2928 (define_insn_and_split "one_cmpldi2"
2929 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2930 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2933 "TARGET_ARM && reload_completed"
2934 [(set (match_dup 0) (not:SI (match_dup 1)))
2935 (set (match_dup 2) (not:SI (match_dup 3)))]
2938 operands[2] = gen_highpart (SImode, operands[0]);
2939 operands[0] = gen_lowpart (SImode, operands[0]);
2940 operands[3] = gen_highpart (SImode, operands[1]);
2941 operands[1] = gen_lowpart (SImode, operands[1]);
2943 [(set_attr "length" "8")
2944 (set_attr "predicable" "yes")]
2947 (define_expand "one_cmplsi2"
2948 [(set (match_operand:SI 0 "s_register_operand" "")
2949 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2954 (define_insn "*arm_one_cmplsi2"
2955 [(set (match_operand:SI 0 "s_register_operand" "=r")
2956 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
2959 [(set_attr "predicable" "yes")]
2962 (define_insn "*thumb_one_cmplsi2"
2963 [(set (match_operand:SI 0 "register_operand" "=l")
2964 (not:SI (match_operand:SI 1 "register_operand" "l")))]
2967 [(set_attr "length" "2")]
2970 (define_insn "*notsi_compare0"
2971 [(set (reg:CC_NOOV CC_REGNUM)
2972 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2974 (set (match_operand:SI 0 "s_register_operand" "=r")
2975 (not:SI (match_dup 1)))]
2978 [(set_attr "conds" "set")]
2981 (define_insn "*notsi_compare0_scratch"
2982 [(set (reg:CC_NOOV CC_REGNUM)
2983 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2985 (clobber (match_scratch:SI 0 "=r"))]
2988 [(set_attr "conds" "set")]
2991 ;; Fixed <--> Floating conversion insns
2993 (define_insn "floatsisf2"
2994 [(set (match_operand:SF 0 "s_register_operand" "=f")
2995 (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
2996 "TARGET_ARM && TARGET_HARD_FLOAT"
2998 [(set_attr "type" "r_2_f")
2999 (set_attr "predicable" "yes")]
3002 (define_insn "floatsidf2"
3003 [(set (match_operand:DF 0 "s_register_operand" "=f")
3004 (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
3005 "TARGET_ARM && TARGET_HARD_FLOAT"
3007 [(set_attr "type" "r_2_f")
3008 (set_attr "predicable" "yes")]
3011 (define_insn "floatsixf2"
3012 [(set (match_operand:XF 0 "s_register_operand" "=f")
3013 (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
3014 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3016 [(set_attr "type" "r_2_f")
3017 (set_attr "predicable" "yes")]
3020 (define_insn "fix_truncsfsi2"
3021 [(set (match_operand:SI 0 "s_register_operand" "=r")
3022 (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
3023 "TARGET_ARM && TARGET_HARD_FLOAT"
3025 [(set_attr "type" "f_2_r")
3026 (set_attr "predicable" "yes")]
3029 (define_insn "fix_truncdfsi2"
3030 [(set (match_operand:SI 0 "s_register_operand" "=r")
3031 (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
3032 "TARGET_ARM && TARGET_HARD_FLOAT"
3034 [(set_attr "type" "f_2_r")
3035 (set_attr "predicable" "yes")]
3038 (define_insn "fix_truncxfsi2"
3039 [(set (match_operand:SI 0 "s_register_operand" "=r")
3040 (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
3041 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3043 [(set_attr "type" "f_2_r")
3044 (set_attr "predicable" "yes")]
3049 (define_insn "truncdfsf2"
3050 [(set (match_operand:SF 0 "s_register_operand" "=f")
3052 (match_operand:DF 1 "s_register_operand" "f")))]
3053 "TARGET_ARM && TARGET_HARD_FLOAT"
3055 [(set_attr "type" "ffarith")
3056 (set_attr "predicable" "yes")]
3059 (define_insn "truncxfsf2"
3060 [(set (match_operand:SF 0 "s_register_operand" "=f")
3062 (match_operand:XF 1 "s_register_operand" "f")))]
3063 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3065 [(set_attr "type" "ffarith")
3066 (set_attr "predicable" "yes")]
3069 (define_insn "truncxfdf2"
3070 [(set (match_operand:DF 0 "s_register_operand" "=f")
3072 (match_operand:XF 1 "s_register_operand" "f")))]
3073 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3075 [(set_attr "type" "ffarith")
3076 (set_attr "predicable" "yes")]
3079 ;; Zero and sign extension instructions.
3081 (define_insn "zero_extendsidi2"
3082 [(set (match_operand:DI 0 "s_register_operand" "=r")
3083 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3086 if (REGNO (operands[1])
3087 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3088 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3089 return \"mov%?\\t%R0, #0\";
3091 [(set_attr "length" "8")
3092 (set_attr "predicable" "yes")]
3095 (define_insn "zero_extendqidi2"
3096 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
3097 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3100 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3101 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3102 [(set_attr "length" "8")
3103 (set_attr "predicable" "yes")
3104 (set_attr "type" "*,load")
3105 (set_attr "pool_range" "*,4092")
3106 (set_attr "neg_pool_range" "*,4084")]
3109 (define_insn "extendsidi2"
3110 [(set (match_operand:DI 0 "s_register_operand" "=r")
3111 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3114 if (REGNO (operands[1])
3115 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3116 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3117 return \"mov%?\\t%R0, %Q0, asr #31\";
3119 [(set_attr "length" "8")
3120 (set_attr "shift" "1")
3121 (set_attr "predicable" "yes")]
3124 (define_expand "zero_extendhisi2"
3126 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3128 (set (match_operand:SI 0 "s_register_operand" "")
3129 (lshiftrt:SI (match_dup 2) (const_int 16)))]
3135 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3137 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3138 here because the insn below will generate an LDRH instruction
3139 rather than an LDR instruction, so we cannot get an unaligned
3141 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3142 gen_rtx_ZERO_EXTEND (SImode,
3146 if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3148 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3151 if (!s_register_operand (operands[1], HImode))
3152 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3153 operands[1] = gen_lowpart (SImode, operands[1]);
3154 operands[2] = gen_reg_rtx (SImode);
3156 else /* TARGET_THUMB */
3158 if (GET_CODE (operands[1]) == MEM)
3162 tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3163 tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3170 if (!s_register_operand (operands[1], HImode))
3171 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3172 operands[1] = gen_lowpart (SImode, operands[1]);
3173 operands[2] = gen_reg_rtx (SImode);
3175 ops[0] = operands[2];
3176 ops[1] = operands[1];
3177 ops[2] = GEN_INT (16);
3179 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3180 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3182 ops[0] = operands[0];
3183 ops[1] = operands[2];
3184 ops[2] = GEN_INT (16);
3186 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3187 gen_rtx_LSHIFTRT (SImode, ops[1],
3195 (define_insn "*thumb_zero_extendhisi2"
3196 [(set (match_operand:SI 0 "register_operand" "=l")
3197 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3200 rtx mem = XEXP (operands[1], 0);
3202 if (GET_CODE (mem) == CONST)
3203 mem = XEXP (mem, 0);
3205 if (GET_CODE (mem) == LABEL_REF)
3206 return \"ldr\\t%0, %1\";
3208 if (GET_CODE (mem) == PLUS)
3210 rtx a = XEXP (mem, 0);
3211 rtx b = XEXP (mem, 1);
3213 /* This can happen due to bugs in reload. */
3214 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3217 ops[0] = operands[0];
3220 output_asm_insn (\"mov %0, %1\", ops);
3222 XEXP (mem, 0) = operands[0];
3225 else if ( GET_CODE (a) == LABEL_REF
3226 && GET_CODE (b) == CONST_INT)
3227 return \"ldr\\t%0, %1\";
3230 return \"ldrh\\t%0, %1\";
3232 [(set_attr "length" "4")
3233 (set_attr "type" "load")
3234 (set_attr "pool_range" "60")]
3237 (define_insn "*arm_zero_extendhisi2"
3238 [(set (match_operand:SI 0 "s_register_operand" "=r")
3239 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3240 "TARGET_ARM && arm_arch4"
3242 [(set_attr "type" "load")
3243 (set_attr "predicable" "yes")
3244 (set_attr "pool_range" "256")
3245 (set_attr "neg_pool_range" "244")]
3249 [(set (match_operand:SI 0 "s_register_operand" "")
3250 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3251 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3252 "TARGET_ARM && (!arm_arch4)"
3253 [(set (match_dup 2) (match_dup 1))
3254 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3256 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3262 [(set (match_operand:SI 0 "s_register_operand" "")
3263 (match_operator:SI 3 "shiftable_operator"
3264 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3265 (match_operand:SI 4 "s_register_operand" "")]))
3266 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3267 "TARGET_ARM && (!arm_arch4)"
3268 [(set (match_dup 2) (match_dup 1))
3271 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3273 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3278 (define_expand "zero_extendqisi2"
3279 [(set (match_operand:SI 0 "s_register_operand" "")
3280 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3283 if (GET_CODE (operands[1]) != MEM)
3287 emit_insn (gen_andsi3 (operands[0],
3288 gen_lowpart (SImode, operands[1]),
3291 else /* TARGET_THUMB */
3293 rtx temp = gen_reg_rtx (SImode);
3296 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3297 operands[1] = gen_lowpart (SImode, operands[1]);
3300 ops[1] = operands[1];
3301 ops[2] = GEN_INT (24);
3303 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3304 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3306 ops[0] = operands[0];
3308 ops[2] = GEN_INT (24);
3310 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3311 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3318 (define_insn "*thumb_zero_extendqisi2"
3319 [(set (match_operand:SI 0 "register_operand" "=l")
3320 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3323 [(set_attr "length" "2")
3324 (set_attr "type" "load")
3325 (set_attr "pool_range" "32")]
3328 (define_insn "*arm_zero_extendqisi2"
3329 [(set (match_operand:SI 0 "s_register_operand" "=r")
3330 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3332 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3333 [(set_attr "type" "load")
3334 (set_attr "predicable" "yes")
3335 (set_attr "pool_range" "4096")
3336 (set_attr "neg_pool_range" "4084")]
3340 [(set (match_operand:SI 0 "s_register_operand" "")
3341 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3342 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3343 "TARGET_ARM && (GET_CODE (operands[1]) != MEM)"
3344 [(set (match_dup 2) (match_dup 1))
3345 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3349 (define_insn "*compareqi_eq0"
3350 [(set (reg:CC_Z CC_REGNUM)
3351 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3355 [(set_attr "conds" "set")]
3358 (define_expand "extendhisi2"
3360 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3362 (set (match_operand:SI 0 "s_register_operand" "")
3363 (ashiftrt:SI (match_dup 2)
3368 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3370 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3371 here because the insn below will generate an LDRH instruction
3372 rather than an LDR instruction, so we cannot get an unaligned
3374 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3375 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3379 if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3381 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3384 if (!s_register_operand (operands[1], HImode))
3385 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3386 operands[1] = gen_lowpart (SImode, operands[1]);
3387 operands[2] = gen_reg_rtx (SImode);
3393 ops[0] = operands[2];
3394 ops[1] = operands[1];
3395 ops[2] = GEN_INT (16);
3397 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3398 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3400 ops[0] = operands[0];
3401 ops[1] = operands[2];
3402 ops[2] = GEN_INT (16);
3404 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3405 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3412 (define_insn "*thumb_extendhisi2_insn"
3413 [(set (match_operand:SI 0 "register_operand" "=l")
3414 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3415 (clobber (match_scratch:SI 2 "=&l"))]
3420 rtx mem = XEXP (operands[1], 0);
3422 /* This code used to try to use 'V', and fix the address only if it was
3423 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3424 range of QImode offsets, and offsettable_address_p does a QImode
3427 if (GET_CODE (mem) == CONST)
3428 mem = XEXP (mem, 0);
3430 if (GET_CODE (mem) == LABEL_REF)
3431 return \"ldr\\t%0, %1\";
3433 if (GET_CODE (mem) == PLUS)
3435 rtx a = XEXP (mem, 0);
3436 rtx b = XEXP (mem, 1);
3438 if (GET_CODE (a) == LABEL_REF
3439 && GET_CODE (b) == CONST_INT)
3440 return \"ldr\\t%0, %1\";
3442 if (GET_CODE (b) == REG)
3443 return \"ldrsh\\t%0, %1\";
3451 ops[2] = const0_rtx;
3454 if (GET_CODE (ops[1]) != REG)
3460 ops[0] = operands[0];
3461 ops[3] = operands[2];
3462 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3465 [(set_attr "length" "4")
3466 (set_attr "type" "load")
3467 (set_attr "pool_range" "1020")]
3470 (define_expand "extendhisi2_mem"
3471 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3473 (zero_extend:SI (match_dup 7)))
3474 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3475 (set (match_operand:SI 0 "" "")
3476 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3481 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3483 mem1 = gen_rtx_MEM (QImode, addr);
3484 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3485 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3486 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3487 operands[0] = gen_lowpart (SImode, operands[0]);
3489 operands[2] = gen_reg_rtx (SImode);
3490 operands[3] = gen_reg_rtx (SImode);
3491 operands[6] = gen_reg_rtx (SImode);
3494 if (BYTES_BIG_ENDIAN)
3496 operands[4] = operands[2];
3497 operands[5] = operands[3];
3501 operands[4] = operands[3];
3502 operands[5] = operands[2];
3507 (define_insn "*arm_extendhisi_insn"
3508 [(set (match_operand:SI 0 "s_register_operand" "=r")
3509 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3510 "TARGET_ARM && arm_arch4"
3512 [(set_attr "type" "load")
3513 (set_attr "predicable" "yes")
3514 (set_attr "pool_range" "256")
3515 (set_attr "neg_pool_range" "244")]
3519 [(set (match_operand:SI 0 "s_register_operand" "")
3520 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3521 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3522 "TARGET_ARM && (!arm_arch4)"
3523 [(set (match_dup 2) (match_dup 1))
3524 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3526 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3532 [(set (match_operand:SI 0 "s_register_operand" "")
3533 (match_operator:SI 3 "shiftable_operator"
3534 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3535 (match_operand:SI 4 "s_register_operand" "")]))
3536 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3537 "TARGET_ARM && (!arm_arch4)"
3538 [(set (match_dup 2) (match_dup 1))
3541 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3542 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3547 (define_expand "extendqihi2"
3549 (ashift:SI (match_operand:QI 1 "general_operand" "")
3551 (set (match_operand:HI 0 "s_register_operand" "")
3552 (ashiftrt:SI (match_dup 2)
3557 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3559 emit_insn (gen_rtx_SET (VOIDmode,
3561 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3564 if (!s_register_operand (operands[1], QImode))
3565 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3566 operands[0] = gen_lowpart (SImode, operands[0]);
3567 operands[1] = gen_lowpart (SImode, operands[1]);
3568 operands[2] = gen_reg_rtx (SImode);
3572 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3573 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3574 (define_insn "*extendqihi_insn"
3575 [(set (match_operand:HI 0 "s_register_operand" "=r")
3576 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3577 "TARGET_ARM && arm_arch4"
3579 /* If the address is invalid, this will split the instruction into two. */
3580 if (bad_signed_byte_operand (operands[1], VOIDmode))
3582 return \"ldr%?sb\\t%0, %1\";
3584 [(set_attr "type" "load")
3585 (set_attr "predicable" "yes")
3586 (set_attr "length" "8")
3587 (set_attr "pool_range" "256")
3588 (set_attr "neg_pool_range" "244")]
3592 [(set (match_operand:HI 0 "s_register_operand" "")
3593 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3594 "TARGET_ARM && arm_arch4 && reload_completed"
3595 [(set (match_dup 3) (match_dup 1))
3596 (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3599 HOST_WIDE_INT offset;
3601 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3602 operands[2] = gen_rtx_MEM (QImode, operands[3]);
3603 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3604 operands[1] = XEXP (operands[1], 0);
3605 if (GET_CODE (operands[1]) == PLUS
3606 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3607 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3608 || const_ok_for_arm (-offset)))
3610 HOST_WIDE_INT low = (offset > 0
3611 ? (offset & 0xff) : -((-offset) & 0xff));
3612 XEXP (operands[2], 0) = plus_constant (operands[3], low);
3613 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3615 /* Ensure the sum is in correct canonical form */
3616 else if (GET_CODE (operands[1]) == PLUS
3617 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3618 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3619 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3620 XEXP (operands[1], 1),
3621 XEXP (operands[1], 0));
3625 (define_expand "extendqisi2"
3627 (ashift:SI (match_operand:QI 1 "general_operand" "")
3629 (set (match_operand:SI 0 "s_register_operand" "")
3630 (ashiftrt:SI (match_dup 2)
3635 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3637 emit_insn (gen_rtx_SET (VOIDmode,
3639 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3642 if (!s_register_operand (operands[1], QImode))
3643 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3644 operands[1] = gen_lowpart (SImode, operands[1]);
3645 operands[2] = gen_reg_rtx (SImode);
3651 ops[0] = operands[2];
3652 ops[1] = operands[1];
3653 ops[2] = GEN_INT (24);
3655 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3656 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3658 ops[0] = operands[0];
3659 ops[1] = operands[2];
3660 ops[2] = GEN_INT (24);
3662 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3663 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3670 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3671 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3672 (define_insn "*arm_extendqisi_insn"
3673 [(set (match_operand:SI 0 "s_register_operand" "=r")
3674 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3675 "TARGET_ARM && arm_arch4"
3677 /* If the address is invalid, this will split the instruction into two. */
3678 if (bad_signed_byte_operand (operands[1], VOIDmode))
3680 return \"ldr%?sb\\t%0, %1\";
3682 [(set_attr "type" "load")
3683 (set_attr "predicable" "yes")
3684 (set_attr "length" "8")
3685 (set_attr "pool_range" "256")
3686 (set_attr "neg_pool_range" "244")]
3690 [(set (match_operand:SI 0 "s_register_operand" "")
3691 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3692 "TARGET_ARM && arm_arch4 && reload_completed"
3693 [(set (match_dup 0) (match_dup 1))
3694 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3697 HOST_WIDE_INT offset;
3699 operands[2] = gen_rtx_MEM (QImode, operands[0]);
3700 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3701 operands[1] = XEXP (operands[1], 0);
3702 if (GET_CODE (operands[1]) == PLUS
3703 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3704 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3705 || const_ok_for_arm (-offset)))
3707 HOST_WIDE_INT low = (offset > 0
3708 ? (offset & 0xff) : -((-offset) & 0xff));
3709 XEXP (operands[2], 0) = plus_constant (operands[0], low);
3710 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3712 /* Ensure the sum is in correct canonical form */
3713 else if (GET_CODE (operands[1]) == PLUS
3714 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3715 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3716 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3717 XEXP (operands[1], 1),
3718 XEXP (operands[1], 0));
3722 (define_insn "*thumb_extendqisi2_insn"
3723 [(set (match_operand:SI 0 "register_operand" "=l,l")
3724 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3729 rtx mem = XEXP (operands[1], 0);
3731 if (GET_CODE (mem) == CONST)
3732 mem = XEXP (mem, 0);
3734 if (GET_CODE (mem) == LABEL_REF)
3735 return \"ldr\\t%0, %1\";
3737 if (GET_CODE (mem) == PLUS
3738 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3739 return \"ldr\\t%0, %1\";
3741 if (which_alternative == 0)
3742 return \"ldrsb\\t%0, %1\";
3744 ops[0] = operands[0];
3746 if (GET_CODE (mem) == PLUS)
3748 rtx a = XEXP (mem, 0);
3749 rtx b = XEXP (mem, 1);
3754 if (GET_CODE (a) == REG)
3756 if (GET_CODE (b) == REG)
3757 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3758 else if (REGNO (a) == REGNO (ops[0]))
3760 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3761 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3762 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3765 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3767 else if (GET_CODE (b) != REG)
3771 if (REGNO (b) == REGNO (ops[0]))
3773 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3774 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3775 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3778 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3781 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3783 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3784 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3785 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3790 ops[2] = const0_rtx;
3792 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3796 [(set_attr "length" "2,6")
3797 (set_attr "type" "load,load")
3798 (set_attr "pool_range" "32,32")]
3801 (define_insn "extendsfdf2"
3802 [(set (match_operand:DF 0 "s_register_operand" "=f")
3803 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
3804 "TARGET_ARM && TARGET_HARD_FLOAT"
3806 [(set_attr "type" "ffarith")
3807 (set_attr "predicable" "yes")]
3810 (define_insn "extendsfxf2"
3811 [(set (match_operand:XF 0 "s_register_operand" "=f")
3812 (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
3813 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3815 [(set_attr "type" "ffarith")
3816 (set_attr "predicable" "yes")]
3819 (define_insn "extenddfxf2"
3820 [(set (match_operand:XF 0 "s_register_operand" "=f")
3821 (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
3822 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3824 [(set_attr "type" "ffarith")
3825 (set_attr "predicable" "yes")]
3829 ;; Move insns (including loads and stores)
3831 ;; XXX Just some ideas about movti.
3832 ;; I don't think these are a good idea on the arm, there just aren't enough
3834 ;;(define_expand "loadti"
3835 ;; [(set (match_operand:TI 0 "s_register_operand" "")
3836 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
3839 ;;(define_expand "storeti"
3840 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3841 ;; (match_operand:TI 1 "s_register_operand" ""))]
3844 ;;(define_expand "movti"
3845 ;; [(set (match_operand:TI 0 "general_operand" "")
3846 ;; (match_operand:TI 1 "general_operand" ""))]
3852 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3853 ;; operands[1] = copy_to_reg (operands[1]);
3854 ;; if (GET_CODE (operands[0]) == MEM)
3855 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3856 ;; else if (GET_CODE (operands[1]) == MEM)
3857 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3861 ;; emit_insn (insn);
3865 ;; Recognise garbage generated above.
3868 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3869 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3873 ;; register mem = (which_alternative < 3);
3874 ;; register const char *template;
3876 ;; operands[mem] = XEXP (operands[mem], 0);
3877 ;; switch (which_alternative)
3879 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3880 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
3881 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
3882 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
3883 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
3884 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
3886 ;; output_asm_insn (template, operands);
3890 (define_expand "movdi"
3891 [(set (match_operand:DI 0 "general_operand" "")
3892 (match_operand:DI 1 "general_operand" ""))]
3897 if (!no_new_pseudos)
3899 if (GET_CODE (operands[0]) != REG)
3900 operands[1] = force_reg (DImode, operands[1]);
3906 (define_insn "*arm_movdi"
3907 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3908 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
3912 return (output_move_double (operands));
3914 [(set_attr "length" "8")
3915 (set_attr "type" "*,load,store2")
3916 (set_attr "pool_range" "*,1020,*")
3917 (set_attr "neg_pool_range" "*,1012,*")]
3920 ;;; ??? This should have alternatives for constants.
3921 ;;; ??? This was originally identical to the movdf_insn pattern.
3922 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3923 ;;; thumb_reorg with a memory reference.
3924 (define_insn "*thumb_movdi_insn"
3925 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3926 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
3928 && ( register_operand (operands[0], DImode)
3929 || register_operand (operands[1], DImode))"
3932 switch (which_alternative)
3936 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3937 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
3938 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
3940 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3942 operands[1] = GEN_INT (- INTVAL (operands[1]));
3943 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3945 return \"ldmia\\t%1, {%0, %H0}\";
3947 return \"stmia\\t%0, {%1, %H1}\";
3949 return thumb_load_double_from_address (operands);
3951 operands[2] = gen_rtx (MEM, SImode,
3952 plus_constant (XEXP (operands[0], 0), 4));
3953 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3956 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3957 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
3958 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
3961 [(set_attr "length" "4,4,6,2,2,6,4,4")
3962 (set_attr "type" "*,*,*,load,store2,load,store2,*")
3963 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
3966 (define_expand "movsi"
3967 [(set (match_operand:SI 0 "general_operand" "")
3968 (match_operand:SI 1 "general_operand" ""))]
3973 /* Everything except mem = const or mem = mem can be done easily */
3974 if (GET_CODE (operands[0]) == MEM)
3975 operands[1] = force_reg (SImode, operands[1]);
3976 if (GET_CODE (operands[1]) == CONST_INT
3977 && !(const_ok_for_arm (INTVAL (operands[1]))
3978 || const_ok_for_arm (~INTVAL (operands[1]))))
3980 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3983 : preserve_subexpressions_p ()));
3987 else /* TARGET_THUMB.... */
3989 if (!no_new_pseudos)
3991 if (GET_CODE (operands[0]) != REG)
3992 operands[1] = force_reg (SImode, operands[1]);
3997 && (CONSTANT_P (operands[1])
3998 || symbol_mentioned_p (operands[1])
3999 || label_mentioned_p (operands[1])))
4000 operands[1] = legitimize_pic_address (operands[1], SImode,
4001 (no_new_pseudos ? operands[0] : 0));
4005 (define_insn "*arm_movsi_insn"
4006 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4007 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
4009 && ( register_operand (operands[0], SImode)
4010 || register_operand (operands[1], SImode))"
4016 [(set_attr "type" "*,*,load,store1")
4017 (set_attr "predicable" "yes")
4018 (set_attr "pool_range" "*,*,4096,*")
4019 (set_attr "neg_pool_range" "*,*,4084,*")]
4023 [(set (match_operand:SI 0 "s_register_operand" "")
4024 (match_operand:SI 1 "const_int_operand" ""))]
4026 && (!(const_ok_for_arm (INTVAL (operands[1]))
4027 || const_ok_for_arm (~INTVAL (operands[1]))))"
4028 [(clobber (const_int 0))]
4030 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4036 (define_insn "*thumb_movsi_insn"
4037 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4038 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
4040 && ( register_operand (operands[0], SImode)
4041 || register_operand (operands[1], SImode))"
4052 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4053 (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
4054 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4058 [(set (match_operand:SI 0 "register_operand" "")
4059 (match_operand:SI 1 "const_int_operand" ""))]
4060 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4061 [(set (match_dup 0) (match_dup 1))
4062 (set (match_dup 0) (neg:SI (match_dup 0)))]
4063 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4067 [(set (match_operand:SI 0 "register_operand" "")
4068 (match_operand:SI 1 "const_int_operand" ""))]
4069 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4070 [(set (match_dup 0) (match_dup 1))
4071 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4074 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4075 unsigned HOST_WIDE_INT mask = 0xff;
4078 for (i = 0; i < 25; i++)
4079 if ((val & (mask << i)) == val)
4085 operands[1] = GEN_INT (val >> i);
4086 operands[2] = GEN_INT (i);
4090 (define_expand "movaddr"
4091 [(set (match_operand:SI 0 "s_register_operand" "")
4092 (match_operand:DI 1 "address_operand" ""))]
4097 (define_insn "*movaddr_insn"
4098 [(set (match_operand:SI 0 "s_register_operand" "=r")
4099 (match_operand:DI 1 "address_operand" "p"))]
4102 && (GET_CODE (operands[1]) == LABEL_REF
4103 || (GET_CODE (operands[1]) == CONST
4104 && GET_CODE (XEXP (operands[1], 0)) == PLUS
4105 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
4106 && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))"
4108 [(set_attr "predicable" "yes")]
4111 ;; When generating pic, we need to load the symbol offset into a register.
4112 ;; So that the optimizer does not confuse this with a normal symbol load
4113 ;; we use an unspec. The offset will be loaded from a constant pool entry,
4114 ;; since that is the only type of relocation we can use.
4116 ;; The rather odd constraints on the following are to force reload to leave
4117 ;; the insn alone, and to force the minipool generation pass to then move
4118 ;; the GOT symbol to memory.
4120 (define_insn "pic_load_addr_arm"
4121 [(set (match_operand:SI 0 "s_register_operand" "=r")
4122 (unspec:SI [(match_operand:SI 1 "" "mX")] 3))]
4123 "TARGET_ARM && flag_pic"
4125 [(set_attr "type" "load")
4126 (set (attr "pool_range") (const_int 4096))
4127 (set (attr "neg_pool_range") (const_int 4084))]
4130 (define_insn "pic_load_addr_thumb"
4131 [(set (match_operand:SI 0 "s_register_operand" "=l")
4132 (unspec:SI [(match_operand:SI 1 "" "mX")] 3))]
4133 "TARGET_THUMB && flag_pic"
4135 [(set_attr "type" "load")
4136 (set (attr "pool_range") (const_int 1024))]
4139 ;; This variant is used for AOF assembly, since it needs to mention the
4140 ;; pic register in the rtl.
4141 (define_expand "pic_load_addr_based"
4142 [(set (match_operand:SI 0 "s_register_operand" "=r")
4143 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] 3))]
4144 "TARGET_ARM && flag_pic"
4145 "operands[2] = pic_offset_table_rtx;"
4148 (define_insn "*pic_load_addr_based_insn"
4149 [(set (match_operand:SI 0 "s_register_operand" "=r")
4150 (unspec:SI [(match_operand 1 "" "")
4151 (match_operand 2 "s_register_operand" "r")] 3))]
4152 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4154 #ifdef AOF_ASSEMBLER
4155 operands[1] = aof_pic_entry (operands[1]);
4157 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4160 [(set_attr "type" "load")
4161 (set (attr "pool_range")
4162 (if_then_else (eq_attr "is_thumb" "yes")
4165 (set (attr "neg_pool_range")
4166 (if_then_else (eq_attr "is_thumb" "yes")
4171 (define_insn "pic_add_dot_plus_four"
4172 [(set (match_operand:SI 0 "register_operand" "+r")
4173 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
4174 (use (label_ref (match_operand 1 "" "")))]
4175 "TARGET_THUMB && flag_pic"
4177 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4178 CODE_LABEL_NUMBER (operands[1]));
4179 return \"add\\t%0, %|pc\";
4181 [(set_attr "length" "2")]
4184 (define_insn "pic_add_dot_plus_eight"
4185 [(set (match_operand:SI 0 "register_operand" "+r")
4186 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
4187 (use (label_ref (match_operand 1 "" "")))]
4188 "TARGET_ARM && flag_pic"
4190 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4191 CODE_LABEL_NUMBER (operands[1]));
4192 return \"add%?\\t%0, %|pc, %0\";
4194 [(set_attr "predicable" "yes")]
4197 ;; If copying one reg to another we can set the condition codes according to
4198 ;; its value. Such a move is common after a return from subroutine and the
4199 ;; result is being tested against zero.
4201 (define_insn "*movsi_compare0"
4202 [(set (reg:CC CC_REGNUM)
4203 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4205 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4210 sub%?s\\t%0, %1, #0"
4211 [(set_attr "conds" "set")]
4214 ;; Subroutine to store a half word from a register into memory.
4215 ;; Operand 0 is the source register (HImode)
4216 ;; Operand 1 is the destination address in a register (SImode)
4218 ;; In both this routine and the next, we must be careful not to spill
4219 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4220 ;; can generate unrecognizable rtl.
4222 (define_expand "storehi"
4223 [;; store the low byte
4224 (set (match_operand 1 "" "") (match_dup 3))
4225 ;; extract the high byte
4227 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4228 ;; store the high byte
4229 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
4233 rtx addr = XEXP (operands[1], 0);
4234 enum rtx_code code = GET_CODE (addr);
4236 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4238 addr = force_reg (SImode, addr);
4240 operands[4] = change_address (operands[1], QImode,
4241 plus_constant (addr, 1));
4242 operands[1] = change_address (operands[1], QImode, NULL_RTX);
4243 operands[3] = gen_lowpart (QImode, operands[0]);
4244 operands[0] = gen_lowpart (SImode, operands[0]);
4245 operands[2] = gen_reg_rtx (SImode);
4249 (define_expand "storehi_bigend"
4250 [(set (match_dup 4) (match_dup 3))
4252 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4253 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 0))]
4257 rtx addr = XEXP (operands[1], 0);
4258 enum rtx_code code = GET_CODE (addr);
4260 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4262 addr = force_reg (SImode, addr);
4264 operands[4] = change_address (operands[1], QImode,
4265 plus_constant (addr, 1));
4266 operands[1] = change_address (operands[1], QImode, NULL_RTX);
4267 operands[3] = gen_lowpart (QImode, operands[0]);
4268 operands[0] = gen_lowpart (SImode, operands[0]);
4269 operands[2] = gen_reg_rtx (SImode);
4273 ;; Subroutine to store a half word integer constant into memory.
4274 (define_expand "storeinthi"
4275 [(set (match_operand 0 "" "")
4276 (subreg:QI (match_operand 1 "" "") 0))
4277 (set (match_dup 3) (subreg:QI (match_dup 2) 0))]
4281 HOST_WIDE_INT value = INTVAL (operands[1]);
4282 rtx addr = XEXP (operands[0], 0);
4283 enum rtx_code code = GET_CODE (addr);
4285 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4287 addr = force_reg (SImode, addr);
4289 operands[1] = gen_reg_rtx (SImode);
4290 if (BYTES_BIG_ENDIAN)
4292 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4293 if ((value & 255) == ((value >> 8) & 255))
4294 operands[2] = operands[1];
4297 operands[2] = gen_reg_rtx (SImode);
4298 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4303 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4304 if ((value & 255) == ((value >> 8) & 255))
4305 operands[2] = operands[1];
4308 operands[2] = gen_reg_rtx (SImode);
4309 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4313 operands[3] = change_address (operands[0], QImode,
4314 plus_constant (addr, 1));
4315 operands[0] = change_address (operands[0], QImode, NULL_RTX);
4319 (define_expand "storehi_single_op"
4320 [(set (match_operand:HI 0 "memory_operand" "")
4321 (match_operand:HI 1 "general_operand" ""))]
4322 "TARGET_ARM && arm_arch4"
4324 if (!s_register_operand (operands[1], HImode))
4325 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4329 (define_expand "movhi"
4330 [(set (match_operand:HI 0 "general_operand" "")
4331 (match_operand:HI 1 "general_operand" ""))]
4336 if (!no_new_pseudos)
4338 if (GET_CODE (operands[0]) == MEM)
4342 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4345 if (GET_CODE (operands[1]) == CONST_INT)
4346 emit_insn (gen_storeinthi (operands[0], operands[1]));
4349 if (GET_CODE (operands[1]) == MEM)
4350 operands[1] = force_reg (HImode, operands[1]);
4351 if (BYTES_BIG_ENDIAN)
4352 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4354 emit_insn (gen_storehi (operands[1], operands[0]));
4358 /* Sign extend a constant, and keep it in an SImode reg. */
4359 else if (GET_CODE (operands[1]) == CONST_INT)
4361 rtx reg = gen_reg_rtx (SImode);
4362 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4364 /* If the constant is already valid, leave it alone. */
4365 if (!const_ok_for_arm (val))
4367 /* If setting all the top bits will make the constant
4368 loadable in a single instruction, then set them.
4369 Otherwise, sign extend the number. */
4371 if (const_ok_for_arm (~(val | ~0xffff)))
4373 else if (val & 0x8000)
4377 emit_insn (gen_movsi (reg, GEN_INT (val)));
4378 operands[1] = gen_rtx_SUBREG (HImode, reg, 0);
4380 else if (!arm_arch4)
4382 /* Note: We do not have to worry about TARGET_MMU_TRAPS
4383 for v4 and up architectures because LDRH instructions will
4384 be used to access the HI values, and these cannot generate
4385 unaligned word access faults in the MMU. */
4386 if (GET_CODE (operands[1]) == MEM)
4388 if (TARGET_MMU_TRAPS)
4391 rtx offset = const0_rtx;
4392 rtx reg = gen_reg_rtx (SImode);
4394 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4395 || (GET_CODE (base) == PLUS
4396 && (GET_CODE (offset = XEXP (base, 1))
4398 && ((INTVAL(offset) & 1) != 1)
4399 && GET_CODE (base = XEXP (base, 0)) == REG))
4400 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4402 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4405 new = gen_rtx_MEM (SImode,
4406 plus_constant (base, new_offset));
4407 MEM_COPY_ATTRIBUTES (new, operands[1]);
4408 emit_insn (gen_movsi (reg, new));
4409 if (((INTVAL (offset) & 2) != 0)
4410 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4412 rtx reg2 = gen_reg_rtx (SImode);
4414 emit_insn (gen_lshrsi3 (reg2, reg,
4420 emit_insn (gen_movhi_bytes (reg, operands[1]));
4422 operands[1] = gen_lowpart (HImode, reg);
4424 else if (BYTES_BIG_ENDIAN)
4427 rtx offset = const0_rtx;
4429 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4430 || (GET_CODE (base) == PLUS
4431 && (GET_CODE (offset = XEXP (base, 1))
4433 && GET_CODE (base = XEXP (base, 0)) == REG))
4434 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4436 rtx reg = gen_reg_rtx (SImode);
4439 if ((INTVAL (offset) & 2) == 2)
4441 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4442 new = gen_rtx_MEM (SImode,
4443 plus_constant (base,
4445 MEM_COPY_ATTRIBUTES (new, operands[1]);
4446 emit_insn (gen_movsi (reg, new));
4450 new = gen_rtx_MEM (SImode,
4451 XEXP (operands[1], 0));
4452 MEM_COPY_ATTRIBUTES (new, operands[1]);
4453 emit_insn (gen_rotated_loadsi (reg, new));
4456 operands[1] = gen_lowpart (HImode, reg);
4460 emit_insn (gen_movhi_bigend (operands[0],
4468 /* Handle loading a large integer during reload */
4469 else if (GET_CODE (operands[1]) == CONST_INT
4470 && !const_ok_for_arm (INTVAL (operands[1]))
4471 && !const_ok_for_arm (~INTVAL (operands[1])))
4473 /* Writing a constant to memory needs a scratch, which should
4474 be handled with SECONDARY_RELOADs. */
4475 if (GET_CODE (operands[0]) != REG)
4478 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4479 emit_insn (gen_movsi (operands[0], operands[1]));
4483 else /* TARGET_THUMB */
4485 if (!no_new_pseudos)
4487 if (GET_CODE (operands[0]) != REG)
4488 operands[1] = force_reg (HImode, operands[1]);
4490 /* ??? We shouldn't really get invalid addresses here, but this can
4491 happen if we are passed a SP (never OK for HImode/QImode) or
4492 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4493 HImode/QImode) relative address. */
4494 /* ??? This should perhaps be fixed elsewhere, for instance, in
4495 fixup_stack_1, by checking for other kinds of invalid addresses,
4496 e.g. a bare reference to a virtual register. This may confuse the
4497 alpha though, which must handle this case differently. */
4498 if (GET_CODE (operands[0]) == MEM
4499 && !memory_address_p (GET_MODE (operands[0]),
4500 XEXP (operands[0], 0)))
4502 rtx temp = copy_to_reg (XEXP (operands[0], 0));
4503 operands[0] = change_address (operands[0], VOIDmode, temp);
4506 if (GET_CODE (operands[1]) == MEM
4507 && !memory_address_p (GET_MODE (operands[1]),
4508 XEXP (operands[1], 0)))
4510 rtx temp = copy_to_reg (XEXP (operands[1], 0));
4511 operands[1] = change_address (operands[1], VOIDmode, temp);
4514 /* Handle loading a large integer during reload */
4515 else if (GET_CODE (operands[1]) == CONST_INT
4516 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4518 /* Writing a constant to memory needs a scratch, which should
4519 be handled with SECONDARY_RELOADs. */
4520 if (GET_CODE (operands[0]) != REG)
4523 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4524 emit_insn (gen_movsi (operands[0], operands[1]));
4531 (define_insn "*thumb_movhi_insn"
4532 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4533 (match_operand:HI 1 "general_operand" "l,mn,l,*h,*r,I"))]
4535 && ( register_operand (operands[0], HImode)
4536 || register_operand (operands[1], HImode))"
4538 switch (which_alternative)
4540 case 0: return \"add %0, %1, #0\";
4541 case 2: return \"strh %1, %0\";
4542 case 3: return \"mov %0, %1\";
4543 case 4: return \"mov %0, %1\";
4544 case 5: return \"mov %0, %1\";
4547 /* The stack pointer can end up being taken as an index register.
4548 Catch this case here and deal with it. */
4549 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4550 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4551 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4554 ops[0] = operands[0];
4555 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4557 output_asm_insn (\"mov %0, %1\", ops);
4559 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4562 return \"ldrh %0, %1\";
4564 [(set_attr "length" "2,4,2,2,2,2")
4565 (set_attr "type" "*,load,store1,*,*,*")
4566 (set_attr "pool_range" "*,64,*,*,*,*")]
4570 (define_insn "rotated_loadsi"
4571 [(set (match_operand:SI 0 "s_register_operand" "=r")
4572 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4574 "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4579 ops[0] = operands[0];
4580 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4581 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4584 [(set_attr "type" "load")
4585 (set_attr "predicable" "yes")]
4588 (define_expand "movhi_bytes"
4589 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4591 (zero_extend:SI (match_dup 6)))
4592 (set (match_operand:SI 0 "" "")
4593 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4598 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4600 mem1 = gen_rtx_MEM (QImode, addr);
4601 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4602 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4603 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4604 operands[0] = gen_lowpart (SImode, operands[0]);
4606 operands[2] = gen_reg_rtx (SImode);
4607 operands[3] = gen_reg_rtx (SImode);
4610 if (BYTES_BIG_ENDIAN)
4612 operands[4] = operands[2];
4613 operands[5] = operands[3];
4617 operands[4] = operands[3];
4618 operands[5] = operands[2];
4623 (define_expand "movhi_bigend"
4625 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4628 (ashiftrt:SI (match_dup 2) (const_int 16)))
4629 (set (match_operand:HI 0 "s_register_operand" "")
4630 (subreg:HI (match_dup 3) 0))]
4633 operands[2] = gen_reg_rtx (SImode);
4634 operands[3] = gen_reg_rtx (SImode);
4638 ;; Pattern to recognise insn generated default case above
4639 (define_insn "*movhi_insn_arch4"
4640 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4641 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4644 && (GET_CODE (operands[1]) != CONST_INT
4645 || const_ok_for_arm (INTVAL (operands[1]))
4646 || const_ok_for_arm (~INTVAL (operands[1])))"
4648 mov%?\\t%0, %1\\t%@ movhi
4649 mvn%?\\t%0, #%B1\\t%@ movhi
4650 str%?h\\t%1, %0\\t%@ movhi
4651 ldr%?h\\t%0, %1\\t%@ movhi"
4652 [(set_attr "type" "*,*,store1,load")
4653 (set_attr "predicable" "yes")
4654 (set_attr "pool_range" "*,*,*,256")
4655 (set_attr "neg_pool_range" "*,*,*,244")]
4658 (define_insn "*movhi_insn_littleend"
4659 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4660 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4663 && !BYTES_BIG_ENDIAN
4664 && !TARGET_MMU_TRAPS
4665 && (GET_CODE (operands[1]) != CONST_INT
4666 || const_ok_for_arm (INTVAL (operands[1]))
4667 || const_ok_for_arm (~INTVAL (operands[1])))"
4669 mov%?\\t%0, %1\\t%@ movhi
4670 mvn%?\\t%0, #%B1\\t%@ movhi
4671 ldr%?\\t%0, %1\\t%@ movhi"
4672 [(set_attr "type" "*,*,load")
4673 (set_attr "predicable" "yes")
4674 (set_attr "pool_range" "4096")
4675 (set_attr "neg_pool_range" "4084")]
4678 (define_insn "*movhi_insn_bigend"
4679 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4680 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4684 && !TARGET_MMU_TRAPS
4685 && (GET_CODE (operands[1]) != CONST_INT
4686 || const_ok_for_arm (INTVAL (operands[1]))
4687 || const_ok_for_arm (~INTVAL (operands[1])))"
4689 mov%?\\t%0, %1\\t%@ movhi
4690 mvn%?\\t%0, #%B1\\t%@ movhi
4691 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4692 [(set_attr "type" "*,*,load")
4693 (set_attr "predicable" "yes")
4694 (set_attr "length" "4,4,8")
4695 (set_attr "pool_range" "*,*,4092")
4696 (set_attr "neg_pool_range" "*,*,4084")]
4699 (define_insn "*loadhi_si_bigend"
4700 [(set (match_operand:SI 0 "s_register_operand" "=r")
4701 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
4705 && !TARGET_MMU_TRAPS"
4706 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4707 [(set_attr "type" "load")
4708 (set_attr "predicable" "yes")
4709 (set_attr "pool_range" "4096")
4710 (set_attr "neg_pool_range" "4084")]
4713 (define_insn "*movhi_bytes"
4714 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4715 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4716 "TARGET_ARM && TARGET_MMU_TRAPS"
4718 mov%?\\t%0, %1\\t%@ movhi
4719 mvn%?\\t%0, #%B1\\t%@ movhi"
4720 [(set_attr "predicable" "yes")]
4723 (define_insn "thumb_movhi_clobber"
4724 [(set (match_operand:HI 0 "memory_operand" "=m")
4725 (match_operand:HI 1 "register_operand" "l"))
4726 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4732 ;; We use a DImode scratch because we may occasionally need an additional
4733 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4734 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4735 (define_expand "reload_outhi"
4736 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4737 (match_operand:HI 1 "s_register_operand" "r")
4738 (match_operand:DI 2 "s_register_operand" "=&l")])]
4741 arm_reload_out_hi (operands);
4743 thumb_reload_out_hi (operands);
4748 (define_expand "reload_inhi"
4749 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4750 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4751 (match_operand:DI 2 "s_register_operand" "=&r")])]
4752 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4755 arm_reload_in_hi (operands);
4757 thumb_reload_out_hi (operands);
4761 (define_expand "movqi"
4762 [(set (match_operand:QI 0 "general_operand" "")
4763 (match_operand:QI 1 "general_operand" ""))]
4768 /* Everything except mem = const or mem = mem can be done easily */
4770 if (!no_new_pseudos)
4772 if (GET_CODE (operands[1]) == CONST_INT)
4774 rtx reg = gen_reg_rtx (SImode);
4776 emit_insn (gen_movsi (reg, operands[1]));
4777 operands[1] = gen_rtx_SUBREG (QImode, reg, 0);
4779 if (GET_CODE (operands[0]) == MEM)
4780 operands[1] = force_reg (QImode, operands[1]);
4783 else /* TARGET_THUMB */
4785 if (!no_new_pseudos)
4787 if (GET_CODE (operands[0]) != REG)
4788 operands[1] = force_reg (QImode, operands[1]);
4790 /* ??? We shouldn't really get invalid addresses here, but this can
4791 happen if we are passed a SP (never OK for HImode/QImode) or
4792 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4793 HImode/QImode) relative address. */
4794 /* ??? This should perhaps be fixed elsewhere, for instance, in
4795 fixup_stack_1, by checking for other kinds of invalid addresses,
4796 e.g. a bare reference to a virtual register. This may confuse the
4797 alpha though, which must handle this case differently. */
4798 if (GET_CODE (operands[0]) == MEM
4799 && !memory_address_p (GET_MODE (operands[0]),
4800 XEXP (operands[0], 0)))
4802 rtx temp = copy_to_reg (XEXP (operands[0], 0));
4803 operands[0] = change_address (operands[0], VOIDmode, temp);
4805 if (GET_CODE (operands[1]) == MEM
4806 && !memory_address_p (GET_MODE (operands[1]),
4807 XEXP (operands[1], 0)))
4809 rtx temp = copy_to_reg (XEXP (operands[1], 0));
4810 operands[1] = change_address (operands[1], VOIDmode, temp);
4813 /* Handle loading a large integer during reload */
4814 else if (GET_CODE (operands[1]) == CONST_INT
4815 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4817 /* Writing a constant to memory needs a scratch, which should
4818 be handled with SECONDARY_RELOADs. */
4819 if (GET_CODE (operands[0]) != REG)
4822 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4823 emit_insn (gen_movsi (operands[0], operands[1]));
4831 (define_insn "*arm_movqi_insn"
4832 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4833 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4835 && ( register_operand (operands[0], QImode)
4836 || register_operand (operands[1], QImode))"
4842 [(set_attr "type" "*,*,load,store1")
4843 (set_attr "predicable" "yes")]
4846 (define_insn "*thumb_movqi_insn"
4847 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4848 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
4850 && ( register_operand (operands[0], QImode)
4851 || register_operand (operands[1], QImode))"
4859 [(set_attr "length" "2")
4860 (set_attr "type" "*,load,store1,*,*,*")
4861 (set_attr "pool_range" "*,32,*,*,*,*")]
4864 (define_expand "movsf"
4865 [(set (match_operand:SF 0 "general_operand" "")
4866 (match_operand:SF 1 "general_operand" ""))]
4871 if (GET_CODE (operands[0]) == MEM)
4872 operands[1] = force_reg (SFmode, operands[1]);
4874 else /* TARGET_THUMB */
4876 if (!no_new_pseudos)
4878 if (GET_CODE (operands[0]) != REG)
4879 operands[1] = force_reg (SFmode, operands[1]);
4886 [(set (match_operand:SF 0 "nonimmediate_operand" "")
4887 (match_operand:SF 1 "immediate_operand" ""))]
4889 && !TARGET_HARD_FLOAT
4891 && GET_CODE (operands[1]) == CONST_DOUBLE"
4892 [(set (match_dup 2) (match_dup 3))]
4894 operands[2] = gen_lowpart (SImode, operands[0]);
4895 operands[3] = gen_lowpart (SImode, operands[1]);
4896 if (operands[2] == 0 || operands[3] == 0)
4901 (define_insn "*arm_movsf_hard_insn"
4902 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
4903 (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
4905 && TARGET_HARD_FLOAT
4906 && (GET_CODE (operands[0]) != MEM
4907 || register_operand (operands[1], SFmode))"
4913 str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
4914 stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
4916 ldr%?\\t%0, %1\\t%@ float
4917 str%?\\t%1, %0\\t%@ float"
4918 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
4919 (set_attr "predicable" "yes")
4921 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
4922 (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
4923 (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
4926 ;; Exactly the same as above, except that all `f' cases are deleted.
4927 ;; This is necessary to prevent reload from ever trying to use a `f' reg
4928 ;; when -msoft-float.
4930 (define_insn "*arm_movsf_soft_insn"
4931 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4932 (match_operand:SF 1 "general_operand" "r,mE,r"))]
4934 && TARGET_SOFT_FLOAT
4935 && (GET_CODE (operands[0]) != MEM
4936 || register_operand (operands[1], SFmode))"
4939 ldr%?\\t%0, %1\\t%@ float
4940 str%?\\t%1, %0\\t%@ float"
4941 [(set_attr "length" "4,4,4")
4942 (set_attr "predicable" "yes")
4943 (set_attr "type" "*,load,store1")
4944 (set_attr "pool_range" "*,4096,*")
4945 (set_attr "neg_pool_range" "*,4084,*")]
4948 ;;; ??? This should have alternatives for constants.
4949 (define_insn "*thumb_movsf_insn"
4950 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4951 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
4953 && ( register_operand (operands[0], SFmode)
4954 || register_operand (operands[1], SFmode))"
4963 [(set_attr "length" "2")
4964 (set_attr "type" "*,load,store1,load,store1,*,*")
4965 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
4968 (define_expand "movdf"
4969 [(set (match_operand:DF 0 "general_operand" "")
4970 (match_operand:DF 1 "general_operand" ""))]
4975 if (GET_CODE (operands[0]) == MEM)
4976 operands[1] = force_reg (DFmode, operands[1]);
4978 else /* TARGET_THUMB */
4980 if (!no_new_pseudos)
4982 if (GET_CODE (operands[0]) != REG)
4983 operands[1] = force_reg (DFmode, operands[1]);
4989 ;; Reloading a df mode value stored in integer regs to memory can require a
4991 (define_expand "reload_outdf"
4992 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
4993 (match_operand:DF 1 "s_register_operand" "r")
4994 (match_operand:SI 2 "s_register_operand" "=&r")]
4998 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5001 operands[2] = XEXP (operands[0], 0);
5002 else if (code == POST_INC || code == PRE_DEC)
5004 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5005 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5006 emit_insn (gen_movdi (operands[0], operands[1]));
5009 else if (code == PRE_INC)
5011 rtx reg = XEXP (XEXP (operands[0], 0), 0);
5013 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5016 else if (code == POST_DEC)
5017 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5019 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5020 XEXP (XEXP (operands[0], 0), 1)));
5022 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5025 if (code == POST_DEC)
5026 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5032 (define_insn "*movdf_hard_insn"
5033 [(set (match_operand:DF 0 "nonimmediate_operand"
5034 "=r,Q,r,m,r, f, f,f, m,!f,!r")
5035 (match_operand:DF 1 "general_operand"
5036 "Q, r,r,r,mF,fG,H,mF,f,r, f"))]
5038 && TARGET_HARD_FLOAT
5039 && (GET_CODE (operands[0]) != MEM
5040 || register_operand (operands[1], DFmode))"
5043 switch (which_alternative)
5046 case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
5047 case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
5048 case 2: case 3: case 4: return output_move_double (operands);
5049 case 5: return \"mvf%?d\\t%0, %1\";
5050 case 6: return \"mnf%?d\\t%0, #%N1\";
5051 case 7: return \"ldf%?d\\t%0, %1\";
5052 case 8: return \"stf%?d\\t%1, %0\";
5053 case 9: return output_mov_double_fpu_from_arm (operands);
5054 case 10: return output_mov_double_arm_from_fpu (operands);
5058 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
5059 (set_attr "predicable" "yes")
5061 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
5062 (set_attr "pool_range" "*,*,*,*,252,*,*,1024,*,*,*")
5063 (set_attr "neg_pool_range" "*,*,*,*,244,*,*,1012,*,*,*")]
5066 ;; Software floating point version. This is essentially the same as movdi.
5067 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
5070 (define_insn "*movdf_soft_insn"
5071 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5072 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5073 "TARGET_ARM && TARGET_SOFT_FLOAT
5075 "* return output_move_double (operands);"
5076 [(set_attr "length" "8,8,8")
5077 (set_attr "type" "*,load,store2")
5078 (set_attr "pool_range" "252")
5079 (set_attr "neg_pool_range" "244")]
5082 ;;; ??? This should have alternatives for constants.
5083 ;;; ??? This was originally identical to the movdi_insn pattern.
5084 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5085 ;;; thumb_reorg with a memory reference.
5086 (define_insn "*thumb_movdf_insn"
5087 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5088 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
5090 && ( register_operand (operands[0], DFmode)
5091 || register_operand (operands[1], DFmode))"
5093 switch (which_alternative)
5097 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5098 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5099 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5101 return \"ldmia\\t%1, {%0, %H0}\";
5103 return \"stmia\\t%0, {%1, %H1}\";
5105 return thumb_load_double_from_address (operands);
5107 operands[2] = gen_rtx (MEM, SImode,
5108 plus_constant (XEXP (operands[0], 0), 4));
5109 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5112 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5113 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5114 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5117 [(set_attr "length" "4,2,2,6,4,4")
5118 (set_attr "type" "*,load,store2,load,store2,*")
5119 (set_attr "pool_range" "*,*,*,1020,*,*")]
5123 (define_expand "movxf"
5124 [(set (match_operand:XF 0 "general_operand" "")
5125 (match_operand:XF 1 "general_operand" ""))]
5126 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5129 ;; Even when the XFmode patterns aren't enabled, we enable this after
5130 ;; reloading so that we can push floating point registers in the prologue.
5132 (define_insn "*movxf_hard_insn"
5133 [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
5134 (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
5135 "TARGET_ARM && TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
5137 switch (which_alternative)
5140 case 0: return \"mvf%?e\\t%0, %1\";
5141 case 1: return \"mnf%?e\\t%0, #%N1\";
5142 case 2: return \"ldf%?e\\t%0, %1\";
5143 case 3: return \"stf%?e\\t%1, %0\";
5144 case 4: return output_mov_long_double_fpu_from_arm (operands);
5145 case 5: return output_mov_long_double_arm_from_fpu (operands);
5146 case 6: return output_mov_long_double_arm_from_arm (operands);
5149 [(set_attr "length" "4,4,4,4,8,8,12")
5150 (set_attr "predicable" "yes")
5151 (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
5152 (set_attr "pool_range" "*,*,1024,*,*,*,*")
5153 (set_attr "neg_pool_range" "*,*,1012,*,*,*,*")]
5157 ;; load- and store-multiple insns
5158 ;; The arm can load/store any set of registers, provided that they are in
5159 ;; ascending order; but that is beyond GCC so stick with what it knows.
5161 (define_expand "load_multiple"
5162 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5163 (match_operand:SI 1 "" ""))
5164 (use (match_operand:SI 2 "" ""))])]
5167 /* Support only fixed point registers. */
5168 if (GET_CODE (operands[2]) != CONST_INT
5169 || INTVAL (operands[2]) > 14
5170 || INTVAL (operands[2]) < 2
5171 || GET_CODE (operands[1]) != MEM
5172 || GET_CODE (operands[0]) != REG
5173 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5174 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5178 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5179 force_reg (SImode, XEXP (operands[1], 0)),
5180 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5181 MEM_IN_STRUCT_P(operands[1]),
5182 MEM_SCALAR_P (operands[1]));
5186 ;; Load multiple with write-back
5188 (define_insn "*ldmsi_postinc"
5189 [(match_parallel 0 "load_multiple_operation"
5190 [(set (match_operand:SI 1 "s_register_operand" "+r")
5191 (plus:SI (match_dup 1)
5192 (match_operand:SI 2 "const_int_operand" "n")))
5193 (set (match_operand:SI 3 "s_register_operand" "=r")
5194 (mem:SI (match_dup 1)))])]
5195 "TARGET_ARM && (INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 1))"
5199 int count = XVECLEN (operands[0], 0);
5201 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
5202 ops[1] = SET_DEST (XVECEXP (operands[0], 0, 1));
5203 ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 1));
5205 output_asm_insn (\"ldm%?ia\\t%0!, {%1-%2}\\t%@ load multiple\", ops);
5209 [(set_attr "type" "load")
5210 (set_attr "predicable" "yes")]
5213 ;; Ordinary load multiple
5215 (define_insn "*ldmsi"
5216 [(match_parallel 0 "load_multiple_operation"
5217 [(set (match_operand:SI 1 "s_register_operand" "=r")
5218 (mem:SI (match_operand:SI 2 "s_register_operand" "r")))])]
5223 int count = XVECLEN (operands[0], 0);
5225 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
5226 ops[1] = SET_DEST (XVECEXP (operands[0], 0, 0));
5227 ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 1));
5229 output_asm_insn (\"ldm%?ia\\t%0, {%1-%2}\\t%@ load multiple\", ops);
5233 [(set_attr "type" "load")
5234 (set_attr "predicable" "yes")]
5237 (define_expand "store_multiple"
5238 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5239 (match_operand:SI 1 "" ""))
5240 (use (match_operand:SI 2 "" ""))])]
5243 /* Support only fixed point registers */
5244 if (GET_CODE (operands[2]) != CONST_INT
5245 || INTVAL (operands[2]) > 14
5246 || INTVAL (operands[2]) < 2
5247 || GET_CODE (operands[1]) != REG
5248 || GET_CODE (operands[0]) != MEM
5249 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5250 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5254 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5255 force_reg (SImode, XEXP (operands[0], 0)),
5256 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5257 MEM_IN_STRUCT_P(operands[0]),
5258 MEM_SCALAR_P (operands[0]));
5262 ;; Store multiple with write-back
5264 (define_insn "*stmsi_postinc"
5265 [(match_parallel 0 "store_multiple_operation"
5266 [(set (match_operand:SI 1 "s_register_operand" "+r")
5267 (plus:SI (match_dup 1)
5268 (match_operand:SI 2 "const_int_operand" "n")))
5269 (set (mem:SI (match_dup 1))
5270 (match_operand:SI 3 "s_register_operand" "r"))])]
5271 "TARGET_ARM && (INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 1))"
5275 int count = XVECLEN (operands[0], 0);
5277 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
5278 ops[1] = SET_SRC (XVECEXP (operands[0], 0, 1));
5279 ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 1));
5281 output_asm_insn (\"stm%?ia\\t%0!, {%1-%2}\\t%@ str multiple\", ops);
5285 [(set_attr "predicable" "yes")
5287 (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 3))
5288 (const_string "store2")
5289 (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
5290 (const_string "store3")]
5291 (const_string "store4")))]
5294 ;; Ordinary store multiple
5296 (define_insn "*stmsi"
5297 [(match_parallel 0 "store_multiple_operation"
5298 [(set (mem:SI (match_operand:SI 2 "s_register_operand" "r"))
5299 (match_operand:SI 1 "s_register_operand" "r"))])]
5304 int count = XVECLEN (operands[0], 0);
5306 ops[0] = XEXP (SET_DEST (XVECEXP (operands[0], 0, 0)), 0);
5307 ops[1] = SET_SRC (XVECEXP (operands[0], 0, 0));
5308 ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 1));
5310 output_asm_insn (\"stm%?ia\\t%0, {%1-%2}\\t%@ str multiple\", ops);
5314 [(set_attr "predicable" "yes")
5316 (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 3))
5317 (const_string "store2")
5318 (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
5319 (const_string "store3")]
5320 (const_string "store4")))]
5323 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5324 ;; We could let this apply for blocks of less than this, but it clobbers so
5325 ;; many registers that there is then probably a better way.
5327 (define_expand "movstrqi"
5328 [(match_operand:BLK 0 "general_operand" "")
5329 (match_operand:BLK 1 "general_operand" "")
5330 (match_operand:SI 2 "const_int_operand" "")
5331 (match_operand:SI 3 "const_int_operand" "")]
5336 if (arm_gen_movstrqi (operands))
5340 else /* TARGET_THUMB */
5342 if ( INTVAL (operands[3]) != 4
5343 || INTVAL (operands[2]) > 48)
5346 thumb_expand_movstrqi (operands);
5354 (define_insn "movmem12b"
5355 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5356 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5357 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5358 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5359 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5360 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5361 (set (match_operand:SI 0 "register_operand" "=l")
5362 (plus:SI (match_dup 2) (const_int 12)))
5363 (set (match_operand:SI 1 "register_operand" "=l")
5364 (plus:SI (match_dup 3) (const_int 12)))
5365 (clobber (match_scratch:SI 4 "=&l"))
5366 (clobber (match_scratch:SI 5 "=&l"))
5367 (clobber (match_scratch:SI 6 "=&l"))]
5369 "* return thumb_output_move_mem_multiple (3, operands);"
5370 [(set_attr "length" "4")
5371 ; This isn't entirely accurate... It loads as well, but in terms of
5372 ; scheduling the following insn it is better to consider it as a store
5373 (set_attr "type" "store3")]
5376 (define_insn "movmem8b"
5377 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5378 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5379 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5380 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5381 (set (match_operand:SI 0 "register_operand" "=l")
5382 (plus:SI (match_dup 2) (const_int 8)))
5383 (set (match_operand:SI 1 "register_operand" "=l")
5384 (plus:SI (match_dup 3) (const_int 8)))
5385 (clobber (match_scratch:SI 4 "=&l"))
5386 (clobber (match_scratch:SI 5 "=&l"))]
5388 "* return thumb_output_move_mem_multiple (2, operands);"
5389 [(set_attr "length" "4")
5390 ; This isn't entirely accurate... It loads as well, but in terms of
5391 ; scheduling the following insn it is better to consider it as a store
5392 (set_attr "type" "store2")]
5397 ;; Comapre & branch insns
5399 (define_insn "cbranchsi4"
5402 (match_operator 0 "arm_comparison_operator"
5403 [(match_operand:SI 1 "register_operand" "l,r")
5404 (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5405 (label_ref (match_operand 3 "" ""))
5409 output_asm_insn (\"cmp\\t%1, %2\", operands);
5410 switch (get_attr_length (insn))
5412 case 4: return \"b%d0\\t%l3\";
5413 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5414 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5417 [(set (attr "far_jump")
5419 (eq_attr "length" "8")
5420 (const_string "yes")
5421 (const_string "no")))
5422 (set (attr "length")
5424 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5425 (le (minus (match_dup 3) (pc)) (const_int 256)))
5428 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5429 (le (minus (match_dup 3) (pc)) (const_int 2054)))
5434 (define_insn "*negated_cbranchsi4"
5437 (match_operator 0 "arm_comparison_operator"
5438 [(match_operand:SI 1 "register_operand" "l")
5439 (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5440 (label_ref (match_operand 3 "" ""))
5444 output_asm_insn (\"cmn\\t%1, %2\", operands);
5445 switch (get_attr_length (insn))
5447 case 4: return \"b%d0\\t%l3\";
5448 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5449 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5452 [(set (attr "far_jump")
5454 (eq_attr "length" "8")
5455 (const_string "yes")
5456 (const_string "no")))
5457 (set (attr "length")
5459 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5460 (le (minus (match_dup 3) (pc)) (const_int 254)))
5463 (and (ge (minus (match_dup 3) (pc)) (const_int -2044))
5464 (le (minus (match_dup 3) (pc)) (const_int 2044)))
5470 ;; Comparison and test insns
5472 (define_expand "cmpsi"
5473 [(match_operand:SI 0 "s_register_operand" "")
5474 (match_operand:SI 1 "arm_add_operand" "")]
5477 arm_compare_op0 = operands[0];
5478 arm_compare_op1 = operands[1];
5483 (define_expand "cmpsf"
5484 [(match_operand:SF 0 "s_register_operand" "")
5485 (match_operand:SF 1 "fpu_rhs_operand" "")]
5486 "TARGET_ARM && TARGET_HARD_FLOAT"
5488 arm_compare_op0 = operands[0];
5489 arm_compare_op1 = operands[1];
5494 (define_expand "cmpdf"
5495 [(match_operand:DF 0 "s_register_operand" "")
5496 (match_operand:DF 1 "fpu_rhs_operand" "")]
5497 "TARGET_ARM && TARGET_HARD_FLOAT"
5499 arm_compare_op0 = operands[0];
5500 arm_compare_op1 = operands[1];
5505 (define_expand "cmpxf"
5506 [(match_operand:XF 0 "s_register_operand" "")
5507 (match_operand:XF 1 "fpu_rhs_operand" "")]
5508 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5510 arm_compare_op0 = operands[0];
5511 arm_compare_op1 = operands[1];
5516 (define_insn "*arm_cmpsi_insn"
5517 [(set (reg:CC CC_REGNUM)
5518 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5519 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
5524 [(set_attr "conds" "set")]
5527 (define_insn "*cmpsi_shiftsi"
5528 [(set (reg:CC CC_REGNUM)
5529 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5530 (match_operator:SI 3 "shift_operator"
5531 [(match_operand:SI 1 "s_register_operand" "r")
5532 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
5535 [(set_attr "conds" "set")
5536 (set_attr "shift" "1")
5540 (define_insn "*cmpsi_shiftsi_swp"
5541 [(set (reg:CC_SWP CC_REGNUM)
5542 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5543 [(match_operand:SI 1 "s_register_operand" "r")
5544 (match_operand:SI 2 "reg_or_int_operand" "rM")])
5545 (match_operand:SI 0 "s_register_operand" "r")))]
5548 [(set_attr "conds" "set")
5549 (set_attr "shift" "1")
5553 (define_insn "*cmpsi_neg_shiftsi"
5554 [(set (reg:CC CC_REGNUM)
5555 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5556 (neg:SI (match_operator:SI 3 "shift_operator"
5557 [(match_operand:SI 1 "s_register_operand" "r")
5558 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5561 [(set_attr "conds" "set")
5562 (set_attr "shift" "1")
5566 (define_insn "*cmpsf_insn"
5567 [(set (reg:CCFP CC_REGNUM)
5568 (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
5569 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5570 "TARGET_ARM && TARGET_HARD_FLOAT"
5574 [(set_attr "conds" "set")
5575 (set_attr "type" "f_2_r")]
5578 (define_insn "*cmpdf_insn"
5579 [(set (reg:CCFP CC_REGNUM)
5580 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
5581 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5582 "TARGET_ARM && TARGET_HARD_FLOAT"
5586 [(set_attr "conds" "set")
5587 (set_attr "type" "f_2_r")]
5590 (define_insn "*cmpesfdf_df"
5591 [(set (reg:CCFP CC_REGNUM)
5592 (compare:CCFP (float_extend:DF
5593 (match_operand:SF 0 "s_register_operand" "f,f"))
5594 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5595 "TARGET_ARM && TARGET_HARD_FLOAT"
5599 [(set_attr "conds" "set")
5600 (set_attr "type" "f_2_r")]
5603 (define_insn "*cmpdf_esfdf"
5604 [(set (reg:CCFP CC_REGNUM)
5605 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5607 (match_operand:SF 1 "s_register_operand" "f"))))]
5608 "TARGET_ARM && TARGET_HARD_FLOAT"
5610 [(set_attr "conds" "set")
5611 (set_attr "type" "f_2_r")]
5614 (define_insn "*cmpxf_insn"
5615 [(set (reg:CCFP CC_REGNUM)
5616 (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
5617 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5618 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5622 [(set_attr "conds" "set")
5623 (set_attr "type" "f_2_r")]
5626 (define_insn "*cmpsf_trap"
5627 [(set (reg:CCFPE CC_REGNUM)
5628 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
5629 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5630 "TARGET_ARM && TARGET_HARD_FLOAT"
5634 [(set_attr "conds" "set")
5635 (set_attr "type" "f_2_r")]
5638 (define_insn "*cmpdf_trap"
5639 [(set (reg:CCFPE CC_REGNUM)
5640 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
5641 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5642 "TARGET_ARM && TARGET_HARD_FLOAT"
5646 [(set_attr "conds" "set")
5647 (set_attr "type" "f_2_r")]
5650 (define_insn "*cmp_esfdf_df_trap"
5651 [(set (reg:CCFPE CC_REGNUM)
5652 (compare:CCFPE (float_extend:DF
5653 (match_operand:SF 0 "s_register_operand" "f,f"))
5654 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5655 "TARGET_ARM && TARGET_HARD_FLOAT"
5659 [(set_attr "conds" "set")
5660 (set_attr "type" "f_2_r")]
5663 (define_insn "*cmp_df_esfdf_trap"
5664 [(set (reg:CCFPE CC_REGNUM)
5665 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
5667 (match_operand:SF 1 "s_register_operand" "f"))))]
5668 "TARGET_ARM && TARGET_HARD_FLOAT"
5670 [(set_attr "conds" "set")
5671 (set_attr "type" "f_2_r")]
5674 (define_insn "*cmpxf_trap"
5675 [(set (reg:CCFPE CC_REGNUM)
5676 (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
5677 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5678 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5682 [(set_attr "conds" "set")
5683 (set_attr "type" "f_2_r")]
5686 ; This insn allows redundant compares to be removed by cse, nothing should
5687 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5688 ; is deleted later on. The match_dup will match the mode here, so that
5689 ; mode changes of the condition codes aren't lost by this even though we don't
5690 ; specify what they are.
5692 (define_insn "*deleted_compare"
5693 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5695 "\\t%@ deleted compare"
5696 [(set_attr "conds" "set")
5697 (set_attr "length" "0")]
5701 ;; Conditional branch insns
5703 (define_expand "beq"
5705 (if_then_else (eq (match_dup 1) (const_int 0))
5706 (label_ref (match_operand 0 "" ""))
5709 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5712 (define_expand "bne"
5714 (if_then_else (ne (match_dup 1) (const_int 0))
5715 (label_ref (match_operand 0 "" ""))
5718 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5721 (define_expand "bgt"
5723 (if_then_else (gt (match_dup 1) (const_int 0))
5724 (label_ref (match_operand 0 "" ""))
5727 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5730 (define_expand "ble"
5732 (if_then_else (le (match_dup 1) (const_int 0))
5733 (label_ref (match_operand 0 "" ""))
5736 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5739 (define_expand "bge"
5741 (if_then_else (ge (match_dup 1) (const_int 0))
5742 (label_ref (match_operand 0 "" ""))
5745 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5748 (define_expand "blt"
5750 (if_then_else (lt (match_dup 1) (const_int 0))
5751 (label_ref (match_operand 0 "" ""))
5754 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5757 (define_expand "bgtu"
5759 (if_then_else (gtu (match_dup 1) (const_int 0))
5760 (label_ref (match_operand 0 "" ""))
5763 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5766 (define_expand "bleu"
5768 (if_then_else (leu (match_dup 1) (const_int 0))
5769 (label_ref (match_operand 0 "" ""))
5772 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5775 (define_expand "bgeu"
5777 (if_then_else (geu (match_dup 1) (const_int 0))
5778 (label_ref (match_operand 0 "" ""))
5781 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5784 (define_expand "bltu"
5786 (if_then_else (ltu (match_dup 1) (const_int 0))
5787 (label_ref (match_operand 0 "" ""))
5790 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5793 (define_expand "bunordered"
5795 (if_then_else (unordered (match_dup 1) (const_int 0))
5796 (label_ref (match_operand 0 "" ""))
5798 "TARGET_ARM && TARGET_HARD_FLOAT"
5799 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5803 (define_expand "bordered"
5805 (if_then_else (ordered (match_dup 1) (const_int 0))
5806 (label_ref (match_operand 0 "" ""))
5808 "TARGET_ARM && TARGET_HARD_FLOAT"
5809 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5813 (define_expand "bungt"
5815 (if_then_else (ungt (match_dup 1) (const_int 0))
5816 (label_ref (match_operand 0 "" ""))
5818 "TARGET_ARM && TARGET_HARD_FLOAT"
5819 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5822 (define_expand "bunlt"
5824 (if_then_else (unlt (match_dup 1) (const_int 0))
5825 (label_ref (match_operand 0 "" ""))
5827 "TARGET_ARM && TARGET_HARD_FLOAT"
5828 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5831 (define_expand "bunge"
5833 (if_then_else (unge (match_dup 1) (const_int 0))
5834 (label_ref (match_operand 0 "" ""))
5836 "TARGET_ARM && TARGET_HARD_FLOAT"
5837 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5840 (define_expand "bunle"
5842 (if_then_else (unle (match_dup 1) (const_int 0))
5843 (label_ref (match_operand 0 "" ""))
5845 "TARGET_ARM && TARGET_HARD_FLOAT"
5846 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5849 ;; The following two patterns need two branch instructions, since there is
5850 ;; no single instruction that will handle all cases.
5851 (define_expand "buneq"
5853 (if_then_else (uneq (match_dup 1) (const_int 0))
5854 (label_ref (match_operand 0 "" ""))
5856 "TARGET_ARM && TARGET_HARD_FLOAT"
5857 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
5860 (define_expand "bltgt"
5862 (if_then_else (ltgt (match_dup 1) (const_int 0))
5863 (label_ref (match_operand 0 "" ""))
5865 "TARGET_ARM && TARGET_HARD_FLOAT"
5866 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
5870 ;; Patterns to match conditional branch insns.
5873 ; Special pattern to match UNEQ.
5874 (define_insn "*arm_buneq"
5876 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5877 (label_ref (match_operand 0 "" ""))
5879 "TARGET_ARM && TARGET_HARD_FLOAT"
5881 if (arm_ccfsm_state != 0)
5884 return \"bvs\\t%l0;beq\\t%l0\";
5886 [(set_attr "conds" "jump_clob")
5887 (set_attr "length" "8")]
5890 ; Special pattern to match LTGT.
5891 (define_insn "*arm_bltgt"
5893 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5894 (label_ref (match_operand 0 "" ""))
5896 "TARGET_ARM && TARGET_HARD_FLOAT"
5898 if (arm_ccfsm_state != 0)
5901 return \"bmi\\t%l0;bgt\\t%l0\";
5903 [(set_attr "conds" "jump_clob")
5904 (set_attr "length" "8")]
5907 (define_insn "*arm_cond_branch"
5909 (if_then_else (match_operator 1 "arm_comparison_operator"
5910 [(match_operand 2 "cc_register" "") (const_int 0)])
5911 (label_ref (match_operand 0 "" ""))
5915 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5917 arm_ccfsm_state += 2;
5920 return \"b%d1\\t%l0\";
5922 [(set_attr "conds" "use")]
5925 ; Special pattern to match reversed UNEQ.
5926 (define_insn "*arm_buneq_reversed"
5928 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5930 (label_ref (match_operand 0 "" ""))))]
5931 "TARGET_ARM && TARGET_HARD_FLOAT"
5933 if (arm_ccfsm_state != 0)
5936 return \"bmi\\t%l0;bgt\\t%l0\";
5938 [(set_attr "conds" "jump_clob")
5939 (set_attr "length" "8")]
5942 ; Special pattern to match reversed LTGT.
5943 (define_insn "*arm_bltgt_reversed"
5945 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5947 (label_ref (match_operand 0 "" ""))))]
5948 "TARGET_ARM && TARGET_HARD_FLOAT"
5950 if (arm_ccfsm_state != 0)
5953 return \"bvs\\t%l0;beq\\t%l0\";
5955 [(set_attr "conds" "jump_clob")
5956 (set_attr "length" "8")]
5959 (define_insn "*arm_cond_branch_reversed"
5961 (if_then_else (match_operator 1 "arm_comparison_operator"
5962 [(match_operand 2 "cc_register" "") (const_int 0)])
5964 (label_ref (match_operand 0 "" ""))))]
5967 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5969 arm_ccfsm_state += 2;
5972 return \"b%D1\\t%l0\";
5974 [(set_attr "conds" "use")]
5981 (define_expand "seq"
5982 [(set (match_operand:SI 0 "s_register_operand" "=r")
5983 (eq:SI (match_dup 1) (const_int 0)))]
5985 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5988 (define_expand "sne"
5989 [(set (match_operand:SI 0 "s_register_operand" "=r")
5990 (ne:SI (match_dup 1) (const_int 0)))]
5992 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5995 (define_expand "sgt"
5996 [(set (match_operand:SI 0 "s_register_operand" "=r")
5997 (gt:SI (match_dup 1) (const_int 0)))]
5999 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6002 (define_expand "sle"
6003 [(set (match_operand:SI 0 "s_register_operand" "=r")
6004 (le:SI (match_dup 1) (const_int 0)))]
6006 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6009 (define_expand "sge"
6010 [(set (match_operand:SI 0 "s_register_operand" "=r")
6011 (ge:SI (match_dup 1) (const_int 0)))]
6013 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6016 (define_expand "slt"
6017 [(set (match_operand:SI 0 "s_register_operand" "=r")
6018 (lt:SI (match_dup 1) (const_int 0)))]
6020 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6023 (define_expand "sgtu"
6024 [(set (match_operand:SI 0 "s_register_operand" "=r")
6025 (gtu:SI (match_dup 1) (const_int 0)))]
6027 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6030 (define_expand "sleu"
6031 [(set (match_operand:SI 0 "s_register_operand" "=r")
6032 (leu:SI (match_dup 1) (const_int 0)))]
6034 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6037 (define_expand "sgeu"
6038 [(set (match_operand:SI 0 "s_register_operand" "=r")
6039 (geu:SI (match_dup 1) (const_int 0)))]
6041 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6044 (define_expand "sltu"
6045 [(set (match_operand:SI 0 "s_register_operand" "=r")
6046 (ltu:SI (match_dup 1) (const_int 0)))]
6048 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6051 (define_expand "sunordered"
6052 [(set (match_operand:SI 0 "s_register_operand" "=r")
6053 (unordered:SI (match_dup 1) (const_int 0)))]
6054 "TARGET_ARM && TARGET_HARD_FLOAT"
6055 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6059 (define_expand "sordered"
6060 [(set (match_operand:SI 0 "s_register_operand" "=r")
6061 (ordered:SI (match_dup 1) (const_int 0)))]
6062 "TARGET_ARM && TARGET_HARD_FLOAT"
6063 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6067 (define_expand "sungt"
6068 [(set (match_operand:SI 0 "s_register_operand" "=r")
6069 (ungt:SI (match_dup 1) (const_int 0)))]
6070 "TARGET_ARM && TARGET_HARD_FLOAT"
6071 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6075 (define_expand "sunge"
6076 [(set (match_operand:SI 0 "s_register_operand" "=r")
6077 (unge:SI (match_dup 1) (const_int 0)))]
6078 "TARGET_ARM && TARGET_HARD_FLOAT"
6079 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6083 (define_expand "sunlt"
6084 [(set (match_operand:SI 0 "s_register_operand" "=r")
6085 (unlt:SI (match_dup 1) (const_int 0)))]
6086 "TARGET_ARM && TARGET_HARD_FLOAT"
6087 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6091 (define_expand "sunle"
6092 [(set (match_operand:SI 0 "s_register_operand" "=r")
6093 (unle:SI (match_dup 1) (const_int 0)))]
6094 "TARGET_ARM && TARGET_HARD_FLOAT"
6095 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6099 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6100 ;;; simple ARM instructions.
6102 ; (define_expand "suneq"
6103 ; [(set (match_operand:SI 0 "s_register_operand" "=r")
6104 ; (uneq:SI (match_dup 1) (const_int 0)))]
6105 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6109 ; (define_expand "sltgt"
6110 ; [(set (match_operand:SI 0 "s_register_operand" "=r")
6111 ; (ltgt:SI (match_dup 1) (const_int 0)))]
6112 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6116 (define_insn "*mov_scc"
6117 [(set (match_operand:SI 0 "s_register_operand" "=r")
6118 (match_operator:SI 1 "arm_comparison_operator"
6119 [(match_operand 2 "cc_register" "") (const_int 0)]))]
6121 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6122 [(set_attr "conds" "use")
6123 (set_attr "length" "8")]
6126 (define_insn "*mov_negscc"
6127 [(set (match_operand:SI 0 "s_register_operand" "=r")
6128 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
6129 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6131 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6132 [(set_attr "conds" "use")
6133 (set_attr "length" "8")]
6136 (define_insn "*mov_notscc"
6137 [(set (match_operand:SI 0 "s_register_operand" "=r")
6138 (not:SI (match_operator:SI 1 "arm_comparison_operator"
6139 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6141 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6142 [(set_attr "conds" "use")
6143 (set_attr "length" "8")]
6147 ;; Conditional move insns
6149 (define_expand "movsicc"
6150 [(set (match_operand:SI 0 "s_register_operand" "")
6151 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6152 (match_operand:SI 2 "arm_not_operand" "")
6153 (match_operand:SI 3 "arm_not_operand" "")))]
6157 enum rtx_code code = GET_CODE (operands[1]);
6158 rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6160 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6164 (define_expand "movsfcc"
6165 [(set (match_operand:SF 0 "s_register_operand" "")
6166 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6167 (match_operand:SF 2 "s_register_operand" "")
6168 (match_operand:SF 3 "nonmemory_operand" "")))]
6172 enum rtx_code code = GET_CODE (operands[1]);
6175 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
6176 Otherwise, ensure it is a valid FP add operand */
6177 if ((!TARGET_HARD_FLOAT)
6178 || (!fpu_add_operand (operands[3], SFmode)))
6179 operands[3] = force_reg (SFmode, operands[3]);
6181 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6182 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6186 (define_expand "movdfcc"
6187 [(set (match_operand:DF 0 "s_register_operand" "")
6188 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6189 (match_operand:DF 2 "s_register_operand" "")
6190 (match_operand:DF 3 "fpu_add_operand" "")))]
6191 "TARGET_ARM && TARGET_HARD_FLOAT"
6194 enum rtx_code code = GET_CODE (operands[1]);
6195 rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6197 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6201 (define_insn "*movsicc_insn"
6202 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6204 (match_operator 3 "arm_comparison_operator"
6205 [(match_operand 4 "cc_register" "") (const_int 0)])
6206 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6207 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6214 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6215 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6216 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6217 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6218 [(set_attr "length" "4,4,4,4,8,8,8,8")
6219 (set_attr "conds" "use")]
6222 (define_insn "*movsfcc_hard_insn"
6223 [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6225 (match_operator 3 "arm_comparison_operator"
6226 [(match_operand 4 "cc_register" "") (const_int 0)])
6227 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6228 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6229 "TARGET_ARM && TARGET_HARD_FLOAT"
6235 mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
6236 mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
6237 mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
6238 mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
6239 [(set_attr "length" "4,4,4,4,8,8,8,8")
6240 (set_attr "type" "ffarith")
6241 (set_attr "conds" "use")]
6244 (define_insn "*movsfcc_soft_insn"
6245 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6246 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
6247 [(match_operand 4 "cc_register" "") (const_int 0)])
6248 (match_operand:SF 1 "s_register_operand" "0,r")
6249 (match_operand:SF 2 "s_register_operand" "r,0")))]
6250 "TARGET_ARM && TARGET_SOFT_FLOAT"
6254 [(set_attr "conds" "use")]
6257 (define_insn "*movdfcc_insn"
6258 [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6260 (match_operator 3 "arm_comparison_operator"
6261 [(match_operand 4 "cc_register" "") (const_int 0)])
6262 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6263 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6264 "TARGET_ARM && TARGET_HARD_FLOAT"
6270 mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
6271 mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
6272 mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
6273 mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
6274 [(set_attr "length" "4,4,4,4,8,8,8,8")
6275 (set_attr "type" "ffarith")
6276 (set_attr "conds" "use")]
6280 ;; Jump and linkage insns
6282 (define_expand "jump"
6284 (label_ref (match_operand 0 "" "")))]
6289 (define_insn "*arm_jump"
6291 (label_ref (match_operand 0 "" "")))]
6295 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6297 arm_ccfsm_state += 2;
6300 return \"b%?\\t%l0\";
6303 [(set_attr "predicable" "yes")]
6306 (define_insn "*thumb_jump"
6308 (label_ref (match_operand 0 "" "")))]
6311 if (get_attr_length (insn) == 2)
6313 return \"bl\\t%l0\\t%@ far jump\";
6315 [(set (attr "far_jump")
6317 (eq_attr "length" "4")
6318 (const_string "yes")
6319 (const_string "no")))
6320 (set (attr "length")
6322 (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6323 (le (minus (match_dup 0) (pc)) (const_int 2044)))
6328 (define_expand "call"
6329 [(parallel [(call (match_operand 0 "memory_operand" "")
6330 (match_operand 1 "general_operand" ""))
6331 (use (match_operand 2 "" ""))
6332 (clobber (reg:SI LR_REGNUM))])]
6338 /* In an untyped call, we can get NULL for operand 2. */
6339 if (operands[2] == NULL_RTX)
6340 operands[2] = const0_rtx;
6342 /* This is to decide if we should generate indirect calls by loading the
6343 32 bit address of the callee into a register before performing the
6344 branch and link. operand[2] encodes the long_call/short_call
6345 attribute of the function being called. This attribute is set whenever
6346 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6347 is used, and the short_call attribute can also be set if function is
6348 declared as static or if it has already been defined in the current
6349 compilation unit. See arm.c and arm.h for info about this. The third
6350 parameter to arm_is_longcall_p is used to tell it which pattern
6352 callee = XEXP (operands[0], 0);
6354 if (GET_CODE (callee) != REG
6355 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6356 XEXP (operands[0], 0) = force_reg (Pmode, callee);
6360 (define_insn "*call_reg"
6361 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
6362 (match_operand 1 "" ""))
6363 (use (match_operand 2 "" ""))
6364 (clobber (reg:SI LR_REGNUM))]
6367 return output_call (operands);
6369 ;; length is worst case, normally it is only two
6370 [(set_attr "length" "12")
6371 (set_attr "type" "call")]
6374 (define_insn "*call_mem"
6375 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
6376 (match_operand 1 "" ""))
6377 (use (match_operand 2 "" ""))
6378 (clobber (reg:SI LR_REGNUM))]
6381 return output_call_mem (operands);
6383 [(set_attr "length" "12")
6384 (set_attr "type" "call")]
6387 (define_insn "*call_indirect"
6388 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6389 (match_operand 1 "" ""))
6390 (use (match_operand 2 "" ""))
6391 (clobber (reg:SI LR_REGNUM))]
6395 if (TARGET_CALLER_INTERWORKING)
6396 return \"bl\\t%__interwork_call_via_%0\";
6398 return \"bl\\t%__call_via_%0\";
6400 [(set_attr "type" "call")]
6403 (define_insn "*call_value_indirect"
6404 [(set (match_operand 0 "" "=l")
6405 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6406 (match_operand 2 "" "")))
6407 (use (match_operand 3 "" ""))
6408 (clobber (reg:SI LR_REGNUM))]
6412 if (TARGET_CALLER_INTERWORKING)
6413 return \"bl\\t%__interwork_call_via_%1\";
6415 return \"bl\\t%__call_via_%1\";
6417 [(set_attr "type" "call")]
6420 (define_expand "call_value"
6421 [(parallel [(set (match_operand 0 "" "")
6422 (call (match_operand 1 "memory_operand" "")
6423 (match_operand 2 "general_operand" "")))
6424 (use (match_operand 3 "" ""))
6425 (clobber (reg:SI LR_REGNUM))])]
6429 rtx callee = XEXP (operands[1], 0);
6431 /* In an untyped call, we can get NULL for operand 2. */
6432 if (operands[3] == 0)
6433 operands[3] = const0_rtx;
6435 /* See the comment in define_expand \"call\". */
6436 if (GET_CODE (callee) != REG
6437 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6438 XEXP (operands[1], 0) = force_reg (Pmode, callee);
6442 (define_insn "*call_value_reg"
6443 [(set (match_operand 0 "" "=r,f")
6444 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r"))
6445 (match_operand 2 "" "")))
6446 (use (match_operand 3 "" ""))
6447 (clobber (reg:SI LR_REGNUM))]
6450 return output_call (&operands[1]);
6452 [(set_attr "length" "12")
6453 (set_attr "type" "call")]
6456 (define_insn "*call_value_mem"
6457 [(set (match_operand 0 "" "=r,f")
6458 (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m"))
6459 (match_operand 2 "" "")))
6460 (use (match_operand 3 "" ""))
6461 (clobber (reg:SI LR_REGNUM))]
6462 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6464 return output_call_mem (&operands[1]);
6466 [(set_attr "length" "12")
6467 (set_attr "type" "call")]
6470 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6471 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6473 (define_insn "*call_symbol"
6474 [(call (mem:SI (match_operand:SI 0 "" "X"))
6475 (match_operand 1 "" ""))
6476 (use (match_operand 2 "" ""))
6477 (clobber (reg:SI LR_REGNUM))]
6479 && (GET_CODE (operands[0]) == SYMBOL_REF)
6480 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6483 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6485 [(set_attr "type" "call")]
6488 (define_insn "*call_value_symbol"
6489 [(set (match_operand 0 "s_register_operand" "=r,f")
6490 (call (mem:SI (match_operand:SI 1 "" "X,X"))
6491 (match_operand:SI 2 "" "")))
6492 (use (match_operand 3 "" ""))
6493 (clobber (reg:SI LR_REGNUM))]
6495 && (GET_CODE (operands[1]) == SYMBOL_REF)
6496 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6499 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6501 [(set_attr "type" "call")]
6504 (define_insn "*call_insn"
6505 [(call (mem:SI (match_operand:SI 0 "" "X"))
6506 (match_operand:SI 1 "" ""))
6507 (use (match_operand 2 "" ""))
6508 (clobber (reg:SI LR_REGNUM))]
6510 && operands[2] == const0_rtx && (GET_CODE (operands[0]) == SYMBOL_REF)"
6512 [(set_attr "length" "4")
6513 (set_attr "type" "call")]
6516 (define_insn "*call_value_insn"
6517 [(set (match_operand 0 "register_operand" "=l")
6518 (call (mem:SI (match_operand 1 "" "X"))
6519 (match_operand 2 "" "")))
6520 (use (match_operand 3 "" ""))
6521 (clobber (reg:SI LR_REGNUM))]
6523 && operands[3] == const0_rtx && (GET_CODE (operands[1]) == SYMBOL_REF)"
6525 [(set_attr "length" "4")
6526 (set_attr "type" "call")]
6529 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6530 (define_expand "sibcall"
6531 [(parallel [(call (match_operand 0 "memory_operand" "")
6532 (match_operand 1 "general_operand" ""))
6533 (use (match_operand 2 "" ""))
6534 (use (reg:SI LR_REGNUM))])]
6538 if (operands[2] == NULL_RTX)
6539 operands[2] = const0_rtx;
6543 (define_expand "sibcall_value"
6544 [(parallel [(set (match_operand 0 "register_operand" "")
6545 (call (match_operand 1 "memory_operand" "")
6546 (match_operand 2 "general_operand" "")))
6547 (use (match_operand 3 "" ""))
6548 (use (reg:SI LR_REGNUM))])]
6552 if (operands[3] == NULL_RTX)
6553 operands[3] = const0_rtx;
6557 (define_insn "*sibcall_insn"
6558 [(call (mem:SI (match_operand:SI 0 "" "X"))
6559 (match_operand 1 "" ""))
6560 (use (match_operand 2 "" ""))
6561 (use (reg:SI LR_REGNUM))]
6562 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6564 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6566 [(set_attr "type" "call")]
6569 (define_insn "*sibcall_value_insn"
6570 [(set (match_operand 0 "s_register_operand" "=r,f")
6571 (call (mem:SI (match_operand:SI 1 "" "X,X"))
6572 (match_operand 2 "" "")))
6573 (use (match_operand 3 "" ""))
6574 (use (reg:SI LR_REGNUM))]
6575 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6577 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6579 [(set_attr "type" "call")]
6582 ;; Often the return insn will be the same as loading from memory, so set attr
6583 (define_insn "return"
6585 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6588 if (arm_ccfsm_state == 2)
6590 arm_ccfsm_state += 2;
6593 return output_return_instruction (NULL, TRUE, FALSE);
6595 [(set_attr "type" "load")
6596 (set_attr "predicable" "yes")]
6599 (define_insn "*cond_return"
6601 (if_then_else (match_operator 0 "arm_comparison_operator"
6602 [(match_operand 1 "cc_register" "") (const_int 0)])
6605 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6608 if (arm_ccfsm_state == 2)
6610 arm_ccfsm_state += 2;
6613 return output_return_instruction (operands[0], TRUE, FALSE);
6615 [(set_attr "conds" "use")
6616 (set_attr "type" "load")]
6619 (define_insn "*cond_return_inverted"
6621 (if_then_else (match_operator 0 "arm_comparison_operator"
6622 [(match_operand 1 "cc_register" "") (const_int 0)])
6625 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6628 if (arm_ccfsm_state == 2)
6630 arm_ccfsm_state += 2;
6633 return output_return_instruction (operands[0], TRUE, TRUE);
6635 [(set_attr "conds" "use")
6636 (set_attr "type" "load")]
6639 ;; Call subroutine returning any type.
6641 (define_expand "untyped_call"
6642 [(parallel [(call (match_operand 0 "" "")
6644 (match_operand 1 "" "")
6645 (match_operand 2 "" "")])]
6651 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6653 for (i = 0; i < XVECLEN (operands[2], 0); i++)
6655 rtx set = XVECEXP (operands[2], 0, i);
6657 emit_move_insn (SET_DEST (set), SET_SRC (set));
6660 /* The optimizer does not know that the call sets the function value
6661 registers we stored in the result block. We avoid problems by
6662 claiming that all hard registers are used and clobbered at this
6664 emit_insn (gen_blockage ());
6670 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6671 ;; all of memory. This blocks insns from being moved across this point.
6673 (define_insn "blockage"
6674 [(unspec_volatile [(const_int 0)] 0)]
6677 [(set_attr "length" "0")
6678 (set_attr "type" "block")]
6681 (define_expand "casesi"
6682 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6683 (match_operand:SI 1 "const_int_operand" "") ; lower bound
6684 (match_operand:SI 2 "const_int_operand" "") ; total range
6685 (match_operand:SI 3 "" "") ; table label
6686 (match_operand:SI 4 "" "")] ; Out of range label
6691 if (operands[1] != const0_rtx)
6693 reg = gen_reg_rtx (SImode);
6695 emit_insn (gen_addsi3 (reg, operands[0],
6696 GEN_INT (-INTVAL (operands[1]))));
6700 if (!const_ok_for_arm (INTVAL (operands[2])))
6701 operands[2] = force_reg (SImode, operands[2]);
6703 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6709 ;; The USE in this pattern is needed to tell flow analysis that this is
6710 ;; a CASESI insn. It has no other purpose.
6711 (define_insn "casesi_internal"
6712 [(parallel [(set (pc)
6714 (leu (match_operand:SI 0 "s_register_operand" "r")
6715 (match_operand:SI 1 "arm_rhs_operand" "rI"))
6716 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6717 (label_ref (match_operand 2 "" ""))))
6718 (label_ref (match_operand 3 "" ""))))
6719 (clobber (reg:CC CC_REGNUM))
6720 (use (label_ref (match_dup 2)))])]
6724 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6725 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6727 [(set_attr "conds" "clob")
6728 (set_attr "length" "12")]
6731 (define_expand "indirect_jump"
6733 (match_operand:SI 0 "s_register_operand" ""))]
6738 (define_insn "*arm_indirect_jump"
6740 (match_operand:SI 0 "s_register_operand" "r"))]
6742 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6743 [(set_attr "predicable" "yes")]
6746 ;; Although not supported by the define_expand above,
6747 ;; cse/combine may generate this form.
6748 (define_insn "*load_indirect_jump"
6750 (match_operand:SI 0 "memory_operand" "m"))]
6752 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6753 [(set_attr "type" "load")
6754 (set_attr "predicable" "yes")]
6757 (define_insn "*thumb_indirect_jump"
6759 (match_operand:SI 0 "register_operand" "l*r"))]
6762 [(set_attr "conds" "clob")
6763 (set_attr "length" "2")]
6774 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6775 return \"mov\\tr8, r8\";
6777 [(set (attr "length")
6778 (if_then_else (eq_attr "is_thumb" "yes")
6784 ;; Patterns to allow combination of arithmetic, cond code and shifts
6786 (define_insn "*arith_shiftsi"
6787 [(set (match_operand:SI 0 "s_register_operand" "=r")
6788 (match_operator:SI 1 "shiftable_operator"
6789 [(match_operator:SI 3 "shift_operator"
6790 [(match_operand:SI 4 "s_register_operand" "r")
6791 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6792 (match_operand:SI 2 "s_register_operand" "r")]))]
6794 "%i1%?\\t%0, %2, %4%S3"
6795 [(set_attr "predicable" "yes")
6796 (set_attr "shift" "4")
6800 (define_insn "*arith_shiftsi_compare0"
6801 [(set (reg:CC_NOOV CC_REGNUM)
6802 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6803 [(match_operator:SI 3 "shift_operator"
6804 [(match_operand:SI 4 "s_register_operand" "r")
6805 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6806 (match_operand:SI 2 "s_register_operand" "r")])
6808 (set (match_operand:SI 0 "s_register_operand" "=r")
6809 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6812 "%i1%?s\\t%0, %2, %4%S3"
6813 [(set_attr "conds" "set")
6814 (set_attr "shift" "4")
6818 (define_insn "*arith_shiftsi_compare0_scratch"
6819 [(set (reg:CC_NOOV CC_REGNUM)
6820 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6821 [(match_operator:SI 3 "shift_operator"
6822 [(match_operand:SI 4 "s_register_operand" "r")
6823 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6824 (match_operand:SI 2 "s_register_operand" "r")])
6826 (clobber (match_scratch:SI 0 "=r"))]
6828 "%i1%?s\\t%0, %2, %4%S3"
6829 [(set_attr "conds" "set")
6830 (set_attr "shift" "4")
6834 (define_insn "*sub_shiftsi"
6835 [(set (match_operand:SI 0 "s_register_operand" "=r")
6836 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6837 (match_operator:SI 2 "shift_operator"
6838 [(match_operand:SI 3 "s_register_operand" "r")
6839 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
6841 "sub%?\\t%0, %1, %3%S2"
6842 [(set_attr "predicable" "yes")
6843 (set_attr "shift" "3")
6847 (define_insn "*sub_shiftsi_compare0"
6848 [(set (reg:CC_NOOV CC_REGNUM)
6850 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6851 (match_operator:SI 2 "shift_operator"
6852 [(match_operand:SI 3 "s_register_operand" "r")
6853 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6855 (set (match_operand:SI 0 "s_register_operand" "=r")
6856 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6859 "sub%?s\\t%0, %1, %3%S2"
6860 [(set_attr "conds" "set")
6861 (set_attr "shift" "3")
6865 (define_insn "*sub_shiftsi_compare0_scratch"
6866 [(set (reg:CC_NOOV CC_REGNUM)
6868 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6869 (match_operator:SI 2 "shift_operator"
6870 [(match_operand:SI 3 "s_register_operand" "r")
6871 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6873 (clobber (match_scratch:SI 0 "=r"))]
6875 "sub%?s\\t%0, %1, %3%S2"
6876 [(set_attr "conds" "set")
6877 (set_attr "shift" "3")
6881 ;; These variants of the above insns can occur if the first operand is the
6882 ;; frame pointer and we eliminate that. This is a kludge, but there doesn't
6883 ;; seem to be a way around it. Most of the predicates have to be null
6884 ;; because the format can be generated part way through reload, so
6885 ;; if we don't match it as soon as it becomes available, reload doesn't know
6886 ;; how to reload pseudos that haven't got hard registers; the constraints will
6887 ;; sort everything out.
6889 (define_insn "*reload_mulsi3"
6890 [(set (match_operand:SI 0 "" "=&r")
6891 (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
6892 [(match_operand:SI 3 "" "r")
6893 (match_operand:SI 4 "" "rM")])
6894 (match_operand:SI 2 "" "r"))
6895 (match_operand:SI 1 "const_int_operand" "n")))]
6896 "TARGET_ARM && reload_in_progress"
6898 output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
6899 operands[2] = operands[1];
6900 operands[1] = operands[0];
6901 return output_add_immediate (operands);
6904 ; we have no idea how long the add_immediate is, it could be up to 4.
6905 (set_attr "length" "20")]
6908 (define_insn "*reload_mulsi_compare0"
6909 [(set (reg:CC_NOOV CC_REGNUM)
6910 (compare:CC_NOOV (plus:SI
6912 (match_operator:SI 5 "shift_operator"
6913 [(match_operand:SI 3 "" "r")
6914 (match_operand:SI 4 "" "rM")])
6915 (match_operand:SI 1 "" "r"))
6916 (match_operand:SI 2 "const_int_operand" "n"))
6918 (set (match_operand:SI 0 "" "=&r")
6919 (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
6922 "TARGET_ARM && reload_in_progress && !arm_is_xscale"
6924 output_add_immediate (operands);
6925 return \"add%?s\\t%0, %0, %3%S5\";
6927 [(set_attr "conds" "set")
6928 (set_attr "shift" "3")
6929 (set_attr "length" "20")]
6932 (define_insn "*reload_mulsi_compare0_scratch"
6933 [(set (reg:CC_NOOV CC_REGNUM)
6934 (compare:CC_NOOV (plus:SI
6936 (match_operator:SI 5 "shift_operator"
6937 [(match_operand:SI 3 "" "r")
6938 (match_operand:SI 4 "" "rM")])
6939 (match_operand:SI 1 "" "r"))
6940 (match_operand:SI 2 "const_int_operand" "n"))
6942 (clobber (match_scratch:SI 0 "=&r"))]
6943 "TARGET_ARM && reload_in_progress && !arm_is_xscale"
6945 output_add_immediate (operands);
6946 return \"add%?s\\t%0, %0, %3%S5\";
6948 [(set_attr "conds" "set")
6949 (set_attr "shift" "3")
6950 (set_attr "length" "20")]
6953 ;; These are similar, but are needed when the mla pattern contains the
6954 ;; eliminated register as operand 3.
6956 (define_insn "*reload_muladdsi"
6957 [(set (match_operand:SI 0 "" "=&r,&r")
6958 (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
6959 (match_operand:SI 2 "" "r,r"))
6960 (match_operand:SI 3 "" "r,r"))
6961 (match_operand:SI 4 "const_int_operand" "n,n")))]
6962 "TARGET_ARM && reload_in_progress"
6964 output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
6965 operands[2] = operands[4];
6966 operands[1] = operands[0];
6967 return output_add_immediate (operands);
6969 [(set_attr "length" "20")
6970 (set_attr "type" "mult")]
6973 (define_insn "*reload_muladdsi_compare0"
6974 [(set (reg:CC_NOOV CC_REGNUM)
6975 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
6976 (match_operand:SI 3 "" "r")
6977 (match_operand:SI 4 "" "r"))
6978 (match_operand:SI 1 "" "r"))
6979 (match_operand:SI 2 "const_int_operand" "n"))
6981 (set (match_operand:SI 0 "" "=&r")
6982 (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
6984 "TARGET_ARM && reload_in_progress && !arm_is_xscale"
6986 output_add_immediate (operands);
6987 output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
6990 [(set_attr "length" "20")
6991 (set_attr "conds" "set")
6992 (set_attr "type" "mult")]
6995 (define_insn "*reload_muladdsi_compare0_scratch"
6996 [(set (reg:CC_NOOV CC_REGNUM)
6997 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
6998 (match_operand:SI 3 "" "r")
6999 (match_operand:SI 4 "" "r"))
7000 (match_operand:SI 1 "" "r"))
7001 (match_operand:SI 2 "const_int_operand" "n"))
7003 (clobber (match_scratch:SI 0 "=&r"))]
7004 "TARGET_ARM && reload_in_progress"
7006 output_add_immediate (operands);
7007 return \"mla%?s\\t%0, %3, %4, %0\";
7009 [(set_attr "length" "20")
7010 (set_attr "conds" "set")
7011 (set_attr "type" "mult")]
7016 (define_insn "*and_scc"
7017 [(set (match_operand:SI 0 "s_register_operand" "=r")
7018 (and:SI (match_operator:SI 1 "arm_comparison_operator"
7019 [(match_operand 3 "cc_register" "") (const_int 0)])
7020 (match_operand:SI 2 "s_register_operand" "r")))]
7022 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7023 [(set_attr "conds" "use")
7024 (set_attr "length" "8")]
7027 (define_insn "*ior_scc"
7028 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7029 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
7030 [(match_operand 3 "cc_register" "") (const_int 0)])
7031 (match_operand:SI 1 "s_register_operand" "0,?r")))]
7035 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7036 [(set_attr "conds" "use")
7037 (set_attr "length" "4,8")]
7040 (define_insn "*compare_scc"
7041 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7042 (match_operator:SI 1 "arm_comparison_operator"
7043 [(match_operand:SI 2 "s_register_operand" "r,r")
7044 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7045 (clobber (reg:CC CC_REGNUM))]
7048 if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
7049 return \"mov\\t%0, %2, lsr #31\";
7051 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
7052 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7054 if (GET_CODE (operands[1]) == NE)
7056 if (which_alternative == 1)
7057 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7058 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7060 if (which_alternative == 1)
7061 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7063 output_asm_insn (\"cmp\\t%2, %3\", operands);
7064 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7066 [(set_attr "conds" "clob")
7067 (set_attr "length" "12")]
7070 (define_insn "*cond_move"
7071 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7072 (if_then_else:SI (match_operator 3 "equality_operator"
7073 [(match_operator 4 "arm_comparison_operator"
7074 [(match_operand 5 "cc_register" "") (const_int 0)])
7076 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7077 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7080 if (GET_CODE (operands[3]) == NE)
7082 if (which_alternative != 1)
7083 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7084 if (which_alternative != 0)
7085 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7088 if (which_alternative != 0)
7089 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7090 if (which_alternative != 1)
7091 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7094 [(set_attr "conds" "use")
7095 (set_attr "length" "4,4,8")]
7098 (define_insn "*cond_arith"
7099 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7100 (match_operator:SI 5 "shiftable_operator"
7101 [(match_operator:SI 4 "arm_comparison_operator"
7102 [(match_operand:SI 2 "s_register_operand" "r,r")
7103 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7104 (match_operand:SI 1 "s_register_operand" "0,?r")]))
7105 (clobber (reg:CC CC_REGNUM))]
7108 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7109 return \"%i5\\t%0, %1, %2, lsr #31\";
7111 output_asm_insn (\"cmp\\t%2, %3\", operands);
7112 if (GET_CODE (operands[5]) == AND)
7113 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7114 else if (GET_CODE (operands[5]) == MINUS)
7115 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7116 else if (which_alternative != 0)
7117 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7118 return \"%i5%d4\\t%0, %1, #1\";
7120 [(set_attr "conds" "clob")
7121 (set_attr "length" "12")]
7124 (define_insn "*cond_sub"
7125 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7126 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7127 (match_operator:SI 4 "arm_comparison_operator"
7128 [(match_operand:SI 2 "s_register_operand" "r,r")
7129 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7130 (clobber (reg:CC CC_REGNUM))]
7133 output_asm_insn (\"cmp\\t%2, %3\", operands);
7134 if (which_alternative != 0)
7135 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7136 return \"sub%d4\\t%0, %1, #1\";
7138 [(set_attr "conds" "clob")
7139 (set_attr "length" "8,12")]
7142 (define_insn "*cmp_ite0"
7143 [(set (match_operand 6 "dominant_cc_register" "")
7146 (match_operator 4 "arm_comparison_operator"
7147 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7148 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7149 (match_operator:SI 5 "arm_comparison_operator"
7150 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7151 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7157 static const char * const opcodes[4][2] =
7159 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7160 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7161 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7162 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7163 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7164 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7165 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7166 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7169 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7171 return opcodes[which_alternative][swap];
7173 [(set_attr "conds" "set")
7174 (set_attr "length" "8")]
7177 (define_insn "*cmp_ite1"
7178 [(set (match_operand 6 "dominant_cc_register" "")
7181 (match_operator 4 "arm_comparison_operator"
7182 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7183 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7184 (match_operator:SI 5 "arm_comparison_operator"
7185 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7186 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7192 static const char * const opcodes[4][2] =
7194 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7195 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7196 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7197 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7198 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7199 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7200 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7201 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7204 comparison_dominates_p (GET_CODE (operands[5]),
7205 reverse_condition (GET_CODE (operands[4])));
7207 return opcodes[which_alternative][swap];
7209 [(set_attr "conds" "set")
7210 (set_attr "length" "8")]
7213 (define_insn "*cmp_and"
7214 [(set (match_operand 6 "dominant_cc_register" "")
7217 (match_operator 4 "arm_comparison_operator"
7218 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7219 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7220 (match_operator:SI 5 "arm_comparison_operator"
7221 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7222 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7227 const char * opcodes[4][2] =
7229 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7230 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7231 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7232 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7233 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7234 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7235 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7236 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7239 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7241 return opcodes[which_alternative][swap];
7243 [(set_attr "conds" "set")
7244 (set_attr "predicable" "no")
7245 (set_attr "length" "8")]
7248 (define_insn "*cmp_ior"
7249 [(set (match_operand 6 "dominant_cc_register" "")
7252 (match_operator 4 "arm_comparison_operator"
7253 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7254 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7255 (match_operator:SI 5 "arm_comparison_operator"
7256 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7257 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7262 const char * opcodes[4][2] =
7264 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7265 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7266 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7267 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7268 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7269 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7270 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7271 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7274 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7276 return opcodes[which_alternative][swap];
7279 [(set_attr "conds" "set")
7280 (set_attr "length" "8")]
7283 (define_insn "*negscc"
7284 [(set (match_operand:SI 0 "s_register_operand" "=r")
7285 (neg:SI (match_operator 3 "arm_comparison_operator"
7286 [(match_operand:SI 1 "s_register_operand" "r")
7287 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7288 (clobber (reg:CC CC_REGNUM))]
7291 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7292 return \"mov\\t%0, %1, asr #31\";
7294 if (GET_CODE (operands[3]) == NE)
7295 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7297 if (GET_CODE (operands[3]) == GT)
7298 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7300 output_asm_insn (\"cmp\\t%1, %2\", operands);
7301 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7302 return \"mvn%d3\\t%0, #0\";
7304 [(set_attr "conds" "clob")
7305 (set_attr "length" "12")]
7308 (define_insn "movcond"
7309 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7311 (match_operator 5 "arm_comparison_operator"
7312 [(match_operand:SI 3 "s_register_operand" "r,r,r")
7313 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7314 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7315 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
7316 (clobber (reg:CC CC_REGNUM))]
7319 if (GET_CODE (operands[5]) == LT
7320 && (operands[4] == const0_rtx))
7322 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7324 if (operands[2] == const0_rtx)
7325 return \"and\\t%0, %1, %3, asr #31\";
7326 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
7328 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7330 if (operands[1] == const0_rtx)
7331 return \"bic\\t%0, %2, %3, asr #31\";
7332 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
7334 /* The only case that falls through to here is when both ops 1 & 2
7338 if (GET_CODE (operands[5]) == GE
7339 && (operands[4] == const0_rtx))
7341 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7343 if (operands[2] == const0_rtx)
7344 return \"bic\\t%0, %1, %3, asr #31\";
7345 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7347 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7349 if (operands[1] == const0_rtx)
7350 return \"and\\t%0, %2, %3, asr #31\";
7351 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7353 /* The only case that falls through to here is when both ops 1 & 2
7356 if (GET_CODE (operands[4]) == CONST_INT
7357 && !const_ok_for_arm (INTVAL (operands[4])))
7358 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7360 output_asm_insn (\"cmp\\t%3, %4\", operands);
7361 if (which_alternative != 0)
7362 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7363 if (which_alternative != 1)
7364 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7367 [(set_attr "conds" "clob")
7368 (set_attr "length" "8,8,12")]
7371 (define_insn "*ifcompare_plus_move"
7372 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7373 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7374 [(match_operand:SI 4 "s_register_operand" "r,r")
7375 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7377 (match_operand:SI 2 "s_register_operand" "r,r")
7378 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7379 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7380 (clobber (reg:CC CC_REGNUM))]
7383 [(set_attr "conds" "clob")
7384 (set_attr "length" "8,12")]
7387 (define_insn "*if_plus_move"
7388 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7390 (match_operator 4 "arm_comparison_operator"
7391 [(match_operand 5 "cc_register" "") (const_int 0)])
7393 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7394 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7395 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7399 sub%d4\\t%0, %2, #%n3
7400 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7401 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7402 [(set_attr "conds" "use")
7403 (set_attr "length" "4,4,8,8")
7404 (set_attr "type" "*,*,*,*")]
7407 (define_insn "*ifcompare_move_plus"
7408 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7409 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7410 [(match_operand:SI 4 "s_register_operand" "r,r")
7411 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7412 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7414 (match_operand:SI 2 "s_register_operand" "r,r")
7415 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7416 (clobber (reg:CC CC_REGNUM))]
7419 [(set_attr "conds" "clob")
7420 (set_attr "length" "8,12")]
7423 (define_insn "*if_move_plus"
7424 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7426 (match_operator 4 "arm_comparison_operator"
7427 [(match_operand 5 "cc_register" "") (const_int 0)])
7428 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7430 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7431 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7435 sub%D4\\t%0, %2, #%n3
7436 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7437 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7438 [(set_attr "conds" "use")
7439 (set_attr "length" "4,4,8,8")
7440 (set_attr "type" "*,*,*,*")]
7443 (define_insn "*ifcompare_arith_arith"
7444 [(set (match_operand:SI 0 "s_register_operand" "=r")
7445 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7446 [(match_operand:SI 5 "s_register_operand" "r")
7447 (match_operand:SI 6 "arm_add_operand" "rIL")])
7448 (match_operator:SI 8 "shiftable_operator"
7449 [(match_operand:SI 1 "s_register_operand" "r")
7450 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7451 (match_operator:SI 7 "shiftable_operator"
7452 [(match_operand:SI 3 "s_register_operand" "r")
7453 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7454 (clobber (reg:CC CC_REGNUM))]
7457 [(set_attr "conds" "clob")
7458 (set_attr "length" "12")]
7461 (define_insn "*if_arith_arith"
7462 [(set (match_operand:SI 0 "s_register_operand" "=r")
7463 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7464 [(match_operand 8 "cc_register" "") (const_int 0)])
7465 (match_operator:SI 6 "shiftable_operator"
7466 [(match_operand:SI 1 "s_register_operand" "r")
7467 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7468 (match_operator:SI 7 "shiftable_operator"
7469 [(match_operand:SI 3 "s_register_operand" "r")
7470 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7472 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7473 [(set_attr "conds" "use")
7474 (set_attr "length" "8")]
7477 (define_insn "*ifcompare_arith_move"
7478 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7479 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7480 [(match_operand:SI 2 "s_register_operand" "r,r")
7481 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7482 (match_operator:SI 7 "shiftable_operator"
7483 [(match_operand:SI 4 "s_register_operand" "r,r")
7484 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7485 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7486 (clobber (reg:CC CC_REGNUM))]
7489 /* If we have an operation where (op x 0) is the identity operation and
7490 the conditional operator is LT or GE and we are comparing against zero and
7491 everything is in registers then we can do this in two instructions */
7492 if (operands[3] == const0_rtx
7493 && GET_CODE (operands[7]) != AND
7494 && GET_CODE (operands[5]) == REG
7495 && GET_CODE (operands[1]) == REG
7496 && REGNO (operands[1]) == REGNO (operands[4])
7497 && REGNO (operands[4]) != REGNO (operands[0]))
7499 if (GET_CODE (operands[6]) == LT)
7500 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7501 else if (GET_CODE (operands[6]) == GE)
7502 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7504 if (GET_CODE (operands[3]) == CONST_INT
7505 && !const_ok_for_arm (INTVAL (operands[3])))
7506 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7508 output_asm_insn (\"cmp\\t%2, %3\", operands);
7509 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7510 if (which_alternative != 0)
7511 return \"mov%D6\\t%0, %1\";
7514 [(set_attr "conds" "clob")
7515 (set_attr "length" "8,12")]
7518 (define_insn "*if_arith_move"
7519 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7520 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7521 [(match_operand 6 "cc_register" "") (const_int 0)])
7522 (match_operator:SI 5 "shiftable_operator"
7523 [(match_operand:SI 2 "s_register_operand" "r,r")
7524 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7525 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7529 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7530 [(set_attr "conds" "use")
7531 (set_attr "length" "4,8")
7532 (set_attr "type" "*,*")]
7535 (define_insn "*ifcompare_move_arith"
7536 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7537 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7538 [(match_operand:SI 4 "s_register_operand" "r,r")
7539 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7540 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7541 (match_operator:SI 7 "shiftable_operator"
7542 [(match_operand:SI 2 "s_register_operand" "r,r")
7543 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7544 (clobber (reg:CC CC_REGNUM))]
7547 /* If we have an operation where (op x 0) is the identity operation and
7548 the conditional operator is LT or GE and we are comparing against zero and
7549 everything is in registers then we can do this in two instructions */
7550 if (operands[5] == const0_rtx
7551 && GET_CODE (operands[7]) != AND
7552 && GET_CODE (operands[3]) == REG
7553 && GET_CODE (operands[1]) == REG
7554 && REGNO (operands[1]) == REGNO (operands[2])
7555 && REGNO (operands[2]) != REGNO (operands[0]))
7557 if (GET_CODE (operands[6]) == GE)
7558 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7559 else if (GET_CODE (operands[6]) == LT)
7560 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7563 if (GET_CODE (operands[5]) == CONST_INT
7564 && !const_ok_for_arm (INTVAL (operands[5])))
7565 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7567 output_asm_insn (\"cmp\\t%4, %5\", operands);
7569 if (which_alternative != 0)
7570 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7571 return \"%I7%D6\\t%0, %2, %3\";
7573 [(set_attr "conds" "clob")
7574 (set_attr "length" "8,12")]
7577 (define_insn "*if_move_arith"
7578 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7580 (match_operator 4 "arm_comparison_operator"
7581 [(match_operand 6 "cc_register" "") (const_int 0)])
7582 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7583 (match_operator:SI 5 "shiftable_operator"
7584 [(match_operand:SI 2 "s_register_operand" "r,r")
7585 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7589 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7590 [(set_attr "conds" "use")
7591 (set_attr "length" "4,8")
7592 (set_attr "type" "*,*")]
7595 (define_insn "*ifcompare_move_not"
7596 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7598 (match_operator 5 "arm_comparison_operator"
7599 [(match_operand:SI 3 "s_register_operand" "r,r")
7600 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7601 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7603 (match_operand:SI 2 "s_register_operand" "r,r"))))
7604 (clobber (reg:CC CC_REGNUM))]
7607 [(set_attr "conds" "clob")
7608 (set_attr "length" "8,12")]
7611 (define_insn "*if_move_not"
7612 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7614 (match_operator 4 "arm_comparison_operator"
7615 [(match_operand 3 "cc_register" "") (const_int 0)])
7616 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7617 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7621 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7622 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7623 [(set_attr "conds" "use")
7624 (set_attr "length" "4,8,8")]
7627 (define_insn "*ifcompare_not_move"
7628 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7630 (match_operator 5 "arm_comparison_operator"
7631 [(match_operand:SI 3 "s_register_operand" "r,r")
7632 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7634 (match_operand:SI 2 "s_register_operand" "r,r"))
7635 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7636 (clobber (reg:CC CC_REGNUM))]
7639 [(set_attr "conds" "clob")
7640 (set_attr "length" "8,12")]
7643 (define_insn "*if_not_move"
7644 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7646 (match_operator 4 "arm_comparison_operator"
7647 [(match_operand 3 "cc_register" "") (const_int 0)])
7648 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7649 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7653 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7654 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7655 [(set_attr "conds" "use")
7656 (set_attr "length" "4,8,8")]
7659 (define_insn "*ifcompare_shift_move"
7660 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7662 (match_operator 6 "arm_comparison_operator"
7663 [(match_operand:SI 4 "s_register_operand" "r,r")
7664 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7665 (match_operator:SI 7 "shift_operator"
7666 [(match_operand:SI 2 "s_register_operand" "r,r")
7667 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7668 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7669 (clobber (reg:CC CC_REGNUM))]
7672 [(set_attr "conds" "clob")
7673 (set_attr "length" "8,12")]
7676 (define_insn "*if_shift_move"
7677 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7679 (match_operator 5 "arm_comparison_operator"
7680 [(match_operand 6 "cc_register" "") (const_int 0)])
7681 (match_operator:SI 4 "shift_operator"
7682 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7683 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7684 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7688 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7689 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7690 [(set_attr "conds" "use")
7691 (set_attr "shift" "2")
7692 (set_attr "length" "4,8,8")]
7695 (define_insn "*ifcompare_move_shift"
7696 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7698 (match_operator 6 "arm_comparison_operator"
7699 [(match_operand:SI 4 "s_register_operand" "r,r")
7700 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7701 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7702 (match_operator:SI 7 "shift_operator"
7703 [(match_operand:SI 2 "s_register_operand" "r,r")
7704 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7705 (clobber (reg:CC CC_REGNUM))]
7708 [(set_attr "conds" "clob")
7709 (set_attr "length" "8,12")]
7712 (define_insn "*if_move_shift"
7713 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7715 (match_operator 5 "arm_comparison_operator"
7716 [(match_operand 6 "cc_register" "") (const_int 0)])
7717 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7718 (match_operator:SI 4 "shift_operator"
7719 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7720 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7724 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7725 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7726 [(set_attr "conds" "use")
7727 (set_attr "shift" "2")
7728 (set_attr "length" "4,8,8")]
7731 (define_insn "*ifcompare_shift_shift"
7732 [(set (match_operand:SI 0 "s_register_operand" "=r")
7734 (match_operator 7 "arm_comparison_operator"
7735 [(match_operand:SI 5 "s_register_operand" "r")
7736 (match_operand:SI 6 "arm_add_operand" "rIL")])
7737 (match_operator:SI 8 "shift_operator"
7738 [(match_operand:SI 1 "s_register_operand" "r")
7739 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7740 (match_operator:SI 9 "shift_operator"
7741 [(match_operand:SI 3 "s_register_operand" "r")
7742 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7743 (clobber (reg:CC CC_REGNUM))]
7746 [(set_attr "conds" "clob")
7747 (set_attr "length" "12")]
7750 (define_insn "*if_shift_shift"
7751 [(set (match_operand:SI 0 "s_register_operand" "=r")
7753 (match_operator 5 "arm_comparison_operator"
7754 [(match_operand 8 "cc_register" "") (const_int 0)])
7755 (match_operator:SI 6 "shift_operator"
7756 [(match_operand:SI 1 "s_register_operand" "r")
7757 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7758 (match_operator:SI 7 "shift_operator"
7759 [(match_operand:SI 3 "s_register_operand" "r")
7760 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7762 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7763 [(set_attr "conds" "use")
7764 (set_attr "shift" "1")
7765 (set_attr "length" "8")]
7768 (define_insn "*ifcompare_not_arith"
7769 [(set (match_operand:SI 0 "s_register_operand" "=r")
7771 (match_operator 6 "arm_comparison_operator"
7772 [(match_operand:SI 4 "s_register_operand" "r")
7773 (match_operand:SI 5 "arm_add_operand" "rIL")])
7774 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7775 (match_operator:SI 7 "shiftable_operator"
7776 [(match_operand:SI 2 "s_register_operand" "r")
7777 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7778 (clobber (reg:CC CC_REGNUM))]
7781 [(set_attr "conds" "clob")
7782 (set_attr "length" "12")]
7785 (define_insn "*if_not_arith"
7786 [(set (match_operand:SI 0 "s_register_operand" "=r")
7788 (match_operator 5 "arm_comparison_operator"
7789 [(match_operand 4 "cc_register" "") (const_int 0)])
7790 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7791 (match_operator:SI 6 "shiftable_operator"
7792 [(match_operand:SI 2 "s_register_operand" "r")
7793 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7795 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7796 [(set_attr "conds" "use")
7797 (set_attr "length" "8")]
7800 (define_insn "*ifcompare_arith_not"
7801 [(set (match_operand:SI 0 "s_register_operand" "=r")
7803 (match_operator 6 "arm_comparison_operator"
7804 [(match_operand:SI 4 "s_register_operand" "r")
7805 (match_operand:SI 5 "arm_add_operand" "rIL")])
7806 (match_operator:SI 7 "shiftable_operator"
7807 [(match_operand:SI 2 "s_register_operand" "r")
7808 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7809 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7810 (clobber (reg:CC CC_REGNUM))]
7813 [(set_attr "conds" "clob")
7814 (set_attr "length" "12")]
7817 (define_insn "*if_arith_not"
7818 [(set (match_operand:SI 0 "s_register_operand" "=r")
7820 (match_operator 5 "arm_comparison_operator"
7821 [(match_operand 4 "cc_register" "") (const_int 0)])
7822 (match_operator:SI 6 "shiftable_operator"
7823 [(match_operand:SI 2 "s_register_operand" "r")
7824 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7825 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7827 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7828 [(set_attr "conds" "use")
7829 (set_attr "length" "8")]
7832 (define_insn "*ifcompare_neg_move"
7833 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7835 (match_operator 5 "arm_comparison_operator"
7836 [(match_operand:SI 3 "s_register_operand" "r,r")
7837 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7838 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7839 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7840 (clobber (reg:CC CC_REGNUM))]
7843 [(set_attr "conds" "clob")
7844 (set_attr "length" "8,12")]
7847 (define_insn "*if_neg_move"
7848 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7850 (match_operator 4 "arm_comparison_operator"
7851 [(match_operand 3 "cc_register" "") (const_int 0)])
7852 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7853 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7857 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7858 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
7859 [(set_attr "conds" "use")
7860 (set_attr "length" "4,8,8")]
7863 (define_insn "*ifcompare_move_neg"
7864 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7866 (match_operator 5 "arm_comparison_operator"
7867 [(match_operand:SI 3 "s_register_operand" "r,r")
7868 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7869 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7870 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
7871 (clobber (reg:CC CC_REGNUM))]
7874 [(set_attr "conds" "clob")
7875 (set_attr "length" "8,12")]
7878 (define_insn "*if_move_neg"
7879 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7881 (match_operator 4 "arm_comparison_operator"
7882 [(match_operand 3 "cc_register" "") (const_int 0)])
7883 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7884 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7888 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
7889 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
7890 [(set_attr "conds" "use")
7891 (set_attr "length" "4,8,8")]
7894 (define_insn "*arith_adjacentmem"
7895 [(set (match_operand:SI 0 "s_register_operand" "=r")
7896 (match_operator:SI 1 "shiftable_operator"
7897 [(match_operand:SI 2 "memory_operand" "m")
7898 (match_operand:SI 3 "memory_operand" "m")]))
7899 (clobber (match_scratch:SI 4 "=r"))]
7900 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
7905 int val1 = 0, val2 = 0;
7907 if (REGNO (operands[0]) > REGNO (operands[4]))
7909 ldm[1] = operands[4];
7910 ldm[2] = operands[0];
7914 ldm[1] = operands[0];
7915 ldm[2] = operands[4];
7917 if (GET_CODE (XEXP (operands[2], 0)) != REG)
7918 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
7919 if (GET_CODE (XEXP (operands[3], 0)) != REG)
7920 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
7921 arith[0] = operands[0];
7922 arith[3] = operands[1];
7936 ldm[0] = ops[0] = operands[4];
7937 ops[1] = XEXP (XEXP (operands[2], 0), 0);
7938 ops[2] = XEXP (XEXP (operands[2], 0), 1);
7939 output_add_immediate (ops);
7941 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7943 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7947 ldm[0] = XEXP (operands[3], 0);
7949 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7951 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7955 ldm[0] = XEXP (operands[2], 0);
7957 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7959 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7961 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
7964 [(set_attr "length" "12")
7965 (set_attr "predicable" "yes")
7966 (set_attr "type" "load")]
7969 ;; the arm can support extended pre-inc instructions
7971 ;; In all these cases, we use operands 0 and 1 for the register being
7972 ;; incremented because those are the operands that local-alloc will
7973 ;; tie and these are the pair most likely to be tieable (and the ones
7974 ;; that will benefit the most).
7976 ;; We reject the frame pointer if it occurs anywhere in these patterns since
7977 ;; elimination will cause too many headaches.
7979 (define_insn "*strqi_preinc"
7980 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7981 (match_operand:SI 2 "index_operand" "rJ")))
7982 (match_operand:QI 3 "s_register_operand" "r"))
7983 (set (match_operand:SI 0 "s_register_operand" "=r")
7984 (plus:SI (match_dup 1) (match_dup 2)))]
7986 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7987 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7988 && (GET_CODE (operands[2]) != REG
7989 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7990 "str%?b\\t%3, [%0, %2]!"
7991 [(set_attr "type" "store1")
7992 (set_attr "predicable" "yes")]
7995 (define_insn "*strqi_predec"
7996 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7997 (match_operand:SI 2 "s_register_operand" "r")))
7998 (match_operand:QI 3 "s_register_operand" "r"))
7999 (set (match_operand:SI 0 "s_register_operand" "=r")
8000 (minus:SI (match_dup 1) (match_dup 2)))]
8002 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8003 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8004 && (GET_CODE (operands[2]) != REG
8005 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8006 "str%?b\\t%3, [%0, -%2]!"
8007 [(set_attr "type" "store1")
8008 (set_attr "predicable" "yes")]
8011 (define_insn "*loadqi_preinc"
8012 [(set (match_operand:QI 3 "s_register_operand" "=r")
8013 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8014 (match_operand:SI 2 "index_operand" "rJ"))))
8015 (set (match_operand:SI 0 "s_register_operand" "=r")
8016 (plus:SI (match_dup 1) (match_dup 2)))]
8018 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8019 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8020 && (GET_CODE (operands[2]) != REG
8021 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8022 "ldr%?b\\t%3, [%0, %2]!"
8023 [(set_attr "type" "load")
8024 (set_attr "predicable" "yes")]
8027 (define_insn "*loadqi_predec"
8028 [(set (match_operand:QI 3 "s_register_operand" "=r")
8029 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8030 (match_operand:SI 2 "s_register_operand" "r"))))
8031 (set (match_operand:SI 0 "s_register_operand" "=r")
8032 (minus:SI (match_dup 1) (match_dup 2)))]
8034 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8035 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8036 && (GET_CODE (operands[2]) != REG
8037 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8038 "ldr%?b\\t%3, [%0, -%2]!"
8039 [(set_attr "type" "load")
8040 (set_attr "predicable" "yes")]
8043 (define_insn "*loadqisi_preinc"
8044 [(set (match_operand:SI 3 "s_register_operand" "=r")
8046 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8047 (match_operand:SI 2 "index_operand" "rJ")))))
8048 (set (match_operand:SI 0 "s_register_operand" "=r")
8049 (plus:SI (match_dup 1) (match_dup 2)))]
8051 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8052 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8053 && (GET_CODE (operands[2]) != REG
8054 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8055 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8056 [(set_attr "type" "load")
8057 (set_attr "predicable" "yes")]
8060 (define_insn "*loadqisi_predec"
8061 [(set (match_operand:SI 3 "s_register_operand" "=r")
8063 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8064 (match_operand:SI 2 "s_register_operand" "r")))))
8065 (set (match_operand:SI 0 "s_register_operand" "=r")
8066 (minus:SI (match_dup 1) (match_dup 2)))]
8068 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8069 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8070 && (GET_CODE (operands[2]) != REG
8071 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8072 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8073 [(set_attr "type" "load")
8074 (set_attr "predicable" "yes")]
8077 (define_insn "*strsi_preinc"
8078 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8079 (match_operand:SI 2 "index_operand" "rJ")))
8080 (match_operand:SI 3 "s_register_operand" "r"))
8081 (set (match_operand:SI 0 "s_register_operand" "=r")
8082 (plus:SI (match_dup 1) (match_dup 2)))]
8084 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8085 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8086 && (GET_CODE (operands[2]) != REG
8087 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8088 "str%?\\t%3, [%0, %2]!"
8089 [(set_attr "type" "store1")
8090 (set_attr "predicable" "yes")]
8093 (define_insn "*strsi_predec"
8094 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8095 (match_operand:SI 2 "s_register_operand" "r")))
8096 (match_operand:SI 3 "s_register_operand" "r"))
8097 (set (match_operand:SI 0 "s_register_operand" "=r")
8098 (minus:SI (match_dup 1) (match_dup 2)))]
8100 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8101 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8102 && (GET_CODE (operands[2]) != REG
8103 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8104 "str%?\\t%3, [%0, -%2]!"
8105 [(set_attr "type" "store1")
8106 (set_attr "predicable" "yes")]
8109 (define_insn "*loadsi_preinc"
8110 [(set (match_operand:SI 3 "s_register_operand" "=r")
8111 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8112 (match_operand:SI 2 "index_operand" "rJ"))))
8113 (set (match_operand:SI 0 "s_register_operand" "=r")
8114 (plus:SI (match_dup 1) (match_dup 2)))]
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]!"
8121 [(set_attr "type" "load")
8122 (set_attr "predicable" "yes")]
8125 (define_insn "*loadsi_predec"
8126 [(set (match_operand:SI 3 "s_register_operand" "=r")
8127 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8128 (match_operand:SI 2 "s_register_operand" "r"))))
8129 (set (match_operand:SI 0 "s_register_operand" "=r")
8130 (minus:SI (match_dup 1) (match_dup 2)))]
8132 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8133 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8134 && (GET_CODE (operands[2]) != REG
8135 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8136 "ldr%?\\t%3, [%0, -%2]!"
8137 [(set_attr "type" "load")
8138 (set_attr "predicable" "yes")]
8141 (define_insn "*loadhi_preinc"
8142 [(set (match_operand:HI 3 "s_register_operand" "=r")
8143 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8144 (match_operand:SI 2 "index_operand" "rJ"))))
8145 (set (match_operand:SI 0 "s_register_operand" "=r")
8146 (plus:SI (match_dup 1) (match_dup 2)))]
8148 && !BYTES_BIG_ENDIAN
8149 && !TARGET_MMU_TRAPS
8150 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8151 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8152 && (GET_CODE (operands[2]) != REG
8153 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8154 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8155 [(set_attr "type" "load")
8156 (set_attr "predicable" "yes")]
8159 (define_insn "*loadhi_predec"
8160 [(set (match_operand:HI 3 "s_register_operand" "=r")
8161 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8162 (match_operand:SI 2 "s_register_operand" "r"))))
8163 (set (match_operand:SI 0 "s_register_operand" "=r")
8164 (minus:SI (match_dup 1) (match_dup 2)))]
8166 && !BYTES_BIG_ENDIAN
8167 && !TARGET_MMU_TRAPS
8168 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8169 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8170 && (GET_CODE (operands[2]) != REG
8171 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8172 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8173 [(set_attr "type" "load")
8174 (set_attr "predicable" "yes")]
8177 (define_insn "*strqi_shiftpreinc"
8178 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8179 [(match_operand:SI 3 "s_register_operand" "r")
8180 (match_operand:SI 4 "const_shift_operand" "n")])
8181 (match_operand:SI 1 "s_register_operand" "0")))
8182 (match_operand:QI 5 "s_register_operand" "r"))
8183 (set (match_operand:SI 0 "s_register_operand" "=r")
8184 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8187 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8188 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8189 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8190 "str%?b\\t%5, [%0, %3%S2]!"
8191 [(set_attr "type" "store1")
8192 (set_attr "predicable" "yes")]
8195 (define_insn "*strqi_shiftpredec"
8196 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8197 (match_operator:SI 2 "shift_operator"
8198 [(match_operand:SI 3 "s_register_operand" "r")
8199 (match_operand:SI 4 "const_shift_operand" "n")])))
8200 (match_operand:QI 5 "s_register_operand" "r"))
8201 (set (match_operand:SI 0 "s_register_operand" "=r")
8202 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8205 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8206 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8207 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8208 "str%?b\\t%5, [%0, -%3%S2]!"
8209 [(set_attr "type" "store1")
8210 (set_attr "predicable" "yes")]
8213 (define_insn "*loadqi_shiftpreinc"
8214 [(set (match_operand:QI 5 "s_register_operand" "=r")
8215 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8216 [(match_operand:SI 3 "s_register_operand" "r")
8217 (match_operand:SI 4 "const_shift_operand" "n")])
8218 (match_operand:SI 1 "s_register_operand" "0"))))
8219 (set (match_operand:SI 0 "s_register_operand" "=r")
8220 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8223 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8224 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8225 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8226 "ldr%?b\\t%5, [%0, %3%S2]!"
8227 [(set_attr "type" "load")
8228 (set_attr "predicable" "yes")]
8231 (define_insn "*loadqi_shiftpredec"
8232 [(set (match_operand:QI 5 "s_register_operand" "=r")
8233 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8234 (match_operator:SI 2 "shift_operator"
8235 [(match_operand:SI 3 "s_register_operand" "r")
8236 (match_operand:SI 4 "const_shift_operand" "n")]))))
8237 (set (match_operand:SI 0 "s_register_operand" "=r")
8238 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8241 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8242 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8243 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8244 "ldr%?b\\t%5, [%0, -%3%S2]!"
8245 [(set_attr "type" "load")
8246 (set_attr "predicable" "yes")]
8249 (define_insn "*strsi_shiftpreinc"
8250 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8251 [(match_operand:SI 3 "s_register_operand" "r")
8252 (match_operand:SI 4 "const_shift_operand" "n")])
8253 (match_operand:SI 1 "s_register_operand" "0")))
8254 (match_operand:SI 5 "s_register_operand" "r"))
8255 (set (match_operand:SI 0 "s_register_operand" "=r")
8256 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8259 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8260 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8261 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8262 "str%?\\t%5, [%0, %3%S2]!"
8263 [(set_attr "type" "store1")
8264 (set_attr "predicable" "yes")]
8267 (define_insn "*strsi_shiftpredec"
8268 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8269 (match_operator:SI 2 "shift_operator"
8270 [(match_operand:SI 3 "s_register_operand" "r")
8271 (match_operand:SI 4 "const_shift_operand" "n")])))
8272 (match_operand:SI 5 "s_register_operand" "r"))
8273 (set (match_operand:SI 0 "s_register_operand" "=r")
8274 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8277 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8278 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8279 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8280 "str%?\\t%5, [%0, -%3%S2]!"
8281 [(set_attr "type" "store1")
8282 (set_attr "predicable" "yes")]
8285 (define_insn "*loadsi_shiftpreinc"
8286 [(set (match_operand:SI 5 "s_register_operand" "=r")
8287 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8288 [(match_operand:SI 3 "s_register_operand" "r")
8289 (match_operand:SI 4 "const_shift_operand" "n")])
8290 (match_operand:SI 1 "s_register_operand" "0"))))
8291 (set (match_operand:SI 0 "s_register_operand" "=r")
8292 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8295 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8296 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8297 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8298 "ldr%?\\t%5, [%0, %3%S2]!"
8299 [(set_attr "type" "load")
8300 (set_attr "predicable" "yes")]
8303 (define_insn "*loadsi_shiftpredec"
8304 [(set (match_operand:SI 5 "s_register_operand" "=r")
8305 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8306 (match_operator:SI 2 "shift_operator"
8307 [(match_operand:SI 3 "s_register_operand" "r")
8308 (match_operand:SI 4 "const_shift_operand" "n")]))))
8309 (set (match_operand:SI 0 "s_register_operand" "=r")
8310 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8313 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8314 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8315 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8316 "ldr%?\\t%5, [%0, -%3%S2]!"
8317 [(set_attr "type" "load")
8318 (set_attr "predicable" "yes")])
8320 (define_insn "*loadhi_shiftpreinc"
8321 [(set (match_operand:HI 5 "s_register_operand" "=r")
8322 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8323 [(match_operand:SI 3 "s_register_operand" "r")
8324 (match_operand:SI 4 "const_shift_operand" "n")])
8325 (match_operand:SI 1 "s_register_operand" "0"))))
8326 (set (match_operand:SI 0 "s_register_operand" "=r")
8327 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8330 && !BYTES_BIG_ENDIAN
8331 && !TARGET_MMU_TRAPS
8332 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8333 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8334 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8335 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8336 [(set_attr "type" "load")
8337 (set_attr "predicable" "yes")]
8340 (define_insn "*loadhi_shiftpredec"
8341 [(set (match_operand:HI 5 "s_register_operand" "=r")
8342 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8343 (match_operator:SI 2 "shift_operator"
8344 [(match_operand:SI 3 "s_register_operand" "r")
8345 (match_operand:SI 4 "const_shift_operand" "n")]))))
8346 (set (match_operand:SI 0 "s_register_operand" "=r")
8347 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8350 && !BYTES_BIG_ENDIAN
8351 && !TARGET_MMU_TRAPS
8352 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8353 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8354 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8355 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8356 [(set_attr "type" "load")
8357 (set_attr "predicable" "yes")]
8360 ; It can also support extended post-inc expressions, but combine doesn't
8362 ; It doesn't seem worth adding peepholes for anything but the most common
8363 ; cases since, unlike combine, the increment must immediately follow the load
8364 ; for this pattern to match.
8365 ; We must watch to see that the source/destination register isn't also the
8366 ; same as the base address register, and that if the index is a register,
8367 ; that it is not the same as the base address register. In such cases the
8368 ; instruction that we would generate would have UNPREDICTABLE behaviour so
8372 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8373 (match_operand:QI 2 "s_register_operand" "r"))
8375 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8377 && (REGNO (operands[2]) != REGNO (operands[0]))
8378 && (GET_CODE (operands[1]) != REG
8379 || (REGNO (operands[1]) != REGNO (operands[0])))"
8380 "str%?b\\t%2, [%0], %1"
8384 [(set (match_operand:QI 0 "s_register_operand" "=r")
8385 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8387 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8389 && REGNO (operands[0]) != REGNO(operands[1])
8390 && (GET_CODE (operands[2]) != REG
8391 || REGNO(operands[0]) != REGNO (operands[2]))"
8392 "ldr%?b\\t%0, [%1], %2"
8396 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8397 (match_operand:SI 2 "s_register_operand" "r"))
8399 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8401 && (REGNO (operands[2]) != REGNO (operands[0]))
8402 && (GET_CODE (operands[1]) != REG
8403 || (REGNO (operands[1]) != REGNO (operands[0])))"
8404 "str%?\\t%2, [%0], %1"
8408 [(set (match_operand:HI 0 "s_register_operand" "=r")
8409 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8411 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8413 && !BYTES_BIG_ENDIAN
8414 && !TARGET_MMU_TRAPS
8415 && REGNO (operands[0]) != REGNO(operands[1])
8416 && (GET_CODE (operands[2]) != REG
8417 || REGNO(operands[0]) != REGNO (operands[2]))"
8418 "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8422 [(set (match_operand:SI 0 "s_register_operand" "=r")
8423 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8425 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8427 && REGNO (operands[0]) != REGNO(operands[1])
8428 && (GET_CODE (operands[2]) != REG
8429 || REGNO(operands[0]) != REGNO (operands[2]))"
8430 "ldr%?\\t%0, [%1], %2"
8434 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8435 (match_operand:SI 1 "index_operand" "rJ")))
8436 (match_operand:QI 2 "s_register_operand" "r"))
8437 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8439 && (REGNO (operands[2]) != REGNO (operands[0]))
8440 && (GET_CODE (operands[1]) != REG
8441 || (REGNO (operands[1]) != REGNO (operands[0])))"
8442 "str%?b\\t%2, [%0, %1]!"
8446 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8447 [(match_operand:SI 0 "s_register_operand" "r")
8448 (match_operand:SI 1 "const_int_operand" "n")])
8449 (match_operand:SI 2 "s_register_operand" "+r")))
8450 (match_operand:QI 3 "s_register_operand" "r"))
8451 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8454 && (REGNO (operands[3]) != REGNO (operands[2]))
8455 && (REGNO (operands[0]) != REGNO (operands[2]))"
8456 "str%?b\\t%3, [%2, %0%S4]!"
8459 ; This pattern is never tried by combine, so do it as a peephole
8462 [(set (match_operand:SI 0 "s_register_operand" "")
8463 (match_operand:SI 1 "s_register_operand" ""))
8464 (set (reg:CC CC_REGNUM)
8465 (compare:CC (match_dup 1) (const_int 0)))]
8467 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8468 (set (match_dup 0) (match_dup 1))])]
8472 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8473 ; reversed, check that the memory references aren't volatile.
8476 [(set (match_operand:SI 0 "s_register_operand" "=r")
8477 (match_operand:SI 4 "memory_operand" "m"))
8478 (set (match_operand:SI 1 "s_register_operand" "=r")
8479 (match_operand:SI 5 "memory_operand" "m"))
8480 (set (match_operand:SI 2 "s_register_operand" "=r")
8481 (match_operand:SI 6 "memory_operand" "m"))
8482 (set (match_operand:SI 3 "s_register_operand" "=r")
8483 (match_operand:SI 7 "memory_operand" "m"))]
8484 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8486 return emit_ldm_seq (operands, 4);
8491 [(set (match_operand:SI 0 "s_register_operand" "=r")
8492 (match_operand:SI 3 "memory_operand" "m"))
8493 (set (match_operand:SI 1 "s_register_operand" "=r")
8494 (match_operand:SI 4 "memory_operand" "m"))
8495 (set (match_operand:SI 2 "s_register_operand" "=r")
8496 (match_operand:SI 5 "memory_operand" "m"))]
8497 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8499 return emit_ldm_seq (operands, 3);
8504 [(set (match_operand:SI 0 "s_register_operand" "=r")
8505 (match_operand:SI 2 "memory_operand" "m"))
8506 (set (match_operand:SI 1 "s_register_operand" "=r")
8507 (match_operand:SI 3 "memory_operand" "m"))]
8508 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8510 return emit_ldm_seq (operands, 2);
8515 [(set (match_operand:SI 4 "memory_operand" "=m")
8516 (match_operand:SI 0 "s_register_operand" "r"))
8517 (set (match_operand:SI 5 "memory_operand" "=m")
8518 (match_operand:SI 1 "s_register_operand" "r"))
8519 (set (match_operand:SI 6 "memory_operand" "=m")
8520 (match_operand:SI 2 "s_register_operand" "r"))
8521 (set (match_operand:SI 7 "memory_operand" "=m")
8522 (match_operand:SI 3 "s_register_operand" "r"))]
8523 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8525 return emit_stm_seq (operands, 4);
8530 [(set (match_operand:SI 3 "memory_operand" "=m")
8531 (match_operand:SI 0 "s_register_operand" "r"))
8532 (set (match_operand:SI 4 "memory_operand" "=m")
8533 (match_operand:SI 1 "s_register_operand" "r"))
8534 (set (match_operand:SI 5 "memory_operand" "=m")
8535 (match_operand:SI 2 "s_register_operand" "r"))]
8536 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8538 return emit_stm_seq (operands, 3);
8543 [(set (match_operand:SI 2 "memory_operand" "=m")
8544 (match_operand:SI 0 "s_register_operand" "r"))
8545 (set (match_operand:SI 3 "memory_operand" "=m")
8546 (match_operand:SI 1 "s_register_operand" "r"))]
8547 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8549 return emit_stm_seq (operands, 2);
8554 [(set (match_operand:SI 0 "s_register_operand" "")
8555 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8557 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8558 [(match_operand:SI 3 "s_register_operand" "")
8559 (match_operand:SI 4 "arm_rhs_operand" "")]))))
8560 (clobber (match_operand:SI 5 "s_register_operand" ""))]
8562 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8563 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8568 ;; This split can be used because CC_Z mode implies that the following
8569 ;; branch will be an equality, or an unsigned inequality, so the sign
8570 ;; extension is not needed.
8573 [(set (reg:CC_Z CC_REGNUM)
8575 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8577 (match_operand 1 "const_int_operand" "")))
8578 (clobber (match_scratch:SI 2 ""))]
8580 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8581 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8582 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8583 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8585 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8589 (define_expand "prologue"
8590 [(clobber (const_int 0))]
8593 arm_expand_prologue ();
8595 thumb_expand_prologue ();
8600 (define_expand "epilogue"
8601 [(unspec_volatile [(return)] 1)]
8605 thumb_expand_epilogue ();
8606 else if (USE_RETURN_INSN (FALSE))
8608 emit_jump_insn (gen_return ());
8611 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8613 gen_rtx_RETURN (VOIDmode)),
8619 (define_insn "sibcall_epilogue"
8620 [(unspec_volatile [(const_int 0)] 1)]
8623 output_asm_insn (\"%@ Sibcall epilogue\", operands);
8624 if (USE_RETURN_INSN (FALSE))
8625 return output_return_instruction (NULL, FALSE, FALSE);
8626 return arm_output_epilogue (FALSE);
8628 ;; Length is absolute worst case
8629 [(set_attr "length" "44")
8630 (set_attr "type" "block")]
8633 (define_insn "*epilogue_insns"
8634 [(unspec_volatile [(return)] 1)]
8638 return arm_output_epilogue (TRUE);
8639 else /* TARGET_THUMB */
8640 return thumb_unexpanded_epilogue ();
8642 ; Length is absolute worst case
8643 [(set_attr "length" "44")
8644 (set_attr "type" "block")]
8647 (define_expand "eh_epilogue"
8648 [(use (match_operand:SI 0 "register_operand" "r"))
8649 (use (match_operand:SI 1 "register_operand" "r"))
8650 (use (match_operand:SI 2 "register_operand" "r"))]
8654 cfun->machine->eh_epilogue_sp_ofs = operands[1];
8655 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8657 rtx ra = gen_rtx_REG (Pmode, 2);
8659 emit_move_insn (ra, operands[2]);
8665 ;; This split is only used during output to reduce the number of patterns
8666 ;; that need assembler instructions adding to them. We allowed the setting
8667 ;; of the conditions to be implicit during rtl generation so that
8668 ;; the conditional compare patterns would work. However this conflicts to
8669 ;; some extent with the conditional data operations, so we have to split them
8673 [(set (match_operand:SI 0 "s_register_operand" "")
8674 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8675 [(match_operand 2 "" "") (match_operand 3 "" "")])
8677 (match_operand 4 "" "")))
8678 (clobber (reg:CC CC_REGNUM))]
8679 "TARGET_ARM && reload_completed"
8680 [(set (match_dup 5) (match_dup 6))
8681 (cond_exec (match_dup 7)
8682 (set (match_dup 0) (match_dup 4)))]
8685 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8686 operands[2], operands[3]);
8687 enum rtx_code rc = GET_CODE (operands[1]);
8689 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8690 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8691 if (mode == CCFPmode || mode == CCFPEmode)
8692 rc = reverse_condition_maybe_unordered (rc);
8694 rc = reverse_condition (rc);
8696 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8701 [(set (match_operand:SI 0 "s_register_operand" "")
8702 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8703 [(match_operand 2 "" "") (match_operand 3 "" "")])
8704 (match_operand 4 "" "")
8706 (clobber (reg:CC CC_REGNUM))]
8707 "TARGET_ARM && reload_completed"
8708 [(set (match_dup 5) (match_dup 6))
8709 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8710 (set (match_dup 0) (match_dup 4)))]
8713 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8714 operands[2], operands[3]);
8716 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8717 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8722 [(set (match_operand:SI 0 "s_register_operand" "")
8723 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8724 [(match_operand 2 "" "") (match_operand 3 "" "")])
8725 (match_operand 4 "" "")
8726 (match_operand 5 "" "")))
8727 (clobber (reg:CC CC_REGNUM))]
8728 "TARGET_ARM && reload_completed"
8729 [(set (match_dup 6) (match_dup 7))
8730 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8731 (set (match_dup 0) (match_dup 4)))
8732 (cond_exec (match_dup 8)
8733 (set (match_dup 0) (match_dup 5)))]
8736 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8737 operands[2], operands[3]);
8738 enum rtx_code rc = GET_CODE (operands[1]);
8740 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8741 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8742 if (mode == CCFPmode || mode == CCFPEmode)
8743 rc = reverse_condition_maybe_unordered (rc);
8745 rc = reverse_condition (rc);
8747 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8752 [(set (match_operand:SI 0 "s_register_operand" "")
8753 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8754 [(match_operand:SI 2 "s_register_operand" "")
8755 (match_operand:SI 3 "arm_add_operand" "")])
8756 (match_operand:SI 4 "arm_rhs_operand" "")
8758 (match_operand:SI 5 "s_register_operand" ""))))
8759 (clobber (reg:CC CC_REGNUM))]
8760 "TARGET_ARM && reload_completed"
8761 [(set (match_dup 6) (match_dup 7))
8762 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8763 (set (match_dup 0) (match_dup 4)))
8764 (cond_exec (match_dup 8)
8765 (set (match_dup 0) (not:SI (match_dup 5))))]
8768 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8769 operands[2], operands[3]);
8770 enum rtx_code rc = GET_CODE (operands[1]);
8772 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8773 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8774 if (mode == CCFPmode || mode == CCFPEmode)
8775 rc = reverse_condition_maybe_unordered (rc);
8777 rc = reverse_condition (rc);
8779 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8783 (define_insn "*cond_move_not"
8784 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8785 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8786 [(match_operand 3 "cc_register" "") (const_int 0)])
8787 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8789 (match_operand:SI 2 "s_register_operand" "r,r"))))]
8793 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8794 [(set_attr "conds" "use")
8795 (set_attr "length" "4,8")]
8798 ;; The next two patterns occur when an AND operation is followed by a
8799 ;; scc insn sequence
8801 (define_insn "*sign_extract_onebit"
8802 [(set (match_operand:SI 0 "s_register_operand" "=r")
8803 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8805 (match_operand:SI 2 "const_int_operand" "n")))]
8808 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8809 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8810 return \"mvnne\\t%0, #0\";
8812 [(set_attr "conds" "clob")
8813 (set_attr "length" "8")]
8816 (define_insn "*not_signextract_onebit"
8817 [(set (match_operand:SI 0 "s_register_operand" "=r")
8819 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8821 (match_operand:SI 2 "const_int_operand" "n"))))]
8824 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8825 output_asm_insn (\"tst\\t%1, %2\", operands);
8826 output_asm_insn (\"mvneq\\t%0, #0\", operands);
8827 return \"movne\\t%0, #0\";
8829 [(set_attr "conds" "clob")
8830 (set_attr "length" "12")]
8833 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
8834 ;; expressions. For simplicity, the first register is also in the unspec
8836 (define_insn "*push_multi"
8837 [(match_parallel 2 "multi_register_push"
8838 [(set (match_operand:BLK 0 "memory_operand" "=m")
8839 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 2))])]
8843 int num_saves = XVECLEN (operands[2], 0);
8845 /* For the StrongARM at least it is faster to
8846 use STR to store only a single register. */
8848 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8854 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
8856 for (i = 1; i < num_saves; i++)
8858 strcat (pattern, \", %|\");
8860 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
8863 strcat (pattern, \"}\");
8864 output_asm_insn (pattern, operands);
8869 [(set_attr "type" "store4")]
8872 ;; Similarly for the floating point registers
8873 (define_insn "*push_fp_multi"
8874 [(match_parallel 2 "multi_register_push"
8875 [(set (match_operand:BLK 0 "memory_operand" "=m")
8876 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")] 2))])]
8882 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
8883 output_asm_insn (pattern, operands);
8886 [(set_attr "type" "f_store")]
8889 ;; Special patterns for dealing with the constant pool
8891 (define_insn "align_4"
8892 [(unspec_volatile [(const_int 0)] 2)]
8895 assemble_align (32);
8900 (define_insn "consttable_end"
8901 [(unspec_volatile [(const_int 0)] 3)]
8904 making_const_table = FALSE;
8909 (define_insn "consttable_1"
8910 [(unspec_volatile [(match_operand 0 "" "")] 4)]
8913 making_const_table = TRUE;
8914 assemble_integer (operands[0], 1, 1);
8918 [(set_attr "length" "4")]
8921 (define_insn "consttable_2"
8922 [(unspec_volatile [(match_operand 0 "" "")] 5)]
8925 making_const_table = TRUE;
8926 assemble_integer (operands[0], 2, 1);
8930 [(set_attr "length" "4")]
8933 (define_insn "consttable_4"
8934 [(unspec_volatile [(match_operand 0 "" "")] 6)]
8938 making_const_table = TRUE;
8939 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8943 union real_extract u;
8944 memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
8945 assemble_real (u.d, GET_MODE (operands[0]));
8949 assemble_integer (operands[0], 4, 1);
8954 [(set_attr "length" "4")]
8957 (define_insn "consttable_8"
8958 [(unspec_volatile [(match_operand 0 "" "")] 7)]
8962 making_const_table = TRUE;
8963 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8967 union real_extract u;
8968 memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
8969 assemble_real (u.d, GET_MODE (operands[0]));
8973 assemble_integer (operands[0], 8, 1);
8978 [(set_attr "length" "8")]
8981 ;; Miscellaneous Thumb patterns
8983 (define_insn "tablejump"
8984 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
8985 (use (label_ref (match_operand 1 "" "")))]
8988 [(set_attr "length" "2")]
8994 [(set (match_operand:SI 0 "s_register_operand" "=r")
8995 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] 128))]
8999 ;; XScale instructions.
9001 (define_insn "prefetch"
9003 [(match_operand:SI 0 "offsettable_memory_operand" "o")] 129)]
9007 ;; General predication pattern
9010 [(match_operator 0 "arm_comparison_operator"
9011 [(match_operand 1 "cc_register" "")