]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/arm/arm.md
builtins.c: Rename movstr*, except for movstrict*, to movmem* and clrstr* to clrmem*.
[thirdparty/gcc.git] / gcc / config / arm / arm.md
1 ;;- Machine description for ARM for GNU compiler
2 ;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;; 2001, 2002, 2003 2004 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).
7
8 ;; This file is part of GCC.
9
10 ;; GCC is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 2, or (at your
13 ;; option) any later version.
14
15 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
18 ;; License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; see the file COPYING. If not, write to
22 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
24
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
27 \f
28 ;;---------------------------------------------------------------------------
29 ;; Constants
30
31 ;; Register numbers
32 (define_constants
33 [(IP_REGNUM 12) ; Scratch register
34 (SP_REGNUM 13) ; Stack pointer
35 (LR_REGNUM 14) ; Return address register
36 (PC_REGNUM 15) ; Program counter
37 (CC_REGNUM 24) ; Condition code pseudo register
38 (LAST_ARM_REGNUM 15)
39 ]
40 )
41 ;; 3rd operand to select_dominance_cc_mode
42 (define_constants
43 [(DOM_CC_X_AND_Y 0)
44 (DOM_CC_NX_OR_Y 1)
45 (DOM_CC_X_OR_Y 2)
46 ]
47 )
48
49 ;; UNSPEC Usage:
50 ;; Note: sin and cos are no-longer used.
51
52 (define_constants
53 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
54 ; operand 0 is the result,
55 ; operand 1 the parameter.
56 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
57 ; operand 0 is the result,
58 ; operand 1 the parameter.
59 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
60 ; operand 0 is the first register,
61 ; subsequent registers are in parallel (use ...)
62 ; expressions.
63 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
64 ; usage, that is, we will add the pic_register
65 ; value to it before trying to dereference it.
66 (UNSPEC_PIC_BASE 4) ; Adding the PC value to the offset to the
67 ; GLOBAL_OFFSET_TABLE. The operation is fully
68 ; described by the RTL but must be wrapped to
69 ; prevent combine from trying to rip it apart.
70 (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses
71 ; being scheduled before the stack adjustment insn.
72 (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
73 ; this unspec is used to prevent the deletion of
74 ; instructions setting registers for EH handling
75 ; and stack frame generation. Operand 0 is the
76 ; register to "use".
77 (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
78 (UNSPEC_WSHUFH 8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
79 (UNSPEC_WACC 9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
80 (UNSPEC_TMOVMSK 10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
81 (UNSPEC_WSAD 11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
82 (UNSPEC_WSADZ 12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
83 (UNSPEC_WMACS 13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
84 (UNSPEC_WMACU 14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
85 (UNSPEC_WMACSZ 15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
86 (UNSPEC_WMACUZ 16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
87 (UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
88 (UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
89 (UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
90 ]
91 )
92
93 ;; UNSPEC_VOLATILE Usage:
94
95 (define_constants
96 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
97 ; insn in the code.
98 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
99 ; instruction epilogue sequence that isn't expanded
100 ; into normal RTL. Used for both normal and sibcall
101 ; epilogues.
102 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
103 ; for inlined constants.
104 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
105 ; table.
106 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
107 ; an 8-bit object.
108 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
109 ; a 16-bit object.
110 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
111 ; a 32-bit object.
112 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
113 ; a 64-bit object.
114 (VUNSPEC_TMRC 8) ; Used by the iWMMXt TMRC instruction.
115 (VUNSPEC_TMCR 9) ; Used by the iWMMXt TMCR instruction.
116 (VUNSPEC_ALIGN8 10) ; 8-byte alignment version of VUNSPEC_ALIGN
117 (VUNSPEC_WCMP_EQ 11) ; Used by the iWMMXt WCMPEQ instructions
118 (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
119 (VUNSPEC_WCMP_GT 13) ; Used by the iwMMXT WCMPGT instructions
120 ]
121 )
122 \f
123 ;;---------------------------------------------------------------------------
124 ;; Attributes
125
126 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
127 ; generating ARM code. This is used to control the length of some insn
128 ; patterns that share the same RTL in both ARM and Thumb code.
129 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
130
131 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
132 ; scheduling decisions for the load unit and the multiplier.
133 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
134
135 ; IS_XSCALE is set to 'yes' when compiling for XScale.
136 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
137
138 ;; Operand number of an input operand that is shifted. Zero if the
139 ;; given instruction does not shift one of its input operands.
140 (define_attr "shift" "" (const_int 0))
141
142 ; Floating Point Unit. If we only have floating point emulation, then there
143 ; is no point in scheduling the floating point insns. (Well, for best
144 ; performance we should try and group them together).
145 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
146 (const (symbol_ref "arm_fpu_attr")))
147
148 ; LENGTH of an instruction (in bytes)
149 (define_attr "length" "" (const_int 4))
150
151 ; POOL_RANGE is how far away from a constant pool entry that this insn
152 ; can be placed. If the distance is zero, then this insn will never
153 ; reference the pool.
154 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
155 ; before its address.
156 (define_attr "pool_range" "" (const_int 0))
157 (define_attr "neg_pool_range" "" (const_int 0))
158
159 ; An assembler sequence may clobber the condition codes without us knowing.
160 ; If such an insn references the pool, then we have no way of knowing how,
161 ; so use the most conservative value for pool_range.
162 (define_asm_attributes
163 [(set_attr "conds" "clob")
164 (set_attr "length" "4")
165 (set_attr "pool_range" "250")])
166
167 ;; The instruction used to implement a particular pattern. This
168 ;; information is used by pipeline descriptions to provide accurate
169 ;; scheduling information.
170
171 (define_attr "insn"
172 "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,other"
173 (const_string "other"))
174
175 ; TYPE attribute is used to detect floating point instructions which, if
176 ; running on a co-processor can run in parallel with other, basic instructions
177 ; If write-buffer scheduling is enabled then it can also be used in the
178 ; scheduling of writes.
179
180 ; Classification of each insn
181 ; alu any alu instruction that doesn't hit memory or fp
182 ; regs or have a shifted source operand
183 ; alu_shift any data instruction that doesn't hit memory or fp
184 ; regs, but has a source operand shifted by a constant
185 ; alu_shift_reg any data instruction that doesn't hit memory or fp
186 ; regs, but has a source operand shifted by a register value
187 ; mult a multiply instruction
188 ; block blockage insn, this blocks all functional units
189 ; float a floating point arithmetic operation (subject to expansion)
190 ; fdivd DFmode floating point division
191 ; fdivs SFmode floating point division
192 ; fmul Floating point multiply
193 ; ffmul Fast floating point multiply
194 ; farith Floating point arithmetic (4 cycle)
195 ; ffarith Fast floating point arithmetic (2 cycle)
196 ; float_em a floating point arithmetic operation that is normally emulated
197 ; even on a machine with an fpa.
198 ; f_load a floating point load from memory
199 ; f_store a floating point store to memory
200 ; f_mem_r a transfer of a floating point register to a real reg via mem
201 ; r_mem_f the reverse of f_mem_r
202 ; f_2_r fast transfer float to arm (no memory needed)
203 ; r_2_f fast transfer arm to float
204 ; branch a branch
205 ; call a subroutine call
206 ; load_byte load byte(s) from memory to arm registers
207 ; load1 load 1 word from memory to arm registers
208 ; load2 load 2 words from memory to arm registers
209 ; load3 load 3 words from memory to arm registers
210 ; load4 load 4 words from memory to arm registers
211 ; store store 1 word to memory from arm registers
212 ; store2 store 2 words
213 ; store3 store 3 words
214 ; store4 store 4 (or more) words
215 ; Additions for Cirrus Maverick co-processor:
216 ; mav_farith Floating point arithmetic (4 cycle)
217 ; mav_dmult Double multiplies (7 cycle)
218 ;
219 (define_attr "type"
220 "alu,alu_shift,alu_shift_reg,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,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult"
221 (if_then_else
222 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
223 (const_string "mult")
224 (const_string "alu")))
225
226 ; Load scheduling, set from the arm_ld_sched variable
227 ; initialized by arm_override_options()
228 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
229
230 ; condition codes: this one is used by final_prescan_insn to speed up
231 ; conditionalizing instructions. It saves having to scan the rtl to see if
232 ; it uses or alters the condition codes.
233 ;
234 ; USE means that the condition codes are used by the insn in the process of
235 ; outputting code, this means (at present) that we can't use the insn in
236 ; inlined branches
237 ;
238 ; SET means that the purpose of the insn is to set the condition codes in a
239 ; well defined manner.
240 ;
241 ; CLOB means that the condition codes are altered in an undefined manner, if
242 ; they are altered at all
243 ;
244 ; JUMP_CLOB is used when the condition cannot be represented by a single
245 ; instruction (UNEQ and LTGT). These cannot be predicated.
246 ;
247 ; NOCOND means that the condition codes are neither altered nor affect the
248 ; output of this insn
249
250 (define_attr "conds" "use,set,clob,jump_clob,nocond"
251 (if_then_else (eq_attr "type" "call")
252 (const_string "clob")
253 (const_string "nocond")))
254
255 ; Predicable means that the insn can be conditionally executed based on
256 ; an automatically added predicate (additional patterns are generated by
257 ; gen...). We default to 'no' because no Thumb patterns match this rule
258 ; and not all ARM patterns do.
259 (define_attr "predicable" "no,yes" (const_string "no"))
260
261 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
262 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
263 ; suffer blockages enough to warrant modelling this (and it can adversely
264 ; affect the schedule).
265 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
266
267 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
268 ; to stall the processor. Used with model_wbuf above.
269 (define_attr "write_conflict" "no,yes"
270 (if_then_else (eq_attr "type"
271 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
272 (const_string "yes")
273 (const_string "no")))
274
275 ; Classify the insns into those that take one cycle and those that take more
276 ; than one on the main cpu execution unit.
277 (define_attr "core_cycles" "single,multi"
278 (if_then_else (eq_attr "type"
279 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
280 (const_string "single")
281 (const_string "multi")))
282
283 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
284 ;; distant label. Only applicable to Thumb code.
285 (define_attr "far_jump" "yes,no" (const_string "no"))
286
287 ;;---------------------------------------------------------------------------
288 ;; Pipeline descriptions
289
290 ;; Processor type. This attribute must exactly match the table in
291 ;; arm-cores.def.
292 (define_attr "tune"
293 "arm2,arm250,arm3,arm6,arm60,arm600,arm610,arm620,arm7,arm7m,arm7d,arm7dm,arm7di,arm7dmi,arm70,arm700,arm700i,arm710,arm720,arm710c,arm7100,arm7500,arm7500fe,arm7tdmi,arm710t,arm720t,arm740t,arm8,arm810,arm9,arm920,arm920t,arm940t,arm9tdmi,arm9e,ep9312,strongarm,strongarm110,strongarm1100,strongarm1110,arm10tdmi,arm1020t,arm926ejs,arm1026ejs,xscale,iwmmxt,arm1136js,arm1136jfs"
294 (const (symbol_ref "arm_tune")))
295
296 ;; True if the generic scheduling description should be used.
297
298 (define_attr "generic_sched" "yes,no"
299 (if_then_else
300 (eq_attr "tune" "arm926ejs,arm1026ejs,arm1136js,arm1136jfs")
301 (const_string "no")
302 (const_string "yes")))
303
304 (include "arm-generic.md")
305 (include "arm926ejs.md")
306 (include "arm1026ejs.md")
307 (include "arm1136jfs.md")
308
309 \f
310 ;;---------------------------------------------------------------------------
311 ;; Insn patterns
312 ;;
313 ;; Addition insns.
314
315 ;; Note: For DImode insns, there is normally no reason why operands should
316 ;; not be in the same register, what we don't want is for something being
317 ;; written to partially overlap something that is an input.
318 ;; Cirrus 64bit additions should not be split because we have a native
319 ;; 64bit addition instructions.
320
321 (define_expand "adddi3"
322 [(parallel
323 [(set (match_operand:DI 0 "s_register_operand" "")
324 (plus:DI (match_operand:DI 1 "s_register_operand" "")
325 (match_operand:DI 2 "s_register_operand" "")))
326 (clobber (reg:CC CC_REGNUM))])]
327 "TARGET_EITHER"
328 "
329 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
330 {
331 if (!cirrus_fp_register (operands[0], DImode))
332 operands[0] = force_reg (DImode, operands[0]);
333 if (!cirrus_fp_register (operands[1], DImode))
334 operands[1] = force_reg (DImode, operands[1]);
335 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
336 DONE;
337 }
338
339 if (TARGET_THUMB)
340 {
341 if (GET_CODE (operands[1]) != REG)
342 operands[1] = force_reg (SImode, operands[1]);
343 if (GET_CODE (operands[2]) != REG)
344 operands[2] = force_reg (SImode, operands[2]);
345 }
346 "
347 )
348
349 (define_insn "*thumb_adddi3"
350 [(set (match_operand:DI 0 "register_operand" "=l")
351 (plus:DI (match_operand:DI 1 "register_operand" "%0")
352 (match_operand:DI 2 "register_operand" "l")))
353 (clobber (reg:CC CC_REGNUM))
354 ]
355 "TARGET_THUMB"
356 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
357 [(set_attr "length" "4")]
358 )
359
360 (define_insn_and_split "*arm_adddi3"
361 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
362 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
363 (match_operand:DI 2 "s_register_operand" "r, 0")))
364 (clobber (reg:CC CC_REGNUM))]
365 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
366 "#"
367 "TARGET_ARM && reload_completed"
368 [(parallel [(set (reg:CC_C CC_REGNUM)
369 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
370 (match_dup 1)))
371 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
372 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
373 (plus:SI (match_dup 4) (match_dup 5))))]
374 "
375 {
376 operands[3] = gen_highpart (SImode, operands[0]);
377 operands[0] = gen_lowpart (SImode, operands[0]);
378 operands[4] = gen_highpart (SImode, operands[1]);
379 operands[1] = gen_lowpart (SImode, operands[1]);
380 operands[5] = gen_highpart (SImode, operands[2]);
381 operands[2] = gen_lowpart (SImode, operands[2]);
382 }"
383 [(set_attr "conds" "clob")
384 (set_attr "length" "8")]
385 )
386
387 (define_insn_and_split "*adddi_sesidi_di"
388 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
389 (plus:DI (sign_extend:DI
390 (match_operand:SI 2 "s_register_operand" "r,r"))
391 (match_operand:DI 1 "s_register_operand" "r,0")))
392 (clobber (reg:CC CC_REGNUM))]
393 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
394 "#"
395 "TARGET_ARM && reload_completed"
396 [(parallel [(set (reg:CC_C CC_REGNUM)
397 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
398 (match_dup 1)))
399 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
400 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
401 (plus:SI (ashiftrt:SI (match_dup 2)
402 (const_int 31))
403 (match_dup 4))))]
404 "
405 {
406 operands[3] = gen_highpart (SImode, operands[0]);
407 operands[0] = gen_lowpart (SImode, operands[0]);
408 operands[4] = gen_highpart (SImode, operands[1]);
409 operands[1] = gen_lowpart (SImode, operands[1]);
410 operands[2] = gen_lowpart (SImode, operands[2]);
411 }"
412 [(set_attr "conds" "clob")
413 (set_attr "length" "8")]
414 )
415
416 (define_insn_and_split "*adddi_zesidi_di"
417 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
418 (plus:DI (zero_extend:DI
419 (match_operand:SI 2 "s_register_operand" "r,r"))
420 (match_operand:DI 1 "s_register_operand" "r,0")))
421 (clobber (reg:CC CC_REGNUM))]
422 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
423 "#"
424 "TARGET_ARM && reload_completed"
425 [(parallel [(set (reg:CC_C CC_REGNUM)
426 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
427 (match_dup 1)))
428 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
429 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
430 (plus:SI (match_dup 4) (const_int 0))))]
431 "
432 {
433 operands[3] = gen_highpart (SImode, operands[0]);
434 operands[0] = gen_lowpart (SImode, operands[0]);
435 operands[4] = gen_highpart (SImode, operands[1]);
436 operands[1] = gen_lowpart (SImode, operands[1]);
437 operands[2] = gen_lowpart (SImode, operands[2]);
438 }"
439 [(set_attr "conds" "clob")
440 (set_attr "length" "8")]
441 )
442
443 (define_expand "addsi3"
444 [(set (match_operand:SI 0 "s_register_operand" "")
445 (plus:SI (match_operand:SI 1 "s_register_operand" "")
446 (match_operand:SI 2 "reg_or_int_operand" "")))]
447 "TARGET_EITHER"
448 "
449 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
450 {
451 arm_split_constant (PLUS, SImode, NULL_RTX,
452 INTVAL (operands[2]), operands[0], operands[1],
453 (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
454 DONE;
455 }
456 "
457 )
458
459 ; If there is a scratch available, this will be faster than synthesizing the
460 ; addition.
461 (define_peephole2
462 [(match_scratch:SI 3 "r")
463 (set (match_operand:SI 0 "arm_general_register_operand" "")
464 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
465 (match_operand:SI 2 "const_int_operand" "")))]
466 "TARGET_ARM &&
467 !(const_ok_for_arm (INTVAL (operands[2]))
468 || const_ok_for_arm (-INTVAL (operands[2])))
469 && const_ok_for_arm (~INTVAL (operands[2]))"
470 [(set (match_dup 3) (match_dup 2))
471 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
472 ""
473 )
474
475 (define_insn_and_split "*arm_addsi3"
476 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
477 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
478 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
479 "TARGET_ARM"
480 "@
481 add%?\\t%0, %1, %2
482 sub%?\\t%0, %1, #%n2
483 #"
484 "TARGET_ARM &&
485 GET_CODE (operands[2]) == CONST_INT
486 && !(const_ok_for_arm (INTVAL (operands[2]))
487 || const_ok_for_arm (-INTVAL (operands[2])))"
488 [(clobber (const_int 0))]
489 "
490 arm_split_constant (PLUS, SImode, curr_insn,
491 INTVAL (operands[2]), operands[0],
492 operands[1], 0);
493 DONE;
494 "
495 [(set_attr "length" "4,4,16")
496 (set_attr "predicable" "yes")]
497 )
498
499 ;; Register group 'k' is a single register group containing only the stack
500 ;; register. Trying to reload it will always fail catastrophically,
501 ;; so never allow those alternatives to match if reloading is needed.
502
503 (define_insn "*thumb_addsi3"
504 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
505 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
506 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
507 "TARGET_THUMB"
508 "*
509 static const char * const asms[] =
510 {
511 \"add\\t%0, %0, %2\",
512 \"sub\\t%0, %0, #%n2\",
513 \"add\\t%0, %1, %2\",
514 \"add\\t%0, %0, %2\",
515 \"add\\t%0, %0, %2\",
516 \"add\\t%0, %1, %2\",
517 \"add\\t%0, %1, %2\"
518 };
519 if ((which_alternative == 2 || which_alternative == 6)
520 && GET_CODE (operands[2]) == CONST_INT
521 && INTVAL (operands[2]) < 0)
522 return \"sub\\t%0, %1, #%n2\";
523 return asms[which_alternative];
524 "
525 [(set_attr "length" "2")]
526 )
527
528 ;; Reloading and elimination of the frame pointer can
529 ;; sometimes cause this optimization to be missed.
530 (define_peephole2
531 [(set (match_operand:SI 0 "arm_general_register_operand" "")
532 (match_operand:SI 1 "const_int_operand" ""))
533 (set (match_dup 0)
534 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
535 "TARGET_THUMB
536 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
537 && (INTVAL (operands[1]) & 3) == 0"
538 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
539 ""
540 )
541
542 (define_insn "*addsi3_compare0"
543 [(set (reg:CC_NOOV CC_REGNUM)
544 (compare:CC_NOOV
545 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
546 (match_operand:SI 2 "arm_add_operand" "rI,L"))
547 (const_int 0)))
548 (set (match_operand:SI 0 "s_register_operand" "=r,r")
549 (plus:SI (match_dup 1) (match_dup 2)))]
550 "TARGET_ARM"
551 "@
552 add%?s\\t%0, %1, %2
553 sub%?s\\t%0, %1, #%n2"
554 [(set_attr "conds" "set")]
555 )
556
557 (define_insn "*addsi3_compare0_scratch"
558 [(set (reg:CC_NOOV CC_REGNUM)
559 (compare:CC_NOOV
560 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
561 (match_operand:SI 1 "arm_add_operand" "rI,L"))
562 (const_int 0)))]
563 "TARGET_ARM"
564 "@
565 cmn%?\\t%0, %1
566 cmp%?\\t%0, #%n1"
567 [(set_attr "conds" "set")]
568 )
569
570 ;; These patterns are the same ones as the two regular addsi3_compare0
571 ;; patterns, except we write them slightly different - the combiner
572 ;; tends to generate them this way.
573 (define_insn "*addsi3_compare0_for_combiner"
574 [(set (reg:CC CC_REGNUM)
575 (compare:CC
576 (match_operand:SI 1 "s_register_operand" "r,r")
577 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
578 (set (match_operand:SI 0 "s_register_operand" "=r,r")
579 (plus:SI (match_dup 1) (match_dup 2)))]
580 "TARGET_ARM"
581 "@
582 add%?s\\t%0, %1, %2
583 sub%?s\\t%0, %1, #%n2"
584 [(set_attr "conds" "set")]
585 )
586
587 (define_insn "*addsi3_compare0_scratch_for_combiner"
588 [(set (reg:CC CC_REGNUM)
589 (compare:CC
590 (match_operand:SI 0 "s_register_operand" "r,r")
591 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
592 "TARGET_ARM"
593 "@
594 cmn%?\\t%0, %1
595 cmp%?\\t%0, #%n1"
596 [(set_attr "conds" "set")]
597 )
598
599 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
600 ;; addend is a constant.
601 (define_insn "*cmpsi2_addneg"
602 [(set (reg:CC CC_REGNUM)
603 (compare:CC
604 (match_operand:SI 1 "s_register_operand" "r,r")
605 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
606 (set (match_operand:SI 0 "s_register_operand" "=r,r")
607 (plus:SI (match_dup 1)
608 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
609 "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
610 "@
611 sub%?s\\t%0, %1, %2
612 add%?s\\t%0, %1, #%n2"
613 [(set_attr "conds" "set")]
614 )
615
616 ;; Convert the sequence
617 ;; sub rd, rn, #1
618 ;; cmn rd, #1 (equivalent to cmp rd, #-1)
619 ;; bne dest
620 ;; into
621 ;; subs rd, rn, #1
622 ;; bcs dest ((unsigned)rn >= 1)
623 ;; similarly for the beq variant using bcc.
624 ;; This is a common looping idiom (while (n--))
625 (define_peephole2
626 [(set (match_operand:SI 0 "arm_general_register_operand" "")
627 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
628 (const_int -1)))
629 (set (match_operand 2 "cc_register" "")
630 (compare (match_dup 0) (const_int -1)))
631 (set (pc)
632 (if_then_else (match_operator 3 "equality_operator"
633 [(match_dup 2) (const_int 0)])
634 (match_operand 4 "" "")
635 (match_operand 5 "" "")))]
636 "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
637 [(parallel[
638 (set (match_dup 2)
639 (compare:CC
640 (match_dup 1) (const_int 1)))
641 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
642 (set (pc)
643 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
644 (match_dup 4)
645 (match_dup 5)))]
646 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
647 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
648 ? GEU : LTU),
649 VOIDmode,
650 operands[2], const0_rtx);"
651 )
652
653 ;; The next four insns work because they compare the result with one of
654 ;; the operands, and we know that the use of the condition code is
655 ;; either GEU or LTU, so we can use the carry flag from the addition
656 ;; instead of doing the compare a second time.
657 (define_insn "*addsi3_compare_op1"
658 [(set (reg:CC_C CC_REGNUM)
659 (compare:CC_C
660 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
661 (match_operand:SI 2 "arm_add_operand" "rI,L"))
662 (match_dup 1)))
663 (set (match_operand:SI 0 "s_register_operand" "=r,r")
664 (plus:SI (match_dup 1) (match_dup 2)))]
665 "TARGET_ARM"
666 "@
667 add%?s\\t%0, %1, %2
668 sub%?s\\t%0, %1, #%n2"
669 [(set_attr "conds" "set")]
670 )
671
672 (define_insn "*addsi3_compare_op2"
673 [(set (reg:CC_C CC_REGNUM)
674 (compare:CC_C
675 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
676 (match_operand:SI 2 "arm_add_operand" "rI,L"))
677 (match_dup 2)))
678 (set (match_operand:SI 0 "s_register_operand" "=r,r")
679 (plus:SI (match_dup 1) (match_dup 2)))]
680 "TARGET_ARM"
681 "@
682 add%?s\\t%0, %1, %2
683 sub%?s\\t%0, %1, #%n2"
684 [(set_attr "conds" "set")]
685 )
686
687 (define_insn "*compare_addsi2_op0"
688 [(set (reg:CC_C CC_REGNUM)
689 (compare:CC_C
690 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
691 (match_operand:SI 1 "arm_add_operand" "rI,L"))
692 (match_dup 0)))]
693 "TARGET_ARM"
694 "@
695 cmn%?\\t%0, %1
696 cmp%?\\t%0, #%n1"
697 [(set_attr "conds" "set")]
698 )
699
700 (define_insn "*compare_addsi2_op1"
701 [(set (reg:CC_C CC_REGNUM)
702 (compare:CC_C
703 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
704 (match_operand:SI 1 "arm_add_operand" "rI,L"))
705 (match_dup 1)))]
706 "TARGET_ARM"
707 "@
708 cmn%?\\t%0, %1
709 cmp%?\\t%0, #%n1"
710 [(set_attr "conds" "set")]
711 )
712
713 (define_insn "*addsi3_carryin"
714 [(set (match_operand:SI 0 "s_register_operand" "=r")
715 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
716 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
717 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
718 "TARGET_ARM"
719 "adc%?\\t%0, %1, %2"
720 [(set_attr "conds" "use")]
721 )
722
723 (define_insn "*addsi3_carryin_shift"
724 [(set (match_operand:SI 0 "s_register_operand" "=r")
725 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
726 (plus:SI
727 (match_operator:SI 2 "shift_operator"
728 [(match_operand:SI 3 "s_register_operand" "r")
729 (match_operand:SI 4 "reg_or_int_operand" "rM")])
730 (match_operand:SI 1 "s_register_operand" "r"))))]
731 "TARGET_ARM"
732 "adc%?\\t%0, %1, %3%S2"
733 [(set_attr "conds" "use")
734 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
735 (const_string "alu_shift")
736 (const_string "alu_shift_reg")))]
737 )
738
739 (define_insn "*addsi3_carryin_alt1"
740 [(set (match_operand:SI 0 "s_register_operand" "=r")
741 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
742 (match_operand:SI 2 "arm_rhs_operand" "rI"))
743 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
744 "TARGET_ARM"
745 "adc%?\\t%0, %1, %2"
746 [(set_attr "conds" "use")]
747 )
748
749 (define_insn "*addsi3_carryin_alt2"
750 [(set (match_operand:SI 0 "s_register_operand" "=r")
751 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
752 (match_operand:SI 1 "s_register_operand" "r"))
753 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
754 "TARGET_ARM"
755 "adc%?\\t%0, %1, %2"
756 [(set_attr "conds" "use")]
757 )
758
759 (define_insn "*addsi3_carryin_alt3"
760 [(set (match_operand:SI 0 "s_register_operand" "=r")
761 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
762 (match_operand:SI 2 "arm_rhs_operand" "rI"))
763 (match_operand:SI 1 "s_register_operand" "r")))]
764 "TARGET_ARM"
765 "adc%?\\t%0, %1, %2"
766 [(set_attr "conds" "use")]
767 )
768
769 (define_insn "incscc"
770 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
771 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
772 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
773 (match_operand:SI 1 "s_register_operand" "0,?r")))]
774 "TARGET_ARM"
775 "@
776 add%d2\\t%0, %1, #1
777 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
778 [(set_attr "conds" "use")
779 (set_attr "length" "4,8")]
780 )
781
782 ; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
783 (define_split
784 [(set (match_operand:SI 0 "s_register_operand" "")
785 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
786 (match_operand:SI 2 "s_register_operand" ""))
787 (const_int -1)))
788 (clobber (match_operand:SI 3 "s_register_operand" ""))]
789 "TARGET_ARM"
790 [(set (match_dup 3) (match_dup 1))
791 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
792 "
793 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
794 ")
795
796 (define_expand "addsf3"
797 [(set (match_operand:SF 0 "s_register_operand" "")
798 (plus:SF (match_operand:SF 1 "s_register_operand" "")
799 (match_operand:SF 2 "arm_float_add_operand" "")))]
800 "TARGET_ARM && TARGET_HARD_FLOAT"
801 "
802 if (TARGET_MAVERICK
803 && !cirrus_fp_register (operands[2], SFmode))
804 operands[2] = force_reg (SFmode, operands[2]);
805 ")
806
807 (define_expand "adddf3"
808 [(set (match_operand:DF 0 "s_register_operand" "")
809 (plus:DF (match_operand:DF 1 "s_register_operand" "")
810 (match_operand:DF 2 "arm_float_add_operand" "")))]
811 "TARGET_ARM && TARGET_HARD_FLOAT"
812 "
813 if (TARGET_MAVERICK
814 && !cirrus_fp_register (operands[2], DFmode))
815 operands[2] = force_reg (DFmode, operands[2]);
816 ")
817
818 (define_expand "subdi3"
819 [(parallel
820 [(set (match_operand:DI 0 "s_register_operand" "")
821 (minus:DI (match_operand:DI 1 "s_register_operand" "")
822 (match_operand:DI 2 "s_register_operand" "")))
823 (clobber (reg:CC CC_REGNUM))])]
824 "TARGET_EITHER"
825 "
826 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
827 && TARGET_ARM
828 && cirrus_fp_register (operands[0], DImode)
829 && cirrus_fp_register (operands[1], DImode))
830 {
831 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
832 DONE;
833 }
834
835 if (TARGET_THUMB)
836 {
837 if (GET_CODE (operands[1]) != REG)
838 operands[1] = force_reg (SImode, operands[1]);
839 if (GET_CODE (operands[2]) != REG)
840 operands[2] = force_reg (SImode, operands[2]);
841 }
842 "
843 )
844
845 (define_insn "*arm_subdi3"
846 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
847 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
848 (match_operand:DI 2 "s_register_operand" "r,0,0")))
849 (clobber (reg:CC CC_REGNUM))]
850 "TARGET_ARM"
851 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
852 [(set_attr "conds" "clob")
853 (set_attr "length" "8")]
854 )
855
856 (define_insn "*thumb_subdi3"
857 [(set (match_operand:DI 0 "register_operand" "=l")
858 (minus:DI (match_operand:DI 1 "register_operand" "0")
859 (match_operand:DI 2 "register_operand" "l")))
860 (clobber (reg:CC CC_REGNUM))]
861 "TARGET_THUMB"
862 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
863 [(set_attr "length" "4")]
864 )
865
866 (define_insn "*subdi_di_zesidi"
867 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
868 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
869 (zero_extend:DI
870 (match_operand:SI 2 "s_register_operand" "r,r"))))
871 (clobber (reg:CC CC_REGNUM))]
872 "TARGET_ARM"
873 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
874 [(set_attr "conds" "clob")
875 (set_attr "length" "8")]
876 )
877
878 (define_insn "*subdi_di_sesidi"
879 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
880 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
881 (sign_extend:DI
882 (match_operand:SI 2 "s_register_operand" "r,r"))))
883 (clobber (reg:CC CC_REGNUM))]
884 "TARGET_ARM"
885 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
886 [(set_attr "conds" "clob")
887 (set_attr "length" "8")]
888 )
889
890 (define_insn "*subdi_zesidi_di"
891 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
892 (minus:DI (zero_extend:DI
893 (match_operand:SI 2 "s_register_operand" "r,r"))
894 (match_operand:DI 1 "s_register_operand" "?r,0")))
895 (clobber (reg:CC CC_REGNUM))]
896 "TARGET_ARM"
897 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
898 [(set_attr "conds" "clob")
899 (set_attr "length" "8")]
900 )
901
902 (define_insn "*subdi_sesidi_di"
903 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
904 (minus:DI (sign_extend:DI
905 (match_operand:SI 2 "s_register_operand" "r,r"))
906 (match_operand:DI 1 "s_register_operand" "?r,0")))
907 (clobber (reg:CC CC_REGNUM))]
908 "TARGET_ARM"
909 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
910 [(set_attr "conds" "clob")
911 (set_attr "length" "8")]
912 )
913
914 (define_insn "*subdi_zesidi_zesidi"
915 [(set (match_operand:DI 0 "s_register_operand" "=r")
916 (minus:DI (zero_extend:DI
917 (match_operand:SI 1 "s_register_operand" "r"))
918 (zero_extend:DI
919 (match_operand:SI 2 "s_register_operand" "r"))))
920 (clobber (reg:CC CC_REGNUM))]
921 "TARGET_ARM"
922 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
923 [(set_attr "conds" "clob")
924 (set_attr "length" "8")]
925 )
926
927 (define_expand "subsi3"
928 [(set (match_operand:SI 0 "s_register_operand" "")
929 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
930 (match_operand:SI 2 "s_register_operand" "")))]
931 "TARGET_EITHER"
932 "
933 if (GET_CODE (operands[1]) == CONST_INT)
934 {
935 if (TARGET_ARM)
936 {
937 arm_split_constant (MINUS, SImode, NULL_RTX,
938 INTVAL (operands[1]), operands[0],
939 operands[2],
940 (no_new_pseudos ? 0
941 : preserve_subexpressions_p ()));
942 DONE;
943 }
944 else /* TARGET_THUMB */
945 operands[1] = force_reg (SImode, operands[1]);
946 }
947 "
948 )
949
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")))]
954 "TARGET_THUMB"
955 "sub\\t%0, %1, %2"
956 [(set_attr "length" "2")]
957 )
958
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")))]
963 "TARGET_ARM"
964 "@
965 rsb%?\\t%0, %2, %1
966 #"
967 "TARGET_ARM
968 && GET_CODE (operands[1]) == CONST_INT
969 && !const_ok_for_arm (INTVAL (operands[1]))"
970 [(clobber (const_int 0))]
971 "
972 arm_split_constant (MINUS, SImode, curr_insn,
973 INTVAL (operands[1]), operands[0], operands[2], 0);
974 DONE;
975 "
976 [(set_attr "length" "4,16")
977 (set_attr "predicable" "yes")]
978 )
979
980 (define_peephole2
981 [(match_scratch:SI 3 "r")
982 (set (match_operand:SI 0 "arm_general_register_operand" "")
983 (minus:SI (match_operand:SI 1 "const_int_operand" "")
984 (match_operand:SI 2 "arm_general_register_operand" "")))]
985 "TARGET_ARM
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)))]
990 ""
991 )
992
993 (define_insn "*subsi3_compare0"
994 [(set (reg:CC_NOOV CC_REGNUM)
995 (compare:CC_NOOV
996 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
997 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
998 (const_int 0)))
999 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1000 (minus:SI (match_dup 1) (match_dup 2)))]
1001 "TARGET_ARM"
1002 "@
1003 sub%?s\\t%0, %1, %2
1004 rsb%?s\\t%0, %2, %1"
1005 [(set_attr "conds" "set")]
1006 )
1007
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)])))]
1013 "TARGET_ARM"
1014 "@
1015 sub%d2\\t%0, %1, #1
1016 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1017 [(set_attr "conds" "use")
1018 (set_attr "length" "*,8")]
1019 )
1020
1021 (define_expand "subsf3"
1022 [(set (match_operand:SF 0 "s_register_operand" "")
1023 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1024 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1025 "TARGET_ARM && TARGET_HARD_FLOAT"
1026 "
1027 if (TARGET_MAVERICK)
1028 {
1029 if (!cirrus_fp_register (operands[1], SFmode))
1030 operands[1] = force_reg (SFmode, operands[1]);
1031 if (!cirrus_fp_register (operands[2], SFmode))
1032 operands[2] = force_reg (SFmode, operands[2]);
1033 }
1034 ")
1035
1036 (define_expand "subdf3"
1037 [(set (match_operand:DF 0 "s_register_operand" "")
1038 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1039 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1040 "TARGET_ARM && TARGET_HARD_FLOAT"
1041 "
1042 if (TARGET_MAVERICK)
1043 {
1044 if (!cirrus_fp_register (operands[1], DFmode))
1045 operands[1] = force_reg (DFmode, operands[1]);
1046 if (!cirrus_fp_register (operands[2], DFmode))
1047 operands[2] = force_reg (DFmode, operands[2]);
1048 }
1049 ")
1050
1051 \f
1052 ;; Multiplication insns
1053
1054 (define_expand "mulsi3"
1055 [(set (match_operand:SI 0 "s_register_operand" "")
1056 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1057 (match_operand:SI 1 "s_register_operand" "")))]
1058 "TARGET_EITHER"
1059 ""
1060 )
1061
1062 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1063 (define_insn "*arm_mulsi3"
1064 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1065 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1066 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1067 "TARGET_ARM"
1068 "mul%?\\t%0, %2, %1"
1069 [(set_attr "insn" "mul")
1070 (set_attr "predicable" "yes")]
1071 )
1072
1073 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1074 ; 1 and 2; are the same, because reload will make operand 0 match
1075 ; operand 1 without realizing that this conflicts with operand 2. We fix
1076 ; this by adding another alternative to match this case, and then `reload'
1077 ; it ourselves. This alternative must come first.
1078 (define_insn "*thumb_mulsi3"
1079 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1080 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1081 (match_operand:SI 2 "register_operand" "l,l,l")))]
1082 "TARGET_THUMB"
1083 "*
1084 if (which_alternative < 2)
1085 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1086 else
1087 return \"mul\\t%0, %0, %2\";
1088 "
1089 [(set_attr "length" "4,4,2")
1090 (set_attr "insn" "mul")]
1091 )
1092
1093 (define_insn "*mulsi3_compare0"
1094 [(set (reg:CC_NOOV CC_REGNUM)
1095 (compare:CC_NOOV (mult:SI
1096 (match_operand:SI 2 "s_register_operand" "r,r")
1097 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1098 (const_int 0)))
1099 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1100 (mult:SI (match_dup 2) (match_dup 1)))]
1101 "TARGET_ARM && !arm_arch_xscale"
1102 "mul%?s\\t%0, %2, %1"
1103 [(set_attr "conds" "set")
1104 (set_attr "insn" "muls")]
1105 )
1106
1107 (define_insn "*mulsi_compare0_scratch"
1108 [(set (reg:CC_NOOV CC_REGNUM)
1109 (compare:CC_NOOV (mult:SI
1110 (match_operand:SI 2 "s_register_operand" "r,r")
1111 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1112 (const_int 0)))
1113 (clobber (match_scratch:SI 0 "=&r,&r"))]
1114 "TARGET_ARM && !arm_arch_xscale"
1115 "mul%?s\\t%0, %2, %1"
1116 [(set_attr "conds" "set")
1117 (set_attr "insn" "muls")]
1118 )
1119
1120 ;; Unnamed templates to match MLA instruction.
1121
1122 (define_insn "*mulsi3addsi"
1123 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1124 (plus:SI
1125 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1126 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1127 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1128 "TARGET_ARM"
1129 "mla%?\\t%0, %2, %1, %3"
1130 [(set_attr "insn" "mla")
1131 (set_attr "predicable" "yes")]
1132 )
1133
1134 (define_insn "*mulsi3addsi_compare0"
1135 [(set (reg:CC_NOOV CC_REGNUM)
1136 (compare:CC_NOOV
1137 (plus:SI (mult:SI
1138 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1139 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1140 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1141 (const_int 0)))
1142 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1143 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1144 (match_dup 3)))]
1145 "TARGET_ARM && !arm_arch_xscale"
1146 "mla%?s\\t%0, %2, %1, %3"
1147 [(set_attr "conds" "set")
1148 (set_attr "insn" "mlas")]
1149 )
1150
1151 (define_insn "*mulsi3addsi_compare0_scratch"
1152 [(set (reg:CC_NOOV CC_REGNUM)
1153 (compare:CC_NOOV
1154 (plus:SI (mult:SI
1155 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1156 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1157 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1158 (const_int 0)))
1159 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1160 "TARGET_ARM && !arm_arch_xscale"
1161 "mla%?s\\t%0, %2, %1, %3"
1162 [(set_attr "conds" "set")
1163 (set_attr "insn" "mlas")]
1164 )
1165
1166 ;; Unnamed template to match long long multiply-accumulate (smlal)
1167
1168 (define_insn "*mulsidi3adddi"
1169 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1170 (plus:DI
1171 (mult:DI
1172 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1173 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1174 (match_operand:DI 1 "s_register_operand" "0")))]
1175 "TARGET_ARM && arm_arch3m"
1176 "smlal%?\\t%Q0, %R0, %3, %2"
1177 [(set_attr "insn" "smlal")
1178 (set_attr "predicable" "yes")]
1179 )
1180
1181 (define_insn "mulsidi3"
1182 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1183 (mult:DI
1184 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1185 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1186 "TARGET_ARM && arm_arch3m"
1187 "smull%?\\t%Q0, %R0, %1, %2"
1188 [(set_attr "insn" "smull")
1189 (set_attr "predicable" "yes")]
1190 )
1191
1192 (define_insn "umulsidi3"
1193 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1194 (mult:DI
1195 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1196 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1197 "TARGET_ARM && arm_arch3m"
1198 "umull%?\\t%Q0, %R0, %1, %2"
1199 [(set_attr "insn" "umull")
1200 (set_attr "predicable" "yes")]
1201 )
1202
1203 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1204
1205 (define_insn "*umulsidi3adddi"
1206 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1207 (plus:DI
1208 (mult:DI
1209 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1210 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1211 (match_operand:DI 1 "s_register_operand" "0")))]
1212 "TARGET_ARM && arm_arch3m"
1213 "umlal%?\\t%Q0, %R0, %3, %2"
1214 [(set_attr "insn" "umlal")
1215 (set_attr "predicable" "yes")]
1216 )
1217
1218 (define_insn "smulsi3_highpart"
1219 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1220 (truncate:SI
1221 (lshiftrt:DI
1222 (mult:DI
1223 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1224 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1225 (const_int 32))))
1226 (clobber (match_scratch:SI 3 "=&r,&r"))]
1227 "TARGET_ARM && arm_arch3m"
1228 "smull%?\\t%3, %0, %2, %1"
1229 [(set_attr "insn" "smull")
1230 (set_attr "predicable" "yes")]
1231 )
1232
1233 (define_insn "umulsi3_highpart"
1234 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1235 (truncate:SI
1236 (lshiftrt:DI
1237 (mult:DI
1238 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1239 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1240 (const_int 32))))
1241 (clobber (match_scratch:SI 3 "=&r,&r"))]
1242 "TARGET_ARM && arm_arch3m"
1243 "umull%?\\t%3, %0, %2, %1"
1244 [(set_attr "insn" "umull")
1245 (set_attr "predicable" "yes")]
1246 )
1247
1248 (define_insn "mulhisi3"
1249 [(set (match_operand:SI 0 "s_register_operand" "=r")
1250 (mult:SI (sign_extend:SI
1251 (match_operand:HI 1 "s_register_operand" "%r"))
1252 (sign_extend:SI
1253 (match_operand:HI 2 "s_register_operand" "r"))))]
1254 "TARGET_ARM && arm_arch5e"
1255 "smulbb%?\\t%0, %1, %2"
1256 [(set_attr "insn" "smulxy")
1257 (set_attr "predicable" "yes")]
1258 )
1259
1260 (define_insn "*mulhisi3tb"
1261 [(set (match_operand:SI 0 "s_register_operand" "=r")
1262 (mult:SI (ashiftrt:SI
1263 (match_operand:SI 1 "s_register_operand" "r")
1264 (const_int 16))
1265 (sign_extend:SI
1266 (match_operand:HI 2 "s_register_operand" "r"))))]
1267 "TARGET_ARM && arm_arch5e"
1268 "smultb%?\\t%0, %1, %2"
1269 [(set_attr "insn" "smulxy")
1270 (set_attr "predicable" "yes")]
1271 )
1272
1273 (define_insn "*mulhisi3bt"
1274 [(set (match_operand:SI 0 "s_register_operand" "=r")
1275 (mult:SI (sign_extend:SI
1276 (match_operand:HI 1 "s_register_operand" "r"))
1277 (ashiftrt:SI
1278 (match_operand:SI 2 "s_register_operand" "r")
1279 (const_int 16))))]
1280 "TARGET_ARM && arm_arch5e"
1281 "smulbt%?\\t%0, %1, %2"
1282 [(set_attr "insn" "smulxy")
1283 (set_attr "predicable" "yes")]
1284 )
1285
1286 (define_insn "*mulhisi3tt"
1287 [(set (match_operand:SI 0 "s_register_operand" "=r")
1288 (mult:SI (ashiftrt:SI
1289 (match_operand:SI 1 "s_register_operand" "r")
1290 (const_int 16))
1291 (ashiftrt:SI
1292 (match_operand:SI 2 "s_register_operand" "r")
1293 (const_int 16))))]
1294 "TARGET_ARM && arm_arch5e"
1295 "smultt%?\\t%0, %1, %2"
1296 [(set_attr "insn" "smulxy")
1297 (set_attr "predicable" "yes")]
1298 )
1299
1300 (define_insn "*mulhisi3addsi"
1301 [(set (match_operand:SI 0 "s_register_operand" "=r")
1302 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1303 (mult:SI (sign_extend:SI
1304 (match_operand:HI 2 "s_register_operand" "%r"))
1305 (sign_extend:SI
1306 (match_operand:HI 3 "s_register_operand" "r")))))]
1307 "TARGET_ARM && arm_arch5e"
1308 "smlabb%?\\t%0, %2, %3, %1"
1309 [(set_attr "insn" "smlaxy")
1310 (set_attr "predicable" "yes")]
1311 )
1312
1313 (define_insn "*mulhidi3adddi"
1314 [(set (match_operand:DI 0 "s_register_operand" "=r")
1315 (plus:DI
1316 (match_operand:DI 1 "s_register_operand" "0")
1317 (mult:DI (sign_extend:DI
1318 (match_operand:HI 2 "s_register_operand" "%r"))
1319 (sign_extend:DI
1320 (match_operand:HI 3 "s_register_operand" "r")))))]
1321 "TARGET_ARM && arm_arch5e"
1322 "smlalbb%?\\t%Q0, %R0, %2, %3"
1323 [(set_attr "insn" "smlalxy")
1324 (set_attr "predicable" "yes")])
1325
1326 (define_expand "mulsf3"
1327 [(set (match_operand:SF 0 "s_register_operand" "")
1328 (mult:SF (match_operand:SF 1 "s_register_operand" "")
1329 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1330 "TARGET_ARM && TARGET_HARD_FLOAT"
1331 "
1332 if (TARGET_MAVERICK
1333 && !cirrus_fp_register (operands[2], SFmode))
1334 operands[2] = force_reg (SFmode, operands[2]);
1335 ")
1336
1337 (define_expand "muldf3"
1338 [(set (match_operand:DF 0 "s_register_operand" "")
1339 (mult:DF (match_operand:DF 1 "s_register_operand" "")
1340 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1341 "TARGET_ARM && TARGET_HARD_FLOAT"
1342 "
1343 if (TARGET_MAVERICK
1344 && !cirrus_fp_register (operands[2], DFmode))
1345 operands[2] = force_reg (DFmode, operands[2]);
1346 ")
1347 \f
1348 ;; Division insns
1349
1350 (define_expand "divsf3"
1351 [(set (match_operand:SF 0 "s_register_operand" "")
1352 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1353 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1354 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1355 "")
1356
1357 (define_expand "divdf3"
1358 [(set (match_operand:DF 0 "s_register_operand" "")
1359 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1360 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1361 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1362 "")
1363 \f
1364 ;; Modulo insns
1365
1366 (define_expand "modsf3"
1367 [(set (match_operand:SF 0 "s_register_operand" "")
1368 (mod:SF (match_operand:SF 1 "s_register_operand" "")
1369 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1370 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1371 "")
1372
1373 (define_expand "moddf3"
1374 [(set (match_operand:DF 0 "s_register_operand" "")
1375 (mod:DF (match_operand:DF 1 "s_register_operand" "")
1376 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1377 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1378 "")
1379 \f
1380 ;; Boolean and,ior,xor insns
1381
1382 ;; Split up double word logical operations
1383
1384 ;; Split up simple DImode logical operations. Simply perform the logical
1385 ;; operation on the upper and lower halves of the registers.
1386 (define_split
1387 [(set (match_operand:DI 0 "s_register_operand" "")
1388 (match_operator:DI 6 "logical_binary_operator"
1389 [(match_operand:DI 1 "s_register_operand" "")
1390 (match_operand:DI 2 "s_register_operand" "")]))]
1391 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1392 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1393 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1394 "
1395 {
1396 operands[3] = gen_highpart (SImode, operands[0]);
1397 operands[0] = gen_lowpart (SImode, operands[0]);
1398 operands[4] = gen_highpart (SImode, operands[1]);
1399 operands[1] = gen_lowpart (SImode, operands[1]);
1400 operands[5] = gen_highpart (SImode, operands[2]);
1401 operands[2] = gen_lowpart (SImode, operands[2]);
1402 }"
1403 )
1404
1405 (define_split
1406 [(set (match_operand:DI 0 "s_register_operand" "")
1407 (match_operator:DI 6 "logical_binary_operator"
1408 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1409 (match_operand:DI 1 "s_register_operand" "")]))]
1410 "TARGET_ARM && reload_completed"
1411 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1412 (set (match_dup 3) (match_op_dup:SI 6
1413 [(ashiftrt:SI (match_dup 2) (const_int 31))
1414 (match_dup 4)]))]
1415 "
1416 {
1417 operands[3] = gen_highpart (SImode, operands[0]);
1418 operands[0] = gen_lowpart (SImode, operands[0]);
1419 operands[4] = gen_highpart (SImode, operands[1]);
1420 operands[1] = gen_lowpart (SImode, operands[1]);
1421 operands[5] = gen_highpart (SImode, operands[2]);
1422 operands[2] = gen_lowpart (SImode, operands[2]);
1423 }"
1424 )
1425
1426 ;; The zero extend of operand 2 means we can just copy the high part of
1427 ;; operand1 into operand0.
1428 (define_split
1429 [(set (match_operand:DI 0 "s_register_operand" "")
1430 (ior:DI
1431 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1432 (match_operand:DI 1 "s_register_operand" "")))]
1433 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1434 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1435 (set (match_dup 3) (match_dup 4))]
1436 "
1437 {
1438 operands[4] = gen_highpart (SImode, operands[1]);
1439 operands[3] = gen_highpart (SImode, operands[0]);
1440 operands[0] = gen_lowpart (SImode, operands[0]);
1441 operands[1] = gen_lowpart (SImode, operands[1]);
1442 }"
1443 )
1444
1445 ;; The zero extend of operand 2 means we can just copy the high part of
1446 ;; operand1 into operand0.
1447 (define_split
1448 [(set (match_operand:DI 0 "s_register_operand" "")
1449 (xor:DI
1450 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1451 (match_operand:DI 1 "s_register_operand" "")))]
1452 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1453 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1454 (set (match_dup 3) (match_dup 4))]
1455 "
1456 {
1457 operands[4] = gen_highpart (SImode, operands[1]);
1458 operands[3] = gen_highpart (SImode, operands[0]);
1459 operands[0] = gen_lowpart (SImode, operands[0]);
1460 operands[1] = gen_lowpart (SImode, operands[1]);
1461 }"
1462 )
1463
1464 (define_insn "anddi3"
1465 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1466 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1467 (match_operand:DI 2 "s_register_operand" "r,r")))]
1468 "TARGET_ARM && ! TARGET_IWMMXT"
1469 "#"
1470 [(set_attr "length" "8")]
1471 )
1472
1473 (define_insn_and_split "*anddi_zesidi_di"
1474 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1475 (and:DI (zero_extend:DI
1476 (match_operand:SI 2 "s_register_operand" "r,r"))
1477 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1478 "TARGET_ARM"
1479 "#"
1480 "TARGET_ARM && reload_completed"
1481 ; The zero extend of operand 2 clears the high word of the output
1482 ; operand.
1483 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1484 (set (match_dup 3) (const_int 0))]
1485 "
1486 {
1487 operands[3] = gen_highpart (SImode, operands[0]);
1488 operands[0] = gen_lowpart (SImode, operands[0]);
1489 operands[1] = gen_lowpart (SImode, operands[1]);
1490 }"
1491 [(set_attr "length" "8")]
1492 )
1493
1494 (define_insn "*anddi_sesdi_di"
1495 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1496 (and:DI (sign_extend:DI
1497 (match_operand:SI 2 "s_register_operand" "r,r"))
1498 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1499 "TARGET_ARM"
1500 "#"
1501 [(set_attr "length" "8")]
1502 )
1503
1504 (define_expand "andsi3"
1505 [(set (match_operand:SI 0 "s_register_operand" "")
1506 (and:SI (match_operand:SI 1 "s_register_operand" "")
1507 (match_operand:SI 2 "reg_or_int_operand" "")))]
1508 "TARGET_EITHER"
1509 "
1510 if (TARGET_ARM)
1511 {
1512 if (GET_CODE (operands[2]) == CONST_INT)
1513 {
1514 arm_split_constant (AND, SImode, NULL_RTX,
1515 INTVAL (operands[2]), operands[0],
1516 operands[1],
1517 (no_new_pseudos
1518 ? 0 : preserve_subexpressions_p ()));
1519 DONE;
1520 }
1521 }
1522 else /* TARGET_THUMB */
1523 {
1524 if (GET_CODE (operands[2]) != CONST_INT)
1525 operands[2] = force_reg (SImode, operands[2]);
1526 else
1527 {
1528 int i;
1529
1530 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1531 {
1532 operands[2] = force_reg (SImode,
1533 GEN_INT (~INTVAL (operands[2])));
1534
1535 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1536
1537 DONE;
1538 }
1539
1540 for (i = 9; i <= 31; i++)
1541 {
1542 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1543 {
1544 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1545 const0_rtx));
1546 DONE;
1547 }
1548 else if ((((HOST_WIDE_INT) 1) << i) - 1
1549 == ~INTVAL (operands[2]))
1550 {
1551 rtx shift = GEN_INT (i);
1552 rtx reg = gen_reg_rtx (SImode);
1553
1554 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1555 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1556
1557 DONE;
1558 }
1559 }
1560
1561 operands[2] = force_reg (SImode, operands[2]);
1562 }
1563 }
1564 "
1565 )
1566
1567 (define_insn_and_split "*arm_andsi3_insn"
1568 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1569 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1570 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1571 "TARGET_ARM"
1572 "@
1573 and%?\\t%0, %1, %2
1574 bic%?\\t%0, %1, #%B2
1575 #"
1576 "TARGET_ARM
1577 && GET_CODE (operands[2]) == CONST_INT
1578 && !(const_ok_for_arm (INTVAL (operands[2]))
1579 || const_ok_for_arm (~INTVAL (operands[2])))"
1580 [(clobber (const_int 0))]
1581 "
1582 arm_split_constant (AND, SImode, curr_insn,
1583 INTVAL (operands[2]), operands[0], operands[1], 0);
1584 DONE;
1585 "
1586 [(set_attr "length" "4,4,16")
1587 (set_attr "predicable" "yes")]
1588 )
1589
1590 (define_insn "*thumb_andsi3_insn"
1591 [(set (match_operand:SI 0 "register_operand" "=l")
1592 (and:SI (match_operand:SI 1 "register_operand" "%0")
1593 (match_operand:SI 2 "register_operand" "l")))]
1594 "TARGET_THUMB"
1595 "and\\t%0, %0, %2"
1596 [(set_attr "length" "2")]
1597 )
1598
1599 (define_insn "*andsi3_compare0"
1600 [(set (reg:CC_NOOV CC_REGNUM)
1601 (compare:CC_NOOV
1602 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1603 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1604 (const_int 0)))
1605 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1606 (and:SI (match_dup 1) (match_dup 2)))]
1607 "TARGET_ARM"
1608 "@
1609 and%?s\\t%0, %1, %2
1610 bic%?s\\t%0, %1, #%B2"
1611 [(set_attr "conds" "set")]
1612 )
1613
1614 (define_insn "*andsi3_compare0_scratch"
1615 [(set (reg:CC_NOOV CC_REGNUM)
1616 (compare:CC_NOOV
1617 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1618 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1619 (const_int 0)))
1620 (clobber (match_scratch:SI 2 "=X,r"))]
1621 "TARGET_ARM"
1622 "@
1623 tst%?\\t%0, %1
1624 bic%?s\\t%2, %0, #%B1"
1625 [(set_attr "conds" "set")]
1626 )
1627
1628 (define_insn "*zeroextractsi_compare0_scratch"
1629 [(set (reg:CC_NOOV CC_REGNUM)
1630 (compare:CC_NOOV (zero_extract:SI
1631 (match_operand:SI 0 "s_register_operand" "r")
1632 (match_operand 1 "const_int_operand" "n")
1633 (match_operand 2 "const_int_operand" "n"))
1634 (const_int 0)))]
1635 "TARGET_ARM
1636 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1637 && INTVAL (operands[1]) > 0
1638 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1639 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1640 "*
1641 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1642 << INTVAL (operands[2]));
1643 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1644 return \"\";
1645 "
1646 [(set_attr "conds" "set")]
1647 )
1648
1649 (define_insn_and_split "*ne_zeroextractsi"
1650 [(set (match_operand:SI 0 "s_register_operand" "=r")
1651 (ne:SI (zero_extract:SI
1652 (match_operand:SI 1 "s_register_operand" "r")
1653 (match_operand:SI 2 "const_int_operand" "n")
1654 (match_operand:SI 3 "const_int_operand" "n"))
1655 (const_int 0)))
1656 (clobber (reg:CC CC_REGNUM))]
1657 "TARGET_ARM
1658 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1659 && INTVAL (operands[2]) > 0
1660 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1661 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1662 "#"
1663 "TARGET_ARM
1664 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1665 && INTVAL (operands[2]) > 0
1666 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1667 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1668 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1669 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1670 (const_int 0)))
1671 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1672 (set (match_dup 0)
1673 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1674 (match_dup 0) (const_int 1)))]
1675 "
1676 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1677 << INTVAL (operands[3]));
1678 "
1679 [(set_attr "conds" "clob")
1680 (set_attr "length" "8")]
1681 )
1682
1683 (define_insn_and_split "*ne_zeroextractsi_shifted"
1684 [(set (match_operand:SI 0 "s_register_operand" "=r")
1685 (ne:SI (zero_extract:SI
1686 (match_operand:SI 1 "s_register_operand" "r")
1687 (match_operand:SI 2 "const_int_operand" "n")
1688 (const_int 0))
1689 (const_int 0)))
1690 (clobber (reg:CC CC_REGNUM))]
1691 "TARGET_ARM"
1692 "#"
1693 "TARGET_ARM"
1694 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1695 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1696 (const_int 0)))
1697 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1698 (set (match_dup 0)
1699 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1700 (match_dup 0) (const_int 1)))]
1701 "
1702 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1703 "
1704 [(set_attr "conds" "clob")
1705 (set_attr "length" "8")]
1706 )
1707
1708 (define_insn_and_split "*ite_ne_zeroextractsi"
1709 [(set (match_operand:SI 0 "s_register_operand" "=r")
1710 (if_then_else:SI (ne (zero_extract:SI
1711 (match_operand:SI 1 "s_register_operand" "r")
1712 (match_operand:SI 2 "const_int_operand" "n")
1713 (match_operand:SI 3 "const_int_operand" "n"))
1714 (const_int 0))
1715 (match_operand:SI 4 "arm_not_operand" "rIK")
1716 (const_int 0)))
1717 (clobber (reg:CC CC_REGNUM))]
1718 "TARGET_ARM
1719 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1720 && INTVAL (operands[2]) > 0
1721 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1722 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1723 && !reg_overlap_mentioned_p (operands[0], operands[4])"
1724 "#"
1725 "TARGET_ARM
1726 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1727 && INTVAL (operands[2]) > 0
1728 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1729 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1730 && !reg_overlap_mentioned_p (operands[0], operands[4])"
1731 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1732 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1733 (const_int 0)))
1734 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1735 (set (match_dup 0)
1736 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1737 (match_dup 0) (match_dup 4)))]
1738 "
1739 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1740 << INTVAL (operands[3]));
1741 "
1742 [(set_attr "conds" "clob")
1743 (set_attr "length" "8")]
1744 )
1745
1746 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1747 [(set (match_operand:SI 0 "s_register_operand" "=r")
1748 (if_then_else:SI (ne (zero_extract:SI
1749 (match_operand:SI 1 "s_register_operand" "r")
1750 (match_operand:SI 2 "const_int_operand" "n")
1751 (const_int 0))
1752 (const_int 0))
1753 (match_operand:SI 3 "arm_not_operand" "rIK")
1754 (const_int 0)))
1755 (clobber (reg:CC CC_REGNUM))]
1756 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1757 "#"
1758 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1759 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1760 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1761 (const_int 0)))
1762 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1763 (set (match_dup 0)
1764 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1765 (match_dup 0) (match_dup 3)))]
1766 "
1767 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1768 "
1769 [(set_attr "conds" "clob")
1770 (set_attr "length" "8")]
1771 )
1772
1773 (define_split
1774 [(set (match_operand:SI 0 "s_register_operand" "")
1775 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1776 (match_operand:SI 2 "const_int_operand" "")
1777 (match_operand:SI 3 "const_int_operand" "")))
1778 (clobber (match_operand:SI 4 "s_register_operand" ""))]
1779 "TARGET_THUMB"
1780 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1781 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1782 "{
1783 HOST_WIDE_INT temp = INTVAL (operands[2]);
1784
1785 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1786 operands[3] = GEN_INT (32 - temp);
1787 }"
1788 )
1789
1790 (define_split
1791 [(set (match_operand:SI 0 "s_register_operand" "")
1792 (match_operator:SI 1 "shiftable_operator"
1793 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1794 (match_operand:SI 3 "const_int_operand" "")
1795 (match_operand:SI 4 "const_int_operand" ""))
1796 (match_operand:SI 5 "s_register_operand" "")]))
1797 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1798 "TARGET_ARM"
1799 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1800 (set (match_dup 0)
1801 (match_op_dup 1
1802 [(lshiftrt:SI (match_dup 6) (match_dup 4))
1803 (match_dup 5)]))]
1804 "{
1805 HOST_WIDE_INT temp = INTVAL (operands[3]);
1806
1807 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1808 operands[4] = GEN_INT (32 - temp);
1809 }"
1810 )
1811
1812 (define_split
1813 [(set (match_operand:SI 0 "s_register_operand" "")
1814 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1815 (match_operand:SI 2 "const_int_operand" "")
1816 (match_operand:SI 3 "const_int_operand" "")))]
1817 "TARGET_THUMB"
1818 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1819 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1820 "{
1821 HOST_WIDE_INT temp = INTVAL (operands[2]);
1822
1823 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1824 operands[3] = GEN_INT (32 - temp);
1825 }"
1826 )
1827
1828 (define_split
1829 [(set (match_operand:SI 0 "s_register_operand" "")
1830 (match_operator:SI 1 "shiftable_operator"
1831 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1832 (match_operand:SI 3 "const_int_operand" "")
1833 (match_operand:SI 4 "const_int_operand" ""))
1834 (match_operand:SI 5 "s_register_operand" "")]))
1835 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1836 "TARGET_ARM"
1837 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1838 (set (match_dup 0)
1839 (match_op_dup 1
1840 [(ashiftrt:SI (match_dup 6) (match_dup 4))
1841 (match_dup 5)]))]
1842 "{
1843 HOST_WIDE_INT temp = INTVAL (operands[3]);
1844
1845 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1846 operands[4] = GEN_INT (32 - temp);
1847 }"
1848 )
1849
1850 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1851 ;;; represented by the bitfield, then this will produce incorrect results.
1852 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1853 ;;; which have a real bit-field insert instruction, the truncation happens
1854 ;;; in the bit-field insert instruction itself. Since arm does not have a
1855 ;;; bit-field insert instruction, we would have to emit code here to truncate
1856 ;;; the value before we insert. This loses some of the advantage of having
1857 ;;; this insv pattern, so this pattern needs to be reevalutated.
1858
1859 (define_expand "insv"
1860 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1861 (match_operand:SI 1 "general_operand" "")
1862 (match_operand:SI 2 "general_operand" ""))
1863 (match_operand:SI 3 "reg_or_int_operand" ""))]
1864 "TARGET_ARM"
1865 "
1866 {
1867 int start_bit = INTVAL (operands[2]);
1868 int width = INTVAL (operands[1]);
1869 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1870 rtx target, subtarget;
1871
1872 target = operands[0];
1873 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1874 subreg as the final target. */
1875 if (GET_CODE (target) == SUBREG)
1876 {
1877 subtarget = gen_reg_rtx (SImode);
1878 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1879 < GET_MODE_SIZE (SImode))
1880 target = SUBREG_REG (target);
1881 }
1882 else
1883 subtarget = target;
1884
1885 if (GET_CODE (operands[3]) == CONST_INT)
1886 {
1887 /* Since we are inserting a known constant, we may be able to
1888 reduce the number of bits that we have to clear so that
1889 the mask becomes simple. */
1890 /* ??? This code does not check to see if the new mask is actually
1891 simpler. It may not be. */
1892 rtx op1 = gen_reg_rtx (SImode);
1893 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1894 start of this pattern. */
1895 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1896 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1897
1898 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1899 emit_insn (gen_iorsi3 (subtarget, op1,
1900 GEN_INT (op3_value << start_bit)));
1901 }
1902 else if (start_bit == 0
1903 && !(const_ok_for_arm (mask)
1904 || const_ok_for_arm (~mask)))
1905 {
1906 /* A Trick, since we are setting the bottom bits in the word,
1907 we can shift operand[3] up, operand[0] down, OR them together
1908 and rotate the result back again. This takes 3 insns, and
1909 the third might be mergeable into another op. */
1910 /* The shift up copes with the possibility that operand[3] is
1911 wider than the bitfield. */
1912 rtx op0 = gen_reg_rtx (SImode);
1913 rtx op1 = gen_reg_rtx (SImode);
1914
1915 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1916 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1917 emit_insn (gen_iorsi3 (op1, op1, op0));
1918 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1919 }
1920 else if ((width + start_bit == 32)
1921 && !(const_ok_for_arm (mask)
1922 || const_ok_for_arm (~mask)))
1923 {
1924 /* Similar trick, but slightly less efficient. */
1925
1926 rtx op0 = gen_reg_rtx (SImode);
1927 rtx op1 = gen_reg_rtx (SImode);
1928
1929 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1930 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1931 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1932 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1933 }
1934 else
1935 {
1936 rtx op0 = GEN_INT (mask);
1937 rtx op1 = gen_reg_rtx (SImode);
1938 rtx op2 = gen_reg_rtx (SImode);
1939
1940 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1941 {
1942 rtx tmp = gen_reg_rtx (SImode);
1943
1944 emit_insn (gen_movsi (tmp, op0));
1945 op0 = tmp;
1946 }
1947
1948 /* Mask out any bits in operand[3] that are not needed. */
1949 emit_insn (gen_andsi3 (op1, operands[3], op0));
1950
1951 if (GET_CODE (op0) == CONST_INT
1952 && (const_ok_for_arm (mask << start_bit)
1953 || const_ok_for_arm (~(mask << start_bit))))
1954 {
1955 op0 = GEN_INT (~(mask << start_bit));
1956 emit_insn (gen_andsi3 (op2, operands[0], op0));
1957 }
1958 else
1959 {
1960 if (GET_CODE (op0) == CONST_INT)
1961 {
1962 rtx tmp = gen_reg_rtx (SImode);
1963
1964 emit_insn (gen_movsi (tmp, op0));
1965 op0 = tmp;
1966 }
1967
1968 if (start_bit != 0)
1969 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1970
1971 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1972 }
1973
1974 if (start_bit != 0)
1975 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1976
1977 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1978 }
1979
1980 if (subtarget != target)
1981 {
1982 /* If TARGET is still a SUBREG, then it must be wider than a word,
1983 so we must be careful only to set the subword we were asked to. */
1984 if (GET_CODE (target) == SUBREG)
1985 emit_move_insn (target, subtarget);
1986 else
1987 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1988 }
1989
1990 DONE;
1991 }"
1992 )
1993
1994 ; constants for op 2 will never be given to these patterns.
1995 (define_insn_and_split "*anddi_notdi_di"
1996 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1997 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1998 (match_operand:DI 2 "s_register_operand" "0,r")))]
1999 "TARGET_ARM"
2000 "#"
2001 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2002 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2003 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2004 "
2005 {
2006 operands[3] = gen_highpart (SImode, operands[0]);
2007 operands[0] = gen_lowpart (SImode, operands[0]);
2008 operands[4] = gen_highpart (SImode, operands[1]);
2009 operands[1] = gen_lowpart (SImode, operands[1]);
2010 operands[5] = gen_highpart (SImode, operands[2]);
2011 operands[2] = gen_lowpart (SImode, operands[2]);
2012 }"
2013 [(set_attr "length" "8")
2014 (set_attr "predicable" "yes")]
2015 )
2016
2017 (define_insn_and_split "*anddi_notzesidi_di"
2018 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2019 (and:DI (not:DI (zero_extend:DI
2020 (match_operand:SI 2 "s_register_operand" "r,r")))
2021 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2022 "TARGET_ARM"
2023 "@
2024 bic%?\\t%Q0, %Q1, %2
2025 #"
2026 ; (not (zero_extend ...)) allows us to just copy the high word from
2027 ; operand1 to operand0.
2028 "TARGET_ARM
2029 && reload_completed
2030 && operands[0] != operands[1]"
2031 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2032 (set (match_dup 3) (match_dup 4))]
2033 "
2034 {
2035 operands[3] = gen_highpart (SImode, operands[0]);
2036 operands[0] = gen_lowpart (SImode, operands[0]);
2037 operands[4] = gen_highpart (SImode, operands[1]);
2038 operands[1] = gen_lowpart (SImode, operands[1]);
2039 }"
2040 [(set_attr "length" "4,8")
2041 (set_attr "predicable" "yes")]
2042 )
2043
2044 (define_insn_and_split "*anddi_notsesidi_di"
2045 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2046 (and:DI (not:DI (sign_extend:DI
2047 (match_operand:SI 2 "s_register_operand" "r,r")))
2048 (match_operand:DI 1 "s_register_operand" "0,r")))]
2049 "TARGET_ARM"
2050 "#"
2051 "TARGET_ARM && reload_completed"
2052 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2053 (set (match_dup 3) (and:SI (not:SI
2054 (ashiftrt:SI (match_dup 2) (const_int 31)))
2055 (match_dup 4)))]
2056 "
2057 {
2058 operands[3] = gen_highpart (SImode, operands[0]);
2059 operands[0] = gen_lowpart (SImode, operands[0]);
2060 operands[4] = gen_highpart (SImode, operands[1]);
2061 operands[1] = gen_lowpart (SImode, operands[1]);
2062 }"
2063 [(set_attr "length" "8")
2064 (set_attr "predicable" "yes")]
2065 )
2066
2067 (define_insn "andsi_notsi_si"
2068 [(set (match_operand:SI 0 "s_register_operand" "=r")
2069 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2070 (match_operand:SI 1 "s_register_operand" "r")))]
2071 "TARGET_ARM"
2072 "bic%?\\t%0, %1, %2"
2073 [(set_attr "predicable" "yes")]
2074 )
2075
2076 (define_insn "bicsi3"
2077 [(set (match_operand:SI 0 "register_operand" "=l")
2078 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2079 (match_operand:SI 2 "register_operand" "0")))]
2080 "TARGET_THUMB"
2081 "bic\\t%0, %0, %1"
2082 [(set_attr "length" "2")]
2083 )
2084
2085 (define_insn "andsi_not_shiftsi_si"
2086 [(set (match_operand:SI 0 "s_register_operand" "=r")
2087 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2088 [(match_operand:SI 2 "s_register_operand" "r")
2089 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2090 (match_operand:SI 1 "s_register_operand" "r")))]
2091 "TARGET_ARM"
2092 "bic%?\\t%0, %1, %2%S4"
2093 [(set_attr "predicable" "yes")
2094 (set_attr "shift" "2")
2095 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2096 (const_string "alu_shift")
2097 (const_string "alu_shift_reg")))]
2098 )
2099
2100 (define_insn "*andsi_notsi_si_compare0"
2101 [(set (reg:CC_NOOV CC_REGNUM)
2102 (compare:CC_NOOV
2103 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2104 (match_operand:SI 1 "s_register_operand" "r"))
2105 (const_int 0)))
2106 (set (match_operand:SI 0 "s_register_operand" "=r")
2107 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2108 "TARGET_ARM"
2109 "bic%?s\\t%0, %1, %2"
2110 [(set_attr "conds" "set")]
2111 )
2112
2113 (define_insn "*andsi_notsi_si_compare0_scratch"
2114 [(set (reg:CC_NOOV CC_REGNUM)
2115 (compare:CC_NOOV
2116 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2117 (match_operand:SI 1 "s_register_operand" "r"))
2118 (const_int 0)))
2119 (clobber (match_scratch:SI 0 "=r"))]
2120 "TARGET_ARM"
2121 "bic%?s\\t%0, %1, %2"
2122 [(set_attr "conds" "set")]
2123 )
2124
2125 (define_insn "iordi3"
2126 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2127 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2128 (match_operand:DI 2 "s_register_operand" "r,r")))]
2129 "TARGET_ARM && ! TARGET_IWMMXT"
2130 "#"
2131 [(set_attr "length" "8")
2132 (set_attr "predicable" "yes")]
2133 )
2134
2135 (define_insn "*iordi_zesidi_di"
2136 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2137 (ior:DI (zero_extend:DI
2138 (match_operand:SI 2 "s_register_operand" "r,r"))
2139 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2140 "TARGET_ARM"
2141 "@
2142 orr%?\\t%Q0, %Q1, %2
2143 #"
2144 [(set_attr "length" "4,8")
2145 (set_attr "predicable" "yes")]
2146 )
2147
2148 (define_insn "*iordi_sesidi_di"
2149 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2150 (ior:DI (sign_extend:DI
2151 (match_operand:SI 2 "s_register_operand" "r,r"))
2152 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2153 "TARGET_ARM"
2154 "#"
2155 [(set_attr "length" "8")
2156 (set_attr "predicable" "yes")]
2157 )
2158
2159 (define_expand "iorsi3"
2160 [(set (match_operand:SI 0 "s_register_operand" "")
2161 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2162 (match_operand:SI 2 "reg_or_int_operand" "")))]
2163 "TARGET_EITHER"
2164 "
2165 if (GET_CODE (operands[2]) == CONST_INT)
2166 {
2167 if (TARGET_ARM)
2168 {
2169 arm_split_constant (IOR, SImode, NULL_RTX,
2170 INTVAL (operands[2]), operands[0], operands[1],
2171 (no_new_pseudos
2172 ? 0 : preserve_subexpressions_p ()));
2173 DONE;
2174 }
2175 else /* TARGET_THUMB */
2176 operands [2] = force_reg (SImode, operands [2]);
2177 }
2178 "
2179 )
2180
2181 (define_insn_and_split "*arm_iorsi3"
2182 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2183 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2184 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2185 "TARGET_ARM"
2186 "@
2187 orr%?\\t%0, %1, %2
2188 #"
2189 "TARGET_ARM
2190 && GET_CODE (operands[2]) == CONST_INT
2191 && !const_ok_for_arm (INTVAL (operands[2]))"
2192 [(clobber (const_int 0))]
2193 "
2194 arm_split_constant (IOR, SImode, curr_insn,
2195 INTVAL (operands[2]), operands[0], operands[1], 0);
2196 DONE;
2197 "
2198 [(set_attr "length" "4,16")
2199 (set_attr "predicable" "yes")]
2200 )
2201
2202 (define_insn "*thumb_iorsi3"
2203 [(set (match_operand:SI 0 "register_operand" "=l")
2204 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2205 (match_operand:SI 2 "register_operand" "l")))]
2206 "TARGET_THUMB"
2207 "orr\\t%0, %0, %2"
2208 [(set_attr "length" "2")]
2209 )
2210
2211 (define_peephole2
2212 [(match_scratch:SI 3 "r")
2213 (set (match_operand:SI 0 "arm_general_register_operand" "")
2214 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2215 (match_operand:SI 2 "const_int_operand" "")))]
2216 "TARGET_ARM
2217 && !const_ok_for_arm (INTVAL (operands[2]))
2218 && const_ok_for_arm (~INTVAL (operands[2]))"
2219 [(set (match_dup 3) (match_dup 2))
2220 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2221 ""
2222 )
2223
2224 (define_insn "*iorsi3_compare0"
2225 [(set (reg:CC_NOOV CC_REGNUM)
2226 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2227 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2228 (const_int 0)))
2229 (set (match_operand:SI 0 "s_register_operand" "=r")
2230 (ior:SI (match_dup 1) (match_dup 2)))]
2231 "TARGET_ARM"
2232 "orr%?s\\t%0, %1, %2"
2233 [(set_attr "conds" "set")]
2234 )
2235
2236 (define_insn "*iorsi3_compare0_scratch"
2237 [(set (reg:CC_NOOV CC_REGNUM)
2238 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2239 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2240 (const_int 0)))
2241 (clobber (match_scratch:SI 0 "=r"))]
2242 "TARGET_ARM"
2243 "orr%?s\\t%0, %1, %2"
2244 [(set_attr "conds" "set")]
2245 )
2246
2247 (define_insn "xordi3"
2248 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2249 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2250 (match_operand:DI 2 "s_register_operand" "r,r")))]
2251 "TARGET_ARM && !TARGET_IWMMXT"
2252 "#"
2253 [(set_attr "length" "8")
2254 (set_attr "predicable" "yes")]
2255 )
2256
2257 (define_insn "*xordi_zesidi_di"
2258 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2259 (xor:DI (zero_extend:DI
2260 (match_operand:SI 2 "s_register_operand" "r,r"))
2261 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2262 "TARGET_ARM"
2263 "@
2264 eor%?\\t%Q0, %Q1, %2
2265 #"
2266 [(set_attr "length" "4,8")
2267 (set_attr "predicable" "yes")]
2268 )
2269
2270 (define_insn "*xordi_sesidi_di"
2271 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2272 (xor:DI (sign_extend:DI
2273 (match_operand:SI 2 "s_register_operand" "r,r"))
2274 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2275 "TARGET_ARM"
2276 "#"
2277 [(set_attr "length" "8")
2278 (set_attr "predicable" "yes")]
2279 )
2280
2281 (define_expand "xorsi3"
2282 [(set (match_operand:SI 0 "s_register_operand" "")
2283 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2284 (match_operand:SI 2 "arm_rhs_operand" "")))]
2285 "TARGET_EITHER"
2286 "if (TARGET_THUMB)
2287 if (GET_CODE (operands[2]) == CONST_INT)
2288 operands[2] = force_reg (SImode, operands[2]);
2289 "
2290 )
2291
2292 (define_insn "*arm_xorsi3"
2293 [(set (match_operand:SI 0 "s_register_operand" "=r")
2294 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2295 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2296 "TARGET_ARM"
2297 "eor%?\\t%0, %1, %2"
2298 [(set_attr "predicable" "yes")]
2299 )
2300
2301 (define_insn "*thumb_xorsi3"
2302 [(set (match_operand:SI 0 "register_operand" "=l")
2303 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2304 (match_operand:SI 2 "register_operand" "l")))]
2305 "TARGET_THUMB"
2306 "eor\\t%0, %0, %2"
2307 [(set_attr "length" "2")]
2308 )
2309
2310 (define_insn "*xorsi3_compare0"
2311 [(set (reg:CC_NOOV CC_REGNUM)
2312 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2313 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2314 (const_int 0)))
2315 (set (match_operand:SI 0 "s_register_operand" "=r")
2316 (xor:SI (match_dup 1) (match_dup 2)))]
2317 "TARGET_ARM"
2318 "eor%?s\\t%0, %1, %2"
2319 [(set_attr "conds" "set")]
2320 )
2321
2322 (define_insn "*xorsi3_compare0_scratch"
2323 [(set (reg:CC_NOOV CC_REGNUM)
2324 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2325 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2326 (const_int 0)))]
2327 "TARGET_ARM"
2328 "teq%?\\t%0, %1"
2329 [(set_attr "conds" "set")]
2330 )
2331
2332 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2333 ; (NOT D) we can sometimes merge the final NOT into one of the following
2334 ; insns.
2335
2336 (define_split
2337 [(set (match_operand:SI 0 "s_register_operand" "")
2338 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2339 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2340 (match_operand:SI 3 "arm_rhs_operand" "")))
2341 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2342 "TARGET_ARM"
2343 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2344 (not:SI (match_dup 3))))
2345 (set (match_dup 0) (not:SI (match_dup 4)))]
2346 ""
2347 )
2348
2349 (define_insn "*andsi_iorsi3_notsi"
2350 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2351 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2352 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2353 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2354 "TARGET_ARM"
2355 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2356 [(set_attr "length" "8")
2357 (set_attr "predicable" "yes")]
2358 )
2359
2360 (define_split
2361 [(set (match_operand:SI 0 "s_register_operand" "")
2362 (match_operator:SI 1 "logical_binary_operator"
2363 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2364 (match_operand:SI 3 "const_int_operand" "")
2365 (match_operand:SI 4 "const_int_operand" ""))
2366 (match_operator:SI 9 "logical_binary_operator"
2367 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2368 (match_operand:SI 6 "const_int_operand" ""))
2369 (match_operand:SI 7 "s_register_operand" "")])]))
2370 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2371 "TARGET_ARM
2372 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2373 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2374 [(set (match_dup 8)
2375 (match_op_dup 1
2376 [(ashift:SI (match_dup 2) (match_dup 4))
2377 (match_dup 5)]))
2378 (set (match_dup 0)
2379 (match_op_dup 1
2380 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2381 (match_dup 7)]))]
2382 "
2383 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2384 ")
2385
2386 (define_split
2387 [(set (match_operand:SI 0 "s_register_operand" "")
2388 (match_operator:SI 1 "logical_binary_operator"
2389 [(match_operator:SI 9 "logical_binary_operator"
2390 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2391 (match_operand:SI 6 "const_int_operand" ""))
2392 (match_operand:SI 7 "s_register_operand" "")])
2393 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2394 (match_operand:SI 3 "const_int_operand" "")
2395 (match_operand:SI 4 "const_int_operand" ""))]))
2396 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2397 "TARGET_ARM
2398 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2399 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2400 [(set (match_dup 8)
2401 (match_op_dup 1
2402 [(ashift:SI (match_dup 2) (match_dup 4))
2403 (match_dup 5)]))
2404 (set (match_dup 0)
2405 (match_op_dup 1
2406 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2407 (match_dup 7)]))]
2408 "
2409 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2410 ")
2411
2412 (define_split
2413 [(set (match_operand:SI 0 "s_register_operand" "")
2414 (match_operator:SI 1 "logical_binary_operator"
2415 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2416 (match_operand:SI 3 "const_int_operand" "")
2417 (match_operand:SI 4 "const_int_operand" ""))
2418 (match_operator:SI 9 "logical_binary_operator"
2419 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2420 (match_operand:SI 6 "const_int_operand" ""))
2421 (match_operand:SI 7 "s_register_operand" "")])]))
2422 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2423 "TARGET_ARM
2424 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2425 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2426 [(set (match_dup 8)
2427 (match_op_dup 1
2428 [(ashift:SI (match_dup 2) (match_dup 4))
2429 (match_dup 5)]))
2430 (set (match_dup 0)
2431 (match_op_dup 1
2432 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2433 (match_dup 7)]))]
2434 "
2435 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2436 ")
2437
2438 (define_split
2439 [(set (match_operand:SI 0 "s_register_operand" "")
2440 (match_operator:SI 1 "logical_binary_operator"
2441 [(match_operator:SI 9 "logical_binary_operator"
2442 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2443 (match_operand:SI 6 "const_int_operand" ""))
2444 (match_operand:SI 7 "s_register_operand" "")])
2445 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2446 (match_operand:SI 3 "const_int_operand" "")
2447 (match_operand:SI 4 "const_int_operand" ""))]))
2448 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2449 "TARGET_ARM
2450 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2451 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2452 [(set (match_dup 8)
2453 (match_op_dup 1
2454 [(ashift:SI (match_dup 2) (match_dup 4))
2455 (match_dup 5)]))
2456 (set (match_dup 0)
2457 (match_op_dup 1
2458 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2459 (match_dup 7)]))]
2460 "
2461 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2462 ")
2463 \f
2464
2465 ;; Minimum and maximum insns
2466
2467 (define_insn "smaxsi3"
2468 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2469 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2470 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2471 (clobber (reg:CC CC_REGNUM))]
2472 "TARGET_ARM"
2473 "@
2474 cmp\\t%1, %2\;movlt\\t%0, %2
2475 cmp\\t%1, %2\;movge\\t%0, %1
2476 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2477 [(set_attr "conds" "clob")
2478 (set_attr "length" "8,8,12")]
2479 )
2480
2481 (define_insn "sminsi3"
2482 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2483 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2484 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2485 (clobber (reg:CC CC_REGNUM))]
2486 "TARGET_ARM"
2487 "@
2488 cmp\\t%1, %2\;movge\\t%0, %2
2489 cmp\\t%1, %2\;movlt\\t%0, %1
2490 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2491 [(set_attr "conds" "clob")
2492 (set_attr "length" "8,8,12")]
2493 )
2494
2495 (define_insn "umaxsi3"
2496 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2497 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2498 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2499 (clobber (reg:CC CC_REGNUM))]
2500 "TARGET_ARM"
2501 "@
2502 cmp\\t%1, %2\;movcc\\t%0, %2
2503 cmp\\t%1, %2\;movcs\\t%0, %1
2504 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2505 [(set_attr "conds" "clob")
2506 (set_attr "length" "8,8,12")]
2507 )
2508
2509 (define_insn "uminsi3"
2510 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2511 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2512 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2513 (clobber (reg:CC CC_REGNUM))]
2514 "TARGET_ARM"
2515 "@
2516 cmp\\t%1, %2\;movcs\\t%0, %2
2517 cmp\\t%1, %2\;movcc\\t%0, %1
2518 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2519 [(set_attr "conds" "clob")
2520 (set_attr "length" "8,8,12")]
2521 )
2522
2523 (define_insn "*store_minmaxsi"
2524 [(set (match_operand:SI 0 "memory_operand" "=m")
2525 (match_operator:SI 3 "minmax_operator"
2526 [(match_operand:SI 1 "s_register_operand" "r")
2527 (match_operand:SI 2 "s_register_operand" "r")]))
2528 (clobber (reg:CC CC_REGNUM))]
2529 "TARGET_ARM"
2530 "*
2531 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2532 operands[1], operands[2]);
2533 output_asm_insn (\"cmp\\t%1, %2\", operands);
2534 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2535 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2536 return \"\";
2537 "
2538 [(set_attr "conds" "clob")
2539 (set_attr "length" "12")
2540 (set_attr "type" "store1")]
2541 )
2542
2543 ; Reject the frame pointer in operand[1], since reloading this after
2544 ; it has been eliminated can cause carnage.
2545 (define_insn "*minmax_arithsi"
2546 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2547 (match_operator:SI 4 "shiftable_operator"
2548 [(match_operator:SI 5 "minmax_operator"
2549 [(match_operand:SI 2 "s_register_operand" "r,r")
2550 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2551 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2552 (clobber (reg:CC CC_REGNUM))]
2553 "TARGET_ARM
2554 && (GET_CODE (operands[1]) != REG
2555 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2556 && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2557 "*
2558 {
2559 enum rtx_code code = GET_CODE (operands[4]);
2560
2561 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2562 operands[2], operands[3]);
2563 output_asm_insn (\"cmp\\t%2, %3\", operands);
2564 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2565 if (which_alternative != 0 || operands[3] != const0_rtx
2566 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2567 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2568 return \"\";
2569 }"
2570 [(set_attr "conds" "clob")
2571 (set_attr "length" "12")]
2572 )
2573
2574 \f
2575 ;; Shift and rotation insns
2576
2577 (define_expand "ashldi3"
2578 [(set (match_operand:DI 0 "s_register_operand" "")
2579 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2580 (match_operand:SI 2 "reg_or_int_operand" "")))]
2581 "TARGET_ARM"
2582 "
2583 if (GET_CODE (operands[2]) == CONST_INT)
2584 {
2585 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2586 {
2587 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2588 DONE;
2589 }
2590 /* Ideally we shouldn't fail here if we could know that operands[1]
2591 ends up already living in an iwmmxt register. Otherwise it's
2592 cheaper to have the alternate code being generated than moving
2593 values to iwmmxt regs and back. */
2594 FAIL;
2595 }
2596 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2597 FAIL;
2598 "
2599 )
2600
2601 (define_insn "arm_ashldi3_1bit"
2602 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2603 (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2604 (const_int 1)))
2605 (clobber (reg:CC CC_REGNUM))]
2606 "TARGET_ARM"
2607 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2608 [(set_attr "conds" "clob")
2609 (set_attr "length" "8")]
2610 )
2611
2612 (define_expand "ashlsi3"
2613 [(set (match_operand:SI 0 "s_register_operand" "")
2614 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2615 (match_operand:SI 2 "arm_rhs_operand" "")))]
2616 "TARGET_EITHER"
2617 "
2618 if (GET_CODE (operands[2]) == CONST_INT
2619 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2620 {
2621 emit_insn (gen_movsi (operands[0], const0_rtx));
2622 DONE;
2623 }
2624 "
2625 )
2626
2627 (define_insn "*thumb_ashlsi3"
2628 [(set (match_operand:SI 0 "register_operand" "=l,l")
2629 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2630 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2631 "TARGET_THUMB"
2632 "lsl\\t%0, %1, %2"
2633 [(set_attr "length" "2")]
2634 )
2635
2636 (define_expand "ashrdi3"
2637 [(set (match_operand:DI 0 "s_register_operand" "")
2638 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2639 (match_operand:SI 2 "reg_or_int_operand" "")))]
2640 "TARGET_ARM"
2641 "
2642 if (GET_CODE (operands[2]) == CONST_INT)
2643 {
2644 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2645 {
2646 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2647 DONE;
2648 }
2649 /* Ideally we shouldn't fail here if we could know that operands[1]
2650 ends up already living in an iwmmxt register. Otherwise it's
2651 cheaper to have the alternate code being generated than moving
2652 values to iwmmxt regs and back. */
2653 FAIL;
2654 }
2655 else if (!TARGET_REALLY_IWMMXT)
2656 FAIL;
2657 "
2658 )
2659
2660 (define_insn "arm_ashrdi3_1bit"
2661 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2662 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2663 (const_int 1)))
2664 (clobber (reg:CC CC_REGNUM))]
2665 "TARGET_ARM"
2666 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2667 [(set_attr "conds" "clob")
2668 (set_attr "length" "8")]
2669 )
2670
2671 (define_expand "ashrsi3"
2672 [(set (match_operand:SI 0 "s_register_operand" "")
2673 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2674 (match_operand:SI 2 "arm_rhs_operand" "")))]
2675 "TARGET_EITHER"
2676 "
2677 if (GET_CODE (operands[2]) == CONST_INT
2678 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2679 operands[2] = GEN_INT (31);
2680 "
2681 )
2682
2683 (define_insn "*thumb_ashrsi3"
2684 [(set (match_operand:SI 0 "register_operand" "=l,l")
2685 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2686 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2687 "TARGET_THUMB"
2688 "asr\\t%0, %1, %2"
2689 [(set_attr "length" "2")]
2690 )
2691
2692 (define_expand "lshrdi3"
2693 [(set (match_operand:DI 0 "s_register_operand" "")
2694 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2695 (match_operand:SI 2 "reg_or_int_operand" "")))]
2696 "TARGET_ARM"
2697 "
2698 if (GET_CODE (operands[2]) == CONST_INT)
2699 {
2700 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2701 {
2702 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2703 DONE;
2704 }
2705 /* Ideally we shouldn't fail here if we could know that operands[1]
2706 ends up already living in an iwmmxt register. Otherwise it's
2707 cheaper to have the alternate code being generated than moving
2708 values to iwmmxt regs and back. */
2709 FAIL;
2710 }
2711 else if (!TARGET_REALLY_IWMMXT)
2712 FAIL;
2713 "
2714 )
2715
2716 (define_insn "arm_lshrdi3_1bit"
2717 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2718 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2719 (const_int 1)))
2720 (clobber (reg:CC CC_REGNUM))]
2721 "TARGET_ARM"
2722 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2723 [(set_attr "conds" "clob")
2724 (set_attr "length" "8")]
2725 )
2726
2727 (define_expand "lshrsi3"
2728 [(set (match_operand:SI 0 "s_register_operand" "")
2729 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2730 (match_operand:SI 2 "arm_rhs_operand" "")))]
2731 "TARGET_EITHER"
2732 "
2733 if (GET_CODE (operands[2]) == CONST_INT
2734 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2735 {
2736 emit_insn (gen_movsi (operands[0], const0_rtx));
2737 DONE;
2738 }
2739 "
2740 )
2741
2742 (define_insn "*thumb_lshrsi3"
2743 [(set (match_operand:SI 0 "register_operand" "=l,l")
2744 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2745 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2746 "TARGET_THUMB"
2747 "lsr\\t%0, %1, %2"
2748 [(set_attr "length" "2")]
2749 )
2750
2751 (define_expand "rotlsi3"
2752 [(set (match_operand:SI 0 "s_register_operand" "")
2753 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2754 (match_operand:SI 2 "reg_or_int_operand" "")))]
2755 "TARGET_ARM"
2756 "
2757 if (GET_CODE (operands[2]) == CONST_INT)
2758 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2759 else
2760 {
2761 rtx reg = gen_reg_rtx (SImode);
2762 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2763 operands[2] = reg;
2764 }
2765 "
2766 )
2767
2768 (define_expand "rotrsi3"
2769 [(set (match_operand:SI 0 "s_register_operand" "")
2770 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2771 (match_operand:SI 2 "arm_rhs_operand" "")))]
2772 "TARGET_EITHER"
2773 "
2774 if (TARGET_ARM)
2775 {
2776 if (GET_CODE (operands[2]) == CONST_INT
2777 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2778 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2779 }
2780 else /* TARGET_THUMB */
2781 {
2782 if (GET_CODE (operands [2]) == CONST_INT)
2783 operands [2] = force_reg (SImode, operands[2]);
2784 }
2785 "
2786 )
2787
2788 (define_insn "*thumb_rotrsi3"
2789 [(set (match_operand:SI 0 "register_operand" "=l")
2790 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2791 (match_operand:SI 2 "register_operand" "l")))]
2792 "TARGET_THUMB"
2793 "ror\\t%0, %0, %2"
2794 [(set_attr "length" "2")]
2795 )
2796
2797 (define_insn "*arm_shiftsi3"
2798 [(set (match_operand:SI 0 "s_register_operand" "=r")
2799 (match_operator:SI 3 "shift_operator"
2800 [(match_operand:SI 1 "s_register_operand" "r")
2801 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2802 "TARGET_ARM"
2803 "mov%?\\t%0, %1%S3"
2804 [(set_attr "predicable" "yes")
2805 (set_attr "shift" "1")
2806 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2807 (const_string "alu_shift")
2808 (const_string "alu_shift_reg")))]
2809 )
2810
2811 (define_insn "*shiftsi3_compare0"
2812 [(set (reg:CC_NOOV CC_REGNUM)
2813 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2814 [(match_operand:SI 1 "s_register_operand" "r")
2815 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2816 (const_int 0)))
2817 (set (match_operand:SI 0 "s_register_operand" "=r")
2818 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2819 "TARGET_ARM"
2820 "mov%?s\\t%0, %1%S3"
2821 [(set_attr "conds" "set")
2822 (set_attr "shift" "1")
2823 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2824 (const_string "alu_shift")
2825 (const_string "alu_shift_reg")))]
2826 )
2827
2828 (define_insn "*shiftsi3_compare0_scratch"
2829 [(set (reg:CC_NOOV CC_REGNUM)
2830 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2831 [(match_operand:SI 1 "s_register_operand" "r")
2832 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2833 (const_int 0)))
2834 (clobber (match_scratch:SI 0 "=r"))]
2835 "TARGET_ARM"
2836 "mov%?s\\t%0, %1%S3"
2837 [(set_attr "conds" "set")
2838 (set_attr "shift" "1")]
2839 )
2840
2841 (define_insn "*notsi_shiftsi"
2842 [(set (match_operand:SI 0 "s_register_operand" "=r")
2843 (not:SI (match_operator:SI 3 "shift_operator"
2844 [(match_operand:SI 1 "s_register_operand" "r")
2845 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2846 "TARGET_ARM"
2847 "mvn%?\\t%0, %1%S3"
2848 [(set_attr "predicable" "yes")
2849 (set_attr "shift" "1")
2850 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2851 (const_string "alu_shift")
2852 (const_string "alu_shift_reg")))]
2853 )
2854
2855 (define_insn "*notsi_shiftsi_compare0"
2856 [(set (reg:CC_NOOV CC_REGNUM)
2857 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2858 [(match_operand:SI 1 "s_register_operand" "r")
2859 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2860 (const_int 0)))
2861 (set (match_operand:SI 0 "s_register_operand" "=r")
2862 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2863 "TARGET_ARM"
2864 "mvn%?s\\t%0, %1%S3"
2865 [(set_attr "conds" "set")
2866 (set_attr "shift" "1")
2867 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2868 (const_string "alu_shift")
2869 (const_string "alu_shift_reg")))]
2870 )
2871
2872 (define_insn "*not_shiftsi_compare0_scratch"
2873 [(set (reg:CC_NOOV CC_REGNUM)
2874 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2875 [(match_operand:SI 1 "s_register_operand" "r")
2876 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2877 (const_int 0)))
2878 (clobber (match_scratch:SI 0 "=r"))]
2879 "TARGET_ARM"
2880 "mvn%?s\\t%0, %1%S3"
2881 [(set_attr "conds" "set")
2882 (set_attr "shift" "1")
2883 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2884 (const_string "alu_shift")
2885 (const_string "alu_shift_reg")))]
2886 )
2887
2888 ;; We don't really have extzv, but defining this using shifts helps
2889 ;; to reduce register pressure later on.
2890
2891 (define_expand "extzv"
2892 [(set (match_dup 4)
2893 (ashift:SI (match_operand:SI 1 "register_operand" "")
2894 (match_operand:SI 2 "const_int_operand" "")))
2895 (set (match_operand:SI 0 "register_operand" "")
2896 (lshiftrt:SI (match_dup 4)
2897 (match_operand:SI 3 "const_int_operand" "")))]
2898 "TARGET_THUMB"
2899 "
2900 {
2901 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2902 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2903
2904 operands[3] = GEN_INT (rshift);
2905
2906 if (lshift == 0)
2907 {
2908 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2909 DONE;
2910 }
2911
2912 operands[2] = GEN_INT (lshift);
2913 operands[4] = gen_reg_rtx (SImode);
2914 }"
2915 )
2916
2917 \f
2918 ;; Unary arithmetic insns
2919
2920 (define_expand "negdi2"
2921 [(parallel
2922 [(set (match_operand:DI 0 "s_register_operand" "")
2923 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2924 (clobber (reg:CC CC_REGNUM))])]
2925 "TARGET_EITHER"
2926 "
2927 if (TARGET_THUMB)
2928 {
2929 if (GET_CODE (operands[1]) != REG)
2930 operands[1] = force_reg (SImode, operands[1]);
2931 }
2932 "
2933 )
2934
2935 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2936 ;; The second alternative is to allow the common case of a *full* overlap.
2937 (define_insn "*arm_negdi2"
2938 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2939 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2940 (clobber (reg:CC CC_REGNUM))]
2941 "TARGET_ARM"
2942 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2943 [(set_attr "conds" "clob")
2944 (set_attr "length" "8")]
2945 )
2946
2947 (define_insn "*thumb_negdi2"
2948 [(set (match_operand:DI 0 "register_operand" "=&l")
2949 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2950 (clobber (reg:CC CC_REGNUM))]
2951 "TARGET_THUMB"
2952 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2953 [(set_attr "length" "6")]
2954 )
2955
2956 (define_expand "negsi2"
2957 [(set (match_operand:SI 0 "s_register_operand" "")
2958 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2959 "TARGET_EITHER"
2960 ""
2961 )
2962
2963 (define_insn "*arm_negsi2"
2964 [(set (match_operand:SI 0 "s_register_operand" "=r")
2965 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2966 "TARGET_ARM"
2967 "rsb%?\\t%0, %1, #0"
2968 [(set_attr "predicable" "yes")]
2969 )
2970
2971 (define_insn "*thumb_negsi2"
2972 [(set (match_operand:SI 0 "register_operand" "=l")
2973 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2974 "TARGET_THUMB"
2975 "neg\\t%0, %1"
2976 [(set_attr "length" "2")]
2977 )
2978
2979 (define_expand "negsf2"
2980 [(set (match_operand:SF 0 "s_register_operand" "")
2981 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2982 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2983 ""
2984 )
2985
2986 (define_expand "negdf2"
2987 [(set (match_operand:DF 0 "s_register_operand" "")
2988 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2989 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2990 "")
2991
2992 ;; abssi2 doesn't really clobber the condition codes if a different register
2993 ;; is being set. To keep things simple, assume during rtl manipulations that
2994 ;; it does, but tell the final scan operator the truth. Similarly for
2995 ;; (neg (abs...))
2996
2997 (define_expand "abssi2"
2998 [(parallel
2999 [(set (match_operand:SI 0 "s_register_operand" "")
3000 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3001 (clobber (reg:CC CC_REGNUM))])]
3002 "TARGET_ARM"
3003 "")
3004
3005 (define_insn "*arm_abssi2"
3006 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3007 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3008 (clobber (reg:CC CC_REGNUM))]
3009 "TARGET_ARM"
3010 "@
3011 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3012 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3013 [(set_attr "conds" "clob,*")
3014 (set_attr "shift" "1")
3015 ;; predicable can't be set based on the variant, so left as no
3016 (set_attr "length" "8")]
3017 )
3018
3019 (define_insn "*neg_abssi2"
3020 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3021 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3022 (clobber (reg:CC CC_REGNUM))]
3023 "TARGET_ARM"
3024 "@
3025 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3026 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3027 [(set_attr "conds" "clob,*")
3028 (set_attr "shift" "1")
3029 ;; predicable can't be set based on the variant, so left as no
3030 (set_attr "length" "8")]
3031 )
3032
3033 (define_expand "abssf2"
3034 [(set (match_operand:SF 0 "s_register_operand" "")
3035 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3036 "TARGET_ARM && TARGET_HARD_FLOAT"
3037 "")
3038
3039 (define_expand "absdf2"
3040 [(set (match_operand:DF 0 "s_register_operand" "")
3041 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3042 "TARGET_ARM && TARGET_HARD_FLOAT"
3043 "")
3044
3045 (define_expand "sqrtsf2"
3046 [(set (match_operand:SF 0 "s_register_operand" "")
3047 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3048 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3049 "")
3050
3051 (define_expand "sqrtdf2"
3052 [(set (match_operand:DF 0 "s_register_operand" "")
3053 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3054 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3055 "")
3056
3057 (define_insn_and_split "one_cmpldi2"
3058 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3059 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3060 "TARGET_ARM"
3061 "#"
3062 "TARGET_ARM && reload_completed"
3063 [(set (match_dup 0) (not:SI (match_dup 1)))
3064 (set (match_dup 2) (not:SI (match_dup 3)))]
3065 "
3066 {
3067 operands[2] = gen_highpart (SImode, operands[0]);
3068 operands[0] = gen_lowpart (SImode, operands[0]);
3069 operands[3] = gen_highpart (SImode, operands[1]);
3070 operands[1] = gen_lowpart (SImode, operands[1]);
3071 }"
3072 [(set_attr "length" "8")
3073 (set_attr "predicable" "yes")]
3074 )
3075
3076 (define_expand "one_cmplsi2"
3077 [(set (match_operand:SI 0 "s_register_operand" "")
3078 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3079 "TARGET_EITHER"
3080 ""
3081 )
3082
3083 (define_insn "*arm_one_cmplsi2"
3084 [(set (match_operand:SI 0 "s_register_operand" "=r")
3085 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
3086 "TARGET_ARM"
3087 "mvn%?\\t%0, %1"
3088 [(set_attr "predicable" "yes")]
3089 )
3090
3091 (define_insn "*thumb_one_cmplsi2"
3092 [(set (match_operand:SI 0 "register_operand" "=l")
3093 (not:SI (match_operand:SI 1 "register_operand" "l")))]
3094 "TARGET_THUMB"
3095 "mvn\\t%0, %1"
3096 [(set_attr "length" "2")]
3097 )
3098
3099 (define_insn "*notsi_compare0"
3100 [(set (reg:CC_NOOV CC_REGNUM)
3101 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3102 (const_int 0)))
3103 (set (match_operand:SI 0 "s_register_operand" "=r")
3104 (not:SI (match_dup 1)))]
3105 "TARGET_ARM"
3106 "mvn%?s\\t%0, %1"
3107 [(set_attr "conds" "set")]
3108 )
3109
3110 (define_insn "*notsi_compare0_scratch"
3111 [(set (reg:CC_NOOV CC_REGNUM)
3112 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3113 (const_int 0)))
3114 (clobber (match_scratch:SI 0 "=r"))]
3115 "TARGET_ARM"
3116 "mvn%?s\\t%0, %1"
3117 [(set_attr "conds" "set")]
3118 )
3119 \f
3120 ;; Fixed <--> Floating conversion insns
3121
3122 (define_expand "floatsisf2"
3123 [(set (match_operand:SF 0 "s_register_operand" "")
3124 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3125 "TARGET_ARM && TARGET_HARD_FLOAT"
3126 "
3127 if (TARGET_MAVERICK)
3128 {
3129 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3130 DONE;
3131 }
3132 ")
3133
3134 (define_expand "floatsidf2"
3135 [(set (match_operand:DF 0 "s_register_operand" "")
3136 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3137 "TARGET_ARM && TARGET_HARD_FLOAT"
3138 "
3139 if (TARGET_MAVERICK)
3140 {
3141 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3142 DONE;
3143 }
3144 ")
3145
3146 (define_expand "fix_truncsfsi2"
3147 [(set (match_operand:SI 0 "s_register_operand" "")
3148 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
3149 "TARGET_ARM && TARGET_HARD_FLOAT"
3150 "
3151 if (TARGET_MAVERICK)
3152 {
3153 if (!cirrus_fp_register (operands[0], SImode))
3154 operands[0] = force_reg (SImode, operands[0]);
3155 if (!cirrus_fp_register (operands[1], SFmode))
3156 operands[1] = force_reg (SFmode, operands[0]);
3157 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3158 DONE;
3159 }
3160 ")
3161
3162 (define_expand "fix_truncdfsi2"
3163 [(set (match_operand:SI 0 "s_register_operand" "")
3164 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
3165 "TARGET_ARM && TARGET_HARD_FLOAT"
3166 "
3167 if (TARGET_MAVERICK)
3168 {
3169 if (!cirrus_fp_register (operands[1], DFmode))
3170 operands[1] = force_reg (DFmode, operands[0]);
3171 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3172 DONE;
3173 }
3174 ")
3175
3176 ;; Truncation insns
3177
3178 (define_expand "truncdfsf2"
3179 [(set (match_operand:SF 0 "s_register_operand" "")
3180 (float_truncate:SF
3181 (match_operand:DF 1 "s_register_operand" "")))]
3182 "TARGET_ARM && TARGET_HARD_FLOAT"
3183 ""
3184 )
3185 \f
3186 ;; Zero and sign extension instructions.
3187
3188 (define_insn "zero_extendsidi2"
3189 [(set (match_operand:DI 0 "s_register_operand" "=r")
3190 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3191 "TARGET_ARM"
3192 "*
3193 if (REGNO (operands[1])
3194 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3195 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3196 return \"mov%?\\t%R0, #0\";
3197 "
3198 [(set_attr "length" "8")
3199 (set_attr "predicable" "yes")]
3200 )
3201
3202 (define_insn "zero_extendqidi2"
3203 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
3204 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3205 "TARGET_ARM"
3206 "@
3207 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3208 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3209 [(set_attr "length" "8")
3210 (set_attr "predicable" "yes")
3211 (set_attr "type" "*,load_byte")
3212 (set_attr "pool_range" "*,4092")
3213 (set_attr "neg_pool_range" "*,4084")]
3214 )
3215
3216 (define_insn "extendsidi2"
3217 [(set (match_operand:DI 0 "s_register_operand" "=r")
3218 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3219 "TARGET_ARM"
3220 "*
3221 if (REGNO (operands[1])
3222 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3223 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3224 return \"mov%?\\t%R0, %Q0, asr #31\";
3225 "
3226 [(set_attr "length" "8")
3227 (set_attr "shift" "1")
3228 (set_attr "predicable" "yes")]
3229 )
3230
3231 (define_expand "zero_extendhisi2"
3232 [(set (match_dup 2)
3233 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3234 (const_int 16)))
3235 (set (match_operand:SI 0 "s_register_operand" "")
3236 (lshiftrt:SI (match_dup 2) (const_int 16)))]
3237 "TARGET_EITHER"
3238 "
3239 {
3240 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3241 {
3242 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3243 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3244 DONE;
3245 }
3246
3247 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3248 {
3249 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3250 DONE;
3251 }
3252
3253 if (!s_register_operand (operands[1], HImode))
3254 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3255
3256 if (arm_arch6)
3257 {
3258 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3259 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3260 DONE;
3261 }
3262
3263 operands[1] = gen_lowpart (SImode, operands[1]);
3264 operands[2] = gen_reg_rtx (SImode);
3265 }"
3266 )
3267
3268 (define_insn "*thumb_zero_extendhisi2"
3269 [(set (match_operand:SI 0 "register_operand" "=l")
3270 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3271 "TARGET_THUMB && !arm_arch6"
3272 "*
3273 rtx mem = XEXP (operands[1], 0);
3274
3275 if (GET_CODE (mem) == CONST)
3276 mem = XEXP (mem, 0);
3277
3278 if (GET_CODE (mem) == LABEL_REF)
3279 return \"ldr\\t%0, %1\";
3280
3281 if (GET_CODE (mem) == PLUS)
3282 {
3283 rtx a = XEXP (mem, 0);
3284 rtx b = XEXP (mem, 1);
3285
3286 /* This can happen due to bugs in reload. */
3287 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3288 {
3289 rtx ops[2];
3290 ops[0] = operands[0];
3291 ops[1] = a;
3292
3293 output_asm_insn (\"mov %0, %1\", ops);
3294
3295 XEXP (mem, 0) = operands[0];
3296 }
3297
3298 else if ( GET_CODE (a) == LABEL_REF
3299 && GET_CODE (b) == CONST_INT)
3300 return \"ldr\\t%0, %1\";
3301 }
3302
3303 return \"ldrh\\t%0, %1\";
3304 "
3305 [(set_attr "length" "4")
3306 (set_attr "type" "load_byte")
3307 (set_attr "pool_range" "60")]
3308 )
3309
3310 (define_insn "*thumb_zero_extendhisi2_v6"
3311 [(set (match_operand:SI 0 "register_operand" "=l,l")
3312 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3313 "TARGET_THUMB && arm_arch6"
3314 "*
3315 rtx mem;
3316
3317 if (which_alternative == 0)
3318 return \"uxth\\t%0, %1\";
3319
3320 mem = XEXP (operands[1], 0);
3321
3322 if (GET_CODE (mem) == CONST)
3323 mem = XEXP (mem, 0);
3324
3325 if (GET_CODE (mem) == LABEL_REF)
3326 return \"ldr\\t%0, %1\";
3327
3328 if (GET_CODE (mem) == PLUS)
3329 {
3330 rtx a = XEXP (mem, 0);
3331 rtx b = XEXP (mem, 1);
3332
3333 /* This can happen due to bugs in reload. */
3334 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3335 {
3336 rtx ops[2];
3337 ops[0] = operands[0];
3338 ops[1] = a;
3339
3340 output_asm_insn (\"mov %0, %1\", ops);
3341
3342 XEXP (mem, 0) = operands[0];
3343 }
3344
3345 else if ( GET_CODE (a) == LABEL_REF
3346 && GET_CODE (b) == CONST_INT)
3347 return \"ldr\\t%0, %1\";
3348 }
3349
3350 return \"ldrh\\t%0, %1\";
3351 "
3352 [(set_attr "length" "2,4")
3353 (set_attr "type" "alu_shift,load_byte")
3354 (set_attr "pool_range" "*,60")]
3355 )
3356
3357 (define_insn "*arm_zero_extendhisi2"
3358 [(set (match_operand:SI 0 "s_register_operand" "=r")
3359 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3360 "TARGET_ARM && arm_arch4 && !arm_arch6"
3361 "ldr%?h\\t%0, %1"
3362 [(set_attr "type" "load_byte")
3363 (set_attr "predicable" "yes")
3364 (set_attr "pool_range" "256")
3365 (set_attr "neg_pool_range" "244")]
3366 )
3367
3368 (define_insn "*arm_zero_extendhisi2_v6"
3369 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3370 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3371 "TARGET_ARM && arm_arch6"
3372 "@
3373 uxth%?\\t%0, %1
3374 ldr%?h\\t%0, %1"
3375 [(set_attr "type" "alu_shift,load_byte")
3376 (set_attr "predicable" "yes")
3377 (set_attr "pool_range" "*,256")
3378 (set_attr "neg_pool_range" "*,244")]
3379 )
3380
3381 (define_insn "*arm_zero_extendhisi2addsi"
3382 [(set (match_operand:SI 0 "s_register_operand" "=r")
3383 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3384 (match_operand:SI 2 "s_register_operand" "r")))]
3385 "TARGET_ARM && arm_arch6"
3386 "uxtah%?\\t%0, %2, %1"
3387 [(set_attr "type" "alu_shift")
3388 (set_attr "predicable" "yes")]
3389 )
3390
3391 (define_split
3392 [(set (match_operand:SI 0 "s_register_operand" "")
3393 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3394 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3395 "TARGET_ARM && (!arm_arch4)"
3396 [(set (match_dup 2) (match_dup 1))
3397 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3398 "
3399 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3400 FAIL;
3401 "
3402 )
3403
3404 (define_split
3405 [(set (match_operand:SI 0 "s_register_operand" "")
3406 (match_operator:SI 3 "shiftable_operator"
3407 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3408 (match_operand:SI 4 "s_register_operand" "")]))
3409 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3410 "TARGET_ARM && (!arm_arch4)"
3411 [(set (match_dup 2) (match_dup 1))
3412 (set (match_dup 0)
3413 (match_op_dup 3
3414 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3415 "
3416 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3417 FAIL;
3418 "
3419 )
3420
3421 (define_expand "zero_extendqisi2"
3422 [(set (match_operand:SI 0 "s_register_operand" "")
3423 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3424 "TARGET_EITHER"
3425 "
3426 if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3427 {
3428 if (TARGET_ARM)
3429 {
3430 emit_insn (gen_andsi3 (operands[0],
3431 gen_lowpart (SImode, operands[1]),
3432 GEN_INT (255)));
3433 }
3434 else /* TARGET_THUMB */
3435 {
3436 rtx temp = gen_reg_rtx (SImode);
3437 rtx ops[3];
3438
3439 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3440 operands[1] = gen_lowpart (SImode, operands[1]);
3441
3442 ops[0] = temp;
3443 ops[1] = operands[1];
3444 ops[2] = GEN_INT (24);
3445
3446 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3447 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3448
3449 ops[0] = operands[0];
3450 ops[1] = temp;
3451 ops[2] = GEN_INT (24);
3452
3453 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3454 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3455 }
3456 DONE;
3457 }
3458 "
3459 )
3460
3461 (define_insn "*thumb_zero_extendqisi2"
3462 [(set (match_operand:SI 0 "register_operand" "=l")
3463 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3464 "TARGET_THUMB && !arm_arch6"
3465 "ldrb\\t%0, %1"
3466 [(set_attr "length" "2")
3467 (set_attr "type" "load_byte")
3468 (set_attr "pool_range" "32")]
3469 )
3470
3471 (define_insn "*thumb_zero_extendqisi2_v6"
3472 [(set (match_operand:SI 0 "register_operand" "=l,l")
3473 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3474 "TARGET_THUMB && arm_arch6"
3475 "@
3476 uxtb\\t%0, %1
3477 ldrb\\t%0, %1"
3478 [(set_attr "length" "2,2")
3479 (set_attr "type" "alu_shift,load_byte")
3480 (set_attr "pool_range" "*,32")]
3481 )
3482
3483 (define_insn "*arm_zero_extendqisi2"
3484 [(set (match_operand:SI 0 "s_register_operand" "=r")
3485 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3486 "TARGET_ARM && !arm_arch6"
3487 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3488 [(set_attr "type" "load_byte")
3489 (set_attr "predicable" "yes")
3490 (set_attr "pool_range" "4096")
3491 (set_attr "neg_pool_range" "4084")]
3492 )
3493
3494 (define_insn "*arm_zero_extendqisi2_v6"
3495 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3496 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3497 "TARGET_ARM && arm_arch6"
3498 "@
3499 uxtb%?\\t%0, %1
3500 ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3501 [(set_attr "type" "alu_shift,load_byte")
3502 (set_attr "predicable" "yes")
3503 (set_attr "pool_range" "*,4096")
3504 (set_attr "neg_pool_range" "*,4084")]
3505 )
3506
3507 (define_insn "*arm_zero_extendqisi2addsi"
3508 [(set (match_operand:SI 0 "s_register_operand" "=r")
3509 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3510 (match_operand:SI 2 "s_register_operand" "r")))]
3511 "TARGET_ARM && arm_arch6"
3512 "uxtab%?\\t%0, %2, %1"
3513 [(set_attr "predicable" "yes")
3514 (set_attr "type" "alu_shift")]
3515 )
3516
3517 (define_split
3518 [(set (match_operand:SI 0 "s_register_operand" "")
3519 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3520 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3521 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3522 [(set (match_dup 2) (match_dup 1))
3523 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3524 ""
3525 )
3526
3527 (define_insn "*compareqi_eq0"
3528 [(set (reg:CC_Z CC_REGNUM)
3529 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3530 (const_int 0)))]
3531 "TARGET_ARM"
3532 "tst\\t%0, #255"
3533 [(set_attr "conds" "set")]
3534 )
3535
3536 (define_expand "extendhisi2"
3537 [(set (match_dup 2)
3538 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3539 (const_int 16)))
3540 (set (match_operand:SI 0 "s_register_operand" "")
3541 (ashiftrt:SI (match_dup 2)
3542 (const_int 16)))]
3543 "TARGET_EITHER"
3544 "
3545 {
3546 if (GET_CODE (operands[1]) == MEM)
3547 {
3548 if (TARGET_THUMB)
3549 {
3550 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3551 DONE;
3552 }
3553 else if (arm_arch4)
3554 {
3555 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3556 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3557 DONE;
3558 }
3559 }
3560
3561 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3562 {
3563 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3564 DONE;
3565 }
3566
3567 if (!s_register_operand (operands[1], HImode))
3568 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3569
3570 if (arm_arch6)
3571 {
3572 if (TARGET_THUMB)
3573 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3574 else
3575 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3576 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3577
3578 DONE;
3579 }
3580
3581 operands[1] = gen_lowpart (SImode, operands[1]);
3582 operands[2] = gen_reg_rtx (SImode);
3583 }"
3584 )
3585
3586 (define_insn "thumb_extendhisi2"
3587 [(set (match_operand:SI 0 "register_operand" "=l")
3588 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3589 (clobber (match_scratch:SI 2 "=&l"))]
3590 "TARGET_THUMB && !arm_arch6"
3591 "*
3592 {
3593 rtx ops[4];
3594 rtx mem = XEXP (operands[1], 0);
3595
3596 /* This code used to try to use 'V', and fix the address only if it was
3597 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3598 range of QImode offsets, and offsettable_address_p does a QImode
3599 address check. */
3600
3601 if (GET_CODE (mem) == CONST)
3602 mem = XEXP (mem, 0);
3603
3604 if (GET_CODE (mem) == LABEL_REF)
3605 return \"ldr\\t%0, %1\";
3606
3607 if (GET_CODE (mem) == PLUS)
3608 {
3609 rtx a = XEXP (mem, 0);
3610 rtx b = XEXP (mem, 1);
3611
3612 if (GET_CODE (a) == LABEL_REF
3613 && GET_CODE (b) == CONST_INT)
3614 return \"ldr\\t%0, %1\";
3615
3616 if (GET_CODE (b) == REG)
3617 return \"ldrsh\\t%0, %1\";
3618
3619 ops[1] = a;
3620 ops[2] = b;
3621 }
3622 else
3623 {
3624 ops[1] = mem;
3625 ops[2] = const0_rtx;
3626 }
3627
3628 if (GET_CODE (ops[1]) != REG)
3629 {
3630 debug_rtx (ops[1]);
3631 abort ();
3632 }
3633
3634 ops[0] = operands[0];
3635 ops[3] = operands[2];
3636 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3637 return \"\";
3638 }"
3639 [(set_attr "length" "4")
3640 (set_attr "type" "load_byte")
3641 (set_attr "pool_range" "1020")]
3642 )
3643
3644 ;; We used to have an early-clobber on the scratch register here.
3645 ;; However, there's a bug somewhere in reload which means that this
3646 ;; can be partially ignored during spill allocation if the memory
3647 ;; address also needs reloading; this causes an abort later on when
3648 ;; we try to verify the operands. Fortunately, we don't really need
3649 ;; the early-clobber: we can always use operand 0 if operand 2
3650 ;; overlaps the address.
3651 (define_insn "*thumb_extendhisi2_insn_v6"
3652 [(set (match_operand:SI 0 "register_operand" "=l,l")
3653 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3654 (clobber (match_scratch:SI 2 "=X,l"))]
3655 "TARGET_THUMB && arm_arch6"
3656 "*
3657 {
3658 rtx ops[4];
3659 rtx mem;
3660
3661 if (which_alternative == 0)
3662 return \"sxth\\t%0, %1\";
3663
3664 mem = XEXP (operands[1], 0);
3665
3666 /* This code used to try to use 'V', and fix the address only if it was
3667 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3668 range of QImode offsets, and offsettable_address_p does a QImode
3669 address check. */
3670
3671 if (GET_CODE (mem) == CONST)
3672 mem = XEXP (mem, 0);
3673
3674 if (GET_CODE (mem) == LABEL_REF)
3675 return \"ldr\\t%0, %1\";
3676
3677 if (GET_CODE (mem) == PLUS)
3678 {
3679 rtx a = XEXP (mem, 0);
3680 rtx b = XEXP (mem, 1);
3681
3682 if (GET_CODE (a) == LABEL_REF
3683 && GET_CODE (b) == CONST_INT)
3684 return \"ldr\\t%0, %1\";
3685
3686 if (GET_CODE (b) == REG)
3687 return \"ldrsh\\t%0, %1\";
3688
3689 ops[1] = a;
3690 ops[2] = b;
3691 }
3692 else
3693 {
3694 ops[1] = mem;
3695 ops[2] = const0_rtx;
3696 }
3697
3698 if (GET_CODE (ops[1]) != REG)
3699 {
3700 debug_rtx (ops[1]);
3701 abort ();
3702 }
3703
3704 ops[0] = operands[0];
3705 if (reg_mentioned_p (operands[2], ops[1]))
3706 ops[3] = ops[0];
3707 else
3708 ops[3] = operands[2];
3709 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3710 return \"\";
3711 }"
3712 [(set_attr "length" "2,4")
3713 (set_attr "type" "alu_shift,load_byte")
3714 (set_attr "pool_range" "*,1020")]
3715 )
3716
3717 (define_expand "extendhisi2_mem"
3718 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3719 (set (match_dup 3)
3720 (zero_extend:SI (match_dup 7)))
3721 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3722 (set (match_operand:SI 0 "" "")
3723 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3724 "TARGET_ARM"
3725 "
3726 {
3727 rtx mem1, mem2;
3728 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3729
3730 mem1 = gen_rtx_MEM (QImode, addr);
3731 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3732 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3733 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3734 operands[0] = gen_lowpart (SImode, operands[0]);
3735 operands[1] = mem1;
3736 operands[2] = gen_reg_rtx (SImode);
3737 operands[3] = gen_reg_rtx (SImode);
3738 operands[6] = gen_reg_rtx (SImode);
3739 operands[7] = mem2;
3740
3741 if (BYTES_BIG_ENDIAN)
3742 {
3743 operands[4] = operands[2];
3744 operands[5] = operands[3];
3745 }
3746 else
3747 {
3748 operands[4] = operands[3];
3749 operands[5] = operands[2];
3750 }
3751 }"
3752 )
3753
3754 (define_insn "*arm_extendhisi2"
3755 [(set (match_operand:SI 0 "s_register_operand" "=r")
3756 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3757 "TARGET_ARM && arm_arch4 && !arm_arch6"
3758 "ldr%?sh\\t%0, %1"
3759 [(set_attr "type" "load_byte")
3760 (set_attr "predicable" "yes")
3761 (set_attr "pool_range" "256")
3762 (set_attr "neg_pool_range" "244")]
3763 )
3764
3765 (define_insn "*arm_extendhisi2_v6"
3766 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3767 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3768 "TARGET_ARM && arm_arch6"
3769 "@
3770 sxth%?\\t%0, %1
3771 ldr%?sh\\t%0, %1"
3772 [(set_attr "type" "alu_shift,load_byte")
3773 (set_attr "predicable" "yes")
3774 (set_attr "pool_range" "*,256")
3775 (set_attr "neg_pool_range" "*,244")]
3776 )
3777
3778 (define_insn "*arm_extendhisi2addsi"
3779 [(set (match_operand:SI 0 "s_register_operand" "=r")
3780 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3781 (match_operand:SI 2 "s_register_operand" "r")))]
3782 "TARGET_ARM && arm_arch6"
3783 "sxtah%?\\t%0, %2, %1"
3784 )
3785
3786 (define_split
3787 [(set (match_operand:SI 0 "s_register_operand" "")
3788 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3789 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3790 "TARGET_ARM && (!arm_arch4)"
3791 [(set (match_dup 2) (match_dup 1))
3792 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3793 "
3794 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3795 FAIL;
3796 "
3797 )
3798
3799 (define_split
3800 [(set (match_operand:SI 0 "s_register_operand" "")
3801 (match_operator:SI 3 "shiftable_operator"
3802 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3803 (match_operand:SI 4 "s_register_operand" "")]))
3804 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3805 "TARGET_ARM && (!arm_arch4)"
3806 [(set (match_dup 2) (match_dup 1))
3807 (set (match_dup 0)
3808 (match_op_dup 3
3809 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3810 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3811 FAIL;
3812 "
3813 )
3814
3815 (define_expand "extendqihi2"
3816 [(set (match_dup 2)
3817 (ashift:SI (match_operand:QI 1 "general_operand" "")
3818 (const_int 24)))
3819 (set (match_operand:HI 0 "s_register_operand" "")
3820 (ashiftrt:SI (match_dup 2)
3821 (const_int 24)))]
3822 "TARGET_ARM"
3823 "
3824 {
3825 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3826 {
3827 emit_insn (gen_rtx_SET (VOIDmode,
3828 operands[0],
3829 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3830 DONE;
3831 }
3832 if (!s_register_operand (operands[1], QImode))
3833 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3834 operands[0] = gen_lowpart (SImode, operands[0]);
3835 operands[1] = gen_lowpart (SImode, operands[1]);
3836 operands[2] = gen_reg_rtx (SImode);
3837 }"
3838 )
3839
3840 (define_insn "*extendqihi_insn"
3841 [(set (match_operand:HI 0 "s_register_operand" "=r")
3842 (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3843 "TARGET_ARM && arm_arch4"
3844 "ldr%?sb\\t%0, %1"
3845 [(set_attr "type" "load_byte")
3846 (set_attr "predicable" "yes")
3847 (set_attr "pool_range" "256")
3848 (set_attr "neg_pool_range" "244")]
3849 )
3850
3851 (define_expand "extendqisi2"
3852 [(set (match_dup 2)
3853 (ashift:SI (match_operand:QI 1 "general_operand" "")
3854 (const_int 24)))
3855 (set (match_operand:SI 0 "s_register_operand" "")
3856 (ashiftrt:SI (match_dup 2)
3857 (const_int 24)))]
3858 "TARGET_EITHER"
3859 "
3860 {
3861 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3862 {
3863 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3864 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3865 DONE;
3866 }
3867
3868 if (!s_register_operand (operands[1], QImode))
3869 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3870
3871 if (arm_arch6)
3872 {
3873 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3874 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3875 DONE;
3876 }
3877
3878 operands[1] = gen_lowpart (SImode, operands[1]);
3879 operands[2] = gen_reg_rtx (SImode);
3880 }"
3881 )
3882
3883 (define_insn "*arm_extendqisi"
3884 [(set (match_operand:SI 0 "s_register_operand" "=r")
3885 (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3886 "TARGET_ARM && arm_arch4 && !arm_arch6"
3887 "ldr%?sb\\t%0, %1"
3888 [(set_attr "type" "load_byte")
3889 (set_attr "predicable" "yes")
3890 (set_attr "pool_range" "256")
3891 (set_attr "neg_pool_range" "244")]
3892 )
3893
3894 (define_insn "*arm_extendqisi_v6"
3895 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3896 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3897 "TARGET_ARM && arm_arch6"
3898 "@
3899 sxtb%?\\t%0, %1
3900 ldr%?sb\\t%0, %1"
3901 [(set_attr "type" "alu_shift,load_byte")
3902 (set_attr "predicable" "yes")
3903 (set_attr "pool_range" "*,256")
3904 (set_attr "neg_pool_range" "*,244")]
3905 )
3906
3907 (define_insn "*arm_extendqisi2addsi"
3908 [(set (match_operand:SI 0 "s_register_operand" "=r")
3909 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3910 (match_operand:SI 2 "s_register_operand" "r")))]
3911 "TARGET_ARM && arm_arch6"
3912 "sxtab%?\\t%0, %2, %1"
3913 [(set_attr "type" "alu_shift")
3914 (set_attr "predicable" "yes")]
3915 )
3916
3917 (define_insn "*thumb_extendqisi2"
3918 [(set (match_operand:SI 0 "register_operand" "=l,l")
3919 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3920 "TARGET_THUMB && !arm_arch6"
3921 "*
3922 {
3923 rtx ops[3];
3924 rtx mem = XEXP (operands[1], 0);
3925
3926 if (GET_CODE (mem) == CONST)
3927 mem = XEXP (mem, 0);
3928
3929 if (GET_CODE (mem) == LABEL_REF)
3930 return \"ldr\\t%0, %1\";
3931
3932 if (GET_CODE (mem) == PLUS
3933 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3934 return \"ldr\\t%0, %1\";
3935
3936 if (which_alternative == 0)
3937 return \"ldrsb\\t%0, %1\";
3938
3939 ops[0] = operands[0];
3940
3941 if (GET_CODE (mem) == PLUS)
3942 {
3943 rtx a = XEXP (mem, 0);
3944 rtx b = XEXP (mem, 1);
3945
3946 ops[1] = a;
3947 ops[2] = b;
3948
3949 if (GET_CODE (a) == REG)
3950 {
3951 if (GET_CODE (b) == REG)
3952 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3953 else if (REGNO (a) == REGNO (ops[0]))
3954 {
3955 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3956 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3957 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3958 }
3959 else
3960 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3961 }
3962 else if (GET_CODE (b) != REG)
3963 abort ();
3964 else
3965 {
3966 if (REGNO (b) == REGNO (ops[0]))
3967 {
3968 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3969 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3970 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3971 }
3972 else
3973 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3974 }
3975 }
3976 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3977 {
3978 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3979 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3980 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3981 }
3982 else
3983 {
3984 ops[1] = mem;
3985 ops[2] = const0_rtx;
3986
3987 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3988 }
3989 return \"\";
3990 }"
3991 [(set_attr "length" "2,6")
3992 (set_attr "type" "load_byte,load_byte")
3993 (set_attr "pool_range" "32,32")]
3994 )
3995
3996 (define_insn "*thumb_extendqisi2_v6"
3997 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3998 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3999 "TARGET_THUMB && arm_arch6"
4000 "*
4001 {
4002 rtx ops[3];
4003 rtx mem;
4004
4005 if (which_alternative == 0)
4006 return \"sxtb\\t%0, %1\";
4007
4008 mem = XEXP (operands[1], 0);
4009
4010 if (GET_CODE (mem) == CONST)
4011 mem = XEXP (mem, 0);
4012
4013 if (GET_CODE (mem) == LABEL_REF)
4014 return \"ldr\\t%0, %1\";
4015
4016 if (GET_CODE (mem) == PLUS
4017 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4018 return \"ldr\\t%0, %1\";
4019
4020 if (which_alternative == 0)
4021 return \"ldrsb\\t%0, %1\";
4022
4023 ops[0] = operands[0];
4024
4025 if (GET_CODE (mem) == PLUS)
4026 {
4027 rtx a = XEXP (mem, 0);
4028 rtx b = XEXP (mem, 1);
4029
4030 ops[1] = a;
4031 ops[2] = b;
4032
4033 if (GET_CODE (a) == REG)
4034 {
4035 if (GET_CODE (b) == REG)
4036 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4037 else if (REGNO (a) == REGNO (ops[0]))
4038 {
4039 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4040 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4041 }
4042 else
4043 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4044 }
4045 else if (GET_CODE (b) != REG)
4046 abort ();
4047 else
4048 {
4049 if (REGNO (b) == REGNO (ops[0]))
4050 {
4051 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4052 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4053 }
4054 else
4055 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4056 }
4057 }
4058 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4059 {
4060 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4061 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4062 }
4063 else
4064 {
4065 ops[1] = mem;
4066 ops[2] = const0_rtx;
4067
4068 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4069 }
4070 return \"\";
4071 }"
4072 [(set_attr "length" "2,2,4")
4073 (set_attr "type" "alu_shift,load_byte,load_byte")
4074 (set_attr "pool_range" "*,32,32")]
4075 )
4076
4077 (define_expand "extendsfdf2"
4078 [(set (match_operand:DF 0 "s_register_operand" "")
4079 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
4080 "TARGET_ARM && TARGET_HARD_FLOAT"
4081 ""
4082 )
4083 \f
4084 ;; Move insns (including loads and stores)
4085
4086 ;; XXX Just some ideas about movti.
4087 ;; I don't think these are a good idea on the arm, there just aren't enough
4088 ;; registers
4089 ;;(define_expand "loadti"
4090 ;; [(set (match_operand:TI 0 "s_register_operand" "")
4091 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4092 ;; "" "")
4093
4094 ;;(define_expand "storeti"
4095 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4096 ;; (match_operand:TI 1 "s_register_operand" ""))]
4097 ;; "" "")
4098
4099 ;;(define_expand "movti"
4100 ;; [(set (match_operand:TI 0 "general_operand" "")
4101 ;; (match_operand:TI 1 "general_operand" ""))]
4102 ;; ""
4103 ;; "
4104 ;;{
4105 ;; rtx insn;
4106 ;;
4107 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4108 ;; operands[1] = copy_to_reg (operands[1]);
4109 ;; if (GET_CODE (operands[0]) == MEM)
4110 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4111 ;; else if (GET_CODE (operands[1]) == MEM)
4112 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4113 ;; else
4114 ;; FAIL;
4115 ;;
4116 ;; emit_insn (insn);
4117 ;; DONE;
4118 ;;}")
4119
4120 ;; Recognize garbage generated above.
4121
4122 ;;(define_insn ""
4123 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4124 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4125 ;; ""
4126 ;; "*
4127 ;; {
4128 ;; register mem = (which_alternative < 3);
4129 ;; register const char *template;
4130 ;;
4131 ;; operands[mem] = XEXP (operands[mem], 0);
4132 ;; switch (which_alternative)
4133 ;; {
4134 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4135 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4136 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4137 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4138 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4139 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
4140 ;; }
4141 ;; output_asm_insn (template, operands);
4142 ;; return \"\";
4143 ;; }")
4144
4145 (define_expand "movdi"
4146 [(set (match_operand:DI 0 "general_operand" "")
4147 (match_operand:DI 1 "general_operand" ""))]
4148 "TARGET_EITHER"
4149 "
4150 if (TARGET_THUMB)
4151 {
4152 if (!no_new_pseudos)
4153 {
4154 if (GET_CODE (operands[0]) != REG)
4155 operands[1] = force_reg (DImode, operands[1]);
4156 }
4157 }
4158 "
4159 )
4160
4161 (define_insn "*arm_movdi"
4162 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r ,m")
4163 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
4164 "TARGET_ARM
4165 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4166 && !TARGET_IWMMXT"
4167 "*
4168 return (output_move_double (operands));
4169 "
4170 [(set_attr "length" "8")
4171 (set_attr "type" "*,load2,store2")
4172 (set_attr "pool_range" "*,1020,*")
4173 (set_attr "neg_pool_range" "*,1008,*")]
4174 )
4175
4176 ;; We can't actually do base+index doubleword loads if the index and
4177 ;; destination overlap. Split here so that we at least have chance to
4178 ;; schedule.
4179 (define_split
4180 [(set (match_operand:DI 0 "s_register_operand" "")
4181 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4182 (match_operand:SI 2 "s_register_operand" ""))))]
4183 "TARGET_LDRD
4184 && reg_overlap_mentioned_p (operands[0], operands[1])
4185 && reg_overlap_mentioned_p (operands[0], operands[2])"
4186 [(set (match_dup 4)
4187 (plus:SI (match_dup 1)
4188 (match_dup 2)))
4189 (set (match_dup 0)
4190 (mem:DI (match_dup 4)))]
4191 "
4192 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4193 "
4194 )
4195
4196 ;;; ??? This should have alternatives for constants.
4197 ;;; ??? This was originally identical to the movdf_insn pattern.
4198 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4199 ;;; thumb_reorg with a memory reference.
4200 (define_insn "*thumb_movdi_insn"
4201 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4202 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
4203 "TARGET_THUMB
4204 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4205 && ( register_operand (operands[0], DImode)
4206 || register_operand (operands[1], DImode))"
4207 "*
4208 {
4209 switch (which_alternative)
4210 {
4211 default:
4212 case 0:
4213 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4214 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4215 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4216 case 1:
4217 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4218 case 2:
4219 operands[1] = GEN_INT (- INTVAL (operands[1]));
4220 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4221 case 3:
4222 return \"ldmia\\t%1, {%0, %H0}\";
4223 case 4:
4224 return \"stmia\\t%0, {%1, %H1}\";
4225 case 5:
4226 return thumb_load_double_from_address (operands);
4227 case 6:
4228 operands[2] = gen_rtx_MEM (SImode,
4229 plus_constant (XEXP (operands[0], 0), 4));
4230 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4231 return \"\";
4232 case 7:
4233 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4234 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4235 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4236 }
4237 }"
4238 [(set_attr "length" "4,4,6,2,2,6,4,4")
4239 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4240 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4241 )
4242
4243 (define_expand "movsi"
4244 [(set (match_operand:SI 0 "general_operand" "")
4245 (match_operand:SI 1 "general_operand" ""))]
4246 "TARGET_EITHER"
4247 "
4248 if (TARGET_ARM)
4249 {
4250 /* Everything except mem = const or mem = mem can be done easily. */
4251 if (GET_CODE (operands[0]) == MEM)
4252 operands[1] = force_reg (SImode, operands[1]);
4253 if (arm_general_register_operand (operands[0], SImode)
4254 && GET_CODE (operands[1]) == CONST_INT
4255 && !(const_ok_for_arm (INTVAL (operands[1]))
4256 || const_ok_for_arm (~INTVAL (operands[1]))))
4257 {
4258 arm_split_constant (SET, SImode, NULL_RTX,
4259 INTVAL (operands[1]), operands[0], NULL_RTX,
4260 (no_new_pseudos ? 0
4261 : preserve_subexpressions_p ()));
4262 DONE;
4263 }
4264 }
4265 else /* TARGET_THUMB.... */
4266 {
4267 if (!no_new_pseudos)
4268 {
4269 if (GET_CODE (operands[0]) != REG)
4270 operands[1] = force_reg (SImode, operands[1]);
4271 }
4272 }
4273
4274 if (flag_pic
4275 && (CONSTANT_P (operands[1])
4276 || symbol_mentioned_p (operands[1])
4277 || label_mentioned_p (operands[1])))
4278 operands[1] = legitimize_pic_address (operands[1], SImode,
4279 (no_new_pseudos ? operands[0] : 0));
4280 "
4281 )
4282
4283 (define_insn "*arm_movsi_insn"
4284 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4285 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
4286 "TARGET_ARM && ! TARGET_IWMMXT
4287 && !(TARGET_HARD_FLOAT && TARGET_VFP)
4288 && ( register_operand (operands[0], SImode)
4289 || register_operand (operands[1], SImode))"
4290 "@
4291 mov%?\\t%0, %1
4292 mvn%?\\t%0, #%B1
4293 ldr%?\\t%0, %1
4294 str%?\\t%1, %0"
4295 [(set_attr "type" "*,*,load1,store1")
4296 (set_attr "predicable" "yes")
4297 (set_attr "pool_range" "*,*,4096,*")
4298 (set_attr "neg_pool_range" "*,*,4084,*")]
4299 )
4300
4301 (define_split
4302 [(set (match_operand:SI 0 "arm_general_register_operand" "")
4303 (match_operand:SI 1 "const_int_operand" ""))]
4304 "TARGET_ARM
4305 && (!(const_ok_for_arm (INTVAL (operands[1]))
4306 || const_ok_for_arm (~INTVAL (operands[1]))))"
4307 [(clobber (const_int 0))]
4308 "
4309 arm_split_constant (SET, SImode, NULL_RTX,
4310 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4311 DONE;
4312 "
4313 )
4314
4315 (define_insn "*thumb_movsi_insn"
4316 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4317 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
4318 "TARGET_THUMB
4319 && ( register_operand (operands[0], SImode)
4320 || register_operand (operands[1], SImode))"
4321 "@
4322 mov %0, %1
4323 mov %0, %1
4324 #
4325 #
4326 ldmia\\t%1, {%0}
4327 stmia\\t%0, {%1}
4328 ldr\\t%0, %1
4329 str\\t%1, %0
4330 mov\\t%0, %1"
4331 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4332 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4333 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4334 )
4335
4336 (define_split
4337 [(set (match_operand:SI 0 "register_operand" "")
4338 (match_operand:SI 1 "const_int_operand" ""))]
4339 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4340 [(set (match_dup 0) (match_dup 1))
4341 (set (match_dup 0) (neg:SI (match_dup 0)))]
4342 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4343 )
4344
4345 (define_split
4346 [(set (match_operand:SI 0 "register_operand" "")
4347 (match_operand:SI 1 "const_int_operand" ""))]
4348 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4349 [(set (match_dup 0) (match_dup 1))
4350 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4351 "
4352 {
4353 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4354 unsigned HOST_WIDE_INT mask = 0xff;
4355 int i;
4356
4357 for (i = 0; i < 25; i++)
4358 if ((val & (mask << i)) == val)
4359 break;
4360
4361 /* Shouldn't happen, but we don't want to split if the shift is zero. */
4362 if (i == 0)
4363 FAIL;
4364
4365 operands[1] = GEN_INT (val >> i);
4366 operands[2] = GEN_INT (i);
4367 }"
4368 )
4369
4370 ;; When generating pic, we need to load the symbol offset into a register.
4371 ;; So that the optimizer does not confuse this with a normal symbol load
4372 ;; we use an unspec. The offset will be loaded from a constant pool entry,
4373 ;; since that is the only type of relocation we can use.
4374
4375 ;; The rather odd constraints on the following are to force reload to leave
4376 ;; the insn alone, and to force the minipool generation pass to then move
4377 ;; the GOT symbol to memory.
4378
4379 (define_insn "pic_load_addr_arm"
4380 [(set (match_operand:SI 0 "s_register_operand" "=r")
4381 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4382 "TARGET_ARM && flag_pic"
4383 "ldr%?\\t%0, %1"
4384 [(set_attr "type" "load1")
4385 (set (attr "pool_range") (const_int 4096))
4386 (set (attr "neg_pool_range") (const_int 4084))]
4387 )
4388
4389 (define_insn "pic_load_addr_thumb"
4390 [(set (match_operand:SI 0 "s_register_operand" "=l")
4391 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4392 "TARGET_THUMB && flag_pic"
4393 "ldr\\t%0, %1"
4394 [(set_attr "type" "load1")
4395 (set (attr "pool_range") (const_int 1024))]
4396 )
4397
4398 ;; This variant is used for AOF assembly, since it needs to mention the
4399 ;; pic register in the rtl.
4400 (define_expand "pic_load_addr_based"
4401 [(set (match_operand:SI 0 "s_register_operand" "")
4402 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4403 "TARGET_ARM && flag_pic"
4404 "operands[2] = pic_offset_table_rtx;"
4405 )
4406
4407 (define_insn "*pic_load_addr_based_insn"
4408 [(set (match_operand:SI 0 "s_register_operand" "=r")
4409 (unspec:SI [(match_operand 1 "" "")
4410 (match_operand 2 "s_register_operand" "r")]
4411 UNSPEC_PIC_SYM))]
4412 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4413 "*
4414 #ifdef AOF_ASSEMBLER
4415 operands[1] = aof_pic_entry (operands[1]);
4416 #endif
4417 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4418 return \"\";
4419 "
4420 [(set_attr "type" "load1")
4421 (set (attr "pool_range")
4422 (if_then_else (eq_attr "is_thumb" "yes")
4423 (const_int 1024)
4424 (const_int 4096)))
4425 (set (attr "neg_pool_range")
4426 (if_then_else (eq_attr "is_thumb" "yes")
4427 (const_int 0)
4428 (const_int 4084)))]
4429 )
4430
4431 (define_insn "pic_add_dot_plus_four"
4432 [(set (match_operand:SI 0 "register_operand" "+r")
4433 (unspec:SI [(plus:SI (match_dup 0)
4434 (const (plus:SI (pc) (const_int 4))))]
4435 UNSPEC_PIC_BASE))
4436 (use (label_ref (match_operand 1 "" "")))]
4437 "TARGET_THUMB && flag_pic"
4438 "*
4439 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4440 CODE_LABEL_NUMBER (operands[1]));
4441 return \"add\\t%0, %|pc\";
4442 "
4443 [(set_attr "length" "2")]
4444 )
4445
4446 (define_insn "pic_add_dot_plus_eight"
4447 [(set (match_operand:SI 0 "register_operand" "+r")
4448 (unspec:SI [(plus:SI (match_dup 0)
4449 (const (plus:SI (pc) (const_int 8))))]
4450 UNSPEC_PIC_BASE))
4451 (use (label_ref (match_operand 1 "" "")))]
4452 "TARGET_ARM && flag_pic"
4453 "*
4454 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4455 CODE_LABEL_NUMBER (operands[1]));
4456 return \"add%?\\t%0, %|pc, %0\";
4457 "
4458 [(set_attr "predicable" "yes")]
4459 )
4460
4461 (define_expand "builtin_setjmp_receiver"
4462 [(label_ref (match_operand 0 "" ""))]
4463 "flag_pic"
4464 "
4465 {
4466 arm_finalize_pic (0);
4467 DONE;
4468 }")
4469
4470 ;; If copying one reg to another we can set the condition codes according to
4471 ;; its value. Such a move is common after a return from subroutine and the
4472 ;; result is being tested against zero.
4473
4474 (define_insn "*movsi_compare0"
4475 [(set (reg:CC CC_REGNUM)
4476 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4477 (const_int 0)))
4478 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4479 (match_dup 1))]
4480 "TARGET_ARM"
4481 "@
4482 cmp%?\\t%0, #0
4483 sub%?s\\t%0, %1, #0"
4484 [(set_attr "conds" "set")]
4485 )
4486
4487 ;; Subroutine to store a half word from a register into memory.
4488 ;; Operand 0 is the source register (HImode)
4489 ;; Operand 1 is the destination address in a register (SImode)
4490
4491 ;; In both this routine and the next, we must be careful not to spill
4492 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4493 ;; can generate unrecognizable rtl.
4494
4495 (define_expand "storehi"
4496 [;; store the low byte
4497 (set (match_operand 1 "" "") (match_dup 3))
4498 ;; extract the high byte
4499 (set (match_dup 2)
4500 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4501 ;; store the high byte
4502 (set (match_dup 4) (match_dup 5))]
4503 "TARGET_ARM"
4504 "
4505 {
4506 rtx op1 = operands[1];
4507 rtx addr = XEXP (op1, 0);
4508 enum rtx_code code = GET_CODE (addr);
4509
4510 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4511 || code == MINUS)
4512 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4513
4514 operands[4] = adjust_address (op1, QImode, 1);
4515 operands[1] = adjust_address (operands[1], QImode, 0);
4516 operands[3] = gen_lowpart (QImode, operands[0]);
4517 operands[0] = gen_lowpart (SImode, operands[0]);
4518 operands[2] = gen_reg_rtx (SImode);
4519 operands[5] = gen_lowpart (QImode, operands[2]);
4520 }"
4521 )
4522
4523 (define_expand "storehi_bigend"
4524 [(set (match_dup 4) (match_dup 3))
4525 (set (match_dup 2)
4526 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4527 (set (match_operand 1 "" "") (match_dup 5))]
4528 "TARGET_ARM"
4529 "
4530 {
4531 rtx op1 = operands[1];
4532 rtx addr = XEXP (op1, 0);
4533 enum rtx_code code = GET_CODE (addr);
4534
4535 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4536 || code == MINUS)
4537 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4538
4539 operands[4] = adjust_address (op1, QImode, 1);
4540 operands[1] = adjust_address (operands[1], QImode, 0);
4541 operands[3] = gen_lowpart (QImode, operands[0]);
4542 operands[0] = gen_lowpart (SImode, operands[0]);
4543 operands[2] = gen_reg_rtx (SImode);
4544 operands[5] = gen_lowpart (QImode, operands[2]);
4545 }"
4546 )
4547
4548 ;; Subroutine to store a half word integer constant into memory.
4549 (define_expand "storeinthi"
4550 [(set (match_operand 0 "" "")
4551 (match_operand 1 "" ""))
4552 (set (match_dup 3) (match_dup 2))]
4553 "TARGET_ARM"
4554 "
4555 {
4556 HOST_WIDE_INT value = INTVAL (operands[1]);
4557 rtx addr = XEXP (operands[0], 0);
4558 rtx op0 = operands[0];
4559 enum rtx_code code = GET_CODE (addr);
4560
4561 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4562 || code == MINUS)
4563 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4564
4565 operands[1] = gen_reg_rtx (SImode);
4566 if (BYTES_BIG_ENDIAN)
4567 {
4568 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4569 if ((value & 255) == ((value >> 8) & 255))
4570 operands[2] = operands[1];
4571 else
4572 {
4573 operands[2] = gen_reg_rtx (SImode);
4574 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4575 }
4576 }
4577 else
4578 {
4579 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4580 if ((value & 255) == ((value >> 8) & 255))
4581 operands[2] = operands[1];
4582 else
4583 {
4584 operands[2] = gen_reg_rtx (SImode);
4585 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4586 }
4587 }
4588
4589 operands[3] = adjust_address (op0, QImode, 1);
4590 operands[0] = adjust_address (operands[0], QImode, 0);
4591 operands[2] = gen_lowpart (QImode, operands[2]);
4592 operands[1] = gen_lowpart (QImode, operands[1]);
4593 }"
4594 )
4595
4596 (define_expand "storehi_single_op"
4597 [(set (match_operand:HI 0 "memory_operand" "")
4598 (match_operand:HI 1 "general_operand" ""))]
4599 "TARGET_ARM && arm_arch4"
4600 "
4601 if (!s_register_operand (operands[1], HImode))
4602 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4603 "
4604 )
4605
4606 (define_expand "movhi"
4607 [(set (match_operand:HI 0 "general_operand" "")
4608 (match_operand:HI 1 "general_operand" ""))]
4609 "TARGET_EITHER"
4610 "
4611 if (TARGET_ARM)
4612 {
4613 if (!no_new_pseudos)
4614 {
4615 if (GET_CODE (operands[0]) == MEM)
4616 {
4617 if (arm_arch4)
4618 {
4619 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4620 DONE;
4621 }
4622 if (GET_CODE (operands[1]) == CONST_INT)
4623 emit_insn (gen_storeinthi (operands[0], operands[1]));
4624 else
4625 {
4626 if (GET_CODE (operands[1]) == MEM)
4627 operands[1] = force_reg (HImode, operands[1]);
4628 if (BYTES_BIG_ENDIAN)
4629 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4630 else
4631 emit_insn (gen_storehi (operands[1], operands[0]));
4632 }
4633 DONE;
4634 }
4635 /* Sign extend a constant, and keep it in an SImode reg. */
4636 else if (GET_CODE (operands[1]) == CONST_INT)
4637 {
4638 rtx reg = gen_reg_rtx (SImode);
4639 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4640
4641 /* If the constant is already valid, leave it alone. */
4642 if (!const_ok_for_arm (val))
4643 {
4644 /* If setting all the top bits will make the constant
4645 loadable in a single instruction, then set them.
4646 Otherwise, sign extend the number. */
4647
4648 if (const_ok_for_arm (~(val | ~0xffff)))
4649 val |= ~0xffff;
4650 else if (val & 0x8000)
4651 val |= ~0xffff;
4652 }
4653
4654 emit_insn (gen_movsi (reg, GEN_INT (val)));
4655 operands[1] = gen_lowpart (HImode, reg);
4656 }
4657 else if (arm_arch4 && !no_new_pseudos && optimize > 0
4658 && GET_CODE (operands[1]) == MEM)
4659 {
4660 rtx reg = gen_reg_rtx (SImode);
4661
4662 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4663 operands[1] = gen_lowpart (HImode, reg);
4664 }
4665 else if (!arm_arch4)
4666 {
4667 if (GET_CODE (operands[1]) == MEM)
4668 {
4669 rtx base;
4670 rtx offset = const0_rtx;
4671 rtx reg = gen_reg_rtx (SImode);
4672
4673 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4674 || (GET_CODE (base) == PLUS
4675 && (GET_CODE (offset = XEXP (base, 1))
4676 == CONST_INT)
4677 && ((INTVAL(offset) & 1) != 1)
4678 && GET_CODE (base = XEXP (base, 0)) == REG))
4679 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4680 {
4681 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4682 rtx new;
4683
4684 new = gen_rtx_MEM (SImode,
4685 plus_constant (base, new_offset));
4686 MEM_COPY_ATTRIBUTES (new, operands[1]);
4687 emit_insn (gen_movsi (reg, new));
4688 if (((INTVAL (offset) & 2) != 0)
4689 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4690 {
4691 rtx reg2 = gen_reg_rtx (SImode);
4692
4693 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4694 reg = reg2;
4695 }
4696 }
4697 else
4698 emit_insn (gen_movhi_bytes (reg, operands[1]));
4699
4700 operands[1] = gen_lowpart (HImode, reg);
4701 }
4702 }
4703 }
4704 /* Handle loading a large integer during reload. */
4705 else if (GET_CODE (operands[1]) == CONST_INT
4706 && !const_ok_for_arm (INTVAL (operands[1]))
4707 && !const_ok_for_arm (~INTVAL (operands[1])))
4708 {
4709 /* Writing a constant to memory needs a scratch, which should
4710 be handled with SECONDARY_RELOADs. */
4711 if (GET_CODE (operands[0]) != REG)
4712 abort ();
4713
4714 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4715 emit_insn (gen_movsi (operands[0], operands[1]));
4716 DONE;
4717 }
4718 }
4719 else /* TARGET_THUMB */
4720 {
4721 if (!no_new_pseudos)
4722 {
4723 if (GET_CODE (operands[0]) != REG)
4724 operands[1] = force_reg (HImode, operands[1]);
4725
4726 /* ??? We shouldn't really get invalid addresses here, but this can
4727 happen if we are passed a SP (never OK for HImode/QImode) or
4728 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4729 HImode/QImode) relative address. */
4730 /* ??? This should perhaps be fixed elsewhere, for instance, in
4731 fixup_stack_1, by checking for other kinds of invalid addresses,
4732 e.g. a bare reference to a virtual register. This may confuse the
4733 alpha though, which must handle this case differently. */
4734 if (GET_CODE (operands[0]) == MEM
4735 && !memory_address_p (GET_MODE (operands[0]),
4736 XEXP (operands[0], 0)))
4737 operands[0]
4738 = replace_equiv_address (operands[0],
4739 copy_to_reg (XEXP (operands[0], 0)));
4740
4741 if (GET_CODE (operands[1]) == MEM
4742 && !memory_address_p (GET_MODE (operands[1]),
4743 XEXP (operands[1], 0)))
4744 operands[1]
4745 = replace_equiv_address (operands[1],
4746 copy_to_reg (XEXP (operands[1], 0)));
4747 }
4748 /* Handle loading a large integer during reload. */
4749 else if (GET_CODE (operands[1]) == CONST_INT
4750 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4751 {
4752 /* Writing a constant to memory needs a scratch, which should
4753 be handled with SECONDARY_RELOADs. */
4754 if (GET_CODE (operands[0]) != REG)
4755 abort ();
4756
4757 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4758 emit_insn (gen_movsi (operands[0], operands[1]));
4759 DONE;
4760 }
4761 }
4762 "
4763 )
4764
4765 (define_insn "*thumb_movhi_insn"
4766 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4767 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
4768 "TARGET_THUMB
4769 && ( register_operand (operands[0], HImode)
4770 || register_operand (operands[1], HImode))"
4771 "*
4772 switch (which_alternative)
4773 {
4774 case 0: return \"add %0, %1, #0\";
4775 case 2: return \"strh %1, %0\";
4776 case 3: return \"mov %0, %1\";
4777 case 4: return \"mov %0, %1\";
4778 case 5: return \"mov %0, %1\";
4779 default: abort ();
4780 case 1:
4781 /* The stack pointer can end up being taken as an index register.
4782 Catch this case here and deal with it. */
4783 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4784 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4785 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4786 {
4787 rtx ops[2];
4788 ops[0] = operands[0];
4789 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4790
4791 output_asm_insn (\"mov %0, %1\", ops);
4792
4793 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4794
4795 }
4796 return \"ldrh %0, %1\";
4797 }"
4798 [(set_attr "length" "2,4,2,2,2,2")
4799 (set_attr "type" "*,load1,store1,*,*,*")]
4800 )
4801
4802
4803 (define_expand "movhi_bytes"
4804 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4805 (set (match_dup 3)
4806 (zero_extend:SI (match_dup 6)))
4807 (set (match_operand:SI 0 "" "")
4808 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4809 "TARGET_ARM"
4810 "
4811 {
4812 rtx mem1, mem2;
4813 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4814
4815 mem1 = gen_rtx_MEM (QImode, addr);
4816 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4817 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4818 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4819 operands[0] = gen_lowpart (SImode, operands[0]);
4820 operands[1] = mem1;
4821 operands[2] = gen_reg_rtx (SImode);
4822 operands[3] = gen_reg_rtx (SImode);
4823 operands[6] = mem2;
4824
4825 if (BYTES_BIG_ENDIAN)
4826 {
4827 operands[4] = operands[2];
4828 operands[5] = operands[3];
4829 }
4830 else
4831 {
4832 operands[4] = operands[3];
4833 operands[5] = operands[2];
4834 }
4835 }"
4836 )
4837
4838 (define_expand "movhi_bigend"
4839 [(set (match_dup 2)
4840 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4841 (const_int 16)))
4842 (set (match_dup 3)
4843 (ashiftrt:SI (match_dup 2) (const_int 16)))
4844 (set (match_operand:HI 0 "s_register_operand" "")
4845 (match_dup 4))]
4846 "TARGET_ARM"
4847 "
4848 operands[2] = gen_reg_rtx (SImode);
4849 operands[3] = gen_reg_rtx (SImode);
4850 operands[4] = gen_lowpart (HImode, operands[3]);
4851 "
4852 )
4853
4854 ;; Pattern to recognize insn generated default case above
4855 (define_insn "*movhi_insn_arch4"
4856 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4857 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4858 "TARGET_ARM
4859 && arm_arch4
4860 && (GET_CODE (operands[1]) != CONST_INT
4861 || const_ok_for_arm (INTVAL (operands[1]))
4862 || const_ok_for_arm (~INTVAL (operands[1])))"
4863 "@
4864 mov%?\\t%0, %1\\t%@ movhi
4865 mvn%?\\t%0, #%B1\\t%@ movhi
4866 str%?h\\t%1, %0\\t%@ movhi
4867 ldr%?h\\t%0, %1\\t%@ movhi"
4868 [(set_attr "type" "*,*,store1,load1")
4869 (set_attr "predicable" "yes")
4870 (set_attr "pool_range" "*,*,*,256")
4871 (set_attr "neg_pool_range" "*,*,*,244")]
4872 )
4873
4874 (define_insn "*movhi_bytes"
4875 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4876 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4877 "TARGET_ARM"
4878 "@
4879 mov%?\\t%0, %1\\t%@ movhi
4880 mvn%?\\t%0, #%B1\\t%@ movhi"
4881 [(set_attr "predicable" "yes")]
4882 )
4883
4884 (define_insn "thumb_movhi_clobber"
4885 [(set (match_operand:HI 0 "memory_operand" "=m")
4886 (match_operand:HI 1 "register_operand" "l"))
4887 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4888 "TARGET_THUMB"
4889 "*
4890 abort ();"
4891 )
4892
4893 ;; We use a DImode scratch because we may occasionally need an additional
4894 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4895 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4896 (define_expand "reload_outhi"
4897 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4898 (match_operand:HI 1 "s_register_operand" "r")
4899 (match_operand:DI 2 "s_register_operand" "=&l")])]
4900 "TARGET_EITHER"
4901 "if (TARGET_ARM)
4902 arm_reload_out_hi (operands);
4903 else
4904 thumb_reload_out_hi (operands);
4905 DONE;
4906 "
4907 )
4908
4909 (define_expand "reload_inhi"
4910 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4911 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4912 (match_operand:DI 2 "s_register_operand" "=&r")])]
4913 "TARGET_EITHER"
4914 "
4915 if (TARGET_ARM)
4916 arm_reload_in_hi (operands);
4917 else
4918 thumb_reload_out_hi (operands);
4919 DONE;
4920 ")
4921
4922 (define_expand "movqi"
4923 [(set (match_operand:QI 0 "general_operand" "")
4924 (match_operand:QI 1 "general_operand" ""))]
4925 "TARGET_EITHER"
4926 "
4927 if (TARGET_ARM)
4928 {
4929 /* Everything except mem = const or mem = mem can be done easily */
4930
4931 if (!no_new_pseudos)
4932 {
4933 if (GET_CODE (operands[1]) == CONST_INT)
4934 {
4935 rtx reg = gen_reg_rtx (SImode);
4936
4937 emit_insn (gen_movsi (reg, operands[1]));
4938 operands[1] = gen_lowpart (QImode, reg);
4939 }
4940 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4941 {
4942 rtx reg = gen_reg_rtx (SImode);
4943
4944 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4945 operands[1] = gen_lowpart (QImode, reg);
4946 }
4947 if (GET_CODE (operands[0]) == MEM)
4948 operands[1] = force_reg (QImode, operands[1]);
4949 }
4950 }
4951 else /* TARGET_THUMB */
4952 {
4953 if (!no_new_pseudos)
4954 {
4955 if (GET_CODE (operands[0]) != REG)
4956 operands[1] = force_reg (QImode, operands[1]);
4957
4958 /* ??? We shouldn't really get invalid addresses here, but this can
4959 happen if we are passed a SP (never OK for HImode/QImode) or
4960 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4961 HImode/QImode) relative address. */
4962 /* ??? This should perhaps be fixed elsewhere, for instance, in
4963 fixup_stack_1, by checking for other kinds of invalid addresses,
4964 e.g. a bare reference to a virtual register. This may confuse the
4965 alpha though, which must handle this case differently. */
4966 if (GET_CODE (operands[0]) == MEM
4967 && !memory_address_p (GET_MODE (operands[0]),
4968 XEXP (operands[0], 0)))
4969 operands[0]
4970 = replace_equiv_address (operands[0],
4971 copy_to_reg (XEXP (operands[0], 0)));
4972 if (GET_CODE (operands[1]) == MEM
4973 && !memory_address_p (GET_MODE (operands[1]),
4974 XEXP (operands[1], 0)))
4975 operands[1]
4976 = replace_equiv_address (operands[1],
4977 copy_to_reg (XEXP (operands[1], 0)));
4978 }
4979 /* Handle loading a large integer during reload. */
4980 else if (GET_CODE (operands[1]) == CONST_INT
4981 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4982 {
4983 /* Writing a constant to memory needs a scratch, which should
4984 be handled with SECONDARY_RELOADs. */
4985 if (GET_CODE (operands[0]) != REG)
4986 abort ();
4987
4988 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4989 emit_insn (gen_movsi (operands[0], operands[1]));
4990 DONE;
4991 }
4992 }
4993 "
4994 )
4995
4996
4997 (define_insn "*arm_movqi_insn"
4998 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4999 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5000 "TARGET_ARM
5001 && ( register_operand (operands[0], QImode)
5002 || register_operand (operands[1], QImode))"
5003 "@
5004 mov%?\\t%0, %1
5005 mvn%?\\t%0, #%B1
5006 ldr%?b\\t%0, %1
5007 str%?b\\t%1, %0"
5008 [(set_attr "type" "*,*,load1,store1")
5009 (set_attr "predicable" "yes")]
5010 )
5011
5012 (define_insn "*thumb_movqi_insn"
5013 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5014 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
5015 "TARGET_THUMB
5016 && ( register_operand (operands[0], QImode)
5017 || register_operand (operands[1], QImode))"
5018 "@
5019 add\\t%0, %1, #0
5020 ldrb\\t%0, %1
5021 strb\\t%1, %0
5022 mov\\t%0, %1
5023 mov\\t%0, %1
5024 mov\\t%0, %1"
5025 [(set_attr "length" "2")
5026 (set_attr "type" "*,load1,store1,*,*,*")
5027 (set_attr "pool_range" "*,32,*,*,*,*")]
5028 )
5029
5030 (define_expand "movsf"
5031 [(set (match_operand:SF 0 "general_operand" "")
5032 (match_operand:SF 1 "general_operand" ""))]
5033 "TARGET_EITHER"
5034 "
5035 if (TARGET_ARM)
5036 {
5037 if (GET_CODE (operands[0]) == MEM)
5038 operands[1] = force_reg (SFmode, operands[1]);
5039 }
5040 else /* TARGET_THUMB */
5041 {
5042 if (!no_new_pseudos)
5043 {
5044 if (GET_CODE (operands[0]) != REG)
5045 operands[1] = force_reg (SFmode, operands[1]);
5046 }
5047 }
5048 "
5049 )
5050
5051 (define_split
5052 [(set (match_operand:SF 0 "nonimmediate_operand" "")
5053 (match_operand:SF 1 "immediate_operand" ""))]
5054 "TARGET_ARM
5055 && !(TARGET_HARD_FLOAT && TARGET_FPA)
5056 && reload_completed
5057 && GET_CODE (operands[1]) == CONST_DOUBLE"
5058 [(set (match_dup 2) (match_dup 3))]
5059 "
5060 operands[2] = gen_lowpart (SImode, operands[0]);
5061 operands[3] = gen_lowpart (SImode, operands[1]);
5062 if (operands[2] == 0 || operands[3] == 0)
5063 FAIL;
5064 "
5065 )
5066
5067 (define_insn "*arm_movsf_soft_insn"
5068 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5069 (match_operand:SF 1 "general_operand" "r,mE,r"))]
5070 "TARGET_ARM
5071 && TARGET_SOFT_FLOAT
5072 && (GET_CODE (operands[0]) != MEM
5073 || register_operand (operands[1], SFmode))"
5074 "@
5075 mov%?\\t%0, %1
5076 ldr%?\\t%0, %1\\t%@ float
5077 str%?\\t%1, %0\\t%@ float"
5078 [(set_attr "length" "4,4,4")
5079 (set_attr "predicable" "yes")
5080 (set_attr "type" "*,load1,store1")
5081 (set_attr "pool_range" "*,4096,*")
5082 (set_attr "neg_pool_range" "*,4084,*")]
5083 )
5084
5085 ;;; ??? This should have alternatives for constants.
5086 (define_insn "*thumb_movsf_insn"
5087 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5088 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
5089 "TARGET_THUMB
5090 && ( register_operand (operands[0], SFmode)
5091 || register_operand (operands[1], SFmode))"
5092 "@
5093 add\\t%0, %1, #0
5094 ldmia\\t%1, {%0}
5095 stmia\\t%0, {%1}
5096 ldr\\t%0, %1
5097 str\\t%1, %0
5098 mov\\t%0, %1
5099 mov\\t%0, %1"
5100 [(set_attr "length" "2")
5101 (set_attr "type" "*,load1,store1,load1,store1,*,*")
5102 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5103 )
5104
5105 (define_expand "movdf"
5106 [(set (match_operand:DF 0 "general_operand" "")
5107 (match_operand:DF 1 "general_operand" ""))]
5108 "TARGET_EITHER"
5109 "
5110 if (TARGET_ARM)
5111 {
5112 if (GET_CODE (operands[0]) == MEM)
5113 operands[1] = force_reg (DFmode, operands[1]);
5114 }
5115 else /* TARGET_THUMB */
5116 {
5117 if (!no_new_pseudos)
5118 {
5119 if (GET_CODE (operands[0]) != REG)
5120 operands[1] = force_reg (DFmode, operands[1]);
5121 }
5122 }
5123 "
5124 )
5125
5126 ;; Reloading a df mode value stored in integer regs to memory can require a
5127 ;; scratch reg.
5128 (define_expand "reload_outdf"
5129 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5130 (match_operand:DF 1 "s_register_operand" "r")
5131 (match_operand:SI 2 "s_register_operand" "=&r")]
5132 "TARGET_ARM"
5133 "
5134 {
5135 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5136
5137 if (code == REG)
5138 operands[2] = XEXP (operands[0], 0);
5139 else if (code == POST_INC || code == PRE_DEC)
5140 {
5141 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5142 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5143 emit_insn (gen_movdi (operands[0], operands[1]));
5144 DONE;
5145 }
5146 else if (code == PRE_INC)
5147 {
5148 rtx reg = XEXP (XEXP (operands[0], 0), 0);
5149
5150 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5151 operands[2] = reg;
5152 }
5153 else if (code == POST_DEC)
5154 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5155 else
5156 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5157 XEXP (XEXP (operands[0], 0), 1)));
5158
5159 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5160 operands[1]));
5161
5162 if (code == POST_DEC)
5163 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5164
5165 DONE;
5166 }"
5167 )
5168
5169 (define_insn "*movdf_soft_insn"
5170 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5171 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5172 "TARGET_ARM && TARGET_SOFT_FLOAT
5173 "
5174 "* return output_move_double (operands);"
5175 [(set_attr "length" "8,8,8")
5176 (set_attr "type" "*,load2,store2")
5177 (set_attr "pool_range" "1020")
5178 (set_attr "neg_pool_range" "1008")]
5179 )
5180
5181 ;;; ??? This should have alternatives for constants.
5182 ;;; ??? This was originally identical to the movdi_insn pattern.
5183 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5184 ;;; thumb_reorg with a memory reference.
5185 (define_insn "*thumb_movdf_insn"
5186 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5187 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
5188 "TARGET_THUMB
5189 && ( register_operand (operands[0], DFmode)
5190 || register_operand (operands[1], DFmode))"
5191 "*
5192 switch (which_alternative)
5193 {
5194 default:
5195 case 0:
5196 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5197 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5198 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5199 case 1:
5200 return \"ldmia\\t%1, {%0, %H0}\";
5201 case 2:
5202 return \"stmia\\t%0, {%1, %H1}\";
5203 case 3:
5204 return thumb_load_double_from_address (operands);
5205 case 4:
5206 operands[2] = gen_rtx_MEM (SImode,
5207 plus_constant (XEXP (operands[0], 0), 4));
5208 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5209 return \"\";
5210 case 5:
5211 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5212 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5213 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5214 }
5215 "
5216 [(set_attr "length" "4,2,2,6,4,4")
5217 (set_attr "type" "*,load2,store2,load2,store2,*")
5218 (set_attr "pool_range" "*,*,*,1020,*,*")]
5219 )
5220
5221 ;; Vector Moves
5222 (define_expand "movv2si"
5223 [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5224 (match_operand:V2SI 1 "general_operand" ""))]
5225 "TARGET_REALLY_IWMMXT"
5226 {
5227 })
5228
5229 (define_expand "movv4hi"
5230 [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5231 (match_operand:V4HI 1 "general_operand" ""))]
5232 "TARGET_REALLY_IWMMXT"
5233 {
5234 })
5235
5236 (define_expand "movv8qi"
5237 [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5238 (match_operand:V8QI 1 "general_operand" ""))]
5239 "TARGET_REALLY_IWMMXT"
5240 {
5241 })
5242 \f
5243
5244 ;; load- and store-multiple insns
5245 ;; The arm can load/store any set of registers, provided that they are in
5246 ;; ascending order; but that is beyond GCC so stick with what it knows.
5247
5248 (define_expand "load_multiple"
5249 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5250 (match_operand:SI 1 "" ""))
5251 (use (match_operand:SI 2 "" ""))])]
5252 "TARGET_ARM"
5253 "
5254 /* Support only fixed point registers. */
5255 if (GET_CODE (operands[2]) != CONST_INT
5256 || INTVAL (operands[2]) > 14
5257 || INTVAL (operands[2]) < 2
5258 || GET_CODE (operands[1]) != MEM
5259 || GET_CODE (operands[0]) != REG
5260 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5261 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5262 FAIL;
5263
5264 operands[3]
5265 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5266 force_reg (SImode, XEXP (operands[1], 0)),
5267 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5268 MEM_IN_STRUCT_P(operands[1]),
5269 MEM_SCALAR_P (operands[1]));
5270 "
5271 )
5272
5273 ;; Load multiple with write-back
5274
5275 (define_insn "*ldmsi_postinc4"
5276 [(match_parallel 0 "load_multiple_operation"
5277 [(set (match_operand:SI 1 "s_register_operand" "=r")
5278 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5279 (const_int 16)))
5280 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5281 (mem:SI (match_dup 2)))
5282 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5283 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5284 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5285 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5286 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5287 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5288 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5289 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5290 [(set_attr "type" "load4")
5291 (set_attr "predicable" "yes")]
5292 )
5293
5294 (define_insn "*ldmsi_postinc3"
5295 [(match_parallel 0 "load_multiple_operation"
5296 [(set (match_operand:SI 1 "s_register_operand" "=r")
5297 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5298 (const_int 12)))
5299 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5300 (mem:SI (match_dup 2)))
5301 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5302 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5303 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5304 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5305 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5306 "ldm%?ia\\t%1!, {%3, %4, %5}"
5307 [(set_attr "type" "load3")
5308 (set_attr "predicable" "yes")]
5309 )
5310
5311 (define_insn "*ldmsi_postinc2"
5312 [(match_parallel 0 "load_multiple_operation"
5313 [(set (match_operand:SI 1 "s_register_operand" "=r")
5314 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5315 (const_int 8)))
5316 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5317 (mem:SI (match_dup 2)))
5318 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5319 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5320 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5321 "ldm%?ia\\t%1!, {%3, %4}"
5322 [(set_attr "type" "load2")
5323 (set_attr "predicable" "yes")]
5324 )
5325
5326 ;; Ordinary load multiple
5327
5328 (define_insn "*ldmsi4"
5329 [(match_parallel 0 "load_multiple_operation"
5330 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5331 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5332 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5333 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5334 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5335 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5336 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5337 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5338 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5339 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5340 [(set_attr "type" "load4")
5341 (set_attr "predicable" "yes")]
5342 )
5343
5344 (define_insn "*ldmsi3"
5345 [(match_parallel 0 "load_multiple_operation"
5346 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5347 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5348 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5349 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5350 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5351 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5352 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5353 "ldm%?ia\\t%1, {%2, %3, %4}"
5354 [(set_attr "type" "load3")
5355 (set_attr "predicable" "yes")]
5356 )
5357
5358 (define_insn "*ldmsi2"
5359 [(match_parallel 0 "load_multiple_operation"
5360 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5361 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5362 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5363 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5364 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5365 "ldm%?ia\\t%1, {%2, %3}"
5366 [(set_attr "type" "load2")
5367 (set_attr "predicable" "yes")]
5368 )
5369
5370 (define_expand "store_multiple"
5371 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5372 (match_operand:SI 1 "" ""))
5373 (use (match_operand:SI 2 "" ""))])]
5374 "TARGET_ARM"
5375 "
5376 /* Support only fixed point registers. */
5377 if (GET_CODE (operands[2]) != CONST_INT
5378 || INTVAL (operands[2]) > 14
5379 || INTVAL (operands[2]) < 2
5380 || GET_CODE (operands[1]) != REG
5381 || GET_CODE (operands[0]) != MEM
5382 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5383 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5384 FAIL;
5385
5386 operands[3]
5387 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5388 force_reg (SImode, XEXP (operands[0], 0)),
5389 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5390 MEM_IN_STRUCT_P(operands[0]),
5391 MEM_SCALAR_P (operands[0]));
5392 "
5393 )
5394
5395 ;; Store multiple with write-back
5396
5397 (define_insn "*stmsi_postinc4"
5398 [(match_parallel 0 "store_multiple_operation"
5399 [(set (match_operand:SI 1 "s_register_operand" "=r")
5400 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5401 (const_int 16)))
5402 (set (mem:SI (match_dup 2))
5403 (match_operand:SI 3 "arm_hard_register_operand" ""))
5404 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5405 (match_operand:SI 4 "arm_hard_register_operand" ""))
5406 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5407 (match_operand:SI 5 "arm_hard_register_operand" ""))
5408 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5409 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5410 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5411 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5412 [(set_attr "predicable" "yes")
5413 (set_attr "type" "store4")]
5414 )
5415
5416 (define_insn "*stmsi_postinc3"
5417 [(match_parallel 0 "store_multiple_operation"
5418 [(set (match_operand:SI 1 "s_register_operand" "=r")
5419 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5420 (const_int 12)))
5421 (set (mem:SI (match_dup 2))
5422 (match_operand:SI 3 "arm_hard_register_operand" ""))
5423 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5424 (match_operand:SI 4 "arm_hard_register_operand" ""))
5425 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5426 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5427 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5428 "stm%?ia\\t%1!, {%3, %4, %5}"
5429 [(set_attr "predicable" "yes")
5430 (set_attr "type" "store3")]
5431 )
5432
5433 (define_insn "*stmsi_postinc2"
5434 [(match_parallel 0 "store_multiple_operation"
5435 [(set (match_operand:SI 1 "s_register_operand" "=r")
5436 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5437 (const_int 8)))
5438 (set (mem:SI (match_dup 2))
5439 (match_operand:SI 3 "arm_hard_register_operand" ""))
5440 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5441 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5442 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5443 "stm%?ia\\t%1!, {%3, %4}"
5444 [(set_attr "predicable" "yes")
5445 (set_attr "type" "store2")]
5446 )
5447
5448 ;; Ordinary store multiple
5449
5450 (define_insn "*stmsi4"
5451 [(match_parallel 0 "store_multiple_operation"
5452 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5453 (match_operand:SI 2 "arm_hard_register_operand" ""))
5454 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5455 (match_operand:SI 3 "arm_hard_register_operand" ""))
5456 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5457 (match_operand:SI 4 "arm_hard_register_operand" ""))
5458 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5459 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5460 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5461 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5462 [(set_attr "predicable" "yes")
5463 (set_attr "type" "store4")]
5464 )
5465
5466 (define_insn "*stmsi3"
5467 [(match_parallel 0 "store_multiple_operation"
5468 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5469 (match_operand:SI 2 "arm_hard_register_operand" ""))
5470 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5471 (match_operand:SI 3 "arm_hard_register_operand" ""))
5472 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5473 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5474 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5475 "stm%?ia\\t%1, {%2, %3, %4}"
5476 [(set_attr "predicable" "yes")
5477 (set_attr "type" "store3")]
5478 )
5479
5480 (define_insn "*stmsi2"
5481 [(match_parallel 0 "store_multiple_operation"
5482 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5483 (match_operand:SI 2 "arm_hard_register_operand" ""))
5484 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5485 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5486 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5487 "stm%?ia\\t%1, {%2, %3}"
5488 [(set_attr "predicable" "yes")
5489 (set_attr "type" "store2")]
5490 )
5491
5492 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5493 ;; We could let this apply for blocks of less than this, but it clobbers so
5494 ;; many registers that there is then probably a better way.
5495
5496 (define_expand "movmemqi"
5497 [(match_operand:BLK 0 "general_operand" "")
5498 (match_operand:BLK 1 "general_operand" "")
5499 (match_operand:SI 2 "const_int_operand" "")
5500 (match_operand:SI 3 "const_int_operand" "")]
5501 "TARGET_EITHER"
5502 "
5503 if (TARGET_ARM)
5504 {
5505 if (arm_gen_movmemqi (operands))
5506 DONE;
5507 FAIL;
5508 }
5509 else /* TARGET_THUMB */
5510 {
5511 if ( INTVAL (operands[3]) != 4
5512 || INTVAL (operands[2]) > 48)
5513 FAIL;
5514
5515 thumb_expand_movmemqi (operands);
5516 DONE;
5517 }
5518 "
5519 )
5520
5521 ;; Thumb block-move insns
5522
5523 (define_insn "movmem12b"
5524 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5525 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5526 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5527 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5528 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5529 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5530 (set (match_operand:SI 0 "register_operand" "=l")
5531 (plus:SI (match_dup 2) (const_int 12)))
5532 (set (match_operand:SI 1 "register_operand" "=l")
5533 (plus:SI (match_dup 3) (const_int 12)))
5534 (clobber (match_scratch:SI 4 "=&l"))
5535 (clobber (match_scratch:SI 5 "=&l"))
5536 (clobber (match_scratch:SI 6 "=&l"))]
5537 "TARGET_THUMB"
5538 "* return thumb_output_move_mem_multiple (3, operands);"
5539 [(set_attr "length" "4")
5540 ; This isn't entirely accurate... It loads as well, but in terms of
5541 ; scheduling the following insn it is better to consider it as a store
5542 (set_attr "type" "store3")]
5543 )
5544
5545 (define_insn "movmem8b"
5546 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5547 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5548 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5549 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5550 (set (match_operand:SI 0 "register_operand" "=l")
5551 (plus:SI (match_dup 2) (const_int 8)))
5552 (set (match_operand:SI 1 "register_operand" "=l")
5553 (plus:SI (match_dup 3) (const_int 8)))
5554 (clobber (match_scratch:SI 4 "=&l"))
5555 (clobber (match_scratch:SI 5 "=&l"))]
5556 "TARGET_THUMB"
5557 "* return thumb_output_move_mem_multiple (2, operands);"
5558 [(set_attr "length" "4")
5559 ; This isn't entirely accurate... It loads as well, but in terms of
5560 ; scheduling the following insn it is better to consider it as a store
5561 (set_attr "type" "store2")]
5562 )
5563
5564 \f
5565
5566 ;; Compare & branch insns
5567 ;; The range calculations are based as follows:
5568 ;; For forward branches, the address calculation returns the address of
5569 ;; the next instruction. This is 2 beyond the branch instruction.
5570 ;; For backward branches, the address calculation returns the address of
5571 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5572 ;; instruction for the shortest sequence, and 4 before the branch instruction
5573 ;; if we have to jump around an unconditional branch.
5574 ;; To the basic branch range the PC offset must be added (this is +4).
5575 ;; So for forward branches we have
5576 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5577 ;; And for backward branches we have
5578 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5579 ;;
5580 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5581 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5582
5583 (define_expand "cbranchsi4"
5584 [(set (pc) (if_then_else
5585 (match_operator 0 "arm_comparison_operator"
5586 [(match_operand:SI 1 "s_register_operand" "")
5587 (match_operand:SI 2 "nonmemory_operand" "")])
5588 (label_ref (match_operand 3 "" ""))
5589 (pc)))]
5590 "TARGET_THUMB"
5591 "
5592 if (thumb_cmpneg_operand (operands[2], SImode))
5593 {
5594 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5595 operands[3], operands[0]));
5596 DONE;
5597 }
5598 if (!thumb_cmp_operand (operands[2], SImode))
5599 operands[2] = force_reg (SImode, operands[2]);
5600 ")
5601
5602 (define_insn "*cbranchsi4_insn"
5603 [(set (pc) (if_then_else
5604 (match_operator 0 "arm_comparison_operator"
5605 [(match_operand:SI 1 "s_register_operand" "l,*h")
5606 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5607 (label_ref (match_operand 3 "" ""))
5608 (pc)))]
5609 "TARGET_THUMB"
5610 "*
5611 output_asm_insn (\"cmp\\t%1, %2\", operands);
5612
5613 switch (get_attr_length (insn))
5614 {
5615 case 4: return \"b%d0\\t%l3\";
5616 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5617 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5618 }
5619 "
5620 [(set (attr "far_jump")
5621 (if_then_else
5622 (eq_attr "length" "8")
5623 (const_string "yes")
5624 (const_string "no")))
5625 (set (attr "length")
5626 (if_then_else
5627 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5628 (le (minus (match_dup 3) (pc)) (const_int 256)))
5629 (const_int 4)
5630 (if_then_else
5631 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5632 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5633 (const_int 6)
5634 (const_int 8))))]
5635 )
5636
5637 (define_insn "cbranchsi4_scratch"
5638 [(set (pc) (if_then_else
5639 (match_operator 4 "arm_comparison_operator"
5640 [(match_operand:SI 1 "s_register_operand" "l,0")
5641 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5642 (label_ref (match_operand 3 "" ""))
5643 (pc)))
5644 (clobber (match_scratch:SI 0 "=l,l"))]
5645 "TARGET_THUMB"
5646 "*
5647 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5648
5649 switch (get_attr_length (insn))
5650 {
5651 case 4: return \"b%d4\\t%l3\";
5652 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5653 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5654 }
5655 "
5656 [(set (attr "far_jump")
5657 (if_then_else
5658 (eq_attr "length" "8")
5659 (const_string "yes")
5660 (const_string "no")))
5661 (set (attr "length")
5662 (if_then_else
5663 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5664 (le (minus (match_dup 3) (pc)) (const_int 256)))
5665 (const_int 4)
5666 (if_then_else
5667 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5668 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5669 (const_int 6)
5670 (const_int 8))))]
5671 )
5672 (define_insn "*movsi_cbranchsi4"
5673 [(set (pc)
5674 (if_then_else
5675 (match_operator 3 "arm_comparison_operator"
5676 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5677 (const_int 0)])
5678 (label_ref (match_operand 2 "" ""))
5679 (pc)))
5680 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5681 (match_dup 1))]
5682 "TARGET_THUMB"
5683 "*{
5684 if (which_alternative == 0)
5685 output_asm_insn (\"cmp\t%0, #0\", operands);
5686 else if (which_alternative == 1)
5687 output_asm_insn (\"sub\t%0, %1, #0\", operands);
5688 else
5689 {
5690 output_asm_insn (\"cmp\t%1, #0\", operands);
5691 if (which_alternative == 2)
5692 output_asm_insn (\"mov\t%0, %1\", operands);
5693 else
5694 output_asm_insn (\"str\t%1, %0\", operands);
5695 }
5696 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5697 {
5698 case 4: return \"b%d3\\t%l2\";
5699 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5700 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5701 }
5702 }"
5703 [(set (attr "far_jump")
5704 (if_then_else
5705 (ior (and (gt (symbol_ref ("which_alternative"))
5706 (const_int 1))
5707 (eq_attr "length" "8"))
5708 (eq_attr "length" "10"))
5709 (const_string "yes")
5710 (const_string "no")))
5711 (set (attr "length")
5712 (if_then_else
5713 (le (symbol_ref ("which_alternative"))
5714 (const_int 1))
5715 (if_then_else
5716 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5717 (le (minus (match_dup 2) (pc)) (const_int 256)))
5718 (const_int 4)
5719 (if_then_else
5720 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5721 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5722 (const_int 6)
5723 (const_int 8)))
5724 (if_then_else
5725 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5726 (le (minus (match_dup 2) (pc)) (const_int 256)))
5727 (const_int 6)
5728 (if_then_else
5729 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5730 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5731 (const_int 8)
5732 (const_int 10)))))]
5733 )
5734
5735 (define_insn "*negated_cbranchsi4"
5736 [(set (pc)
5737 (if_then_else
5738 (match_operator 0 "arm_comparison_operator"
5739 [(match_operand:SI 1 "s_register_operand" "l")
5740 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5741 (label_ref (match_operand 3 "" ""))
5742 (pc)))]
5743 "TARGET_THUMB"
5744 "*
5745 output_asm_insn (\"cmn\\t%1, %2\", operands);
5746 switch (get_attr_length (insn))
5747 {
5748 case 4: return \"b%d0\\t%l3\";
5749 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5750 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5751 }
5752 "
5753 [(set (attr "far_jump")
5754 (if_then_else
5755 (eq_attr "length" "8")
5756 (const_string "yes")
5757 (const_string "no")))
5758 (set (attr "length")
5759 (if_then_else
5760 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5761 (le (minus (match_dup 3) (pc)) (const_int 256)))
5762 (const_int 4)
5763 (if_then_else
5764 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5765 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5766 (const_int 6)
5767 (const_int 8))))]
5768 )
5769
5770 (define_insn "*tbit_cbranch"
5771 [(set (pc)
5772 (if_then_else
5773 (match_operator 0 "equality_operator"
5774 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5775 (const_int 1)
5776 (match_operand:SI 2 "const_int_operand" "i"))
5777 (const_int 0)])
5778 (label_ref (match_operand 3 "" ""))
5779 (pc)))
5780 (clobber (match_scratch:SI 4 "=l"))]
5781 "TARGET_THUMB"
5782 "*
5783 {
5784 rtx op[3];
5785 op[0] = operands[4];
5786 op[1] = operands[1];
5787 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5788
5789 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5790 switch (get_attr_length (insn))
5791 {
5792 case 4: return \"b%d0\\t%l3\";
5793 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5794 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5795 }
5796 }"
5797 [(set (attr "far_jump")
5798 (if_then_else
5799 (eq_attr "length" "8")
5800 (const_string "yes")
5801 (const_string "no")))
5802 (set (attr "length")
5803 (if_then_else
5804 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5805 (le (minus (match_dup 3) (pc)) (const_int 256)))
5806 (const_int 4)
5807 (if_then_else
5808 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5809 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5810 (const_int 6)
5811 (const_int 8))))]
5812 )
5813
5814 (define_insn "*tstsi3_cbranch"
5815 [(set (pc)
5816 (if_then_else
5817 (match_operator 3 "equality_operator"
5818 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5819 (match_operand:SI 1 "s_register_operand" "l"))
5820 (const_int 0)])
5821 (label_ref (match_operand 2 "" ""))
5822 (pc)))]
5823 "TARGET_THUMB"
5824 "*
5825 {
5826 output_asm_insn (\"tst\\t%0, %1\", operands);
5827 switch (get_attr_length (insn))
5828 {
5829 case 4: return \"b%d3\\t%l2\";
5830 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5831 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5832 }
5833 }"
5834 [(set (attr "far_jump")
5835 (if_then_else
5836 (eq_attr "length" "8")
5837 (const_string "yes")
5838 (const_string "no")))
5839 (set (attr "length")
5840 (if_then_else
5841 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5842 (le (minus (match_dup 2) (pc)) (const_int 256)))
5843 (const_int 4)
5844 (if_then_else
5845 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5846 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5847 (const_int 6)
5848 (const_int 8))))]
5849 )
5850
5851 (define_insn "*andsi3_cbranch"
5852 [(set (pc)
5853 (if_then_else
5854 (match_operator 5 "equality_operator"
5855 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5856 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5857 (const_int 0)])
5858 (label_ref (match_operand 4 "" ""))
5859 (pc)))
5860 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5861 (and:SI (match_dup 2) (match_dup 3)))
5862 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5863 "TARGET_THUMB"
5864 "*
5865 {
5866 if (which_alternative == 0)
5867 output_asm_insn (\"and\\t%0, %3\", operands);
5868 else if (which_alternative == 1)
5869 {
5870 output_asm_insn (\"and\\t%1, %3\", operands);
5871 output_asm_insn (\"mov\\t%0, %1\", operands);
5872 }
5873 else
5874 {
5875 output_asm_insn (\"and\\t%1, %3\", operands);
5876 output_asm_insn (\"str\\t%1, %0\", operands);
5877 }
5878
5879 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5880 {
5881 case 4: return \"b%d5\\t%l4\";
5882 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5883 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5884 }
5885 }"
5886 [(set (attr "far_jump")
5887 (if_then_else
5888 (ior (and (eq (symbol_ref ("which_alternative"))
5889 (const_int 0))
5890 (eq_attr "length" "8"))
5891 (eq_attr "length" "10"))
5892 (const_string "yes")
5893 (const_string "no")))
5894 (set (attr "length")
5895 (if_then_else
5896 (eq (symbol_ref ("which_alternative"))
5897 (const_int 0))
5898 (if_then_else
5899 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5900 (le (minus (match_dup 4) (pc)) (const_int 256)))
5901 (const_int 4)
5902 (if_then_else
5903 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5904 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5905 (const_int 6)
5906 (const_int 8)))
5907 (if_then_else
5908 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5909 (le (minus (match_dup 4) (pc)) (const_int 256)))
5910 (const_int 6)
5911 (if_then_else
5912 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5913 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5914 (const_int 8)
5915 (const_int 10)))))]
5916 )
5917
5918 (define_insn "*orrsi3_cbranch_scratch"
5919 [(set (pc)
5920 (if_then_else
5921 (match_operator 4 "equality_operator"
5922 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
5923 (match_operand:SI 2 "s_register_operand" "l"))
5924 (const_int 0)])
5925 (label_ref (match_operand 3 "" ""))
5926 (pc)))
5927 (clobber (match_scratch:SI 0 "=l"))]
5928 "TARGET_THUMB"
5929 "*
5930 {
5931 output_asm_insn (\"orr\\t%0, %2\", operands);
5932 switch (get_attr_length (insn))
5933 {
5934 case 4: return \"b%d4\\t%l3\";
5935 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5936 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5937 }
5938 }"
5939 [(set (attr "far_jump")
5940 (if_then_else
5941 (eq_attr "length" "8")
5942 (const_string "yes")
5943 (const_string "no")))
5944 (set (attr "length")
5945 (if_then_else
5946 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5947 (le (minus (match_dup 3) (pc)) (const_int 256)))
5948 (const_int 4)
5949 (if_then_else
5950 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5951 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5952 (const_int 6)
5953 (const_int 8))))]
5954 )
5955
5956 (define_insn "*orrsi3_cbranch"
5957 [(set (pc)
5958 (if_then_else
5959 (match_operator 5 "equality_operator"
5960 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5961 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5962 (const_int 0)])
5963 (label_ref (match_operand 4 "" ""))
5964 (pc)))
5965 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5966 (ior:SI (match_dup 2) (match_dup 3)))
5967 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5968 "TARGET_THUMB"
5969 "*
5970 {
5971 if (which_alternative == 0)
5972 output_asm_insn (\"orr\\t%0, %3\", operands);
5973 else if (which_alternative == 1)
5974 {
5975 output_asm_insn (\"orr\\t%1, %3\", operands);
5976 output_asm_insn (\"mov\\t%0, %1\", operands);
5977 }
5978 else
5979 {
5980 output_asm_insn (\"orr\\t%1, %3\", operands);
5981 output_asm_insn (\"str\\t%1, %0\", operands);
5982 }
5983
5984 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5985 {
5986 case 4: return \"b%d5\\t%l4\";
5987 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5988 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5989 }
5990 }"
5991 [(set (attr "far_jump")
5992 (if_then_else
5993 (ior (and (eq (symbol_ref ("which_alternative"))
5994 (const_int 0))
5995 (eq_attr "length" "8"))
5996 (eq_attr "length" "10"))
5997 (const_string "yes")
5998 (const_string "no")))
5999 (set (attr "length")
6000 (if_then_else
6001 (eq (symbol_ref ("which_alternative"))
6002 (const_int 0))
6003 (if_then_else
6004 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6005 (le (minus (match_dup 4) (pc)) (const_int 256)))
6006 (const_int 4)
6007 (if_then_else
6008 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6009 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6010 (const_int 6)
6011 (const_int 8)))
6012 (if_then_else
6013 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6014 (le (minus (match_dup 4) (pc)) (const_int 256)))
6015 (const_int 6)
6016 (if_then_else
6017 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6018 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6019 (const_int 8)
6020 (const_int 10)))))]
6021 )
6022
6023 (define_insn "*xorsi3_cbranch_scratch"
6024 [(set (pc)
6025 (if_then_else
6026 (match_operator 4 "equality_operator"
6027 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6028 (match_operand:SI 2 "s_register_operand" "l"))
6029 (const_int 0)])
6030 (label_ref (match_operand 3 "" ""))
6031 (pc)))
6032 (clobber (match_scratch:SI 0 "=l"))]
6033 "TARGET_THUMB"
6034 "*
6035 {
6036 output_asm_insn (\"eor\\t%0, %2\", operands);
6037 switch (get_attr_length (insn))
6038 {
6039 case 4: return \"b%d4\\t%l3\";
6040 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6041 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6042 }
6043 }"
6044 [(set (attr "far_jump")
6045 (if_then_else
6046 (eq_attr "length" "8")
6047 (const_string "yes")
6048 (const_string "no")))
6049 (set (attr "length")
6050 (if_then_else
6051 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6052 (le (minus (match_dup 3) (pc)) (const_int 256)))
6053 (const_int 4)
6054 (if_then_else
6055 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6056 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6057 (const_int 6)
6058 (const_int 8))))]
6059 )
6060
6061 (define_insn "*xorsi3_cbranch"
6062 [(set (pc)
6063 (if_then_else
6064 (match_operator 5 "equality_operator"
6065 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6066 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6067 (const_int 0)])
6068 (label_ref (match_operand 4 "" ""))
6069 (pc)))
6070 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6071 (xor:SI (match_dup 2) (match_dup 3)))
6072 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6073 "TARGET_THUMB"
6074 "*
6075 {
6076 if (which_alternative == 0)
6077 output_asm_insn (\"eor\\t%0, %3\", operands);
6078 else if (which_alternative == 1)
6079 {
6080 output_asm_insn (\"eor\\t%1, %3\", operands);
6081 output_asm_insn (\"mov\\t%0, %1\", operands);
6082 }
6083 else
6084 {
6085 output_asm_insn (\"eor\\t%1, %3\", operands);
6086 output_asm_insn (\"str\\t%1, %0\", operands);
6087 }
6088
6089 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6090 {
6091 case 4: return \"b%d5\\t%l4\";
6092 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6093 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6094 }
6095 }"
6096 [(set (attr "far_jump")
6097 (if_then_else
6098 (ior (and (eq (symbol_ref ("which_alternative"))
6099 (const_int 0))
6100 (eq_attr "length" "8"))
6101 (eq_attr "length" "10"))
6102 (const_string "yes")
6103 (const_string "no")))
6104 (set (attr "length")
6105 (if_then_else
6106 (eq (symbol_ref ("which_alternative"))
6107 (const_int 0))
6108 (if_then_else
6109 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6110 (le (minus (match_dup 4) (pc)) (const_int 256)))
6111 (const_int 4)
6112 (if_then_else
6113 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6114 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6115 (const_int 6)
6116 (const_int 8)))
6117 (if_then_else
6118 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6119 (le (minus (match_dup 4) (pc)) (const_int 256)))
6120 (const_int 6)
6121 (if_then_else
6122 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6123 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6124 (const_int 8)
6125 (const_int 10)))))]
6126 )
6127
6128 (define_insn "*bicsi3_cbranch_scratch"
6129 [(set (pc)
6130 (if_then_else
6131 (match_operator 4 "equality_operator"
6132 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6133 (match_operand:SI 1 "s_register_operand" "0"))
6134 (const_int 0)])
6135 (label_ref (match_operand 3 "" ""))
6136 (pc)))
6137 (clobber (match_scratch:SI 0 "=l"))]
6138 "TARGET_THUMB"
6139 "*
6140 {
6141 output_asm_insn (\"bic\\t%0, %2\", operands);
6142 switch (get_attr_length (insn))
6143 {
6144 case 4: return \"b%d4\\t%l3\";
6145 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6146 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6147 }
6148 }"
6149 [(set (attr "far_jump")
6150 (if_then_else
6151 (eq_attr "length" "8")
6152 (const_string "yes")
6153 (const_string "no")))
6154 (set (attr "length")
6155 (if_then_else
6156 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6157 (le (minus (match_dup 3) (pc)) (const_int 256)))
6158 (const_int 4)
6159 (if_then_else
6160 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6161 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6162 (const_int 6)
6163 (const_int 8))))]
6164 )
6165
6166 (define_insn "*bicsi3_cbranch"
6167 [(set (pc)
6168 (if_then_else
6169 (match_operator 5 "equality_operator"
6170 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6171 (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6172 (const_int 0)])
6173 (label_ref (match_operand 4 "" ""))
6174 (pc)))
6175 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6176 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6177 (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6178 "TARGET_THUMB"
6179 "*
6180 {
6181 if (which_alternative == 0)
6182 output_asm_insn (\"bic\\t%0, %3\", operands);
6183 else if (which_alternative <= 2)
6184 {
6185 output_asm_insn (\"bic\\t%1, %3\", operands);
6186 /* It's ok if OP0 is a lo-reg, even though the mov will set the
6187 conditions again, since we're only testing for equality. */
6188 output_asm_insn (\"mov\\t%0, %1\", operands);
6189 }
6190 else
6191 {
6192 output_asm_insn (\"bic\\t%1, %3\", operands);
6193 output_asm_insn (\"str\\t%1, %0\", operands);
6194 }
6195
6196 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6197 {
6198 case 4: return \"b%d5\\t%l4\";
6199 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6200 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6201 }
6202 }"
6203 [(set (attr "far_jump")
6204 (if_then_else
6205 (ior (and (eq (symbol_ref ("which_alternative"))
6206 (const_int 0))
6207 (eq_attr "length" "8"))
6208 (eq_attr "length" "10"))
6209 (const_string "yes")
6210 (const_string "no")))
6211 (set (attr "length")
6212 (if_then_else
6213 (eq (symbol_ref ("which_alternative"))
6214 (const_int 0))
6215 (if_then_else
6216 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6217 (le (minus (match_dup 4) (pc)) (const_int 256)))
6218 (const_int 4)
6219 (if_then_else
6220 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6221 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6222 (const_int 6)
6223 (const_int 8)))
6224 (if_then_else
6225 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6226 (le (minus (match_dup 4) (pc)) (const_int 256)))
6227 (const_int 6)
6228 (if_then_else
6229 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6230 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6231 (const_int 8)
6232 (const_int 10)))))]
6233 )
6234
6235 (define_insn "*cbranchne_decr1"
6236 [(set (pc)
6237 (if_then_else (match_operator 3 "equality_operator"
6238 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6239 (const_int 0)])
6240 (label_ref (match_operand 4 "" ""))
6241 (pc)))
6242 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6243 (plus:SI (match_dup 2) (const_int -1)))
6244 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6245 "TARGET_THUMB"
6246 "*
6247 {
6248 rtx cond[2];
6249 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6250 ? GEU : LTU),
6251 VOIDmode, operands[2], const1_rtx);
6252 cond[1] = operands[4];
6253
6254 if (which_alternative == 0)
6255 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6256 else if (which_alternative == 1)
6257 {
6258 /* We must provide an alternative for a hi reg because reload
6259 cannot handle output reloads on a jump instruction, but we
6260 can't subtract into that. Fortunately a mov from lo to hi
6261 does not clobber the condition codes. */
6262 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6263 output_asm_insn (\"mov\\t%0, %1\", operands);
6264 }
6265 else
6266 {
6267 /* Similarly, but the target is memory. */
6268 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6269 output_asm_insn (\"str\\t%1, %0\", operands);
6270 }
6271
6272 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6273 {
6274 case 4:
6275 output_asm_insn (\"b%d0\\t%l1\", cond);
6276 return \"\";
6277 case 6:
6278 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6279 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6280 default:
6281 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6282 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6283 }
6284 }
6285 "
6286 [(set (attr "far_jump")
6287 (if_then_else
6288 (ior (and (eq (symbol_ref ("which_alternative"))
6289 (const_int 0))
6290 (eq_attr "length" "8"))
6291 (eq_attr "length" "10"))
6292 (const_string "yes")
6293 (const_string "no")))
6294 (set_attr_alternative "length"
6295 [
6296 ;; Alternative 0
6297 (if_then_else
6298 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6299 (le (minus (match_dup 4) (pc)) (const_int 256)))
6300 (const_int 4)
6301 (if_then_else
6302 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6303 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6304 (const_int 6)
6305 (const_int 8)))
6306 ;; Alternative 1
6307 (if_then_else
6308 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6309 (le (minus (match_dup 4) (pc)) (const_int 256)))
6310 (const_int 6)
6311 (if_then_else
6312 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6313 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6314 (const_int 8)
6315 (const_int 10)))
6316 ;; Alternative 2
6317 (if_then_else
6318 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6319 (le (minus (match_dup 4) (pc)) (const_int 256)))
6320 (const_int 6)
6321 (if_then_else
6322 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6323 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6324 (const_int 8)
6325 (const_int 10)))
6326 ;; Alternative 3
6327 (if_then_else
6328 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6329 (le (minus (match_dup 4) (pc)) (const_int 256)))
6330 (const_int 6)
6331 (if_then_else
6332 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6333 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6334 (const_int 8)
6335 (const_int 10)))])]
6336 )
6337
6338 (define_insn "*addsi3_cbranch"
6339 [(set (pc)
6340 (if_then_else
6341 (match_operator 4 "comparison_operator"
6342 [(plus:SI
6343 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6344 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6345 (const_int 0)])
6346 (label_ref (match_operand 5 "" ""))
6347 (pc)))
6348 (set
6349 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6350 (plus:SI (match_dup 2) (match_dup 3)))
6351 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6352 "TARGET_THUMB
6353 && (GET_CODE (operands[4]) == EQ
6354 || GET_CODE (operands[4]) == NE
6355 || GET_CODE (operands[4]) == GE
6356 || GET_CODE (operands[4]) == LT)"
6357 "*
6358 {
6359 rtx cond[3];
6360
6361
6362 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6363 cond[1] = operands[2];
6364 cond[2] = operands[3];
6365
6366 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6367 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6368 else
6369 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6370
6371 if (which_alternative >= 3
6372 && which_alternative < 4)
6373 output_asm_insn (\"mov\\t%0, %1\", operands);
6374 else if (which_alternative >= 4)
6375 output_asm_insn (\"str\\t%1, %0\", operands);
6376
6377 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6378 {
6379 case 4:
6380 return \"b%d4\\t%l5\";
6381 case 6:
6382 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6383 default:
6384 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6385 }
6386 }
6387 "
6388 [(set (attr "far_jump")
6389 (if_then_else
6390 (ior (and (lt (symbol_ref ("which_alternative"))
6391 (const_int 3))
6392 (eq_attr "length" "8"))
6393 (eq_attr "length" "10"))
6394 (const_string "yes")
6395 (const_string "no")))
6396 (set (attr "length")
6397 (if_then_else
6398 (lt (symbol_ref ("which_alternative"))
6399 (const_int 3))
6400 (if_then_else
6401 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6402 (le (minus (match_dup 5) (pc)) (const_int 256)))
6403 (const_int 4)
6404 (if_then_else
6405 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6406 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6407 (const_int 6)
6408 (const_int 8)))
6409 (if_then_else
6410 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6411 (le (minus (match_dup 5) (pc)) (const_int 256)))
6412 (const_int 6)
6413 (if_then_else
6414 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6415 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6416 (const_int 8)
6417 (const_int 10)))))]
6418 )
6419
6420 (define_insn "*addsi3_cbranch_scratch"
6421 [(set (pc)
6422 (if_then_else
6423 (match_operator 3 "comparison_operator"
6424 [(plus:SI
6425 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6426 (match_operand:SI 2 "reg_or_int_operand" "J,l,I,L"))
6427 (const_int 0)])
6428 (label_ref (match_operand 4 "" ""))
6429 (pc)))
6430 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6431 "TARGET_THUMB
6432 && (GET_CODE (operands[3]) == EQ
6433 || GET_CODE (operands[3]) == NE
6434 || GET_CODE (operands[3]) == GE
6435 || GET_CODE (operands[3]) == LT)"
6436 "*
6437 {
6438 switch (which_alternative)
6439 {
6440 case 0:
6441 output_asm_insn (\"cmp\t%1, #%n2\", operands);
6442 break;
6443 case 1:
6444 output_asm_insn (\"cmn\t%1, %2\", operands);
6445 break;
6446 case 3:
6447 output_asm_insn (\"add\t%0, %1, %2\", operands);
6448 break;
6449 case 4:
6450 output_asm_insn (\"add\t%0, %0, %2\", operands);
6451 break;
6452 }
6453
6454 switch (get_attr_length (insn))
6455 {
6456 case 4:
6457 return \"b%d3\\t%l4\";
6458 case 6:
6459 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6460 default:
6461 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6462 }
6463 }
6464 "
6465 [(set (attr "far_jump")
6466 (if_then_else
6467 (eq_attr "length" "8")
6468 (const_string "yes")
6469 (const_string "no")))
6470 (set (attr "length")
6471 (if_then_else
6472 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6473 (le (minus (match_dup 4) (pc)) (const_int 256)))
6474 (const_int 4)
6475 (if_then_else
6476 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6477 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6478 (const_int 6)
6479 (const_int 8))))]
6480 )
6481
6482 (define_insn "*subsi3_cbranch"
6483 [(set (pc)
6484 (if_then_else
6485 (match_operator 4 "comparison_operator"
6486 [(minus:SI
6487 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6488 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6489 (const_int 0)])
6490 (label_ref (match_operand 5 "" ""))
6491 (pc)))
6492 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6493 (minus:SI (match_dup 2) (match_dup 3)))
6494 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6495 "TARGET_THUMB
6496 && (GET_CODE (operands[4]) == EQ
6497 || GET_CODE (operands[4]) == NE
6498 || GET_CODE (operands[4]) == GE
6499 || GET_CODE (operands[4]) == LT)"
6500 "*
6501 {
6502 if (which_alternative == 0)
6503 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6504 else if (which_alternative == 1)
6505 {
6506 /* We must provide an alternative for a hi reg because reload
6507 cannot handle output reloads on a jump instruction, but we
6508 can't subtract into that. Fortunately a mov from lo to hi
6509 does not clobber the condition codes. */
6510 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6511 output_asm_insn (\"mov\\t%0, %1\", operands);
6512 }
6513 else
6514 {
6515 /* Similarly, but the target is memory. */
6516 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6517 output_asm_insn (\"str\\t%1, %0\", operands);
6518 }
6519
6520 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6521 {
6522 case 4:
6523 return \"b%d4\\t%l5\";
6524 case 6:
6525 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6526 default:
6527 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6528 }
6529 }
6530 "
6531 [(set (attr "far_jump")
6532 (if_then_else
6533 (ior (and (eq (symbol_ref ("which_alternative"))
6534 (const_int 0))
6535 (eq_attr "length" "8"))
6536 (eq_attr "length" "10"))
6537 (const_string "yes")
6538 (const_string "no")))
6539 (set (attr "length")
6540 (if_then_else
6541 (eq (symbol_ref ("which_alternative"))
6542 (const_int 0))
6543 (if_then_else
6544 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6545 (le (minus (match_dup 5) (pc)) (const_int 256)))
6546 (const_int 4)
6547 (if_then_else
6548 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6549 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6550 (const_int 6)
6551 (const_int 8)))
6552 (if_then_else
6553 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6554 (le (minus (match_dup 5) (pc)) (const_int 256)))
6555 (const_int 6)
6556 (if_then_else
6557 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6558 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6559 (const_int 8)
6560 (const_int 10)))))]
6561 )
6562
6563 (define_insn "*subsi3_cbranch_scratch"
6564 [(set (pc)
6565 (if_then_else
6566 (match_operator 0 "arm_comparison_operator"
6567 [(minus:SI (match_operand:SI 1 "register_operand" "l")
6568 (match_operand:SI 2 "nonmemory_operand" "l"))
6569 (const_int 0)])
6570 (label_ref (match_operand 3 "" ""))
6571 (pc)))]
6572 "TARGET_THUMB
6573 && (GET_CODE (operands[0]) == EQ
6574 || GET_CODE (operands[0]) == NE
6575 || GET_CODE (operands[0]) == GE
6576 || GET_CODE (operands[0]) == LT)"
6577 "*
6578 output_asm_insn (\"cmp\\t%1, %2\", operands);
6579 switch (get_attr_length (insn))
6580 {
6581 case 4: return \"b%d0\\t%l3\";
6582 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6583 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6584 }
6585 "
6586 [(set (attr "far_jump")
6587 (if_then_else
6588 (eq_attr "length" "8")
6589 (const_string "yes")
6590 (const_string "no")))
6591 (set (attr "length")
6592 (if_then_else
6593 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6594 (le (minus (match_dup 3) (pc)) (const_int 256)))
6595 (const_int 4)
6596 (if_then_else
6597 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6598 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6599 (const_int 6)
6600 (const_int 8))))]
6601 )
6602
6603 ;; Comparison and test insns
6604
6605 (define_expand "cmpsi"
6606 [(match_operand:SI 0 "s_register_operand" "")
6607 (match_operand:SI 1 "arm_add_operand" "")]
6608 "TARGET_ARM"
6609 "{
6610 arm_compare_op0 = operands[0];
6611 arm_compare_op1 = operands[1];
6612 DONE;
6613 }"
6614 )
6615
6616 (define_expand "cmpsf"
6617 [(match_operand:SF 0 "s_register_operand" "")
6618 (match_operand:SF 1 "arm_float_compare_operand" "")]
6619 "TARGET_ARM && TARGET_HARD_FLOAT"
6620 "
6621 arm_compare_op0 = operands[0];
6622 arm_compare_op1 = operands[1];
6623 DONE;
6624 "
6625 )
6626
6627 (define_expand "cmpdf"
6628 [(match_operand:DF 0 "s_register_operand" "")
6629 (match_operand:DF 1 "arm_float_compare_operand" "")]
6630 "TARGET_ARM && TARGET_HARD_FLOAT"
6631 "
6632 arm_compare_op0 = operands[0];
6633 arm_compare_op1 = operands[1];
6634 DONE;
6635 "
6636 )
6637
6638 (define_insn "*arm_cmpsi_insn"
6639 [(set (reg:CC CC_REGNUM)
6640 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6641 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
6642 "TARGET_ARM"
6643 "@
6644 cmp%?\\t%0, %1
6645 cmn%?\\t%0, #%n1"
6646 [(set_attr "conds" "set")]
6647 )
6648
6649 (define_insn "*cmpsi_shiftsi"
6650 [(set (reg:CC CC_REGNUM)
6651 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6652 (match_operator:SI 3 "shift_operator"
6653 [(match_operand:SI 1 "s_register_operand" "r")
6654 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
6655 "TARGET_ARM"
6656 "cmp%?\\t%0, %1%S3"
6657 [(set_attr "conds" "set")
6658 (set_attr "shift" "1")
6659 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6660 (const_string "alu_shift")
6661 (const_string "alu_shift_reg")))]
6662 )
6663
6664 (define_insn "*cmpsi_shiftsi_swp"
6665 [(set (reg:CC_SWP CC_REGNUM)
6666 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6667 [(match_operand:SI 1 "s_register_operand" "r")
6668 (match_operand:SI 2 "reg_or_int_operand" "rM")])
6669 (match_operand:SI 0 "s_register_operand" "r")))]
6670 "TARGET_ARM"
6671 "cmp%?\\t%0, %1%S3"
6672 [(set_attr "conds" "set")
6673 (set_attr "shift" "1")
6674 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6675 (const_string "alu_shift")
6676 (const_string "alu_shift_reg")))]
6677 )
6678
6679 (define_insn "*cmpsi_neg_shiftsi"
6680 [(set (reg:CC CC_REGNUM)
6681 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6682 (neg:SI (match_operator:SI 3 "shift_operator"
6683 [(match_operand:SI 1 "s_register_operand" "r")
6684 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
6685 "TARGET_ARM"
6686 "cmn%?\\t%0, %1%S3"
6687 [(set_attr "conds" "set")
6688 (set_attr "shift" "1")
6689 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6690 (const_string "alu_shift")
6691 (const_string "alu_shift_reg")))]
6692 )
6693
6694 ;; Cirrus SF compare instruction
6695 (define_insn "*cirrus_cmpsf"
6696 [(set (reg:CCFP CC_REGNUM)
6697 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6698 (match_operand:SF 1 "cirrus_fp_register" "v")))]
6699 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6700 "cfcmps%?\\tr15, %V0, %V1"
6701 [(set_attr "type" "mav_farith")
6702 (set_attr "cirrus" "compare")]
6703 )
6704
6705 ;; Cirrus DF compare instruction
6706 (define_insn "*cirrus_cmpdf"
6707 [(set (reg:CCFP CC_REGNUM)
6708 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6709 (match_operand:DF 1 "cirrus_fp_register" "v")))]
6710 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6711 "cfcmpd%?\\tr15, %V0, %V1"
6712 [(set_attr "type" "mav_farith")
6713 (set_attr "cirrus" "compare")]
6714 )
6715
6716 ;; Cirrus DI compare instruction
6717 (define_expand "cmpdi"
6718 [(match_operand:DI 0 "cirrus_fp_register" "")
6719 (match_operand:DI 1 "cirrus_fp_register" "")]
6720 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6721 "{
6722 arm_compare_op0 = operands[0];
6723 arm_compare_op1 = operands[1];
6724 DONE;
6725 }")
6726
6727 (define_insn "*cirrus_cmpdi"
6728 [(set (reg:CC CC_REGNUM)
6729 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6730 (match_operand:DI 1 "cirrus_fp_register" "v")))]
6731 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6732 "cfcmp64%?\\tr15, %V0, %V1"
6733 [(set_attr "type" "mav_farith")
6734 (set_attr "cirrus" "compare")]
6735 )
6736
6737 ; This insn allows redundant compares to be removed by cse, nothing should
6738 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6739 ; is deleted later on. The match_dup will match the mode here, so that
6740 ; mode changes of the condition codes aren't lost by this even though we don't
6741 ; specify what they are.
6742
6743 (define_insn "*deleted_compare"
6744 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6745 "TARGET_ARM"
6746 "\\t%@ deleted compare"
6747 [(set_attr "conds" "set")
6748 (set_attr "length" "0")]
6749 )
6750
6751 \f
6752 ;; Conditional branch insns
6753
6754 (define_expand "beq"
6755 [(set (pc)
6756 (if_then_else (eq (match_dup 1) (const_int 0))
6757 (label_ref (match_operand 0 "" ""))
6758 (pc)))]
6759 "TARGET_ARM"
6760 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6761 )
6762
6763 (define_expand "bne"
6764 [(set (pc)
6765 (if_then_else (ne (match_dup 1) (const_int 0))
6766 (label_ref (match_operand 0 "" ""))
6767 (pc)))]
6768 "TARGET_ARM"
6769 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6770 )
6771
6772 (define_expand "bgt"
6773 [(set (pc)
6774 (if_then_else (gt (match_dup 1) (const_int 0))
6775 (label_ref (match_operand 0 "" ""))
6776 (pc)))]
6777 "TARGET_ARM"
6778 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6779 )
6780
6781 (define_expand "ble"
6782 [(set (pc)
6783 (if_then_else (le (match_dup 1) (const_int 0))
6784 (label_ref (match_operand 0 "" ""))
6785 (pc)))]
6786 "TARGET_ARM"
6787 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6788 )
6789
6790 (define_expand "bge"
6791 [(set (pc)
6792 (if_then_else (ge (match_dup 1) (const_int 0))
6793 (label_ref (match_operand 0 "" ""))
6794 (pc)))]
6795 "TARGET_ARM"
6796 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6797 )
6798
6799 (define_expand "blt"
6800 [(set (pc)
6801 (if_then_else (lt (match_dup 1) (const_int 0))
6802 (label_ref (match_operand 0 "" ""))
6803 (pc)))]
6804 "TARGET_ARM"
6805 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6806 )
6807
6808 (define_expand "bgtu"
6809 [(set (pc)
6810 (if_then_else (gtu (match_dup 1) (const_int 0))
6811 (label_ref (match_operand 0 "" ""))
6812 (pc)))]
6813 "TARGET_ARM"
6814 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6815 )
6816
6817 (define_expand "bleu"
6818 [(set (pc)
6819 (if_then_else (leu (match_dup 1) (const_int 0))
6820 (label_ref (match_operand 0 "" ""))
6821 (pc)))]
6822 "TARGET_ARM"
6823 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6824 )
6825
6826 (define_expand "bgeu"
6827 [(set (pc)
6828 (if_then_else (geu (match_dup 1) (const_int 0))
6829 (label_ref (match_operand 0 "" ""))
6830 (pc)))]
6831 "TARGET_ARM"
6832 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6833 )
6834
6835 (define_expand "bltu"
6836 [(set (pc)
6837 (if_then_else (ltu (match_dup 1) (const_int 0))
6838 (label_ref (match_operand 0 "" ""))
6839 (pc)))]
6840 "TARGET_ARM"
6841 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6842 )
6843
6844 (define_expand "bunordered"
6845 [(set (pc)
6846 (if_then_else (unordered (match_dup 1) (const_int 0))
6847 (label_ref (match_operand 0 "" ""))
6848 (pc)))]
6849 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6850 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6851 arm_compare_op1);"
6852 )
6853
6854 (define_expand "bordered"
6855 [(set (pc)
6856 (if_then_else (ordered (match_dup 1) (const_int 0))
6857 (label_ref (match_operand 0 "" ""))
6858 (pc)))]
6859 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6860 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6861 arm_compare_op1);"
6862 )
6863
6864 (define_expand "bungt"
6865 [(set (pc)
6866 (if_then_else (ungt (match_dup 1) (const_int 0))
6867 (label_ref (match_operand 0 "" ""))
6868 (pc)))]
6869 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6870 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6871 )
6872
6873 (define_expand "bunlt"
6874 [(set (pc)
6875 (if_then_else (unlt (match_dup 1) (const_int 0))
6876 (label_ref (match_operand 0 "" ""))
6877 (pc)))]
6878 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6879 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6880 )
6881
6882 (define_expand "bunge"
6883 [(set (pc)
6884 (if_then_else (unge (match_dup 1) (const_int 0))
6885 (label_ref (match_operand 0 "" ""))
6886 (pc)))]
6887 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6888 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6889 )
6890
6891 (define_expand "bunle"
6892 [(set (pc)
6893 (if_then_else (unle (match_dup 1) (const_int 0))
6894 (label_ref (match_operand 0 "" ""))
6895 (pc)))]
6896 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6897 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6898 )
6899
6900 ;; The following two patterns need two branch instructions, since there is
6901 ;; no single instruction that will handle all cases.
6902 (define_expand "buneq"
6903 [(set (pc)
6904 (if_then_else (uneq (match_dup 1) (const_int 0))
6905 (label_ref (match_operand 0 "" ""))
6906 (pc)))]
6907 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6908 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6909 )
6910
6911 (define_expand "bltgt"
6912 [(set (pc)
6913 (if_then_else (ltgt (match_dup 1) (const_int 0))
6914 (label_ref (match_operand 0 "" ""))
6915 (pc)))]
6916 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6917 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6918 )
6919
6920 ;;
6921 ;; Patterns to match conditional branch insns.
6922 ;;
6923
6924 ; Special pattern to match UNEQ.
6925 (define_insn "*arm_buneq"
6926 [(set (pc)
6927 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6928 (label_ref (match_operand 0 "" ""))
6929 (pc)))]
6930 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6931 "*
6932 if (arm_ccfsm_state != 0)
6933 abort ();
6934
6935 return \"bvs\\t%l0\;beq\\t%l0\";
6936 "
6937 [(set_attr "conds" "jump_clob")
6938 (set_attr "length" "8")]
6939 )
6940
6941 ; Special pattern to match LTGT.
6942 (define_insn "*arm_bltgt"
6943 [(set (pc)
6944 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6945 (label_ref (match_operand 0 "" ""))
6946 (pc)))]
6947 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6948 "*
6949 if (arm_ccfsm_state != 0)
6950 abort ();
6951
6952 return \"bmi\\t%l0\;bgt\\t%l0\";
6953 "
6954 [(set_attr "conds" "jump_clob")
6955 (set_attr "length" "8")]
6956 )
6957
6958 (define_insn "*arm_cond_branch"
6959 [(set (pc)
6960 (if_then_else (match_operator 1 "arm_comparison_operator"
6961 [(match_operand 2 "cc_register" "") (const_int 0)])
6962 (label_ref (match_operand 0 "" ""))
6963 (pc)))]
6964 "TARGET_ARM"
6965 "*
6966 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6967 {
6968 arm_ccfsm_state += 2;
6969 return \"\";
6970 }
6971 return \"b%d1\\t%l0\";
6972 "
6973 [(set_attr "conds" "use")
6974 (set_attr "type" "branch")]
6975 )
6976
6977 ; Special pattern to match reversed UNEQ.
6978 (define_insn "*arm_buneq_reversed"
6979 [(set (pc)
6980 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6981 (pc)
6982 (label_ref (match_operand 0 "" ""))))]
6983 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6984 "*
6985 if (arm_ccfsm_state != 0)
6986 abort ();
6987
6988 return \"bmi\\t%l0\;bgt\\t%l0\";
6989 "
6990 [(set_attr "conds" "jump_clob")
6991 (set_attr "length" "8")]
6992 )
6993
6994 ; Special pattern to match reversed LTGT.
6995 (define_insn "*arm_bltgt_reversed"
6996 [(set (pc)
6997 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6998 (pc)
6999 (label_ref (match_operand 0 "" ""))))]
7000 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7001 "*
7002 if (arm_ccfsm_state != 0)
7003 abort ();
7004
7005 return \"bvs\\t%l0\;beq\\t%l0\";
7006 "
7007 [(set_attr "conds" "jump_clob")
7008 (set_attr "length" "8")]
7009 )
7010
7011 (define_insn "*arm_cond_branch_reversed"
7012 [(set (pc)
7013 (if_then_else (match_operator 1 "arm_comparison_operator"
7014 [(match_operand 2 "cc_register" "") (const_int 0)])
7015 (pc)
7016 (label_ref (match_operand 0 "" ""))))]
7017 "TARGET_ARM"
7018 "*
7019 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7020 {
7021 arm_ccfsm_state += 2;
7022 return \"\";
7023 }
7024 return \"b%D1\\t%l0\";
7025 "
7026 [(set_attr "conds" "use")
7027 (set_attr "type" "branch")]
7028 )
7029
7030 \f
7031
7032 ; scc insns
7033
7034 (define_expand "seq"
7035 [(set (match_operand:SI 0 "s_register_operand" "")
7036 (eq:SI (match_dup 1) (const_int 0)))]
7037 "TARGET_ARM"
7038 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7039 )
7040
7041 (define_expand "sne"
7042 [(set (match_operand:SI 0 "s_register_operand" "")
7043 (ne:SI (match_dup 1) (const_int 0)))]
7044 "TARGET_ARM"
7045 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7046 )
7047
7048 (define_expand "sgt"
7049 [(set (match_operand:SI 0 "s_register_operand" "")
7050 (gt:SI (match_dup 1) (const_int 0)))]
7051 "TARGET_ARM"
7052 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7053 )
7054
7055 (define_expand "sle"
7056 [(set (match_operand:SI 0 "s_register_operand" "")
7057 (le:SI (match_dup 1) (const_int 0)))]
7058 "TARGET_ARM"
7059 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7060 )
7061
7062 (define_expand "sge"
7063 [(set (match_operand:SI 0 "s_register_operand" "")
7064 (ge:SI (match_dup 1) (const_int 0)))]
7065 "TARGET_ARM"
7066 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7067 )
7068
7069 (define_expand "slt"
7070 [(set (match_operand:SI 0 "s_register_operand" "")
7071 (lt:SI (match_dup 1) (const_int 0)))]
7072 "TARGET_ARM"
7073 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7074 )
7075
7076 (define_expand "sgtu"
7077 [(set (match_operand:SI 0 "s_register_operand" "")
7078 (gtu:SI (match_dup 1) (const_int 0)))]
7079 "TARGET_ARM"
7080 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7081 )
7082
7083 (define_expand "sleu"
7084 [(set (match_operand:SI 0 "s_register_operand" "")
7085 (leu:SI (match_dup 1) (const_int 0)))]
7086 "TARGET_ARM"
7087 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7088 )
7089
7090 (define_expand "sgeu"
7091 [(set (match_operand:SI 0 "s_register_operand" "")
7092 (geu:SI (match_dup 1) (const_int 0)))]
7093 "TARGET_ARM"
7094 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7095 )
7096
7097 (define_expand "sltu"
7098 [(set (match_operand:SI 0 "s_register_operand" "")
7099 (ltu:SI (match_dup 1) (const_int 0)))]
7100 "TARGET_ARM"
7101 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7102 )
7103
7104 (define_expand "sunordered"
7105 [(set (match_operand:SI 0 "s_register_operand" "")
7106 (unordered:SI (match_dup 1) (const_int 0)))]
7107 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7108 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7109 arm_compare_op1);"
7110 )
7111
7112 (define_expand "sordered"
7113 [(set (match_operand:SI 0 "s_register_operand" "")
7114 (ordered:SI (match_dup 1) (const_int 0)))]
7115 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7116 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7117 arm_compare_op1);"
7118 )
7119
7120 (define_expand "sungt"
7121 [(set (match_operand:SI 0 "s_register_operand" "")
7122 (ungt:SI (match_dup 1) (const_int 0)))]
7123 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7124 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7125 arm_compare_op1);"
7126 )
7127
7128 (define_expand "sunge"
7129 [(set (match_operand:SI 0 "s_register_operand" "")
7130 (unge:SI (match_dup 1) (const_int 0)))]
7131 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7132 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7133 arm_compare_op1);"
7134 )
7135
7136 (define_expand "sunlt"
7137 [(set (match_operand:SI 0 "s_register_operand" "")
7138 (unlt:SI (match_dup 1) (const_int 0)))]
7139 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7140 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7141 arm_compare_op1);"
7142 )
7143
7144 (define_expand "sunle"
7145 [(set (match_operand:SI 0 "s_register_operand" "")
7146 (unle:SI (match_dup 1) (const_int 0)))]
7147 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7148 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7149 arm_compare_op1);"
7150 )
7151
7152 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7153 ;;; simple ARM instructions.
7154 ;
7155 ; (define_expand "suneq"
7156 ; [(set (match_operand:SI 0 "s_register_operand" "")
7157 ; (uneq:SI (match_dup 1) (const_int 0)))]
7158 ; "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7159 ; "abort ();"
7160 ; )
7161 ;
7162 ; (define_expand "sltgt"
7163 ; [(set (match_operand:SI 0 "s_register_operand" "")
7164 ; (ltgt:SI (match_dup 1) (const_int 0)))]
7165 ; "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7166 ; "abort ();"
7167 ; )
7168
7169 (define_insn "*mov_scc"
7170 [(set (match_operand:SI 0 "s_register_operand" "=r")
7171 (match_operator:SI 1 "arm_comparison_operator"
7172 [(match_operand 2 "cc_register" "") (const_int 0)]))]
7173 "TARGET_ARM"
7174 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7175 [(set_attr "conds" "use")
7176 (set_attr "length" "8")]
7177 )
7178
7179 (define_insn "*mov_negscc"
7180 [(set (match_operand:SI 0 "s_register_operand" "=r")
7181 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7182 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7183 "TARGET_ARM"
7184 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7185 [(set_attr "conds" "use")
7186 (set_attr "length" "8")]
7187 )
7188
7189 (define_insn "*mov_notscc"
7190 [(set (match_operand:SI 0 "s_register_operand" "=r")
7191 (not:SI (match_operator:SI 1 "arm_comparison_operator"
7192 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7193 "TARGET_ARM"
7194 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7195 [(set_attr "conds" "use")
7196 (set_attr "length" "8")]
7197 )
7198
7199 \f
7200 ;; Conditional move insns
7201
7202 (define_expand "movsicc"
7203 [(set (match_operand:SI 0 "s_register_operand" "")
7204 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7205 (match_operand:SI 2 "arm_not_operand" "")
7206 (match_operand:SI 3 "arm_not_operand" "")))]
7207 "TARGET_ARM"
7208 "
7209 {
7210 enum rtx_code code = GET_CODE (operands[1]);
7211 rtx ccreg;
7212
7213 if (code == UNEQ || code == LTGT)
7214 FAIL;
7215
7216 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7217 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7218 }"
7219 )
7220
7221 (define_expand "movsfcc"
7222 [(set (match_operand:SF 0 "s_register_operand" "")
7223 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7224 (match_operand:SF 2 "s_register_operand" "")
7225 (match_operand:SF 3 "nonmemory_operand" "")))]
7226 "TARGET_ARM"
7227 "
7228 {
7229 enum rtx_code code = GET_CODE (operands[1]);
7230 rtx ccreg;
7231
7232 if (code == UNEQ || code == LTGT)
7233 FAIL;
7234
7235 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
7236 Otherwise, ensure it is a valid FP add operand */
7237 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7238 || (!arm_float_add_operand (operands[3], SFmode)))
7239 operands[3] = force_reg (SFmode, operands[3]);
7240
7241 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7242 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7243 }"
7244 )
7245
7246 (define_expand "movdfcc"
7247 [(set (match_operand:DF 0 "s_register_operand" "")
7248 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7249 (match_operand:DF 2 "s_register_operand" "")
7250 (match_operand:DF 3 "arm_float_add_operand" "")))]
7251 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7252 "
7253 {
7254 enum rtx_code code = GET_CODE (operands[1]);
7255 rtx ccreg;
7256
7257 if (code == UNEQ || code == LTGT)
7258 FAIL;
7259
7260 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7261 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7262 }"
7263 )
7264
7265 (define_insn "*movsicc_insn"
7266 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7267 (if_then_else:SI
7268 (match_operator 3 "arm_comparison_operator"
7269 [(match_operand 4 "cc_register" "") (const_int 0)])
7270 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7271 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7272 "TARGET_ARM"
7273 "@
7274 mov%D3\\t%0, %2
7275 mvn%D3\\t%0, #%B2
7276 mov%d3\\t%0, %1
7277 mvn%d3\\t%0, #%B1
7278 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7279 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7280 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7281 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7282 [(set_attr "length" "4,4,4,4,8,8,8,8")
7283 (set_attr "conds" "use")]
7284 )
7285
7286 (define_insn "*movsfcc_soft_insn"
7287 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7288 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7289 [(match_operand 4 "cc_register" "") (const_int 0)])
7290 (match_operand:SF 1 "s_register_operand" "0,r")
7291 (match_operand:SF 2 "s_register_operand" "r,0")))]
7292 "TARGET_ARM && TARGET_SOFT_FLOAT"
7293 "@
7294 mov%D3\\t%0, %2
7295 mov%d3\\t%0, %1"
7296 [(set_attr "conds" "use")]
7297 )
7298
7299 \f
7300 ;; Jump and linkage insns
7301
7302 (define_expand "jump"
7303 [(set (pc)
7304 (label_ref (match_operand 0 "" "")))]
7305 "TARGET_EITHER"
7306 ""
7307 )
7308
7309 (define_insn "*arm_jump"
7310 [(set (pc)
7311 (label_ref (match_operand 0 "" "")))]
7312 "TARGET_ARM"
7313 "*
7314 {
7315 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7316 {
7317 arm_ccfsm_state += 2;
7318 return \"\";
7319 }
7320 return \"b%?\\t%l0\";
7321 }
7322 "
7323 [(set_attr "predicable" "yes")]
7324 )
7325
7326 (define_insn "*thumb_jump"
7327 [(set (pc)
7328 (label_ref (match_operand 0 "" "")))]
7329 "TARGET_THUMB"
7330 "*
7331 if (get_attr_length (insn) == 2)
7332 return \"b\\t%l0\";
7333 return \"bl\\t%l0\\t%@ far jump\";
7334 "
7335 [(set (attr "far_jump")
7336 (if_then_else
7337 (eq_attr "length" "4")
7338 (const_string "yes")
7339 (const_string "no")))
7340 (set (attr "length")
7341 (if_then_else
7342 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7343 (le (minus (match_dup 0) (pc)) (const_int 2048)))
7344 (const_int 2)
7345 (const_int 4)))]
7346 )
7347
7348 (define_expand "call"
7349 [(parallel [(call (match_operand 0 "memory_operand" "")
7350 (match_operand 1 "general_operand" ""))
7351 (use (match_operand 2 "" ""))
7352 (clobber (reg:SI LR_REGNUM))])]
7353 "TARGET_EITHER"
7354 "
7355 {
7356 rtx callee;
7357
7358 /* In an untyped call, we can get NULL for operand 2. */
7359 if (operands[2] == NULL_RTX)
7360 operands[2] = const0_rtx;
7361
7362 /* This is to decide if we should generate indirect calls by loading the
7363 32 bit address of the callee into a register before performing the
7364 branch and link. operand[2] encodes the long_call/short_call
7365 attribute of the function being called. This attribute is set whenever
7366 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7367 is used, and the short_call attribute can also be set if function is
7368 declared as static or if it has already been defined in the current
7369 compilation unit. See arm.c and arm.h for info about this. The third
7370 parameter to arm_is_longcall_p is used to tell it which pattern
7371 invoked it. */
7372 callee = XEXP (operands[0], 0);
7373
7374 if (GET_CODE (callee) != REG
7375 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7376 XEXP (operands[0], 0) = force_reg (Pmode, callee);
7377 }"
7378 )
7379
7380 (define_insn "*call_reg_armv5"
7381 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7382 (match_operand 1 "" ""))
7383 (use (match_operand 2 "" ""))
7384 (clobber (reg:SI LR_REGNUM))]
7385 "TARGET_ARM && arm_arch5"
7386 "blx%?\\t%0"
7387 [(set_attr "type" "call")]
7388 )
7389
7390 (define_insn "*call_reg_arm"
7391 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7392 (match_operand 1 "" ""))
7393 (use (match_operand 2 "" ""))
7394 (clobber (reg:SI LR_REGNUM))]
7395 "TARGET_ARM && !arm_arch5"
7396 "*
7397 return output_call (operands);
7398 "
7399 ;; length is worst case, normally it is only two
7400 [(set_attr "length" "12")
7401 (set_attr "type" "call")]
7402 )
7403
7404 (define_insn "*call_mem"
7405 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7406 (match_operand 1 "" ""))
7407 (use (match_operand 2 "" ""))
7408 (clobber (reg:SI LR_REGNUM))]
7409 "TARGET_ARM"
7410 "*
7411 return output_call_mem (operands);
7412 "
7413 [(set_attr "length" "12")
7414 (set_attr "type" "call")]
7415 )
7416
7417 (define_insn "*call_reg_thumb_v5"
7418 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7419 (match_operand 1 "" ""))
7420 (use (match_operand 2 "" ""))
7421 (clobber (reg:SI LR_REGNUM))]
7422 "TARGET_THUMB && arm_arch5"
7423 "blx\\t%0"
7424 [(set_attr "length" "2")
7425 (set_attr "type" "call")]
7426 )
7427
7428 (define_insn "*call_reg_thumb"
7429 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7430 (match_operand 1 "" ""))
7431 (use (match_operand 2 "" ""))
7432 (clobber (reg:SI LR_REGNUM))]
7433 "TARGET_THUMB && !arm_arch5"
7434 "*
7435 {
7436 if (TARGET_CALLER_INTERWORKING)
7437 return \"bl\\t%__interwork_call_via_%0\";
7438 else
7439 return \"bl\\t%__call_via_%0\";
7440 }"
7441 [(set_attr "type" "call")]
7442 )
7443
7444 (define_expand "call_value"
7445 [(parallel [(set (match_operand 0 "" "")
7446 (call (match_operand 1 "memory_operand" "")
7447 (match_operand 2 "general_operand" "")))
7448 (use (match_operand 3 "" ""))
7449 (clobber (reg:SI LR_REGNUM))])]
7450 "TARGET_EITHER"
7451 "
7452 {
7453 rtx callee = XEXP (operands[1], 0);
7454
7455 /* In an untyped call, we can get NULL for operand 2. */
7456 if (operands[3] == 0)
7457 operands[3] = const0_rtx;
7458
7459 /* See the comment in define_expand \"call\". */
7460 if (GET_CODE (callee) != REG
7461 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7462 XEXP (operands[1], 0) = force_reg (Pmode, callee);
7463 }"
7464 )
7465
7466 (define_insn "*call_value_reg_armv5"
7467 [(set (match_operand 0 "" "")
7468 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7469 (match_operand 2 "" "")))
7470 (use (match_operand 3 "" ""))
7471 (clobber (reg:SI LR_REGNUM))]
7472 "TARGET_ARM && arm_arch5"
7473 "blx%?\\t%1"
7474 [(set_attr "type" "call")]
7475 )
7476
7477 (define_insn "*call_value_reg_arm"
7478 [(set (match_operand 0 "" "")
7479 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7480 (match_operand 2 "" "")))
7481 (use (match_operand 3 "" ""))
7482 (clobber (reg:SI LR_REGNUM))]
7483 "TARGET_ARM && !arm_arch5"
7484 "*
7485 return output_call (&operands[1]);
7486 "
7487 [(set_attr "length" "12")
7488 (set_attr "type" "call")]
7489 )
7490
7491 (define_insn "*call_value_mem"
7492 [(set (match_operand 0 "" "")
7493 (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7494 (match_operand 2 "" "")))
7495 (use (match_operand 3 "" ""))
7496 (clobber (reg:SI LR_REGNUM))]
7497 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7498 "*
7499 return output_call_mem (&operands[1]);
7500 "
7501 [(set_attr "length" "12")
7502 (set_attr "type" "call")]
7503 )
7504
7505 (define_insn "*call_value_reg_thumb_v5"
7506 [(set (match_operand 0 "" "")
7507 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7508 (match_operand 2 "" "")))
7509 (use (match_operand 3 "" ""))
7510 (clobber (reg:SI LR_REGNUM))]
7511 "TARGET_THUMB && arm_arch5"
7512 "blx\\t%1"
7513 [(set_attr "length" "2")
7514 (set_attr "type" "call")]
7515 )
7516
7517 (define_insn "*call_value_reg_thumb"
7518 [(set (match_operand 0 "" "")
7519 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7520 (match_operand 2 "" "")))
7521 (use (match_operand 3 "" ""))
7522 (clobber (reg:SI LR_REGNUM))]
7523 "TARGET_THUMB && !arm_arch5"
7524 "*
7525 {
7526 if (TARGET_CALLER_INTERWORKING)
7527 return \"bl\\t%__interwork_call_via_%1\";
7528 else
7529 return \"bl\\t%__call_via_%1\";
7530 }"
7531 [(set_attr "type" "call")]
7532 )
7533
7534 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7535 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7536
7537 (define_insn "*call_symbol"
7538 [(call (mem:SI (match_operand:SI 0 "" ""))
7539 (match_operand 1 "" ""))
7540 (use (match_operand 2 "" ""))
7541 (clobber (reg:SI LR_REGNUM))]
7542 "TARGET_ARM
7543 && (GET_CODE (operands[0]) == SYMBOL_REF)
7544 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7545 "*
7546 {
7547 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7548 }"
7549 [(set_attr "type" "call")]
7550 )
7551
7552 (define_insn "*call_value_symbol"
7553 [(set (match_operand 0 "s_register_operand" "")
7554 (call (mem:SI (match_operand:SI 1 "" ""))
7555 (match_operand:SI 2 "" "")))
7556 (use (match_operand 3 "" ""))
7557 (clobber (reg:SI LR_REGNUM))]
7558 "TARGET_ARM
7559 && (GET_CODE (operands[1]) == SYMBOL_REF)
7560 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7561 "*
7562 {
7563 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7564 }"
7565 [(set_attr "type" "call")]
7566 )
7567
7568 (define_insn "*call_insn"
7569 [(call (mem:SI (match_operand:SI 0 "" ""))
7570 (match_operand:SI 1 "" ""))
7571 (use (match_operand 2 "" ""))
7572 (clobber (reg:SI LR_REGNUM))]
7573 "TARGET_THUMB
7574 && GET_CODE (operands[0]) == SYMBOL_REF
7575 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7576 "bl\\t%a0"
7577 [(set_attr "length" "4")
7578 (set_attr "type" "call")]
7579 )
7580
7581 (define_insn "*call_value_insn"
7582 [(set (match_operand 0 "register_operand" "")
7583 (call (mem:SI (match_operand 1 "" ""))
7584 (match_operand 2 "" "")))
7585 (use (match_operand 3 "" ""))
7586 (clobber (reg:SI LR_REGNUM))]
7587 "TARGET_THUMB
7588 && GET_CODE (operands[1]) == SYMBOL_REF
7589 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7590 "bl\\t%a1"
7591 [(set_attr "length" "4")
7592 (set_attr "type" "call")]
7593 )
7594
7595 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7596 (define_expand "sibcall"
7597 [(parallel [(call (match_operand 0 "memory_operand" "")
7598 (match_operand 1 "general_operand" ""))
7599 (return)
7600 (use (match_operand 2 "" ""))])]
7601 "TARGET_ARM"
7602 "
7603 {
7604 if (operands[2] == NULL_RTX)
7605 operands[2] = const0_rtx;
7606 }"
7607 )
7608
7609 (define_expand "sibcall_value"
7610 [(parallel [(set (match_operand 0 "register_operand" "")
7611 (call (match_operand 1 "memory_operand" "")
7612 (match_operand 2 "general_operand" "")))
7613 (return)
7614 (use (match_operand 3 "" ""))])]
7615 "TARGET_ARM"
7616 "
7617 {
7618 if (operands[3] == NULL_RTX)
7619 operands[3] = const0_rtx;
7620 }"
7621 )
7622
7623 (define_insn "*sibcall_insn"
7624 [(call (mem:SI (match_operand:SI 0 "" "X"))
7625 (match_operand 1 "" ""))
7626 (return)
7627 (use (match_operand 2 "" ""))]
7628 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7629 "*
7630 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7631 "
7632 [(set_attr "type" "call")]
7633 )
7634
7635 (define_insn "*sibcall_value_insn"
7636 [(set (match_operand 0 "s_register_operand" "")
7637 (call (mem:SI (match_operand:SI 1 "" "X"))
7638 (match_operand 2 "" "")))
7639 (return)
7640 (use (match_operand 3 "" ""))]
7641 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7642 "*
7643 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7644 "
7645 [(set_attr "type" "call")]
7646 )
7647
7648 ;; Often the return insn will be the same as loading from memory, so set attr
7649 (define_insn "return"
7650 [(return)]
7651 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7652 "*
7653 {
7654 if (arm_ccfsm_state == 2)
7655 {
7656 arm_ccfsm_state += 2;
7657 return \"\";
7658 }
7659 return output_return_instruction (const_true_rtx, TRUE, FALSE);
7660 }"
7661 [(set_attr "type" "load1")
7662 (set_attr "length" "12")
7663 (set_attr "predicable" "yes")]
7664 )
7665
7666 (define_insn "*cond_return"
7667 [(set (pc)
7668 (if_then_else (match_operator 0 "arm_comparison_operator"
7669 [(match_operand 1 "cc_register" "") (const_int 0)])
7670 (return)
7671 (pc)))]
7672 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7673 "*
7674 {
7675 if (arm_ccfsm_state == 2)
7676 {
7677 arm_ccfsm_state += 2;
7678 return \"\";
7679 }
7680 return output_return_instruction (operands[0], TRUE, FALSE);
7681 }"
7682 [(set_attr "conds" "use")
7683 (set_attr "length" "12")
7684 (set_attr "type" "load1")]
7685 )
7686
7687 (define_insn "*cond_return_inverted"
7688 [(set (pc)
7689 (if_then_else (match_operator 0 "arm_comparison_operator"
7690 [(match_operand 1 "cc_register" "") (const_int 0)])
7691 (pc)
7692 (return)))]
7693 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7694 "*
7695 {
7696 if (arm_ccfsm_state == 2)
7697 {
7698 arm_ccfsm_state += 2;
7699 return \"\";
7700 }
7701 return output_return_instruction (operands[0], TRUE, TRUE);
7702 }"
7703 [(set_attr "conds" "use")
7704 (set_attr "length" "12")
7705 (set_attr "type" "load1")]
7706 )
7707
7708 ;; Generate a sequence of instructions to determine if the processor is
7709 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7710 ;; mask.
7711
7712 (define_expand "return_addr_mask"
7713 [(set (match_dup 1)
7714 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7715 (const_int 0)))
7716 (set (match_operand:SI 0 "s_register_operand" "")
7717 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7718 (const_int -1)
7719 (const_int 67108860)))] ; 0x03fffffc
7720 "TARGET_ARM"
7721 "
7722 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7723 ")
7724
7725 (define_insn "*check_arch2"
7726 [(set (match_operand:CC_NOOV 0 "cc_register" "")
7727 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7728 (const_int 0)))]
7729 "TARGET_ARM"
7730 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7731 [(set_attr "length" "8")
7732 (set_attr "conds" "set")]
7733 )
7734
7735 ;; Call subroutine returning any type.
7736
7737 (define_expand "untyped_call"
7738 [(parallel [(call (match_operand 0 "" "")
7739 (const_int 0))
7740 (match_operand 1 "" "")
7741 (match_operand 2 "" "")])]
7742 "TARGET_ARM"
7743 "
7744 {
7745 int i;
7746
7747 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
7748
7749 for (i = 0; i < XVECLEN (operands[2], 0); i++)
7750 {
7751 rtx set = XVECEXP (operands[2], 0, i);
7752
7753 emit_move_insn (SET_DEST (set), SET_SRC (set));
7754 }
7755
7756 /* The optimizer does not know that the call sets the function value
7757 registers we stored in the result block. We avoid problems by
7758 claiming that all hard registers are used and clobbered at this
7759 point. */
7760 emit_insn (gen_blockage ());
7761
7762 DONE;
7763 }"
7764 )
7765
7766 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7767 ;; all of memory. This blocks insns from being moved across this point.
7768
7769 (define_insn "blockage"
7770 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7771 "TARGET_EITHER"
7772 ""
7773 [(set_attr "length" "0")
7774 (set_attr "type" "block")]
7775 )
7776
7777 (define_expand "casesi"
7778 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
7779 (match_operand:SI 1 "const_int_operand" "") ; lower bound
7780 (match_operand:SI 2 "const_int_operand" "") ; total range
7781 (match_operand:SI 3 "" "") ; table label
7782 (match_operand:SI 4 "" "")] ; Out of range label
7783 "TARGET_ARM"
7784 "
7785 {
7786 rtx reg;
7787 if (operands[1] != const0_rtx)
7788 {
7789 reg = gen_reg_rtx (SImode);
7790
7791 emit_insn (gen_addsi3 (reg, operands[0],
7792 GEN_INT (-INTVAL (operands[1]))));
7793 operands[0] = reg;
7794 }
7795
7796 if (!const_ok_for_arm (INTVAL (operands[2])))
7797 operands[2] = force_reg (SImode, operands[2]);
7798
7799 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7800 operands[4]));
7801 DONE;
7802 }"
7803 )
7804
7805 ;; The USE in this pattern is needed to tell flow analysis that this is
7806 ;; a CASESI insn. It has no other purpose.
7807 (define_insn "casesi_internal"
7808 [(parallel [(set (pc)
7809 (if_then_else
7810 (leu (match_operand:SI 0 "s_register_operand" "r")
7811 (match_operand:SI 1 "arm_rhs_operand" "rI"))
7812 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7813 (label_ref (match_operand 2 "" ""))))
7814 (label_ref (match_operand 3 "" ""))))
7815 (clobber (reg:CC CC_REGNUM))
7816 (use (label_ref (match_dup 2)))])]
7817 "TARGET_ARM"
7818 "*
7819 if (flag_pic)
7820 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
7821 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
7822 "
7823 [(set_attr "conds" "clob")
7824 (set_attr "length" "12")]
7825 )
7826
7827 (define_expand "indirect_jump"
7828 [(set (pc)
7829 (match_operand:SI 0 "s_register_operand" ""))]
7830 "TARGET_EITHER"
7831 ""
7832 )
7833
7834 ;; NB Never uses BX.
7835 (define_insn "*arm_indirect_jump"
7836 [(set (pc)
7837 (match_operand:SI 0 "s_register_operand" "r"))]
7838 "TARGET_ARM"
7839 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
7840 [(set_attr "predicable" "yes")]
7841 )
7842
7843 (define_insn "*load_indirect_jump"
7844 [(set (pc)
7845 (match_operand:SI 0 "memory_operand" "m"))]
7846 "TARGET_ARM"
7847 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
7848 [(set_attr "type" "load1")
7849 (set_attr "pool_range" "4096")
7850 (set_attr "neg_pool_range" "4084")
7851 (set_attr "predicable" "yes")]
7852 )
7853
7854 ;; NB Never uses BX.
7855 (define_insn "*thumb_indirect_jump"
7856 [(set (pc)
7857 (match_operand:SI 0 "register_operand" "l*r"))]
7858 "TARGET_THUMB"
7859 "mov\\tpc, %0"
7860 [(set_attr "conds" "clob")
7861 (set_attr "length" "2")]
7862 )
7863
7864 \f
7865 ;; Misc insns
7866
7867 (define_insn "nop"
7868 [(const_int 0)]
7869 "TARGET_EITHER"
7870 "*
7871 if (TARGET_ARM)
7872 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
7873 return \"mov\\tr8, r8\";
7874 "
7875 [(set (attr "length")
7876 (if_then_else (eq_attr "is_thumb" "yes")
7877 (const_int 2)
7878 (const_int 4)))]
7879 )
7880
7881 \f
7882 ;; Patterns to allow combination of arithmetic, cond code and shifts
7883
7884 (define_insn "*arith_shiftsi"
7885 [(set (match_operand:SI 0 "s_register_operand" "=r")
7886 (match_operator:SI 1 "shiftable_operator"
7887 [(match_operator:SI 3 "shift_operator"
7888 [(match_operand:SI 4 "s_register_operand" "r")
7889 (match_operand:SI 5 "reg_or_int_operand" "rI")])
7890 (match_operand:SI 2 "s_register_operand" "r")]))]
7891 "TARGET_ARM"
7892 "%i1%?\\t%0, %2, %4%S3"
7893 [(set_attr "predicable" "yes")
7894 (set_attr "shift" "4")
7895 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7896 (const_string "alu_shift")
7897 (const_string "alu_shift_reg")))]
7898 )
7899
7900 (define_split
7901 [(set (match_operand:SI 0 "s_register_operand" "")
7902 (match_operator:SI 1 "shiftable_operator"
7903 [(match_operator:SI 2 "shiftable_operator"
7904 [(match_operator:SI 3 "shift_operator"
7905 [(match_operand:SI 4 "s_register_operand" "")
7906 (match_operand:SI 5 "reg_or_int_operand" "")])
7907 (match_operand:SI 6 "s_register_operand" "")])
7908 (match_operand:SI 7 "arm_rhs_operand" "")]))
7909 (clobber (match_operand:SI 8 "s_register_operand" ""))]
7910 "TARGET_ARM"
7911 [(set (match_dup 8)
7912 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7913 (match_dup 6)]))
7914 (set (match_dup 0)
7915 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
7916 "")
7917
7918 (define_insn "*arith_shiftsi_compare0"
7919 [(set (reg:CC_NOOV CC_REGNUM)
7920 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7921 [(match_operator:SI 3 "shift_operator"
7922 [(match_operand:SI 4 "s_register_operand" "r")
7923 (match_operand:SI 5 "reg_or_int_operand" "rI")])
7924 (match_operand:SI 2 "s_register_operand" "r")])
7925 (const_int 0)))
7926 (set (match_operand:SI 0 "s_register_operand" "=r")
7927 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7928 (match_dup 2)]))]
7929 "TARGET_ARM"
7930 "%i1%?s\\t%0, %2, %4%S3"
7931 [(set_attr "conds" "set")
7932 (set_attr "shift" "4")
7933 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7934 (const_string "alu_shift")
7935 (const_string "alu_shift_reg")))]
7936 )
7937
7938 (define_insn "*arith_shiftsi_compare0_scratch"
7939 [(set (reg:CC_NOOV CC_REGNUM)
7940 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7941 [(match_operator:SI 3 "shift_operator"
7942 [(match_operand:SI 4 "s_register_operand" "r")
7943 (match_operand:SI 5 "reg_or_int_operand" "rI")])
7944 (match_operand:SI 2 "s_register_operand" "r")])
7945 (const_int 0)))
7946 (clobber (match_scratch:SI 0 "=r"))]
7947 "TARGET_ARM"
7948 "%i1%?s\\t%0, %2, %4%S3"
7949 [(set_attr "conds" "set")
7950 (set_attr "shift" "4")
7951 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7952 (const_string "alu_shift")
7953 (const_string "alu_shift_reg")))]
7954 )
7955
7956 (define_insn "*sub_shiftsi"
7957 [(set (match_operand:SI 0 "s_register_operand" "=r")
7958 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7959 (match_operator:SI 2 "shift_operator"
7960 [(match_operand:SI 3 "s_register_operand" "r")
7961 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7962 "TARGET_ARM"
7963 "sub%?\\t%0, %1, %3%S2"
7964 [(set_attr "predicable" "yes")
7965 (set_attr "shift" "3")
7966 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7967 (const_string "alu_shift")
7968 (const_string "alu_shift_reg")))]
7969 )
7970
7971 (define_insn "*sub_shiftsi_compare0"
7972 [(set (reg:CC_NOOV CC_REGNUM)
7973 (compare:CC_NOOV
7974 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7975 (match_operator:SI 2 "shift_operator"
7976 [(match_operand:SI 3 "s_register_operand" "r")
7977 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7978 (const_int 0)))
7979 (set (match_operand:SI 0 "s_register_operand" "=r")
7980 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7981 (match_dup 4)])))]
7982 "TARGET_ARM"
7983 "sub%?s\\t%0, %1, %3%S2"
7984 [(set_attr "conds" "set")
7985 (set_attr "shift" "3")
7986 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7987 (const_string "alu_shift")
7988 (const_string "alu_shift_reg")))]
7989 )
7990
7991 (define_insn "*sub_shiftsi_compare0_scratch"
7992 [(set (reg:CC_NOOV CC_REGNUM)
7993 (compare:CC_NOOV
7994 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7995 (match_operator:SI 2 "shift_operator"
7996 [(match_operand:SI 3 "s_register_operand" "r")
7997 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7998 (const_int 0)))
7999 (clobber (match_scratch:SI 0 "=r"))]
8000 "TARGET_ARM"
8001 "sub%?s\\t%0, %1, %3%S2"
8002 [(set_attr "conds" "set")
8003 (set_attr "shift" "3")
8004 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8005 (const_string "alu_shift")
8006 (const_string "alu_shift_reg")))]
8007 )
8008
8009 \f
8010
8011 (define_insn "*and_scc"
8012 [(set (match_operand:SI 0 "s_register_operand" "=r")
8013 (and:SI (match_operator:SI 1 "arm_comparison_operator"
8014 [(match_operand 3 "cc_register" "") (const_int 0)])
8015 (match_operand:SI 2 "s_register_operand" "r")))]
8016 "TARGET_ARM"
8017 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8018 [(set_attr "conds" "use")
8019 (set_attr "length" "8")]
8020 )
8021
8022 (define_insn "*ior_scc"
8023 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8024 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8025 [(match_operand 3 "cc_register" "") (const_int 0)])
8026 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8027 "TARGET_ARM"
8028 "@
8029 orr%d2\\t%0, %1, #1
8030 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8031 [(set_attr "conds" "use")
8032 (set_attr "length" "4,8")]
8033 )
8034
8035 (define_insn "*compare_scc"
8036 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8037 (match_operator:SI 1 "arm_comparison_operator"
8038 [(match_operand:SI 2 "s_register_operand" "r,r")
8039 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8040 (clobber (reg:CC CC_REGNUM))]
8041 "TARGET_ARM"
8042 "*
8043 if (operands[3] == const0_rtx)
8044 {
8045 if (GET_CODE (operands[1]) == LT)
8046 return \"mov\\t%0, %2, lsr #31\";
8047
8048 if (GET_CODE (operands[1]) == GE)
8049 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8050
8051 if (GET_CODE (operands[1]) == EQ)
8052 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8053 }
8054
8055 if (GET_CODE (operands[1]) == NE)
8056 {
8057 if (which_alternative == 1)
8058 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8059 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8060 }
8061 if (which_alternative == 1)
8062 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8063 else
8064 output_asm_insn (\"cmp\\t%2, %3\", operands);
8065 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8066 "
8067 [(set_attr "conds" "clob")
8068 (set_attr "length" "12")]
8069 )
8070
8071 (define_insn "*cond_move"
8072 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8073 (if_then_else:SI (match_operator 3 "equality_operator"
8074 [(match_operator 4 "arm_comparison_operator"
8075 [(match_operand 5 "cc_register" "") (const_int 0)])
8076 (const_int 0)])
8077 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8078 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8079 "TARGET_ARM"
8080 "*
8081 if (GET_CODE (operands[3]) == NE)
8082 {
8083 if (which_alternative != 1)
8084 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8085 if (which_alternative != 0)
8086 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8087 return \"\";
8088 }
8089 if (which_alternative != 0)
8090 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8091 if (which_alternative != 1)
8092 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8093 return \"\";
8094 "
8095 [(set_attr "conds" "use")
8096 (set_attr "length" "4,4,8")]
8097 )
8098
8099 (define_insn "*cond_arith"
8100 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8101 (match_operator:SI 5 "shiftable_operator"
8102 [(match_operator:SI 4 "arm_comparison_operator"
8103 [(match_operand:SI 2 "s_register_operand" "r,r")
8104 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8105 (match_operand:SI 1 "s_register_operand" "0,?r")]))
8106 (clobber (reg:CC CC_REGNUM))]
8107 "TARGET_ARM"
8108 "*
8109 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8110 return \"%i5\\t%0, %1, %2, lsr #31\";
8111
8112 output_asm_insn (\"cmp\\t%2, %3\", operands);
8113 if (GET_CODE (operands[5]) == AND)
8114 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8115 else if (GET_CODE (operands[5]) == MINUS)
8116 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8117 else if (which_alternative != 0)
8118 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8119 return \"%i5%d4\\t%0, %1, #1\";
8120 "
8121 [(set_attr "conds" "clob")
8122 (set_attr "length" "12")]
8123 )
8124
8125 (define_insn "*cond_sub"
8126 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8127 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8128 (match_operator:SI 4 "arm_comparison_operator"
8129 [(match_operand:SI 2 "s_register_operand" "r,r")
8130 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8131 (clobber (reg:CC CC_REGNUM))]
8132 "TARGET_ARM"
8133 "*
8134 output_asm_insn (\"cmp\\t%2, %3\", operands);
8135 if (which_alternative != 0)
8136 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8137 return \"sub%d4\\t%0, %1, #1\";
8138 "
8139 [(set_attr "conds" "clob")
8140 (set_attr "length" "8,12")]
8141 )
8142
8143 (define_insn "*cmp_ite0"
8144 [(set (match_operand 6 "dominant_cc_register" "")
8145 (compare
8146 (if_then_else:SI
8147 (match_operator 4 "arm_comparison_operator"
8148 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8149 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8150 (match_operator:SI 5 "arm_comparison_operator"
8151 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8152 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8153 (const_int 0))
8154 (const_int 0)))]
8155 "TARGET_ARM"
8156 "*
8157 {
8158 static const char * const opcodes[4][2] =
8159 {
8160 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8161 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8162 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8163 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8164 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8165 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8166 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8167 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8168 };
8169 int swap =
8170 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8171
8172 return opcodes[which_alternative][swap];
8173 }"
8174 [(set_attr "conds" "set")
8175 (set_attr "length" "8")]
8176 )
8177
8178 (define_insn "*cmp_ite1"
8179 [(set (match_operand 6 "dominant_cc_register" "")
8180 (compare
8181 (if_then_else:SI
8182 (match_operator 4 "arm_comparison_operator"
8183 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8184 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8185 (match_operator:SI 5 "arm_comparison_operator"
8186 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8187 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8188 (const_int 1))
8189 (const_int 0)))]
8190 "TARGET_ARM"
8191 "*
8192 {
8193 static const char * const opcodes[4][2] =
8194 {
8195 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8196 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8197 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8198 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8199 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8200 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8201 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8202 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8203 };
8204 int swap =
8205 comparison_dominates_p (GET_CODE (operands[5]),
8206 reverse_condition (GET_CODE (operands[4])));
8207
8208 return opcodes[which_alternative][swap];
8209 }"
8210 [(set_attr "conds" "set")
8211 (set_attr "length" "8")]
8212 )
8213
8214 (define_insn "*cmp_and"
8215 [(set (match_operand 6 "dominant_cc_register" "")
8216 (compare
8217 (and:SI
8218 (match_operator 4 "arm_comparison_operator"
8219 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8220 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8221 (match_operator:SI 5 "arm_comparison_operator"
8222 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8223 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8224 (const_int 0)))]
8225 "TARGET_ARM"
8226 "*
8227 {
8228 static const char *const opcodes[4][2] =
8229 {
8230 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8231 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8232 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8233 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8234 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8235 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8236 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8237 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8238 };
8239 int swap =
8240 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8241
8242 return opcodes[which_alternative][swap];
8243 }"
8244 [(set_attr "conds" "set")
8245 (set_attr "predicable" "no")
8246 (set_attr "length" "8")]
8247 )
8248
8249 (define_insn "*cmp_ior"
8250 [(set (match_operand 6 "dominant_cc_register" "")
8251 (compare
8252 (ior:SI
8253 (match_operator 4 "arm_comparison_operator"
8254 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8255 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8256 (match_operator:SI 5 "arm_comparison_operator"
8257 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8258 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8259 (const_int 0)))]
8260 "TARGET_ARM"
8261 "*
8262 {
8263 static const char *const opcodes[4][2] =
8264 {
8265 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8266 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8267 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8268 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8269 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8270 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8271 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8272 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8273 };
8274 int swap =
8275 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8276
8277 return opcodes[which_alternative][swap];
8278 }
8279 "
8280 [(set_attr "conds" "set")
8281 (set_attr "length" "8")]
8282 )
8283
8284 (define_insn_and_split "*ior_scc_scc"
8285 [(set (match_operand:SI 0 "s_register_operand" "=r")
8286 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8287 [(match_operand:SI 1 "s_register_operand" "r")
8288 (match_operand:SI 2 "arm_add_operand" "rIL")])
8289 (match_operator:SI 6 "arm_comparison_operator"
8290 [(match_operand:SI 4 "s_register_operand" "r")
8291 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8292 (clobber (reg:CC CC_REGNUM))]
8293 "TARGET_ARM
8294 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8295 != CCmode)"
8296 "#"
8297 "TARGET_ARM && reload_completed"
8298 [(set (match_dup 7)
8299 (compare
8300 (ior:SI
8301 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8302 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8303 (const_int 0)))
8304 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8305 "operands[7]
8306 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8307 DOM_CC_X_OR_Y),
8308 CC_REGNUM);"
8309 [(set_attr "conds" "clob")
8310 (set_attr "length" "16")])
8311
8312 ; If the above pattern is followed by a CMP insn, then the compare is
8313 ; redundant, since we can rework the conditional instruction that follows.
8314 (define_insn_and_split "*ior_scc_scc_cmp"
8315 [(set (match_operand 0 "dominant_cc_register" "")
8316 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8317 [(match_operand:SI 1 "s_register_operand" "r")
8318 (match_operand:SI 2 "arm_add_operand" "rIL")])
8319 (match_operator:SI 6 "arm_comparison_operator"
8320 [(match_operand:SI 4 "s_register_operand" "r")
8321 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8322 (const_int 0)))
8323 (set (match_operand:SI 7 "s_register_operand" "=r")
8324 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8325 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8326 "TARGET_ARM"
8327 "#"
8328 "TARGET_ARM && reload_completed"
8329 [(set (match_dup 0)
8330 (compare
8331 (ior:SI
8332 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8333 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8334 (const_int 0)))
8335 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8336 ""
8337 [(set_attr "conds" "set")
8338 (set_attr "length" "16")])
8339
8340 (define_insn_and_split "*and_scc_scc"
8341 [(set (match_operand:SI 0 "s_register_operand" "=r")
8342 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8343 [(match_operand:SI 1 "s_register_operand" "r")
8344 (match_operand:SI 2 "arm_add_operand" "rIL")])
8345 (match_operator:SI 6 "arm_comparison_operator"
8346 [(match_operand:SI 4 "s_register_operand" "r")
8347 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8348 (clobber (reg:CC CC_REGNUM))]
8349 "TARGET_ARM
8350 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8351 != CCmode)"
8352 "#"
8353 "TARGET_ARM && reload_completed
8354 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8355 != CCmode)"
8356 [(set (match_dup 7)
8357 (compare
8358 (and:SI
8359 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8360 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8361 (const_int 0)))
8362 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8363 "operands[7]
8364 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8365 DOM_CC_X_AND_Y),
8366 CC_REGNUM);"
8367 [(set_attr "conds" "clob")
8368 (set_attr "length" "16")])
8369
8370 ; If the above pattern is followed by a CMP insn, then the compare is
8371 ; redundant, since we can rework the conditional instruction that follows.
8372 (define_insn_and_split "*and_scc_scc_cmp"
8373 [(set (match_operand 0 "dominant_cc_register" "")
8374 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8375 [(match_operand:SI 1 "s_register_operand" "r")
8376 (match_operand:SI 2 "arm_add_operand" "rIL")])
8377 (match_operator:SI 6 "arm_comparison_operator"
8378 [(match_operand:SI 4 "s_register_operand" "r")
8379 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8380 (const_int 0)))
8381 (set (match_operand:SI 7 "s_register_operand" "=r")
8382 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8383 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8384 "TARGET_ARM"
8385 "#"
8386 "TARGET_ARM && reload_completed"
8387 [(set (match_dup 0)
8388 (compare
8389 (and:SI
8390 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8391 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8392 (const_int 0)))
8393 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8394 ""
8395 [(set_attr "conds" "set")
8396 (set_attr "length" "16")])
8397
8398 ;; If there is no dominance in the comparison, then we can still save an
8399 ;; instruction in the AND case, since we can know that the second compare
8400 ;; need only zero the value if false (if true, then the value is already
8401 ;; correct).
8402 (define_insn_and_split "*and_scc_scc_nodom"
8403 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8404 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8405 [(match_operand:SI 1 "s_register_operand" "r,r,0")
8406 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8407 (match_operator:SI 6 "arm_comparison_operator"
8408 [(match_operand:SI 4 "s_register_operand" "r,r,r")
8409 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8410 (clobber (reg:CC CC_REGNUM))]
8411 "TARGET_ARM
8412 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8413 == CCmode)"
8414 "#"
8415 "TARGET_ARM && reload_completed"
8416 [(parallel [(set (match_dup 0)
8417 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8418 (clobber (reg:CC CC_REGNUM))])
8419 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8420 (set (match_dup 0)
8421 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8422 (match_dup 0)
8423 (const_int 0)))]
8424 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8425 operands[4], operands[5]),
8426 CC_REGNUM);
8427 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8428 operands[5]);"
8429 [(set_attr "conds" "clob")
8430 (set_attr "length" "20")])
8431
8432 (define_split
8433 [(set (reg:CC_NOOV CC_REGNUM)
8434 (compare:CC_NOOV (ior:SI
8435 (and:SI (match_operand:SI 0 "s_register_operand" "")
8436 (const_int 1))
8437 (match_operator:SI 1 "comparison_operator"
8438 [(match_operand:SI 2 "s_register_operand" "")
8439 (match_operand:SI 3 "arm_add_operand" "")]))
8440 (const_int 0)))
8441 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8442 "TARGET_ARM"
8443 [(set (match_dup 4)
8444 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8445 (match_dup 0)))
8446 (set (reg:CC_NOOV CC_REGNUM)
8447 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8448 (const_int 0)))]
8449 "")
8450
8451 (define_split
8452 [(set (reg:CC_NOOV CC_REGNUM)
8453 (compare:CC_NOOV (ior:SI
8454 (match_operator:SI 1 "comparison_operator"
8455 [(match_operand:SI 2 "s_register_operand" "")
8456 (match_operand:SI 3 "arm_add_operand" "")])
8457 (and:SI (match_operand:SI 0 "s_register_operand" "")
8458 (const_int 1)))
8459 (const_int 0)))
8460 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8461 "TARGET_ARM"
8462 [(set (match_dup 4)
8463 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8464 (match_dup 0)))
8465 (set (reg:CC_NOOV CC_REGNUM)
8466 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8467 (const_int 0)))]
8468 "")
8469
8470 (define_insn "*negscc"
8471 [(set (match_operand:SI 0 "s_register_operand" "=r")
8472 (neg:SI (match_operator 3 "arm_comparison_operator"
8473 [(match_operand:SI 1 "s_register_operand" "r")
8474 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8475 (clobber (reg:CC CC_REGNUM))]
8476 "TARGET_ARM"
8477 "*
8478 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8479 return \"mov\\t%0, %1, asr #31\";
8480
8481 if (GET_CODE (operands[3]) == NE)
8482 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8483
8484 if (GET_CODE (operands[3]) == GT)
8485 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8486
8487 output_asm_insn (\"cmp\\t%1, %2\", operands);
8488 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8489 return \"mvn%d3\\t%0, #0\";
8490 "
8491 [(set_attr "conds" "clob")
8492 (set_attr "length" "12")]
8493 )
8494
8495 (define_insn "movcond"
8496 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8497 (if_then_else:SI
8498 (match_operator 5 "arm_comparison_operator"
8499 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8500 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8501 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8502 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8503 (clobber (reg:CC CC_REGNUM))]
8504 "TARGET_ARM"
8505 "*
8506 if (GET_CODE (operands[5]) == LT
8507 && (operands[4] == const0_rtx))
8508 {
8509 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8510 {
8511 if (operands[2] == const0_rtx)
8512 return \"and\\t%0, %1, %3, asr #31\";
8513 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8514 }
8515 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8516 {
8517 if (operands[1] == const0_rtx)
8518 return \"bic\\t%0, %2, %3, asr #31\";
8519 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8520 }
8521 /* The only case that falls through to here is when both ops 1 & 2
8522 are constants. */
8523 }
8524
8525 if (GET_CODE (operands[5]) == GE
8526 && (operands[4] == const0_rtx))
8527 {
8528 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8529 {
8530 if (operands[2] == const0_rtx)
8531 return \"bic\\t%0, %1, %3, asr #31\";
8532 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8533 }
8534 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8535 {
8536 if (operands[1] == const0_rtx)
8537 return \"and\\t%0, %2, %3, asr #31\";
8538 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8539 }
8540 /* The only case that falls through to here is when both ops 1 & 2
8541 are constants. */
8542 }
8543 if (GET_CODE (operands[4]) == CONST_INT
8544 && !const_ok_for_arm (INTVAL (operands[4])))
8545 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8546 else
8547 output_asm_insn (\"cmp\\t%3, %4\", operands);
8548 if (which_alternative != 0)
8549 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8550 if (which_alternative != 1)
8551 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8552 return \"\";
8553 "
8554 [(set_attr "conds" "clob")
8555 (set_attr "length" "8,8,12")]
8556 )
8557
8558 (define_insn "*ifcompare_plus_move"
8559 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8560 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8561 [(match_operand:SI 4 "s_register_operand" "r,r")
8562 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8563 (plus:SI
8564 (match_operand:SI 2 "s_register_operand" "r,r")
8565 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8566 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8567 (clobber (reg:CC CC_REGNUM))]
8568 "TARGET_ARM"
8569 "#"
8570 [(set_attr "conds" "clob")
8571 (set_attr "length" "8,12")]
8572 )
8573
8574 (define_insn "*if_plus_move"
8575 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8576 (if_then_else:SI
8577 (match_operator 4 "arm_comparison_operator"
8578 [(match_operand 5 "cc_register" "") (const_int 0)])
8579 (plus:SI
8580 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8581 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8582 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8583 "TARGET_ARM"
8584 "@
8585 add%d4\\t%0, %2, %3
8586 sub%d4\\t%0, %2, #%n3
8587 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8588 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8589 [(set_attr "conds" "use")
8590 (set_attr "length" "4,4,8,8")
8591 (set_attr "type" "*,*,*,*")]
8592 )
8593
8594 (define_insn "*ifcompare_move_plus"
8595 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8596 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8597 [(match_operand:SI 4 "s_register_operand" "r,r")
8598 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8599 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8600 (plus:SI
8601 (match_operand:SI 2 "s_register_operand" "r,r")
8602 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8603 (clobber (reg:CC CC_REGNUM))]
8604 "TARGET_ARM"
8605 "#"
8606 [(set_attr "conds" "clob")
8607 (set_attr "length" "8,12")]
8608 )
8609
8610 (define_insn "*if_move_plus"
8611 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8612 (if_then_else:SI
8613 (match_operator 4 "arm_comparison_operator"
8614 [(match_operand 5 "cc_register" "") (const_int 0)])
8615 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8616 (plus:SI
8617 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8618 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8619 "TARGET_ARM"
8620 "@
8621 add%D4\\t%0, %2, %3
8622 sub%D4\\t%0, %2, #%n3
8623 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8624 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8625 [(set_attr "conds" "use")
8626 (set_attr "length" "4,4,8,8")
8627 (set_attr "type" "*,*,*,*")]
8628 )
8629
8630 (define_insn "*ifcompare_arith_arith"
8631 [(set (match_operand:SI 0 "s_register_operand" "=r")
8632 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8633 [(match_operand:SI 5 "s_register_operand" "r")
8634 (match_operand:SI 6 "arm_add_operand" "rIL")])
8635 (match_operator:SI 8 "shiftable_operator"
8636 [(match_operand:SI 1 "s_register_operand" "r")
8637 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8638 (match_operator:SI 7 "shiftable_operator"
8639 [(match_operand:SI 3 "s_register_operand" "r")
8640 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8641 (clobber (reg:CC CC_REGNUM))]
8642 "TARGET_ARM"
8643 "#"
8644 [(set_attr "conds" "clob")
8645 (set_attr "length" "12")]
8646 )
8647
8648 (define_insn "*if_arith_arith"
8649 [(set (match_operand:SI 0 "s_register_operand" "=r")
8650 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8651 [(match_operand 8 "cc_register" "") (const_int 0)])
8652 (match_operator:SI 6 "shiftable_operator"
8653 [(match_operand:SI 1 "s_register_operand" "r")
8654 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8655 (match_operator:SI 7 "shiftable_operator"
8656 [(match_operand:SI 3 "s_register_operand" "r")
8657 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8658 "TARGET_ARM"
8659 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8660 [(set_attr "conds" "use")
8661 (set_attr "length" "8")]
8662 )
8663
8664 (define_insn "*ifcompare_arith_move"
8665 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8666 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8667 [(match_operand:SI 2 "s_register_operand" "r,r")
8668 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8669 (match_operator:SI 7 "shiftable_operator"
8670 [(match_operand:SI 4 "s_register_operand" "r,r")
8671 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8672 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8673 (clobber (reg:CC CC_REGNUM))]
8674 "TARGET_ARM"
8675 "*
8676 /* If we have an operation where (op x 0) is the identity operation and
8677 the conditional operator is LT or GE and we are comparing against zero and
8678 everything is in registers then we can do this in two instructions. */
8679 if (operands[3] == const0_rtx
8680 && GET_CODE (operands[7]) != AND
8681 && GET_CODE (operands[5]) == REG
8682 && GET_CODE (operands[1]) == REG
8683 && REGNO (operands[1]) == REGNO (operands[4])
8684 && REGNO (operands[4]) != REGNO (operands[0]))
8685 {
8686 if (GET_CODE (operands[6]) == LT)
8687 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8688 else if (GET_CODE (operands[6]) == GE)
8689 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8690 }
8691 if (GET_CODE (operands[3]) == CONST_INT
8692 && !const_ok_for_arm (INTVAL (operands[3])))
8693 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8694 else
8695 output_asm_insn (\"cmp\\t%2, %3\", operands);
8696 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8697 if (which_alternative != 0)
8698 return \"mov%D6\\t%0, %1\";
8699 return \"\";
8700 "
8701 [(set_attr "conds" "clob")
8702 (set_attr "length" "8,12")]
8703 )
8704
8705 (define_insn "*if_arith_move"
8706 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8707 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8708 [(match_operand 6 "cc_register" "") (const_int 0)])
8709 (match_operator:SI 5 "shiftable_operator"
8710 [(match_operand:SI 2 "s_register_operand" "r,r")
8711 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8712 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8713 "TARGET_ARM"
8714 "@
8715 %I5%d4\\t%0, %2, %3
8716 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8717 [(set_attr "conds" "use")
8718 (set_attr "length" "4,8")
8719 (set_attr "type" "*,*")]
8720 )
8721
8722 (define_insn "*ifcompare_move_arith"
8723 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8724 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8725 [(match_operand:SI 4 "s_register_operand" "r,r")
8726 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8727 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8728 (match_operator:SI 7 "shiftable_operator"
8729 [(match_operand:SI 2 "s_register_operand" "r,r")
8730 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8731 (clobber (reg:CC CC_REGNUM))]
8732 "TARGET_ARM"
8733 "*
8734 /* If we have an operation where (op x 0) is the identity operation and
8735 the conditional operator is LT or GE and we are comparing against zero and
8736 everything is in registers then we can do this in two instructions */
8737 if (operands[5] == const0_rtx
8738 && GET_CODE (operands[7]) != AND
8739 && GET_CODE (operands[3]) == REG
8740 && GET_CODE (operands[1]) == REG
8741 && REGNO (operands[1]) == REGNO (operands[2])
8742 && REGNO (operands[2]) != REGNO (operands[0]))
8743 {
8744 if (GET_CODE (operands[6]) == GE)
8745 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8746 else if (GET_CODE (operands[6]) == LT)
8747 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8748 }
8749
8750 if (GET_CODE (operands[5]) == CONST_INT
8751 && !const_ok_for_arm (INTVAL (operands[5])))
8752 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8753 else
8754 output_asm_insn (\"cmp\\t%4, %5\", operands);
8755
8756 if (which_alternative != 0)
8757 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8758 return \"%I7%D6\\t%0, %2, %3\";
8759 "
8760 [(set_attr "conds" "clob")
8761 (set_attr "length" "8,12")]
8762 )
8763
8764 (define_insn "*if_move_arith"
8765 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8766 (if_then_else:SI
8767 (match_operator 4 "arm_comparison_operator"
8768 [(match_operand 6 "cc_register" "") (const_int 0)])
8769 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8770 (match_operator:SI 5 "shiftable_operator"
8771 [(match_operand:SI 2 "s_register_operand" "r,r")
8772 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8773 "TARGET_ARM"
8774 "@
8775 %I5%D4\\t%0, %2, %3
8776 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8777 [(set_attr "conds" "use")
8778 (set_attr "length" "4,8")
8779 (set_attr "type" "*,*")]
8780 )
8781
8782 (define_insn "*ifcompare_move_not"
8783 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8784 (if_then_else:SI
8785 (match_operator 5 "arm_comparison_operator"
8786 [(match_operand:SI 3 "s_register_operand" "r,r")
8787 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8788 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8789 (not:SI
8790 (match_operand:SI 2 "s_register_operand" "r,r"))))
8791 (clobber (reg:CC CC_REGNUM))]
8792 "TARGET_ARM"
8793 "#"
8794 [(set_attr "conds" "clob")
8795 (set_attr "length" "8,12")]
8796 )
8797
8798 (define_insn "*if_move_not"
8799 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8800 (if_then_else:SI
8801 (match_operator 4 "arm_comparison_operator"
8802 [(match_operand 3 "cc_register" "") (const_int 0)])
8803 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8804 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8805 "TARGET_ARM"
8806 "@
8807 mvn%D4\\t%0, %2
8808 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8809 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8810 [(set_attr "conds" "use")
8811 (set_attr "length" "4,8,8")]
8812 )
8813
8814 (define_insn "*ifcompare_not_move"
8815 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8816 (if_then_else:SI
8817 (match_operator 5 "arm_comparison_operator"
8818 [(match_operand:SI 3 "s_register_operand" "r,r")
8819 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8820 (not:SI
8821 (match_operand:SI 2 "s_register_operand" "r,r"))
8822 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8823 (clobber (reg:CC CC_REGNUM))]
8824 "TARGET_ARM"
8825 "#"
8826 [(set_attr "conds" "clob")
8827 (set_attr "length" "8,12")]
8828 )
8829
8830 (define_insn "*if_not_move"
8831 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8832 (if_then_else:SI
8833 (match_operator 4 "arm_comparison_operator"
8834 [(match_operand 3 "cc_register" "") (const_int 0)])
8835 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8836 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8837 "TARGET_ARM"
8838 "@
8839 mvn%d4\\t%0, %2
8840 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
8841 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8842 [(set_attr "conds" "use")
8843 (set_attr "length" "4,8,8")]
8844 )
8845
8846 (define_insn "*ifcompare_shift_move"
8847 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8848 (if_then_else:SI
8849 (match_operator 6 "arm_comparison_operator"
8850 [(match_operand:SI 4 "s_register_operand" "r,r")
8851 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8852 (match_operator:SI 7 "shift_operator"
8853 [(match_operand:SI 2 "s_register_operand" "r,r")
8854 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
8855 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8856 (clobber (reg:CC CC_REGNUM))]
8857 "TARGET_ARM"
8858 "#"
8859 [(set_attr "conds" "clob")
8860 (set_attr "length" "8,12")]
8861 )
8862
8863 (define_insn "*if_shift_move"
8864 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8865 (if_then_else:SI
8866 (match_operator 5 "arm_comparison_operator"
8867 [(match_operand 6 "cc_register" "") (const_int 0)])
8868 (match_operator:SI 4 "shift_operator"
8869 [(match_operand:SI 2 "s_register_operand" "r,r,r")
8870 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
8871 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8872 "TARGET_ARM"
8873 "@
8874 mov%d5\\t%0, %2%S4
8875 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
8876 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8877 [(set_attr "conds" "use")
8878 (set_attr "shift" "2")
8879 (set_attr "length" "4,8,8")
8880 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8881 (const_string "alu_shift")
8882 (const_string "alu_shift_reg")))]
8883 )
8884
8885 (define_insn "*ifcompare_move_shift"
8886 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8887 (if_then_else:SI
8888 (match_operator 6 "arm_comparison_operator"
8889 [(match_operand:SI 4 "s_register_operand" "r,r")
8890 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8891 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8892 (match_operator:SI 7 "shift_operator"
8893 [(match_operand:SI 2 "s_register_operand" "r,r")
8894 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
8895 (clobber (reg:CC CC_REGNUM))]
8896 "TARGET_ARM"
8897 "#"
8898 [(set_attr "conds" "clob")
8899 (set_attr "length" "8,12")]
8900 )
8901
8902 (define_insn "*if_move_shift"
8903 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8904 (if_then_else:SI
8905 (match_operator 5 "arm_comparison_operator"
8906 [(match_operand 6 "cc_register" "") (const_int 0)])
8907 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8908 (match_operator:SI 4 "shift_operator"
8909 [(match_operand:SI 2 "s_register_operand" "r,r,r")
8910 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
8911 "TARGET_ARM"
8912 "@
8913 mov%D5\\t%0, %2%S4
8914 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
8915 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8916 [(set_attr "conds" "use")
8917 (set_attr "shift" "2")
8918 (set_attr "length" "4,8,8")
8919 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8920 (const_string "alu_shift")
8921 (const_string "alu_shift_reg")))]
8922 )
8923
8924 (define_insn "*ifcompare_shift_shift"
8925 [(set (match_operand:SI 0 "s_register_operand" "=r")
8926 (if_then_else:SI
8927 (match_operator 7 "arm_comparison_operator"
8928 [(match_operand:SI 5 "s_register_operand" "r")
8929 (match_operand:SI 6 "arm_add_operand" "rIL")])
8930 (match_operator:SI 8 "shift_operator"
8931 [(match_operand:SI 1 "s_register_operand" "r")
8932 (match_operand:SI 2 "arm_rhs_operand" "rM")])
8933 (match_operator:SI 9 "shift_operator"
8934 [(match_operand:SI 3 "s_register_operand" "r")
8935 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
8936 (clobber (reg:CC CC_REGNUM))]
8937 "TARGET_ARM"
8938 "#"
8939 [(set_attr "conds" "clob")
8940 (set_attr "length" "12")]
8941 )
8942
8943 (define_insn "*if_shift_shift"
8944 [(set (match_operand:SI 0 "s_register_operand" "=r")
8945 (if_then_else:SI
8946 (match_operator 5 "arm_comparison_operator"
8947 [(match_operand 8 "cc_register" "") (const_int 0)])
8948 (match_operator:SI 6 "shift_operator"
8949 [(match_operand:SI 1 "s_register_operand" "r")
8950 (match_operand:SI 2 "arm_rhs_operand" "rM")])
8951 (match_operator:SI 7 "shift_operator"
8952 [(match_operand:SI 3 "s_register_operand" "r")
8953 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
8954 "TARGET_ARM"
8955 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8956 [(set_attr "conds" "use")
8957 (set_attr "shift" "1")
8958 (set_attr "length" "8")
8959 (set (attr "type") (if_then_else
8960 (and (match_operand 2 "const_int_operand" "")
8961 (match_operand 4 "const_int_operand" ""))
8962 (const_string "alu_shift")
8963 (const_string "alu_shift_reg")))]
8964 )
8965
8966 (define_insn "*ifcompare_not_arith"
8967 [(set (match_operand:SI 0 "s_register_operand" "=r")
8968 (if_then_else:SI
8969 (match_operator 6 "arm_comparison_operator"
8970 [(match_operand:SI 4 "s_register_operand" "r")
8971 (match_operand:SI 5 "arm_add_operand" "rIL")])
8972 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8973 (match_operator:SI 7 "shiftable_operator"
8974 [(match_operand:SI 2 "s_register_operand" "r")
8975 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
8976 (clobber (reg:CC CC_REGNUM))]
8977 "TARGET_ARM"
8978 "#"
8979 [(set_attr "conds" "clob")
8980 (set_attr "length" "12")]
8981 )
8982
8983 (define_insn "*if_not_arith"
8984 [(set (match_operand:SI 0 "s_register_operand" "=r")
8985 (if_then_else:SI
8986 (match_operator 5 "arm_comparison_operator"
8987 [(match_operand 4 "cc_register" "") (const_int 0)])
8988 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8989 (match_operator:SI 6 "shiftable_operator"
8990 [(match_operand:SI 2 "s_register_operand" "r")
8991 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
8992 "TARGET_ARM"
8993 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8994 [(set_attr "conds" "use")
8995 (set_attr "length" "8")]
8996 )
8997
8998 (define_insn "*ifcompare_arith_not"
8999 [(set (match_operand:SI 0 "s_register_operand" "=r")
9000 (if_then_else:SI
9001 (match_operator 6 "arm_comparison_operator"
9002 [(match_operand:SI 4 "s_register_operand" "r")
9003 (match_operand:SI 5 "arm_add_operand" "rIL")])
9004 (match_operator:SI 7 "shiftable_operator"
9005 [(match_operand:SI 2 "s_register_operand" "r")
9006 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9007 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9008 (clobber (reg:CC CC_REGNUM))]
9009 "TARGET_ARM"
9010 "#"
9011 [(set_attr "conds" "clob")
9012 (set_attr "length" "12")]
9013 )
9014
9015 (define_insn "*if_arith_not"
9016 [(set (match_operand:SI 0 "s_register_operand" "=r")
9017 (if_then_else:SI
9018 (match_operator 5 "arm_comparison_operator"
9019 [(match_operand 4 "cc_register" "") (const_int 0)])
9020 (match_operator:SI 6 "shiftable_operator"
9021 [(match_operand:SI 2 "s_register_operand" "r")
9022 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9023 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9024 "TARGET_ARM"
9025 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9026 [(set_attr "conds" "use")
9027 (set_attr "length" "8")]
9028 )
9029
9030 (define_insn "*ifcompare_neg_move"
9031 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9032 (if_then_else:SI
9033 (match_operator 5 "arm_comparison_operator"
9034 [(match_operand:SI 3 "s_register_operand" "r,r")
9035 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9036 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9037 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9038 (clobber (reg:CC CC_REGNUM))]
9039 "TARGET_ARM"
9040 "#"
9041 [(set_attr "conds" "clob")
9042 (set_attr "length" "8,12")]
9043 )
9044
9045 (define_insn "*if_neg_move"
9046 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9047 (if_then_else:SI
9048 (match_operator 4 "arm_comparison_operator"
9049 [(match_operand 3 "cc_register" "") (const_int 0)])
9050 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9051 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9052 "TARGET_ARM"
9053 "@
9054 rsb%d4\\t%0, %2, #0
9055 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9056 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9057 [(set_attr "conds" "use")
9058 (set_attr "length" "4,8,8")]
9059 )
9060
9061 (define_insn "*ifcompare_move_neg"
9062 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9063 (if_then_else:SI
9064 (match_operator 5 "arm_comparison_operator"
9065 [(match_operand:SI 3 "s_register_operand" "r,r")
9066 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9067 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9068 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9069 (clobber (reg:CC CC_REGNUM))]
9070 "TARGET_ARM"
9071 "#"
9072 [(set_attr "conds" "clob")
9073 (set_attr "length" "8,12")]
9074 )
9075
9076 (define_insn "*if_move_neg"
9077 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9078 (if_then_else:SI
9079 (match_operator 4 "arm_comparison_operator"
9080 [(match_operand 3 "cc_register" "") (const_int 0)])
9081 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9082 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9083 "TARGET_ARM"
9084 "@
9085 rsb%D4\\t%0, %2, #0
9086 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9087 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9088 [(set_attr "conds" "use")
9089 (set_attr "length" "4,8,8")]
9090 )
9091
9092 (define_insn "*arith_adjacentmem"
9093 [(set (match_operand:SI 0 "s_register_operand" "=r")
9094 (match_operator:SI 1 "shiftable_operator"
9095 [(match_operand:SI 2 "memory_operand" "m")
9096 (match_operand:SI 3 "memory_operand" "m")]))
9097 (clobber (match_scratch:SI 4 "=r"))]
9098 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9099 "*
9100 {
9101 rtx ldm[3];
9102 rtx arith[4];
9103 int val1 = 0, val2 = 0;
9104
9105 if (REGNO (operands[0]) > REGNO (operands[4]))
9106 {
9107 ldm[1] = operands[4];
9108 ldm[2] = operands[0];
9109 }
9110 else
9111 {
9112 ldm[1] = operands[0];
9113 ldm[2] = operands[4];
9114 }
9115 if (GET_CODE (XEXP (operands[2], 0)) != REG)
9116 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
9117 if (GET_CODE (XEXP (operands[3], 0)) != REG)
9118 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9119 arith[0] = operands[0];
9120 arith[3] = operands[1];
9121 if (val1 < val2)
9122 {
9123 arith[1] = ldm[1];
9124 arith[2] = ldm[2];
9125 }
9126 else
9127 {
9128 arith[1] = ldm[2];
9129 arith[2] = ldm[1];
9130 }
9131 if (val1 && val2)
9132 {
9133 rtx ops[3];
9134 ldm[0] = ops[0] = operands[4];
9135 ops[1] = XEXP (XEXP (operands[2], 0), 0);
9136 ops[2] = XEXP (XEXP (operands[2], 0), 1);
9137 output_add_immediate (ops);
9138 if (val1 < val2)
9139 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9140 else
9141 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9142 }
9143 else if (val1)
9144 {
9145 ldm[0] = XEXP (operands[3], 0);
9146 if (val1 < val2)
9147 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9148 else
9149 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9150 }
9151 else
9152 {
9153 ldm[0] = XEXP (operands[2], 0);
9154 if (val1 < val2)
9155 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9156 else
9157 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9158 }
9159 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9160 return \"\";
9161 }"
9162 [(set_attr "length" "12")
9163 (set_attr "predicable" "yes")
9164 (set_attr "type" "load1")]
9165 )
9166
9167 ;; the arm can support extended pre-inc instructions
9168
9169 ;; In all these cases, we use operands 0 and 1 for the register being
9170 ;; incremented because those are the operands that local-alloc will
9171 ;; tie and these are the pair most likely to be tieable (and the ones
9172 ;; that will benefit the most).
9173
9174 ;; We reject the frame pointer if it occurs anywhere in these patterns since
9175 ;; elimination will cause too many headaches.
9176
9177 (define_insn "*strqi_preinc"
9178 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9179 (match_operand:SI 2 "index_operand" "rJ")))
9180 (match_operand:QI 3 "s_register_operand" "r"))
9181 (set (match_operand:SI 0 "s_register_operand" "=r")
9182 (plus:SI (match_dup 1) (match_dup 2)))]
9183 "TARGET_ARM
9184 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9185 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9186 && (GET_CODE (operands[2]) != REG
9187 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9188 "str%?b\\t%3, [%0, %2]!"
9189 [(set_attr "type" "store1")
9190 (set_attr "predicable" "yes")]
9191 )
9192
9193 (define_insn "*strqi_predec"
9194 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9195 (match_operand:SI 2 "s_register_operand" "r")))
9196 (match_operand:QI 3 "s_register_operand" "r"))
9197 (set (match_operand:SI 0 "s_register_operand" "=r")
9198 (minus:SI (match_dup 1) (match_dup 2)))]
9199 "TARGET_ARM
9200 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9201 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9202 && (GET_CODE (operands[2]) != REG
9203 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9204 "str%?b\\t%3, [%0, -%2]!"
9205 [(set_attr "type" "store1")
9206 (set_attr "predicable" "yes")]
9207 )
9208
9209 (define_insn "*loadqi_preinc"
9210 [(set (match_operand:QI 3 "s_register_operand" "=r")
9211 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9212 (match_operand:SI 2 "index_operand" "rJ"))))
9213 (set (match_operand:SI 0 "s_register_operand" "=r")
9214 (plus:SI (match_dup 1) (match_dup 2)))]
9215 "TARGET_ARM
9216 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9217 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9218 && (GET_CODE (operands[2]) != REG
9219 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9220 "ldr%?b\\t%3, [%0, %2]!"
9221 [(set_attr "type" "load_byte")
9222 (set_attr "predicable" "yes")]
9223 )
9224
9225 (define_insn "*loadqi_predec"
9226 [(set (match_operand:QI 3 "s_register_operand" "=r")
9227 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9228 (match_operand:SI 2 "s_register_operand" "r"))))
9229 (set (match_operand:SI 0 "s_register_operand" "=r")
9230 (minus:SI (match_dup 1) (match_dup 2)))]
9231 "TARGET_ARM
9232 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9233 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9234 && (GET_CODE (operands[2]) != REG
9235 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9236 "ldr%?b\\t%3, [%0, -%2]!"
9237 [(set_attr "type" "load_byte")
9238 (set_attr "predicable" "yes")]
9239 )
9240
9241 (define_insn "*loadqisi_preinc"
9242 [(set (match_operand:SI 3 "s_register_operand" "=r")
9243 (zero_extend:SI
9244 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9245 (match_operand:SI 2 "index_operand" "rJ")))))
9246 (set (match_operand:SI 0 "s_register_operand" "=r")
9247 (plus:SI (match_dup 1) (match_dup 2)))]
9248 "TARGET_ARM
9249 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9250 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9251 && (GET_CODE (operands[2]) != REG
9252 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9253 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
9254 [(set_attr "type" "load_byte")
9255 (set_attr "predicable" "yes")]
9256 )
9257
9258 (define_insn "*loadqisi_predec"
9259 [(set (match_operand:SI 3 "s_register_operand" "=r")
9260 (zero_extend:SI
9261 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9262 (match_operand:SI 2 "s_register_operand" "r")))))
9263 (set (match_operand:SI 0 "s_register_operand" "=r")
9264 (minus:SI (match_dup 1) (match_dup 2)))]
9265 "TARGET_ARM
9266 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9267 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9268 && (GET_CODE (operands[2]) != REG
9269 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9270 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
9271 [(set_attr "type" "load_byte")
9272 (set_attr "predicable" "yes")]
9273 )
9274
9275 (define_insn "*strsi_preinc"
9276 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9277 (match_operand:SI 2 "index_operand" "rJ")))
9278 (match_operand:SI 3 "s_register_operand" "r"))
9279 (set (match_operand:SI 0 "s_register_operand" "=r")
9280 (plus:SI (match_dup 1) (match_dup 2)))]
9281 "TARGET_ARM
9282 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9283 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9284 && (GET_CODE (operands[2]) != REG
9285 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9286 "str%?\\t%3, [%0, %2]!"
9287 [(set_attr "type" "store1")
9288 (set_attr "predicable" "yes")]
9289 )
9290
9291 (define_insn "*strsi_predec"
9292 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9293 (match_operand:SI 2 "s_register_operand" "r")))
9294 (match_operand:SI 3 "s_register_operand" "r"))
9295 (set (match_operand:SI 0 "s_register_operand" "=r")
9296 (minus:SI (match_dup 1) (match_dup 2)))]
9297 "TARGET_ARM
9298 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9299 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9300 && (GET_CODE (operands[2]) != REG
9301 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9302 "str%?\\t%3, [%0, -%2]!"
9303 [(set_attr "type" "store1")
9304 (set_attr "predicable" "yes")]
9305 )
9306
9307 (define_insn "*loadsi_preinc"
9308 [(set (match_operand:SI 3 "s_register_operand" "=r")
9309 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9310 (match_operand:SI 2 "index_operand" "rJ"))))
9311 (set (match_operand:SI 0 "s_register_operand" "=r")
9312 (plus:SI (match_dup 1) (match_dup 2)))]
9313 "TARGET_ARM
9314 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9315 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9316 && (GET_CODE (operands[2]) != REG
9317 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9318 "ldr%?\\t%3, [%0, %2]!"
9319 [(set_attr "type" "load1")
9320 (set_attr "predicable" "yes")]
9321 )
9322
9323 (define_insn "*loadsi_predec"
9324 [(set (match_operand:SI 3 "s_register_operand" "=r")
9325 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9326 (match_operand:SI 2 "s_register_operand" "r"))))
9327 (set (match_operand:SI 0 "s_register_operand" "=r")
9328 (minus:SI (match_dup 1) (match_dup 2)))]
9329 "TARGET_ARM
9330 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9331 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9332 && (GET_CODE (operands[2]) != REG
9333 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9334 "ldr%?\\t%3, [%0, -%2]!"
9335 [(set_attr "type" "load1")
9336 (set_attr "predicable" "yes")]
9337 )
9338
9339 (define_insn "*strqi_shiftpreinc"
9340 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9341 [(match_operand:SI 3 "s_register_operand" "r")
9342 (match_operand:SI 4 "const_shift_operand" "n")])
9343 (match_operand:SI 1 "s_register_operand" "0")))
9344 (match_operand:QI 5 "s_register_operand" "r"))
9345 (set (match_operand:SI 0 "s_register_operand" "=r")
9346 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9347 (match_dup 1)))]
9348 "TARGET_ARM
9349 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9350 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9351 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9352 "str%?b\\t%5, [%0, %3%S2]!"
9353 [(set_attr "type" "store1")
9354 (set_attr "predicable" "yes")]
9355 )
9356
9357 (define_insn "*strqi_shiftpredec"
9358 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9359 (match_operator:SI 2 "shift_operator"
9360 [(match_operand:SI 3 "s_register_operand" "r")
9361 (match_operand:SI 4 "const_shift_operand" "n")])))
9362 (match_operand:QI 5 "s_register_operand" "r"))
9363 (set (match_operand:SI 0 "s_register_operand" "=r")
9364 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9365 (match_dup 4)])))]
9366 "TARGET_ARM
9367 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9368 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9369 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9370 "str%?b\\t%5, [%0, -%3%S2]!"
9371 [(set_attr "type" "store1")
9372 (set_attr "predicable" "yes")]
9373 )
9374
9375 (define_insn "*loadqi_shiftpreinc"
9376 [(set (match_operand:QI 5 "s_register_operand" "=r")
9377 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9378 [(match_operand:SI 3 "s_register_operand" "r")
9379 (match_operand:SI 4 "const_shift_operand" "n")])
9380 (match_operand:SI 1 "s_register_operand" "0"))))
9381 (set (match_operand:SI 0 "s_register_operand" "=r")
9382 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9383 (match_dup 1)))]
9384 "TARGET_ARM
9385 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9386 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9387 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9388 "ldr%?b\\t%5, [%0, %3%S2]!"
9389 [(set_attr "type" "load_byte")
9390 (set_attr "predicable" "yes")]
9391 )
9392
9393 (define_insn "*loadqi_shiftpredec"
9394 [(set (match_operand:QI 5 "s_register_operand" "=r")
9395 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9396 (match_operator:SI 2 "shift_operator"
9397 [(match_operand:SI 3 "s_register_operand" "r")
9398 (match_operand:SI 4 "const_shift_operand" "n")]))))
9399 (set (match_operand:SI 0 "s_register_operand" "=r")
9400 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9401 (match_dup 4)])))]
9402 "TARGET_ARM
9403 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9404 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9405 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9406 "ldr%?b\\t%5, [%0, -%3%S2]!"
9407 [(set_attr "type" "load_byte")
9408 (set_attr "predicable" "yes")]
9409 )
9410
9411 (define_insn "*strsi_shiftpreinc"
9412 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9413 [(match_operand:SI 3 "s_register_operand" "r")
9414 (match_operand:SI 4 "const_shift_operand" "n")])
9415 (match_operand:SI 1 "s_register_operand" "0")))
9416 (match_operand:SI 5 "s_register_operand" "r"))
9417 (set (match_operand:SI 0 "s_register_operand" "=r")
9418 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9419 (match_dup 1)))]
9420 "TARGET_ARM
9421 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9422 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9423 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9424 "str%?\\t%5, [%0, %3%S2]!"
9425 [(set_attr "type" "store1")
9426 (set_attr "predicable" "yes")]
9427 )
9428
9429 (define_insn "*strsi_shiftpredec"
9430 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9431 (match_operator:SI 2 "shift_operator"
9432 [(match_operand:SI 3 "s_register_operand" "r")
9433 (match_operand:SI 4 "const_shift_operand" "n")])))
9434 (match_operand:SI 5 "s_register_operand" "r"))
9435 (set (match_operand:SI 0 "s_register_operand" "=r")
9436 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9437 (match_dup 4)])))]
9438 "TARGET_ARM
9439 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9440 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9441 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9442 "str%?\\t%5, [%0, -%3%S2]!"
9443 [(set_attr "type" "store1")
9444 (set_attr "predicable" "yes")]
9445 )
9446
9447 (define_insn "*loadsi_shiftpreinc"
9448 [(set (match_operand:SI 5 "s_register_operand" "=r")
9449 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9450 [(match_operand:SI 3 "s_register_operand" "r")
9451 (match_operand:SI 4 "const_shift_operand" "n")])
9452 (match_operand:SI 1 "s_register_operand" "0"))))
9453 (set (match_operand:SI 0 "s_register_operand" "=r")
9454 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9455 (match_dup 1)))]
9456 "TARGET_ARM
9457 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9458 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9459 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9460 "ldr%?\\t%5, [%0, %3%S2]!"
9461 [(set_attr "type" "load1")
9462 (set_attr "predicable" "yes")]
9463 )
9464
9465 (define_insn "*loadsi_shiftpredec"
9466 [(set (match_operand:SI 5 "s_register_operand" "=r")
9467 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9468 (match_operator:SI 2 "shift_operator"
9469 [(match_operand:SI 3 "s_register_operand" "r")
9470 (match_operand:SI 4 "const_shift_operand" "n")]))))
9471 (set (match_operand:SI 0 "s_register_operand" "=r")
9472 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9473 (match_dup 4)])))]
9474 "TARGET_ARM
9475 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9476 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9477 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9478 "ldr%?\\t%5, [%0, -%3%S2]!"
9479 [(set_attr "type" "load1")
9480 (set_attr "predicable" "yes")])
9481
9482 ; It can also support extended post-inc expressions, but combine doesn't
9483 ; try these....
9484 ; It doesn't seem worth adding peepholes for anything but the most common
9485 ; cases since, unlike combine, the increment must immediately follow the load
9486 ; for this pattern to match.
9487 ; We must watch to see that the source/destination register isn't also the
9488 ; same as the base address register, and that if the index is a register,
9489 ; that it is not the same as the base address register. In such cases the
9490 ; instruction that we would generate would have UNPREDICTABLE behavior so
9491 ; we cannot use it.
9492
9493 (define_peephole
9494 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9495 (match_operand:QI 2 "s_register_operand" "r"))
9496 (set (match_dup 0)
9497 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9498 "TARGET_ARM
9499 && (REGNO (operands[2]) != REGNO (operands[0]))
9500 && (GET_CODE (operands[1]) != REG
9501 || (REGNO (operands[1]) != REGNO (operands[0])))"
9502 "str%?b\\t%2, [%0], %1"
9503 )
9504
9505 (define_peephole
9506 [(set (match_operand:QI 0 "s_register_operand" "=r")
9507 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9508 (set (match_dup 1)
9509 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9510 "TARGET_ARM
9511 && REGNO (operands[0]) != REGNO(operands[1])
9512 && (GET_CODE (operands[2]) != REG
9513 || REGNO(operands[0]) != REGNO (operands[2]))"
9514 "ldr%?b\\t%0, [%1], %2"
9515 )
9516
9517 (define_peephole
9518 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9519 (match_operand:SI 2 "s_register_operand" "r"))
9520 (set (match_dup 0)
9521 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9522 "TARGET_ARM
9523 && (REGNO (operands[2]) != REGNO (operands[0]))
9524 && (GET_CODE (operands[1]) != REG
9525 || (REGNO (operands[1]) != REGNO (operands[0])))"
9526 "str%?\\t%2, [%0], %1"
9527 )
9528
9529 (define_peephole
9530 [(set (match_operand:SI 0 "s_register_operand" "=r")
9531 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9532 (set (match_dup 1)
9533 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9534 "TARGET_ARM
9535 && REGNO (operands[0]) != REGNO(operands[1])
9536 && (GET_CODE (operands[2]) != REG
9537 || REGNO(operands[0]) != REGNO (operands[2]))"
9538 "ldr%?\\t%0, [%1], %2"
9539 )
9540
9541 (define_peephole
9542 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9543 (match_operand:SI 1 "index_operand" "rJ")))
9544 (match_operand:QI 2 "s_register_operand" "r"))
9545 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9546 "TARGET_ARM
9547 && (REGNO (operands[2]) != REGNO (operands[0]))
9548 && (GET_CODE (operands[1]) != REG
9549 || (REGNO (operands[1]) != REGNO (operands[0])))"
9550 "str%?b\\t%2, [%0, %1]!"
9551 )
9552
9553 (define_peephole
9554 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9555 [(match_operand:SI 0 "s_register_operand" "r")
9556 (match_operand:SI 1 "const_int_operand" "n")])
9557 (match_operand:SI 2 "s_register_operand" "+r")))
9558 (match_operand:QI 3 "s_register_operand" "r"))
9559 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9560 (match_dup 2)))]
9561 "TARGET_ARM
9562 && (REGNO (operands[3]) != REGNO (operands[2]))
9563 && (REGNO (operands[0]) != REGNO (operands[2]))"
9564 "str%?b\\t%3, [%2, %0%S4]!"
9565 )
9566
9567 ; This pattern is never tried by combine, so do it as a peephole
9568
9569 (define_peephole2
9570 [(set (match_operand:SI 0 "arm_general_register_operand" "")
9571 (match_operand:SI 1 "arm_general_register_operand" ""))
9572 (set (reg:CC CC_REGNUM)
9573 (compare:CC (match_dup 1) (const_int 0)))]
9574 "TARGET_ARM"
9575 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9576 (set (match_dup 0) (match_dup 1))])]
9577 ""
9578 )
9579
9580 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9581 ; reversed, check that the memory references aren't volatile.
9582
9583 (define_peephole
9584 [(set (match_operand:SI 0 "s_register_operand" "=r")
9585 (match_operand:SI 4 "memory_operand" "m"))
9586 (set (match_operand:SI 1 "s_register_operand" "=r")
9587 (match_operand:SI 5 "memory_operand" "m"))
9588 (set (match_operand:SI 2 "s_register_operand" "=r")
9589 (match_operand:SI 6 "memory_operand" "m"))
9590 (set (match_operand:SI 3 "s_register_operand" "=r")
9591 (match_operand:SI 7 "memory_operand" "m"))]
9592 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9593 "*
9594 return emit_ldm_seq (operands, 4);
9595 "
9596 )
9597
9598 (define_peephole
9599 [(set (match_operand:SI 0 "s_register_operand" "=r")
9600 (match_operand:SI 3 "memory_operand" "m"))
9601 (set (match_operand:SI 1 "s_register_operand" "=r")
9602 (match_operand:SI 4 "memory_operand" "m"))
9603 (set (match_operand:SI 2 "s_register_operand" "=r")
9604 (match_operand:SI 5 "memory_operand" "m"))]
9605 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9606 "*
9607 return emit_ldm_seq (operands, 3);
9608 "
9609 )
9610
9611 (define_peephole
9612 [(set (match_operand:SI 0 "s_register_operand" "=r")
9613 (match_operand:SI 2 "memory_operand" "m"))
9614 (set (match_operand:SI 1 "s_register_operand" "=r")
9615 (match_operand:SI 3 "memory_operand" "m"))]
9616 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9617 "*
9618 return emit_ldm_seq (operands, 2);
9619 "
9620 )
9621
9622 (define_peephole
9623 [(set (match_operand:SI 4 "memory_operand" "=m")
9624 (match_operand:SI 0 "s_register_operand" "r"))
9625 (set (match_operand:SI 5 "memory_operand" "=m")
9626 (match_operand:SI 1 "s_register_operand" "r"))
9627 (set (match_operand:SI 6 "memory_operand" "=m")
9628 (match_operand:SI 2 "s_register_operand" "r"))
9629 (set (match_operand:SI 7 "memory_operand" "=m")
9630 (match_operand:SI 3 "s_register_operand" "r"))]
9631 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9632 "*
9633 return emit_stm_seq (operands, 4);
9634 "
9635 )
9636
9637 (define_peephole
9638 [(set (match_operand:SI 3 "memory_operand" "=m")
9639 (match_operand:SI 0 "s_register_operand" "r"))
9640 (set (match_operand:SI 4 "memory_operand" "=m")
9641 (match_operand:SI 1 "s_register_operand" "r"))
9642 (set (match_operand:SI 5 "memory_operand" "=m")
9643 (match_operand:SI 2 "s_register_operand" "r"))]
9644 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9645 "*
9646 return emit_stm_seq (operands, 3);
9647 "
9648 )
9649
9650 (define_peephole
9651 [(set (match_operand:SI 2 "memory_operand" "=m")
9652 (match_operand:SI 0 "s_register_operand" "r"))
9653 (set (match_operand:SI 3 "memory_operand" "=m")
9654 (match_operand:SI 1 "s_register_operand" "r"))]
9655 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9656 "*
9657 return emit_stm_seq (operands, 2);
9658 "
9659 )
9660
9661 (define_split
9662 [(set (match_operand:SI 0 "s_register_operand" "")
9663 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9664 (const_int 0))
9665 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9666 [(match_operand:SI 3 "s_register_operand" "")
9667 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9668 (clobber (match_operand:SI 5 "s_register_operand" ""))]
9669 "TARGET_ARM"
9670 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9671 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9672 (match_dup 5)))]
9673 ""
9674 )
9675
9676 ;; This split can be used because CC_Z mode implies that the following
9677 ;; branch will be an equality, or an unsigned inequality, so the sign
9678 ;; extension is not needed.
9679
9680 (define_split
9681 [(set (reg:CC_Z CC_REGNUM)
9682 (compare:CC_Z
9683 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9684 (const_int 24))
9685 (match_operand 1 "const_int_operand" "")))
9686 (clobber (match_scratch:SI 2 ""))]
9687 "TARGET_ARM
9688 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9689 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9690 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9691 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9692 "
9693 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9694 "
9695 )
9696
9697 (define_expand "prologue"
9698 [(clobber (const_int 0))]
9699 "TARGET_EITHER"
9700 "if (TARGET_ARM)
9701 arm_expand_prologue ();
9702 else
9703 thumb_expand_prologue ();
9704 DONE;
9705 "
9706 )
9707
9708 (define_expand "epilogue"
9709 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9710 "TARGET_EITHER"
9711 "
9712 if (TARGET_THUMB)
9713 thumb_expand_epilogue ();
9714 else if (USE_RETURN_INSN (FALSE))
9715 {
9716 emit_jump_insn (gen_return ());
9717 DONE;
9718 }
9719 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9720 gen_rtvec (1,
9721 gen_rtx_RETURN (VOIDmode)),
9722 VUNSPEC_EPILOGUE));
9723 DONE;
9724 "
9725 )
9726
9727 ;; Note - although unspec_volatile's USE all hard registers,
9728 ;; USEs are ignored after relaod has completed. Thus we need
9729 ;; to add an unspec of the link register to ensure that flow
9730 ;; does not think that it is unused by the sibcall branch that
9731 ;; will replace the standard function epilogue.
9732 (define_insn "sibcall_epilogue"
9733 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9734 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9735 "TARGET_ARM"
9736 "*
9737 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9738 return output_return_instruction (const_true_rtx, FALSE, FALSE);
9739 return arm_output_epilogue (next_nonnote_insn (insn));
9740 "
9741 ;; Length is absolute worst case
9742 [(set_attr "length" "44")
9743 (set_attr "type" "block")
9744 ;; We don't clobber the conditions, but the potential length of this
9745 ;; operation is sufficient to make conditionalizing the sequence
9746 ;; unlikely to be profitable.
9747 (set_attr "conds" "clob")]
9748 )
9749
9750 (define_insn "*epilogue_insns"
9751 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9752 "TARGET_EITHER"
9753 "*
9754 if (TARGET_ARM)
9755 return arm_output_epilogue (NULL);
9756 else /* TARGET_THUMB */
9757 return thumb_unexpanded_epilogue ();
9758 "
9759 ; Length is absolute worst case
9760 [(set_attr "length" "44")
9761 (set_attr "type" "block")
9762 ;; We don't clobber the conditions, but the potential length of this
9763 ;; operation is sufficient to make conditionalizing the sequence
9764 ;; unlikely to be profitable.
9765 (set_attr "conds" "clob")]
9766 )
9767
9768 (define_expand "eh_epilogue"
9769 [(use (match_operand:SI 0 "register_operand" ""))
9770 (use (match_operand:SI 1 "register_operand" ""))
9771 (use (match_operand:SI 2 "register_operand" ""))]
9772 "TARGET_EITHER"
9773 "
9774 {
9775 cfun->machine->eh_epilogue_sp_ofs = operands[1];
9776 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9777 {
9778 rtx ra = gen_rtx_REG (Pmode, 2);
9779
9780 emit_move_insn (ra, operands[2]);
9781 operands[2] = ra;
9782 }
9783 /* This is a hack -- we may have crystalized the function type too
9784 early. */
9785 cfun->machine->func_type = 0;
9786 }"
9787 )
9788
9789 ;; This split is only used during output to reduce the number of patterns
9790 ;; that need assembler instructions adding to them. We allowed the setting
9791 ;; of the conditions to be implicit during rtl generation so that
9792 ;; the conditional compare patterns would work. However this conflicts to
9793 ;; some extent with the conditional data operations, so we have to split them
9794 ;; up again here.
9795
9796 (define_split
9797 [(set (match_operand:SI 0 "s_register_operand" "")
9798 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9799 [(match_operand 2 "" "") (match_operand 3 "" "")])
9800 (match_dup 0)
9801 (match_operand 4 "" "")))
9802 (clobber (reg:CC CC_REGNUM))]
9803 "TARGET_ARM && reload_completed"
9804 [(set (match_dup 5) (match_dup 6))
9805 (cond_exec (match_dup 7)
9806 (set (match_dup 0) (match_dup 4)))]
9807 "
9808 {
9809 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9810 operands[2], operands[3]);
9811 enum rtx_code rc = GET_CODE (operands[1]);
9812
9813 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9814 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9815 if (mode == CCFPmode || mode == CCFPEmode)
9816 rc = reverse_condition_maybe_unordered (rc);
9817 else
9818 rc = reverse_condition (rc);
9819
9820 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9821 }"
9822 )
9823
9824 (define_split
9825 [(set (match_operand:SI 0 "s_register_operand" "")
9826 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9827 [(match_operand 2 "" "") (match_operand 3 "" "")])
9828 (match_operand 4 "" "")
9829 (match_dup 0)))
9830 (clobber (reg:CC CC_REGNUM))]
9831 "TARGET_ARM && reload_completed"
9832 [(set (match_dup 5) (match_dup 6))
9833 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9834 (set (match_dup 0) (match_dup 4)))]
9835 "
9836 {
9837 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9838 operands[2], operands[3]);
9839
9840 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9841 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9842 }"
9843 )
9844
9845 (define_split
9846 [(set (match_operand:SI 0 "s_register_operand" "")
9847 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9848 [(match_operand 2 "" "") (match_operand 3 "" "")])
9849 (match_operand 4 "" "")
9850 (match_operand 5 "" "")))
9851 (clobber (reg:CC CC_REGNUM))]
9852 "TARGET_ARM && reload_completed"
9853 [(set (match_dup 6) (match_dup 7))
9854 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9855 (set (match_dup 0) (match_dup 4)))
9856 (cond_exec (match_dup 8)
9857 (set (match_dup 0) (match_dup 5)))]
9858 "
9859 {
9860 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9861 operands[2], operands[3]);
9862 enum rtx_code rc = GET_CODE (operands[1]);
9863
9864 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9865 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9866 if (mode == CCFPmode || mode == CCFPEmode)
9867 rc = reverse_condition_maybe_unordered (rc);
9868 else
9869 rc = reverse_condition (rc);
9870
9871 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9872 }"
9873 )
9874
9875 (define_split
9876 [(set (match_operand:SI 0 "s_register_operand" "")
9877 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9878 [(match_operand:SI 2 "s_register_operand" "")
9879 (match_operand:SI 3 "arm_add_operand" "")])
9880 (match_operand:SI 4 "arm_rhs_operand" "")
9881 (not:SI
9882 (match_operand:SI 5 "s_register_operand" ""))))
9883 (clobber (reg:CC CC_REGNUM))]
9884 "TARGET_ARM && reload_completed"
9885 [(set (match_dup 6) (match_dup 7))
9886 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9887 (set (match_dup 0) (match_dup 4)))
9888 (cond_exec (match_dup 8)
9889 (set (match_dup 0) (not:SI (match_dup 5))))]
9890 "
9891 {
9892 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9893 operands[2], operands[3]);
9894 enum rtx_code rc = GET_CODE (operands[1]);
9895
9896 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9897 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9898 if (mode == CCFPmode || mode == CCFPEmode)
9899 rc = reverse_condition_maybe_unordered (rc);
9900 else
9901 rc = reverse_condition (rc);
9902
9903 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9904 }"
9905 )
9906
9907 (define_insn "*cond_move_not"
9908 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9909 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9910 [(match_operand 3 "cc_register" "") (const_int 0)])
9911 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9912 (not:SI
9913 (match_operand:SI 2 "s_register_operand" "r,r"))))]
9914 "TARGET_ARM"
9915 "@
9916 mvn%D4\\t%0, %2
9917 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9918 [(set_attr "conds" "use")
9919 (set_attr "length" "4,8")]
9920 )
9921
9922 ;; The next two patterns occur when an AND operation is followed by a
9923 ;; scc insn sequence
9924
9925 (define_insn "*sign_extract_onebit"
9926 [(set (match_operand:SI 0 "s_register_operand" "=r")
9927 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9928 (const_int 1)
9929 (match_operand:SI 2 "const_int_operand" "n")))
9930 (clobber (reg:CC CC_REGNUM))]
9931 "TARGET_ARM"
9932 "*
9933 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9934 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9935 return \"mvnne\\t%0, #0\";
9936 "
9937 [(set_attr "conds" "clob")
9938 (set_attr "length" "8")]
9939 )
9940
9941 (define_insn "*not_signextract_onebit"
9942 [(set (match_operand:SI 0 "s_register_operand" "=r")
9943 (not:SI
9944 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9945 (const_int 1)
9946 (match_operand:SI 2 "const_int_operand" "n"))))
9947 (clobber (reg:CC CC_REGNUM))]
9948 "TARGET_ARM"
9949 "*
9950 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9951 output_asm_insn (\"tst\\t%1, %2\", operands);
9952 output_asm_insn (\"mvneq\\t%0, #0\", operands);
9953 return \"movne\\t%0, #0\";
9954 "
9955 [(set_attr "conds" "clob")
9956 (set_attr "length" "12")]
9957 )
9958
9959 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
9960 ;; expressions. For simplicity, the first register is also in the unspec
9961 ;; part.
9962 (define_insn "*push_multi"
9963 [(match_parallel 2 "multi_register_push"
9964 [(set (match_operand:BLK 0 "memory_operand" "=m")
9965 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9966 UNSPEC_PUSH_MULT))])]
9967 "TARGET_ARM"
9968 "*
9969 {
9970 int num_saves = XVECLEN (operands[2], 0);
9971
9972 /* For the StrongARM at least it is faster to
9973 use STR to store only a single register. */
9974 if (num_saves == 1)
9975 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9976 else
9977 {
9978 int i;
9979 char pattern[100];
9980
9981 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9982
9983 for (i = 1; i < num_saves; i++)
9984 {
9985 strcat (pattern, \", %|\");
9986 strcat (pattern,
9987 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9988 }
9989
9990 strcat (pattern, \"}\");
9991 output_asm_insn (pattern, operands);
9992 }
9993
9994 return \"\";
9995 }"
9996 [(set_attr "type" "store4")]
9997 )
9998
9999 (define_insn "stack_tie"
10000 [(set (mem:BLK (scratch))
10001 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10002 (match_operand:SI 1 "s_register_operand" "r")]
10003 UNSPEC_PRLG_STK))]
10004 ""
10005 ""
10006 [(set_attr "length" "0")]
10007 )
10008
10009 ;; Similarly for the floating point registers
10010 (define_insn "*push_fp_multi"
10011 [(match_parallel 2 "multi_register_push"
10012 [(set (match_operand:BLK 0 "memory_operand" "=m")
10013 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10014 UNSPEC_PUSH_MULT))])]
10015 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
10016 "*
10017 {
10018 char pattern[100];
10019
10020 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10021 output_asm_insn (pattern, operands);
10022 return \"\";
10023 }"
10024 [(set_attr "type" "f_store")]
10025 )
10026
10027 ;; Special patterns for dealing with the constant pool
10028
10029 (define_insn "align_4"
10030 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10031 "TARGET_EITHER"
10032 "*
10033 assemble_align (32);
10034 return \"\";
10035 "
10036 )
10037
10038 (define_insn "align_8"
10039 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10040 "TARGET_EITHER"
10041 "*
10042 assemble_align (64);
10043 return \"\";
10044 "
10045 )
10046
10047 (define_insn "consttable_end"
10048 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10049 "TARGET_EITHER"
10050 "*
10051 making_const_table = FALSE;
10052 return \"\";
10053 "
10054 )
10055
10056 (define_insn "consttable_1"
10057 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10058 "TARGET_THUMB"
10059 "*
10060 making_const_table = TRUE;
10061 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10062 assemble_zeros (3);
10063 return \"\";
10064 "
10065 [(set_attr "length" "4")]
10066 )
10067
10068 (define_insn "consttable_2"
10069 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10070 "TARGET_THUMB"
10071 "*
10072 making_const_table = TRUE;
10073 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10074 assemble_zeros (2);
10075 return \"\";
10076 "
10077 [(set_attr "length" "4")]
10078 )
10079
10080 (define_insn "consttable_4"
10081 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10082 "TARGET_EITHER"
10083 "*
10084 {
10085 making_const_table = TRUE;
10086 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10087 {
10088 case MODE_FLOAT:
10089 {
10090 REAL_VALUE_TYPE r;
10091 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10092 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10093 break;
10094 }
10095 default:
10096 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10097 break;
10098 }
10099 return \"\";
10100 }"
10101 [(set_attr "length" "4")]
10102 )
10103
10104 (define_insn "consttable_8"
10105 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10106 "TARGET_EITHER"
10107 "*
10108 {
10109 making_const_table = TRUE;
10110 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10111 {
10112 case MODE_FLOAT:
10113 {
10114 REAL_VALUE_TYPE r;
10115 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10116 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10117 break;
10118 }
10119 default:
10120 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10121 break;
10122 }
10123 return \"\";
10124 }"
10125 [(set_attr "length" "8")]
10126 )
10127
10128 ;; Miscellaneous Thumb patterns
10129
10130 (define_expand "tablejump"
10131 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10132 (use (label_ref (match_operand 1 "" "")))])]
10133 "TARGET_THUMB"
10134 "
10135 if (flag_pic)
10136 {
10137 /* Hopefully, CSE will eliminate this copy. */
10138 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10139 rtx reg2 = gen_reg_rtx (SImode);
10140
10141 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10142 operands[0] = reg2;
10143 }
10144 "
10145 )
10146
10147 ;; NB never uses BX.
10148 (define_insn "*thumb_tablejump"
10149 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10150 (use (label_ref (match_operand 1 "" "")))]
10151 "TARGET_THUMB"
10152 "mov\\t%|pc, %0"
10153 [(set_attr "length" "2")]
10154 )
10155
10156 ;; V5 Instructions,
10157
10158 (define_insn "clzsi2"
10159 [(set (match_operand:SI 0 "s_register_operand" "=r")
10160 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10161 "TARGET_ARM && arm_arch5"
10162 "clz%?\\t%0, %1"
10163 [(set_attr "predicable" "yes")])
10164
10165 (define_expand "ffssi2"
10166 [(set (match_operand:SI 0 "s_register_operand" "")
10167 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10168 "TARGET_ARM && arm_arch5"
10169 "
10170 {
10171 rtx t1, t2, t3;
10172
10173 t1 = gen_reg_rtx (SImode);
10174 t2 = gen_reg_rtx (SImode);
10175 t3 = gen_reg_rtx (SImode);
10176
10177 emit_insn (gen_negsi2 (t1, operands[1]));
10178 emit_insn (gen_andsi3 (t2, operands[1], t1));
10179 emit_insn (gen_clzsi2 (t3, t2));
10180 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10181 DONE;
10182 }"
10183 )
10184
10185 (define_expand "ctzsi2"
10186 [(set (match_operand:SI 0 "s_register_operand" "")
10187 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10188 "TARGET_ARM && arm_arch5"
10189 "
10190 {
10191 rtx t1, t2, t3;
10192
10193 t1 = gen_reg_rtx (SImode);
10194 t2 = gen_reg_rtx (SImode);
10195 t3 = gen_reg_rtx (SImode);
10196
10197 emit_insn (gen_negsi2 (t1, operands[1]));
10198 emit_insn (gen_andsi3 (t2, operands[1], t1));
10199 emit_insn (gen_clzsi2 (t3, t2));
10200 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10201 DONE;
10202 }"
10203 )
10204
10205 ;; V5E instructions.
10206
10207 (define_insn "prefetch"
10208 [(prefetch (match_operand:SI 0 "address_operand" "p")
10209 (match_operand:SI 1 "" "")
10210 (match_operand:SI 2 "" ""))]
10211 "TARGET_ARM && arm_arch5e"
10212 "pld\\t%a0")
10213
10214 ;; General predication pattern
10215
10216 (define_cond_exec
10217 [(match_operator 0 "arm_comparison_operator"
10218 [(match_operand 1 "cc_register" "")
10219 (const_int 0)])]
10220 "TARGET_ARM"
10221 ""
10222 )
10223
10224 (define_insn "prologue_use"
10225 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10226 ""
10227 "%@ %0 needed for prologue"
10228 )
10229
10230 ;; Load the FPA co-processor patterns
10231 (include "fpa.md")
10232 ;; Load the Maverick co-processor patterns
10233 (include "cirrus.md")
10234 ;; Load the Intel Wireless Multimedia Extension patterns
10235 (include "iwmmxt.md")
10236 ;; Load the VFP co-processor patterns
10237 (include "vfp.md")
10238