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).
8 ;; This file is part of GCC.
10 ;; GCC is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 2, or (at your
13 ;; option) any later version.
15 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
18 ;; License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; see the file COPYING. If not, write to
22 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
28 ;;---------------------------------------------------------------------------
33 [(IP_REGNUM 12) ; Scratch register
34 (SP_REGNUM 13) ; Stack pointer
35 (LR_REGNUM 14) ; Return address register
36 (PC_REGNUM 15) ; Program counter
37 (CC_REGNUM 24) ; Condition code pseudo register
41 ;; 3rd operand to select_dominance_cc_mode
50 ;; Note: sin and cos are no-longer used.
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 ...)
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
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.
93 ;; UNSPEC_VOLATILE Usage:
96 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
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
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
106 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
108 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
110 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
112 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
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
123 ;;---------------------------------------------------------------------------
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")))
131 ; PROG_MODE attribute is used to determine whether condition codes are
132 ; clobbered by a call insn: they are if in prog32 mode. This is controlled
133 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
134 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
136 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
137 ; scheduling decisions for the load unit and the multiplier.
138 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
140 ;; Operand number of an input operand that is shifted. Zero if the
141 ;; given instruction does not shift one of its input operands.
142 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
143 (define_attr "shift" "" (const_int 0))
145 ; Floating Point Unit. If we only have floating point emulation, then there
146 ; is no point in scheduling the floating point insns. (Well, for best
147 ; performance we should try and group them together).
148 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
149 (const (symbol_ref "arm_fpu_attr")))
151 ; LENGTH of an instruction (in bytes)
152 (define_attr "length" "" (const_int 4))
154 ; POOL_RANGE is how far away from a constant pool entry that this insn
155 ; can be placed. If the distance is zero, then this insn will never
156 ; reference the pool.
157 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
158 ; before its address.
159 (define_attr "pool_range" "" (const_int 0))
160 (define_attr "neg_pool_range" "" (const_int 0))
162 ; An assembler sequence may clobber the condition codes without us knowing.
163 ; If such an insn references the pool, then we have no way of knowing how,
164 ; so use the most conservative value for pool_range.
165 (define_asm_attributes
166 [(set_attr "conds" "clob")
167 (set_attr "length" "4")
168 (set_attr "pool_range" "250")])
170 ;; The instruction used to implement a particular pattern. This
171 ;; information is used by pipeline descriptions to provide accurate
172 ;; scheduling information.
175 "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"
176 (const_string "other"))
178 ; TYPE attribute is used to detect floating point instructions which, if
179 ; running on a co-processor can run in parallel with other, basic instructions
180 ; If write-buffer scheduling is enabled then it can also be used in the
181 ; scheduling of writes.
183 ; Classification of each insn
184 ; alu any alu instruction that doesn't hit memory or fp
185 ; regs or have a shifted source operand
186 ; alu_shift any data instruction that doesn't hit memory or fp
187 ; regs, but has a source operand shifted by a constant
188 ; alu_shift_reg any data instruction that doesn't hit memory or fp
189 ; regs, but has a source operand shifted by a register value
190 ; mult a multiply instruction
191 ; block blockage insn, this blocks all functional units
192 ; float a floating point arithmetic operation (subject to expansion)
193 ; fdivd DFmode floating point division
194 ; fdivs SFmode floating point division
195 ; fmul Floating point multiply
196 ; ffmul Fast floating point multiply
197 ; farith Floating point arithmetic (4 cycle)
198 ; ffarith Fast floating point arithmetic (2 cycle)
199 ; float_em a floating point arithmetic operation that is normally emulated
200 ; even on a machine with an fpa.
201 ; f_load a floating point load from memory
202 ; f_store a floating point store to memory
203 ; f_mem_r a transfer of a floating point register to a real reg via mem
204 ; r_mem_f the reverse of f_mem_r
205 ; f_2_r fast transfer float to arm (no memory needed)
206 ; r_2_f fast transfer arm to float
208 ; call a subroutine call
209 ; load_byte load byte(s) from memory to arm registers
210 ; load1 load 1 word from memory to arm registers
211 ; load2 load 2 words from memory to arm registers
212 ; load3 load 3 words from memory to arm registers
213 ; load4 load 4 words from memory to arm registers
214 ; store store 1 word to memory from arm registers
215 ; store2 store 2 words
216 ; store3 store 3 words
217 ; store4 store 4 (or more) words
218 ; Additions for Cirrus Maverick co-processor:
219 ; mav_farith Floating point arithmetic (4 cycle)
220 ; mav_dmult Double multiplies (7 cycle)
223 "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"
225 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
226 (const_string "mult")
227 (const_string "alu")))
229 ; Load scheduling, set from the arm_ld_sched variable
230 ; initialized by arm_override_options()
231 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
233 ; condition codes: this one is used by final_prescan_insn to speed up
234 ; conditionalizing instructions. It saves having to scan the rtl to see if
235 ; it uses or alters the condition codes.
237 ; USE means that the condition codes are used by the insn in the process of
238 ; outputting code, this means (at present) that we can't use the insn in
241 ; SET means that the purpose of the insn is to set the condition codes in a
242 ; well defined manner.
244 ; CLOB means that the condition codes are altered in an undefined manner, if
245 ; they are altered at all
247 ; JUMP_CLOB is used when the condition cannot be represented by a single
248 ; instruction (UNEQ and LTGT). These cannot be predicated.
250 ; NOCOND means that the condition codes are neither altered nor affect the
251 ; output of this insn
253 (define_attr "conds" "use,set,clob,jump_clob,nocond"
254 (if_then_else (eq_attr "type" "call")
255 (if_then_else (eq_attr "prog_mode" "prog32")
256 (const_string "clob") (const_string "nocond"))
257 (const_string "nocond")))
259 ; Predicable means that the insn can be conditionally executed based on
260 ; an automatically added predicate (additional patterns are generated by
261 ; gen...). We default to 'no' because no Thumb patterns match this rule
262 ; and not all ARM patterns do.
263 (define_attr "predicable" "no,yes" (const_string "no"))
265 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
266 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
267 ; suffer blockages enough to warrant modelling this (and it can adversely
268 ; affect the schedule).
269 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
271 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
272 ; to stall the processor. Used with model_wbuf above.
273 (define_attr "write_conflict" "no,yes"
274 (if_then_else (eq_attr "type"
275 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
277 (const_string "no")))
279 ; Classify the insns into those that take one cycle and those that take more
280 ; than one on the main cpu execution unit.
281 (define_attr "core_cycles" "single,multi"
282 (if_then_else (eq_attr "type"
283 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
284 (const_string "single")
285 (const_string "multi")))
287 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
288 ;; distant label. Only applicable to Thumb code.
289 (define_attr "far_jump" "yes,no" (const_string "no"))
291 ;;---------------------------------------------------------------------------
292 ;; Pipeline descriptions
294 ;; Processor type. This attribute must exactly match the table in
297 "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"
298 (const (symbol_ref "arm_tune")))
300 ;; True if the generic scheduling description should be used.
302 (define_attr "generic_sched" "yes,no"
304 (eq_attr "tune" "arm926ejs,arm1026ejs,arm1136js,arm1136jfs")
306 (const_string "yes")))
308 (include "arm-generic.md")
309 (include "arm926ejs.md")
310 (include "arm1026ejs.md")
311 (include "arm1136jfs.md")
314 ;;---------------------------------------------------------------------------
319 ;; Note: For DImode insns, there is normally no reason why operands should
320 ;; not be in the same register, what we don't want is for something being
321 ;; written to partially overlap something that is an input.
322 ;; Cirrus 64bit additions should not be split because we have a native
323 ;; 64bit addition instructions.
325 (define_expand "adddi3"
327 [(set (match_operand:DI 0 "s_register_operand" "")
328 (plus:DI (match_operand:DI 1 "s_register_operand" "")
329 (match_operand:DI 2 "s_register_operand" "")))
330 (clobber (reg:CC CC_REGNUM))])]
333 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
335 if (!cirrus_fp_register (operands[0], DImode))
336 operands[0] = force_reg (DImode, operands[0]);
337 if (!cirrus_fp_register (operands[1], DImode))
338 operands[1] = force_reg (DImode, operands[1]);
339 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
345 if (GET_CODE (operands[1]) != REG)
346 operands[1] = force_reg (SImode, operands[1]);
347 if (GET_CODE (operands[2]) != REG)
348 operands[2] = force_reg (SImode, operands[2]);
353 (define_insn "*thumb_adddi3"
354 [(set (match_operand:DI 0 "register_operand" "=l")
355 (plus:DI (match_operand:DI 1 "register_operand" "%0")
356 (match_operand:DI 2 "register_operand" "l")))
357 (clobber (reg:CC CC_REGNUM))
360 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
361 [(set_attr "length" "4")]
364 (define_insn_and_split "*arm_adddi3"
365 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
366 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
367 (match_operand:DI 2 "s_register_operand" "r, 0")))
368 (clobber (reg:CC CC_REGNUM))]
369 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
371 "TARGET_ARM && reload_completed"
372 [(parallel [(set (reg:CC_C CC_REGNUM)
373 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
375 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
376 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
377 (plus:SI (match_dup 4) (match_dup 5))))]
380 operands[3] = gen_highpart (SImode, operands[0]);
381 operands[0] = gen_lowpart (SImode, operands[0]);
382 operands[4] = gen_highpart (SImode, operands[1]);
383 operands[1] = gen_lowpart (SImode, operands[1]);
384 operands[5] = gen_highpart (SImode, operands[2]);
385 operands[2] = gen_lowpart (SImode, operands[2]);
387 [(set_attr "conds" "clob")
388 (set_attr "length" "8")]
391 (define_insn_and_split "*adddi_sesidi_di"
392 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
393 (plus:DI (sign_extend:DI
394 (match_operand:SI 2 "s_register_operand" "r,r"))
395 (match_operand:DI 1 "s_register_operand" "r,0")))
396 (clobber (reg:CC CC_REGNUM))]
397 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
399 "TARGET_ARM && reload_completed"
400 [(parallel [(set (reg:CC_C CC_REGNUM)
401 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
403 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
404 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
405 (plus:SI (ashiftrt:SI (match_dup 2)
410 operands[3] = gen_highpart (SImode, operands[0]);
411 operands[0] = gen_lowpart (SImode, operands[0]);
412 operands[4] = gen_highpart (SImode, operands[1]);
413 operands[1] = gen_lowpart (SImode, operands[1]);
414 operands[2] = gen_lowpart (SImode, operands[2]);
416 [(set_attr "conds" "clob")
417 (set_attr "length" "8")]
420 (define_insn_and_split "*adddi_zesidi_di"
421 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
422 (plus:DI (zero_extend:DI
423 (match_operand:SI 2 "s_register_operand" "r,r"))
424 (match_operand:DI 1 "s_register_operand" "r,0")))
425 (clobber (reg:CC CC_REGNUM))]
426 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
428 "TARGET_ARM && reload_completed"
429 [(parallel [(set (reg:CC_C CC_REGNUM)
430 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
432 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
433 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
434 (plus:SI (match_dup 4) (const_int 0))))]
437 operands[3] = gen_highpart (SImode, operands[0]);
438 operands[0] = gen_lowpart (SImode, operands[0]);
439 operands[4] = gen_highpart (SImode, operands[1]);
440 operands[1] = gen_lowpart (SImode, operands[1]);
441 operands[2] = gen_lowpart (SImode, operands[2]);
443 [(set_attr "conds" "clob")
444 (set_attr "length" "8")]
447 (define_expand "addsi3"
448 [(set (match_operand:SI 0 "s_register_operand" "")
449 (plus:SI (match_operand:SI 1 "s_register_operand" "")
450 (match_operand:SI 2 "reg_or_int_operand" "")))]
453 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
455 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
457 (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
463 ; If there is a scratch available, this will be faster than synthesizing the
466 [(match_scratch:SI 3 "r")
467 (set (match_operand:SI 0 "s_register_operand" "")
468 (plus:SI (match_operand:SI 1 "s_register_operand" "")
469 (match_operand:SI 2 "const_int_operand" "")))]
471 !(const_ok_for_arm (INTVAL (operands[2]))
472 || const_ok_for_arm (-INTVAL (operands[2])))
473 && const_ok_for_arm (~INTVAL (operands[2]))"
474 [(set (match_dup 3) (match_dup 2))
475 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
479 (define_insn_and_split "*arm_addsi3"
480 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
481 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
482 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
489 GET_CODE (operands[2]) == CONST_INT
490 && !(const_ok_for_arm (INTVAL (operands[2]))
491 || const_ok_for_arm (-INTVAL (operands[2])))"
492 [(clobber (const_int 0))]
494 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
498 [(set_attr "length" "4,4,16")
499 (set_attr "predicable" "yes")]
502 ;; Register group 'k' is a single register group containing only the stack
503 ;; register. Trying to reload it will always fail catastrophically,
504 ;; so never allow those alternatives to match if reloading is needed.
506 (define_insn "*thumb_addsi3"
507 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
508 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
509 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
512 static const char * const asms[] =
514 \"add\\t%0, %0, %2\",
515 \"sub\\t%0, %0, #%n2\",
516 \"add\\t%0, %1, %2\",
517 \"add\\t%0, %0, %2\",
518 \"add\\t%0, %0, %2\",
519 \"add\\t%0, %1, %2\",
522 if ((which_alternative == 2 || which_alternative == 6)
523 && GET_CODE (operands[2]) == CONST_INT
524 && INTVAL (operands[2]) < 0)
525 return \"sub\\t%0, %1, #%n2\";
526 return asms[which_alternative];
528 [(set_attr "length" "2")]
531 ;; Reloading and elimination of the frame pointer can
532 ;; sometimes cause this optimization to be missed.
534 [(set (match_operand:SI 0 "register_operand" "")
535 (match_operand:SI 1 "const_int_operand" ""))
537 (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
539 && REGNO (operands[2]) == STACK_POINTER_REGNUM
540 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
541 && (INTVAL (operands[1]) & 3) == 0"
542 [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
546 (define_insn "*addsi3_compare0"
547 [(set (reg:CC_NOOV CC_REGNUM)
549 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
550 (match_operand:SI 2 "arm_add_operand" "rI,L"))
552 (set (match_operand:SI 0 "s_register_operand" "=r,r")
553 (plus:SI (match_dup 1) (match_dup 2)))]
557 sub%?s\\t%0, %1, #%n2"
558 [(set_attr "conds" "set")]
561 (define_insn "*addsi3_compare0_scratch"
562 [(set (reg:CC_NOOV CC_REGNUM)
564 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
565 (match_operand:SI 1 "arm_add_operand" "rI,L"))
571 [(set_attr "conds" "set")]
574 ;; These patterns are the same ones as the two regular addsi3_compare0
575 ;; patterns, except we write them slightly different - the combiner
576 ;; tends to generate them this way.
577 (define_insn "*addsi3_compare0_for_combiner"
578 [(set (reg:CC CC_REGNUM)
580 (match_operand:SI 1 "s_register_operand" "r,r")
581 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
582 (set (match_operand:SI 0 "s_register_operand" "=r,r")
583 (plus:SI (match_dup 1) (match_dup 2)))]
587 sub%?s\\t%0, %1, #%n2"
588 [(set_attr "conds" "set")]
591 (define_insn "*addsi3_compare0_scratch_for_combiner"
592 [(set (reg:CC CC_REGNUM)
594 (match_operand:SI 0 "s_register_operand" "r,r")
595 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
600 [(set_attr "conds" "set")]
603 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
604 ;; addend is a constant.
605 (define_insn "*cmpsi2_addneg"
606 [(set (reg:CC CC_REGNUM)
608 (match_operand:SI 1 "s_register_operand" "r,r")
609 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
610 (set (match_operand:SI 0 "s_register_operand" "=r,r")
611 (plus:SI (match_dup 1)
612 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
613 "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
616 add%?s\\t%0, %1, #%n2"
617 [(set_attr "conds" "set")]
620 ;; Convert the sequence
622 ;; cmn rd, #1 (equivalent to cmp rd, #-1)
626 ;; bcs dest ((unsigned)rn >= 1)
627 ;; similarly for the beq variant using bcc.
628 ;; This is a common looping idiom (while (n--))
630 [(set (match_operand:SI 0 "s_register_operand" "")
631 (plus:SI (match_operand:SI 1 "s_register_operand" "")
633 (set (match_operand 2 "cc_register" "")
634 (compare (match_dup 0) (const_int -1)))
636 (if_then_else (match_operator 3 "equality_operator"
637 [(match_dup 2) (const_int 0)])
638 (match_operand 4 "" "")
639 (match_operand 5 "" "")))]
640 "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
644 (match_dup 1) (const_int 1)))
645 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
647 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
650 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
651 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
654 operands[2], const0_rtx);"
657 ;; The next four insns work because they compare the result with one of
658 ;; the operands, and we know that the use of the condition code is
659 ;; either GEU or LTU, so we can use the carry flag from the addition
660 ;; instead of doing the compare a second time.
661 (define_insn "*addsi3_compare_op1"
662 [(set (reg:CC_C CC_REGNUM)
664 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
665 (match_operand:SI 2 "arm_add_operand" "rI,L"))
667 (set (match_operand:SI 0 "s_register_operand" "=r,r")
668 (plus:SI (match_dup 1) (match_dup 2)))]
672 sub%?s\\t%0, %1, #%n2"
673 [(set_attr "conds" "set")]
676 (define_insn "*addsi3_compare_op2"
677 [(set (reg:CC_C CC_REGNUM)
679 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
680 (match_operand:SI 2 "arm_add_operand" "rI,L"))
682 (set (match_operand:SI 0 "s_register_operand" "=r,r")
683 (plus:SI (match_dup 1) (match_dup 2)))]
687 sub%?s\\t%0, %1, #%n2"
688 [(set_attr "conds" "set")]
691 (define_insn "*compare_addsi2_op0"
692 [(set (reg:CC_C CC_REGNUM)
694 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
695 (match_operand:SI 1 "arm_add_operand" "rI,L"))
701 [(set_attr "conds" "set")]
704 (define_insn "*compare_addsi2_op1"
705 [(set (reg:CC_C CC_REGNUM)
707 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
708 (match_operand:SI 1 "arm_add_operand" "rI,L"))
714 [(set_attr "conds" "set")]
717 (define_insn "*addsi3_carryin"
718 [(set (match_operand:SI 0 "s_register_operand" "=r")
719 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
720 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
721 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
724 [(set_attr "conds" "use")]
727 (define_insn "*addsi3_carryin_shift"
728 [(set (match_operand:SI 0 "s_register_operand" "=r")
729 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
731 (match_operator:SI 2 "shift_operator"
732 [(match_operand:SI 3 "s_register_operand" "r")
733 (match_operand:SI 4 "reg_or_int_operand" "rM")])
734 (match_operand:SI 1 "s_register_operand" "r"))))]
736 "adc%?\\t%0, %1, %3%S2"
737 [(set_attr "conds" "use")
738 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
739 (const_string "alu_shift")
740 (const_string "alu_shift_reg")))]
743 (define_insn "*addsi3_carryin_alt1"
744 [(set (match_operand:SI 0 "s_register_operand" "=r")
745 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
746 (match_operand:SI 2 "arm_rhs_operand" "rI"))
747 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
750 [(set_attr "conds" "use")]
753 (define_insn "*addsi3_carryin_alt2"
754 [(set (match_operand:SI 0 "s_register_operand" "=r")
755 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
756 (match_operand:SI 1 "s_register_operand" "r"))
757 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
760 [(set_attr "conds" "use")]
763 (define_insn "*addsi3_carryin_alt3"
764 [(set (match_operand:SI 0 "s_register_operand" "=r")
765 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
766 (match_operand:SI 2 "arm_rhs_operand" "rI"))
767 (match_operand:SI 1 "s_register_operand" "r")))]
770 [(set_attr "conds" "use")]
773 (define_insn "incscc"
774 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
775 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
776 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
777 (match_operand:SI 1 "s_register_operand" "0,?r")))]
781 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
782 [(set_attr "conds" "use")
783 (set_attr "length" "4,8")]
786 ; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
788 [(set (match_operand:SI 0 "s_register_operand" "")
789 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
790 (match_operand:SI 2 "s_register_operand" ""))
792 (clobber (match_operand:SI 3 "s_register_operand" ""))]
794 [(set (match_dup 3) (match_dup 1))
795 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
797 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
800 (define_expand "addsf3"
801 [(set (match_operand:SF 0 "s_register_operand" "")
802 (plus:SF (match_operand:SF 1 "s_register_operand" "")
803 (match_operand:SF 2 "arm_float_add_operand" "")))]
804 "TARGET_ARM && TARGET_HARD_FLOAT"
807 && !cirrus_fp_register (operands[2], SFmode))
808 operands[2] = force_reg (SFmode, operands[2]);
811 (define_expand "adddf3"
812 [(set (match_operand:DF 0 "s_register_operand" "")
813 (plus:DF (match_operand:DF 1 "s_register_operand" "")
814 (match_operand:DF 2 "arm_float_add_operand" "")))]
815 "TARGET_ARM && TARGET_HARD_FLOAT"
818 && !cirrus_fp_register (operands[2], DFmode))
819 operands[2] = force_reg (DFmode, operands[2]);
822 (define_expand "subdi3"
824 [(set (match_operand:DI 0 "s_register_operand" "")
825 (minus:DI (match_operand:DI 1 "s_register_operand" "")
826 (match_operand:DI 2 "s_register_operand" "")))
827 (clobber (reg:CC CC_REGNUM))])]
830 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
832 && cirrus_fp_register (operands[0], DImode)
833 && cirrus_fp_register (operands[1], DImode))
835 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
841 if (GET_CODE (operands[1]) != REG)
842 operands[1] = force_reg (SImode, operands[1]);
843 if (GET_CODE (operands[2]) != REG)
844 operands[2] = force_reg (SImode, operands[2]);
849 (define_insn "*arm_subdi3"
850 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
851 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
852 (match_operand:DI 2 "s_register_operand" "r,0,0")))
853 (clobber (reg:CC CC_REGNUM))]
855 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
856 [(set_attr "conds" "clob")
857 (set_attr "length" "8")]
860 (define_insn "*thumb_subdi3"
861 [(set (match_operand:DI 0 "register_operand" "=l")
862 (minus:DI (match_operand:DI 1 "register_operand" "0")
863 (match_operand:DI 2 "register_operand" "l")))
864 (clobber (reg:CC CC_REGNUM))]
866 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
867 [(set_attr "length" "4")]
870 (define_insn "*subdi_di_zesidi"
871 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
872 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
874 (match_operand:SI 2 "s_register_operand" "r,r"))))
875 (clobber (reg:CC CC_REGNUM))]
877 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
878 [(set_attr "conds" "clob")
879 (set_attr "length" "8")]
882 (define_insn "*subdi_di_sesidi"
883 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
884 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
886 (match_operand:SI 2 "s_register_operand" "r,r"))))
887 (clobber (reg:CC CC_REGNUM))]
889 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
890 [(set_attr "conds" "clob")
891 (set_attr "length" "8")]
894 (define_insn "*subdi_zesidi_di"
895 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
896 (minus:DI (zero_extend:DI
897 (match_operand:SI 2 "s_register_operand" "r,r"))
898 (match_operand:DI 1 "s_register_operand" "?r,0")))
899 (clobber (reg:CC CC_REGNUM))]
901 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
902 [(set_attr "conds" "clob")
903 (set_attr "length" "8")]
906 (define_insn "*subdi_sesidi_di"
907 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
908 (minus:DI (sign_extend:DI
909 (match_operand:SI 2 "s_register_operand" "r,r"))
910 (match_operand:DI 1 "s_register_operand" "?r,0")))
911 (clobber (reg:CC CC_REGNUM))]
913 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
914 [(set_attr "conds" "clob")
915 (set_attr "length" "8")]
918 (define_insn "*subdi_zesidi_zesidi"
919 [(set (match_operand:DI 0 "s_register_operand" "=r")
920 (minus:DI (zero_extend:DI
921 (match_operand:SI 1 "s_register_operand" "r"))
923 (match_operand:SI 2 "s_register_operand" "r"))))
924 (clobber (reg:CC CC_REGNUM))]
926 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
927 [(set_attr "conds" "clob")
928 (set_attr "length" "8")]
931 (define_expand "subsi3"
932 [(set (match_operand:SI 0 "s_register_operand" "")
933 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
934 (match_operand:SI 2 "s_register_operand" "")))]
937 if (GET_CODE (operands[1]) == CONST_INT)
941 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
944 : preserve_subexpressions_p ()));
947 else /* TARGET_THUMB */
948 operands[1] = force_reg (SImode, operands[1]);
953 (define_insn "*thumb_subsi3_insn"
954 [(set (match_operand:SI 0 "register_operand" "=l")
955 (minus:SI (match_operand:SI 1 "register_operand" "l")
956 (match_operand:SI 2 "register_operand" "l")))]
959 [(set_attr "length" "2")]
962 (define_insn_and_split "*arm_subsi3_insn"
963 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
964 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
965 (match_operand:SI 2 "s_register_operand" "r,r")))]
971 && GET_CODE (operands[1]) == CONST_INT
972 && !const_ok_for_arm (INTVAL (operands[1]))"
973 [(clobber (const_int 0))]
975 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
979 [(set_attr "length" "4,16")
980 (set_attr "predicable" "yes")]
984 [(match_scratch:SI 3 "r")
985 (set (match_operand:SI 0 "s_register_operand" "")
986 (minus:SI (match_operand:SI 1 "const_int_operand" "")
987 (match_operand:SI 2 "s_register_operand" "")))]
989 && !const_ok_for_arm (INTVAL (operands[1]))
990 && const_ok_for_arm (~INTVAL (operands[1]))"
991 [(set (match_dup 3) (match_dup 1))
992 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
996 (define_insn "*subsi3_compare0"
997 [(set (reg:CC_NOOV CC_REGNUM)
999 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1000 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1002 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1003 (minus:SI (match_dup 1) (match_dup 2)))]
1007 rsb%?s\\t%0, %2, %1"
1008 [(set_attr "conds" "set")]
1011 (define_insn "decscc"
1012 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1013 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1014 (match_operator:SI 2 "arm_comparison_operator"
1015 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1019 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1020 [(set_attr "conds" "use")
1021 (set_attr "length" "*,8")]
1024 (define_expand "subsf3"
1025 [(set (match_operand:SF 0 "s_register_operand" "")
1026 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1027 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1028 "TARGET_ARM && TARGET_HARD_FLOAT"
1030 if (TARGET_MAVERICK)
1032 if (!cirrus_fp_register (operands[1], SFmode))
1033 operands[1] = force_reg (SFmode, operands[1]);
1034 if (!cirrus_fp_register (operands[2], SFmode))
1035 operands[2] = force_reg (SFmode, operands[2]);
1039 (define_expand "subdf3"
1040 [(set (match_operand:DF 0 "s_register_operand" "")
1041 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1042 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1043 "TARGET_ARM && TARGET_HARD_FLOAT"
1045 if (TARGET_MAVERICK)
1047 if (!cirrus_fp_register (operands[1], DFmode))
1048 operands[1] = force_reg (DFmode, operands[1]);
1049 if (!cirrus_fp_register (operands[2], DFmode))
1050 operands[2] = force_reg (DFmode, operands[2]);
1055 ;; Multiplication insns
1057 (define_expand "mulsi3"
1058 [(set (match_operand:SI 0 "s_register_operand" "")
1059 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1060 (match_operand:SI 1 "s_register_operand" "")))]
1065 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1066 (define_insn "*arm_mulsi3"
1067 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1068 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1069 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1071 "mul%?\\t%0, %2, %1"
1072 [(set_attr "insn" "mul")
1073 (set_attr "predicable" "yes")]
1076 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1077 ; 1 and 2; are the same, because reload will make operand 0 match
1078 ; operand 1 without realizing that this conflicts with operand 2. We fix
1079 ; this by adding another alternative to match this case, and then `reload'
1080 ; it ourselves. This alternative must come first.
1081 (define_insn "*thumb_mulsi3"
1082 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1083 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1084 (match_operand:SI 2 "register_operand" "l,l,l")))]
1087 if (which_alternative < 2)
1088 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1090 return \"mul\\t%0, %0, %2\";
1092 [(set_attr "length" "4,4,2")
1093 (set_attr "insn" "mul")]
1096 (define_insn "*mulsi3_compare0"
1097 [(set (reg:CC_NOOV CC_REGNUM)
1098 (compare:CC_NOOV (mult:SI
1099 (match_operand:SI 2 "s_register_operand" "r,r")
1100 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1102 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1103 (mult:SI (match_dup 2) (match_dup 1)))]
1104 "TARGET_ARM && !arm_arch_xscale"
1105 "mul%?s\\t%0, %2, %1"
1106 [(set_attr "conds" "set")
1107 (set_attr "insn" "muls")]
1110 (define_insn "*mulsi_compare0_scratch"
1111 [(set (reg:CC_NOOV CC_REGNUM)
1112 (compare:CC_NOOV (mult:SI
1113 (match_operand:SI 2 "s_register_operand" "r,r")
1114 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1116 (clobber (match_scratch:SI 0 "=&r,&r"))]
1117 "TARGET_ARM && !arm_arch_xscale"
1118 "mul%?s\\t%0, %2, %1"
1119 [(set_attr "conds" "set")
1120 (set_attr "insn" "muls")]
1123 ;; Unnamed templates to match MLA instruction.
1125 (define_insn "*mulsi3addsi"
1126 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1128 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1129 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1130 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1132 "mla%?\\t%0, %2, %1, %3"
1133 [(set_attr "insn" "mla")
1134 (set_attr "predicable" "yes")]
1137 (define_insn "*mulsi3addsi_compare0"
1138 [(set (reg:CC_NOOV CC_REGNUM)
1141 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1142 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1143 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1145 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1146 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1148 "TARGET_ARM && !arm_arch_xscale"
1149 "mla%?s\\t%0, %2, %1, %3"
1150 [(set_attr "conds" "set")
1151 (set_attr "insn" "mlas")]
1154 (define_insn "*mulsi3addsi_compare0_scratch"
1155 [(set (reg:CC_NOOV CC_REGNUM)
1158 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1159 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1160 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1162 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1163 "TARGET_ARM && !arm_arch_xscale"
1164 "mla%?s\\t%0, %2, %1, %3"
1165 [(set_attr "conds" "set")
1166 (set_attr "insn" "mlas")]
1169 ;; Unnamed template to match long long multiply-accumulate (smlal)
1171 (define_insn "*mulsidi3adddi"
1172 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1175 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1176 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1177 (match_operand:DI 1 "s_register_operand" "0")))]
1178 "TARGET_ARM && arm_arch3m"
1179 "smlal%?\\t%Q0, %R0, %3, %2"
1180 [(set_attr "insn" "smlal")
1181 (set_attr "predicable" "yes")]
1184 (define_insn "mulsidi3"
1185 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1187 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1188 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1189 "TARGET_ARM && arm_arch3m"
1190 "smull%?\\t%Q0, %R0, %1, %2"
1191 [(set_attr "insn" "smull")
1192 (set_attr "predicable" "yes")]
1195 (define_insn "umulsidi3"
1196 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1198 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1199 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1200 "TARGET_ARM && arm_arch3m"
1201 "umull%?\\t%Q0, %R0, %1, %2"
1202 [(set_attr "insn" "umull")
1203 (set_attr "predicable" "yes")]
1206 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1208 (define_insn "*umulsidi3adddi"
1209 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1212 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1213 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1214 (match_operand:DI 1 "s_register_operand" "0")))]
1215 "TARGET_ARM && arm_arch3m"
1216 "umlal%?\\t%Q0, %R0, %3, %2"
1217 [(set_attr "insn" "umlal")
1218 (set_attr "predicable" "yes")]
1221 (define_insn "smulsi3_highpart"
1222 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1226 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1227 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1229 (clobber (match_scratch:SI 3 "=&r,&r"))]
1230 "TARGET_ARM && arm_arch3m"
1231 "smull%?\\t%3, %0, %2, %1"
1232 [(set_attr "insn" "smull")
1233 (set_attr "predicable" "yes")]
1236 (define_insn "umulsi3_highpart"
1237 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1241 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1242 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1244 (clobber (match_scratch:SI 3 "=&r,&r"))]
1245 "TARGET_ARM && arm_arch3m"
1246 "umull%?\\t%3, %0, %2, %1"
1247 [(set_attr "insn" "umull")
1248 (set_attr "predicable" "yes")]
1251 (define_insn "mulhisi3"
1252 [(set (match_operand:SI 0 "s_register_operand" "=r")
1253 (mult:SI (sign_extend:SI
1254 (match_operand:HI 1 "s_register_operand" "%r"))
1256 (match_operand:HI 2 "s_register_operand" "r"))))]
1257 "TARGET_ARM && arm_arch5e"
1258 "smulbb%?\\t%0, %1, %2"
1259 [(set_attr "insn" "smulxy")
1260 (set_attr "predicable" "yes")]
1263 (define_insn "*mulhisi3tb"
1264 [(set (match_operand:SI 0 "s_register_operand" "=r")
1265 (mult:SI (ashiftrt:SI
1266 (match_operand:SI 1 "s_register_operand" "r")
1269 (match_operand:HI 2 "s_register_operand" "r"))))]
1270 "TARGET_ARM && arm_arch5e"
1271 "smultb%?\\t%0, %1, %2"
1272 [(set_attr "insn" "smulxy")
1273 (set_attr "predicable" "yes")]
1276 (define_insn "*mulhisi3bt"
1277 [(set (match_operand:SI 0 "s_register_operand" "=r")
1278 (mult:SI (sign_extend:SI
1279 (match_operand:HI 1 "s_register_operand" "r"))
1281 (match_operand:SI 2 "s_register_operand" "r")
1283 "TARGET_ARM && arm_arch5e"
1284 "smulbt%?\\t%0, %1, %2"
1285 [(set_attr "insn" "smulxy")
1286 (set_attr "predicable" "yes")]
1289 (define_insn "*mulhisi3tt"
1290 [(set (match_operand:SI 0 "s_register_operand" "=r")
1291 (mult:SI (ashiftrt:SI
1292 (match_operand:SI 1 "s_register_operand" "r")
1295 (match_operand:SI 2 "s_register_operand" "r")
1297 "TARGET_ARM && arm_arch5e"
1298 "smultt%?\\t%0, %1, %2"
1299 [(set_attr "insn" "smulxy")
1300 (set_attr "predicable" "yes")]
1303 (define_insn "*mulhisi3addsi"
1304 [(set (match_operand:SI 0 "s_register_operand" "=r")
1305 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1306 (mult:SI (sign_extend:SI
1307 (match_operand:HI 2 "s_register_operand" "%r"))
1309 (match_operand:HI 3 "s_register_operand" "r")))))]
1310 "TARGET_ARM && arm_arch5e"
1311 "smlabb%?\\t%0, %2, %3, %1"
1312 [(set_attr "insn" "smlaxy")
1313 (set_attr "predicable" "yes")]
1316 (define_insn "*mulhidi3adddi"
1317 [(set (match_operand:DI 0 "s_register_operand" "=r")
1319 (match_operand:DI 1 "s_register_operand" "0")
1320 (mult:DI (sign_extend:DI
1321 (match_operand:HI 2 "s_register_operand" "%r"))
1323 (match_operand:HI 3 "s_register_operand" "r")))))]
1324 "TARGET_ARM && arm_arch5e"
1325 "smlalbb%?\\t%Q0, %R0, %2, %3"
1326 [(set_attr "insn" "smlalxy")
1327 (set_attr "predicable" "yes")])
1329 (define_expand "mulsf3"
1330 [(set (match_operand:SF 0 "s_register_operand" "")
1331 (mult:SF (match_operand:SF 1 "s_register_operand" "")
1332 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1333 "TARGET_ARM && TARGET_HARD_FLOAT"
1336 && !cirrus_fp_register (operands[2], SFmode))
1337 operands[2] = force_reg (SFmode, operands[2]);
1340 (define_expand "muldf3"
1341 [(set (match_operand:DF 0 "s_register_operand" "")
1342 (mult:DF (match_operand:DF 1 "s_register_operand" "")
1343 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1344 "TARGET_ARM && TARGET_HARD_FLOAT"
1347 && !cirrus_fp_register (operands[2], DFmode))
1348 operands[2] = force_reg (DFmode, operands[2]);
1353 (define_expand "divsf3"
1354 [(set (match_operand:SF 0 "s_register_operand" "")
1355 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1356 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1357 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1360 (define_expand "divdf3"
1361 [(set (match_operand:DF 0 "s_register_operand" "")
1362 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1363 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1364 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1369 (define_expand "modsf3"
1370 [(set (match_operand:SF 0 "s_register_operand" "")
1371 (mod:SF (match_operand:SF 1 "s_register_operand" "")
1372 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1373 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1376 (define_expand "moddf3"
1377 [(set (match_operand:DF 0 "s_register_operand" "")
1378 (mod:DF (match_operand:DF 1 "s_register_operand" "")
1379 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1380 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1383 ;; Boolean and,ior,xor insns
1385 ;; Split up double word logical operations
1387 ;; Split up simple DImode logical operations. Simply perform the logical
1388 ;; operation on the upper and lower halves of the registers.
1390 [(set (match_operand:DI 0 "s_register_operand" "")
1391 (match_operator:DI 6 "logical_binary_operator"
1392 [(match_operand:DI 1 "s_register_operand" "")
1393 (match_operand:DI 2 "s_register_operand" "")]))]
1394 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1395 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1396 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1399 operands[3] = gen_highpart (SImode, operands[0]);
1400 operands[0] = gen_lowpart (SImode, operands[0]);
1401 operands[4] = gen_highpart (SImode, operands[1]);
1402 operands[1] = gen_lowpart (SImode, operands[1]);
1403 operands[5] = gen_highpart (SImode, operands[2]);
1404 operands[2] = gen_lowpart (SImode, operands[2]);
1409 [(set (match_operand:DI 0 "s_register_operand" "")
1410 (match_operator:DI 6 "logical_binary_operator"
1411 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1412 (match_operand:DI 1 "s_register_operand" "")]))]
1413 "TARGET_ARM && reload_completed"
1414 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1415 (set (match_dup 3) (match_op_dup:SI 6
1416 [(ashiftrt:SI (match_dup 2) (const_int 31))
1420 operands[3] = gen_highpart (SImode, operands[0]);
1421 operands[0] = gen_lowpart (SImode, operands[0]);
1422 operands[4] = gen_highpart (SImode, operands[1]);
1423 operands[1] = gen_lowpart (SImode, operands[1]);
1424 operands[5] = gen_highpart (SImode, operands[2]);
1425 operands[2] = gen_lowpart (SImode, operands[2]);
1429 ;; The zero extend of operand 2 means we can just copy the high part of
1430 ;; operand1 into operand0.
1432 [(set (match_operand:DI 0 "s_register_operand" "")
1434 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1435 (match_operand:DI 1 "s_register_operand" "")))]
1436 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1437 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1438 (set (match_dup 3) (match_dup 4))]
1441 operands[4] = gen_highpart (SImode, operands[1]);
1442 operands[3] = gen_highpart (SImode, operands[0]);
1443 operands[0] = gen_lowpart (SImode, operands[0]);
1444 operands[1] = gen_lowpart (SImode, operands[1]);
1448 ;; The zero extend of operand 2 means we can just copy the high part of
1449 ;; operand1 into operand0.
1451 [(set (match_operand:DI 0 "s_register_operand" "")
1453 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1454 (match_operand:DI 1 "s_register_operand" "")))]
1455 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1456 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1457 (set (match_dup 3) (match_dup 4))]
1460 operands[4] = gen_highpart (SImode, operands[1]);
1461 operands[3] = gen_highpart (SImode, operands[0]);
1462 operands[0] = gen_lowpart (SImode, operands[0]);
1463 operands[1] = gen_lowpart (SImode, operands[1]);
1467 (define_insn "anddi3"
1468 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1469 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1470 (match_operand:DI 2 "s_register_operand" "r,r")))]
1471 "TARGET_ARM && ! TARGET_IWMMXT"
1473 [(set_attr "length" "8")]
1476 (define_insn_and_split "*anddi_zesidi_di"
1477 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1478 (and:DI (zero_extend:DI
1479 (match_operand:SI 2 "s_register_operand" "r,r"))
1480 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1483 "TARGET_ARM && reload_completed"
1484 ; The zero extend of operand 2 clears the high word of the output
1486 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1487 (set (match_dup 3) (const_int 0))]
1490 operands[3] = gen_highpart (SImode, operands[0]);
1491 operands[0] = gen_lowpart (SImode, operands[0]);
1492 operands[1] = gen_lowpart (SImode, operands[1]);
1494 [(set_attr "length" "8")]
1497 (define_insn "*anddi_sesdi_di"
1498 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1499 (and:DI (sign_extend:DI
1500 (match_operand:SI 2 "s_register_operand" "r,r"))
1501 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1504 [(set_attr "length" "8")]
1507 (define_expand "andsi3"
1508 [(set (match_operand:SI 0 "s_register_operand" "")
1509 (and:SI (match_operand:SI 1 "s_register_operand" "")
1510 (match_operand:SI 2 "reg_or_int_operand" "")))]
1515 if (GET_CODE (operands[2]) == CONST_INT)
1517 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1520 ? 0 : preserve_subexpressions_p ()));
1524 else /* TARGET_THUMB */
1526 if (GET_CODE (operands[2]) != CONST_INT)
1527 operands[2] = force_reg (SImode, operands[2]);
1532 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1534 operands[2] = force_reg (SImode,
1535 GEN_INT (~INTVAL (operands[2])));
1537 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1542 for (i = 9; i <= 31; i++)
1544 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1546 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1550 else if ((((HOST_WIDE_INT) 1) << i) - 1
1551 == ~INTVAL (operands[2]))
1553 rtx shift = GEN_INT (i);
1554 rtx reg = gen_reg_rtx (SImode);
1556 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1557 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1563 operands[2] = force_reg (SImode, operands[2]);
1569 (define_insn_and_split "*arm_andsi3_insn"
1570 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1571 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1572 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1576 bic%?\\t%0, %1, #%B2
1579 && GET_CODE (operands[2]) == CONST_INT
1580 && !(const_ok_for_arm (INTVAL (operands[2]))
1581 || const_ok_for_arm (~INTVAL (operands[2])))"
1582 [(clobber (const_int 0))]
1584 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1588 [(set_attr "length" "4,4,16")
1589 (set_attr "predicable" "yes")]
1592 (define_insn "*thumb_andsi3_insn"
1593 [(set (match_operand:SI 0 "register_operand" "=l")
1594 (and:SI (match_operand:SI 1 "register_operand" "%0")
1595 (match_operand:SI 2 "register_operand" "l")))]
1598 [(set_attr "length" "2")]
1601 (define_insn "*andsi3_compare0"
1602 [(set (reg:CC_NOOV CC_REGNUM)
1604 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1605 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1607 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1608 (and:SI (match_dup 1) (match_dup 2)))]
1612 bic%?s\\t%0, %1, #%B2"
1613 [(set_attr "conds" "set")]
1616 (define_insn "*andsi3_compare0_scratch"
1617 [(set (reg:CC_NOOV CC_REGNUM)
1619 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1620 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1622 (clobber (match_scratch:SI 2 "=X,r"))]
1626 bic%?s\\t%2, %0, #%B1"
1627 [(set_attr "conds" "set")]
1630 (define_insn "*zeroextractsi_compare0_scratch"
1631 [(set (reg:CC_NOOV CC_REGNUM)
1632 (compare:CC_NOOV (zero_extract:SI
1633 (match_operand:SI 0 "s_register_operand" "r")
1634 (match_operand 1 "const_int_operand" "n")
1635 (match_operand 2 "const_int_operand" "n"))
1638 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1639 && INTVAL (operands[1]) > 0
1640 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1641 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1643 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1644 << INTVAL (operands[2]));
1645 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1648 [(set_attr "conds" "set")]
1651 (define_insn "*ne_zeroextractsi"
1652 [(set (match_operand:SI 0 "s_register_operand" "=r")
1653 (ne:SI (zero_extract:SI
1654 (match_operand:SI 1 "s_register_operand" "r")
1655 (match_operand:SI 2 "const_int_operand" "n")
1656 (match_operand:SI 3 "const_int_operand" "n"))
1658 (clobber (reg:CC CC_REGNUM))]
1660 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1661 && INTVAL (operands[2]) > 0
1662 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1663 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1665 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1666 << INTVAL (operands[3]));
1667 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1668 return \"movne\\t%0, #1\";
1670 [(set_attr "conds" "clob")
1671 (set_attr "length" "8")]
1675 [(set (match_operand:SI 0 "s_register_operand" "")
1676 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1677 (match_operand:SI 2 "const_int_operand" "")
1678 (match_operand:SI 3 "const_int_operand" "")))
1679 (clobber (match_operand:SI 4 "s_register_operand" ""))]
1681 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1682 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1684 HOST_WIDE_INT temp = INTVAL (operands[2]);
1686 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1687 operands[3] = GEN_INT (32 - temp);
1692 [(set (match_operand:SI 0 "s_register_operand" "")
1693 (match_operator:SI 1 "shiftable_operator"
1694 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1695 (match_operand:SI 3 "const_int_operand" "")
1696 (match_operand:SI 4 "const_int_operand" ""))
1697 (match_operand:SI 5 "s_register_operand" "")]))
1698 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1700 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1703 [(lshiftrt:SI (match_dup 6) (match_dup 4))
1706 HOST_WIDE_INT temp = INTVAL (operands[3]);
1708 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1709 operands[4] = GEN_INT (32 - temp);
1714 [(set (match_operand:SI 0 "s_register_operand" "")
1715 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1716 (match_operand:SI 2 "const_int_operand" "")
1717 (match_operand:SI 3 "const_int_operand" "")))]
1719 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1720 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1722 HOST_WIDE_INT temp = INTVAL (operands[2]);
1724 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1725 operands[3] = GEN_INT (32 - temp);
1730 [(set (match_operand:SI 0 "s_register_operand" "")
1731 (match_operator:SI 1 "shiftable_operator"
1732 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1733 (match_operand:SI 3 "const_int_operand" "")
1734 (match_operand:SI 4 "const_int_operand" ""))
1735 (match_operand:SI 5 "s_register_operand" "")]))
1736 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1738 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1741 [(ashiftrt:SI (match_dup 6) (match_dup 4))
1744 HOST_WIDE_INT temp = INTVAL (operands[3]);
1746 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1747 operands[4] = GEN_INT (32 - temp);
1751 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1752 ;;; represented by the bitfield, then this will produce incorrect results.
1753 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1754 ;;; which have a real bit-field insert instruction, the truncation happens
1755 ;;; in the bit-field insert instruction itself. Since arm does not have a
1756 ;;; bit-field insert instruction, we would have to emit code here to truncate
1757 ;;; the value before we insert. This loses some of the advantage of having
1758 ;;; this insv pattern, so this pattern needs to be reevalutated.
1760 (define_expand "insv"
1761 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1762 (match_operand:SI 1 "general_operand" "")
1763 (match_operand:SI 2 "general_operand" ""))
1764 (match_operand:SI 3 "reg_or_int_operand" ""))]
1768 int start_bit = INTVAL (operands[2]);
1769 int width = INTVAL (operands[1]);
1770 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1771 rtx target, subtarget;
1773 target = operands[0];
1774 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1775 subreg as the final target. */
1776 if (GET_CODE (target) == SUBREG)
1778 subtarget = gen_reg_rtx (SImode);
1779 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1780 < GET_MODE_SIZE (SImode))
1781 target = SUBREG_REG (target);
1786 if (GET_CODE (operands[3]) == CONST_INT)
1788 /* Since we are inserting a known constant, we may be able to
1789 reduce the number of bits that we have to clear so that
1790 the mask becomes simple. */
1791 /* ??? This code does not check to see if the new mask is actually
1792 simpler. It may not be. */
1793 rtx op1 = gen_reg_rtx (SImode);
1794 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1795 start of this pattern. */
1796 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1797 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1799 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1800 emit_insn (gen_iorsi3 (subtarget, op1,
1801 GEN_INT (op3_value << start_bit)));
1803 else if (start_bit == 0
1804 && !(const_ok_for_arm (mask)
1805 || const_ok_for_arm (~mask)))
1807 /* A Trick, since we are setting the bottom bits in the word,
1808 we can shift operand[3] up, operand[0] down, OR them together
1809 and rotate the result back again. This takes 3 insns, and
1810 the third might be mergeable into another op. */
1811 /* The shift up copes with the possibility that operand[3] is
1812 wider than the bitfield. */
1813 rtx op0 = gen_reg_rtx (SImode);
1814 rtx op1 = gen_reg_rtx (SImode);
1816 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1817 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1818 emit_insn (gen_iorsi3 (op1, op1, op0));
1819 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1821 else if ((width + start_bit == 32)
1822 && !(const_ok_for_arm (mask)
1823 || const_ok_for_arm (~mask)))
1825 /* Similar trick, but slightly less efficient. */
1827 rtx op0 = gen_reg_rtx (SImode);
1828 rtx op1 = gen_reg_rtx (SImode);
1830 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1831 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1832 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1833 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1837 rtx op0 = GEN_INT (mask);
1838 rtx op1 = gen_reg_rtx (SImode);
1839 rtx op2 = gen_reg_rtx (SImode);
1841 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1843 rtx tmp = gen_reg_rtx (SImode);
1845 emit_insn (gen_movsi (tmp, op0));
1849 /* Mask out any bits in operand[3] that are not needed. */
1850 emit_insn (gen_andsi3 (op1, operands[3], op0));
1852 if (GET_CODE (op0) == CONST_INT
1853 && (const_ok_for_arm (mask << start_bit)
1854 || const_ok_for_arm (~(mask << start_bit))))
1856 op0 = GEN_INT (~(mask << start_bit));
1857 emit_insn (gen_andsi3 (op2, operands[0], op0));
1861 if (GET_CODE (op0) == CONST_INT)
1863 rtx tmp = gen_reg_rtx (SImode);
1865 emit_insn (gen_movsi (tmp, op0));
1870 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1872 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1876 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1878 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1881 if (subtarget != target)
1883 /* If TARGET is still a SUBREG, then it must be wider than a word,
1884 so we must be careful only to set the subword we were asked to. */
1885 if (GET_CODE (target) == SUBREG)
1886 emit_move_insn (target, subtarget);
1888 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1895 ; constants for op 2 will never be given to these patterns.
1896 (define_insn_and_split "*anddi_notdi_di"
1897 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1898 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1899 (match_operand:DI 2 "s_register_operand" "0,r")))]
1902 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1903 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1904 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1907 operands[3] = gen_highpart (SImode, operands[0]);
1908 operands[0] = gen_lowpart (SImode, operands[0]);
1909 operands[4] = gen_highpart (SImode, operands[1]);
1910 operands[1] = gen_lowpart (SImode, operands[1]);
1911 operands[5] = gen_highpart (SImode, operands[2]);
1912 operands[2] = gen_lowpart (SImode, operands[2]);
1914 [(set_attr "length" "8")
1915 (set_attr "predicable" "yes")]
1918 (define_insn_and_split "*anddi_notzesidi_di"
1919 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1920 (and:DI (not:DI (zero_extend:DI
1921 (match_operand:SI 2 "s_register_operand" "r,r")))
1922 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1925 bic%?\\t%Q0, %Q1, %2
1927 ; (not (zero_extend ...)) allows us to just copy the high word from
1928 ; operand1 to operand0.
1931 && operands[0] != operands[1]"
1932 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1933 (set (match_dup 3) (match_dup 4))]
1936 operands[3] = gen_highpart (SImode, operands[0]);
1937 operands[0] = gen_lowpart (SImode, operands[0]);
1938 operands[4] = gen_highpart (SImode, operands[1]);
1939 operands[1] = gen_lowpart (SImode, operands[1]);
1941 [(set_attr "length" "4,8")
1942 (set_attr "predicable" "yes")]
1945 (define_insn_and_split "*anddi_notsesidi_di"
1946 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1947 (and:DI (not:DI (sign_extend:DI
1948 (match_operand:SI 2 "s_register_operand" "r,r")))
1949 (match_operand:DI 1 "s_register_operand" "0,r")))]
1952 "TARGET_ARM && reload_completed"
1953 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1954 (set (match_dup 3) (and:SI (not:SI
1955 (ashiftrt:SI (match_dup 2) (const_int 31)))
1959 operands[3] = gen_highpart (SImode, operands[0]);
1960 operands[0] = gen_lowpart (SImode, operands[0]);
1961 operands[4] = gen_highpart (SImode, operands[1]);
1962 operands[1] = gen_lowpart (SImode, operands[1]);
1964 [(set_attr "length" "8")
1965 (set_attr "predicable" "yes")]
1968 (define_insn "andsi_notsi_si"
1969 [(set (match_operand:SI 0 "s_register_operand" "=r")
1970 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1971 (match_operand:SI 1 "s_register_operand" "r")))]
1973 "bic%?\\t%0, %1, %2"
1974 [(set_attr "predicable" "yes")]
1977 (define_insn "bicsi3"
1978 [(set (match_operand:SI 0 "register_operand" "=l")
1979 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
1980 (match_operand:SI 2 "register_operand" "0")))]
1983 [(set_attr "length" "2")]
1986 (define_insn "andsi_not_shiftsi_si"
1987 [(set (match_operand:SI 0 "s_register_operand" "=r")
1988 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
1989 [(match_operand:SI 2 "s_register_operand" "r")
1990 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
1991 (match_operand:SI 1 "s_register_operand" "r")))]
1993 "bic%?\\t%0, %1, %2%S4"
1994 [(set_attr "predicable" "yes")
1995 (set_attr "shift" "2")
1996 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
1997 (const_string "alu_shift")
1998 (const_string "alu_shift_reg")))]
2001 (define_insn "*andsi_notsi_si_compare0"
2002 [(set (reg:CC_NOOV CC_REGNUM)
2004 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2005 (match_operand:SI 1 "s_register_operand" "r"))
2007 (set (match_operand:SI 0 "s_register_operand" "=r")
2008 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2010 "bic%?s\\t%0, %1, %2"
2011 [(set_attr "conds" "set")]
2014 (define_insn "*andsi_notsi_si_compare0_scratch"
2015 [(set (reg:CC_NOOV CC_REGNUM)
2017 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2018 (match_operand:SI 1 "s_register_operand" "r"))
2020 (clobber (match_scratch:SI 0 "=r"))]
2022 "bic%?s\\t%0, %1, %2"
2023 [(set_attr "conds" "set")]
2026 (define_insn "iordi3"
2027 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2028 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2029 (match_operand:DI 2 "s_register_operand" "r,r")))]
2030 "TARGET_ARM && ! TARGET_IWMMXT"
2032 [(set_attr "length" "8")
2033 (set_attr "predicable" "yes")]
2036 (define_insn "*iordi_zesidi_di"
2037 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2038 (ior:DI (zero_extend:DI
2039 (match_operand:SI 2 "s_register_operand" "r,r"))
2040 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2043 orr%?\\t%Q0, %Q1, %2
2045 [(set_attr "length" "4,8")
2046 (set_attr "predicable" "yes")]
2049 (define_insn "*iordi_sesidi_di"
2050 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2051 (ior:DI (sign_extend:DI
2052 (match_operand:SI 2 "s_register_operand" "r,r"))
2053 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2056 [(set_attr "length" "8")
2057 (set_attr "predicable" "yes")]
2060 (define_expand "iorsi3"
2061 [(set (match_operand:SI 0 "s_register_operand" "")
2062 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2063 (match_operand:SI 2 "reg_or_int_operand" "")))]
2066 if (GET_CODE (operands[2]) == CONST_INT)
2070 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2073 ? 0 : preserve_subexpressions_p ()));
2076 else /* TARGET_THUMB */
2077 operands [2] = force_reg (SImode, operands [2]);
2082 (define_insn_and_split "*arm_iorsi3"
2083 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2084 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2085 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2091 && GET_CODE (operands[2]) == CONST_INT
2092 && !const_ok_for_arm (INTVAL (operands[2]))"
2093 [(clobber (const_int 0))]
2095 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2099 [(set_attr "length" "4,16")
2100 (set_attr "predicable" "yes")]
2103 (define_insn "*thumb_iorsi3"
2104 [(set (match_operand:SI 0 "register_operand" "=l")
2105 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2106 (match_operand:SI 2 "register_operand" "l")))]
2109 [(set_attr "length" "2")]
2113 [(match_scratch:SI 3 "r")
2114 (set (match_operand:SI 0 "s_register_operand" "")
2115 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2116 (match_operand:SI 2 "const_int_operand" "")))]
2118 && !const_ok_for_arm (INTVAL (operands[2]))
2119 && const_ok_for_arm (~INTVAL (operands[2]))"
2120 [(set (match_dup 3) (match_dup 2))
2121 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2125 (define_insn "*iorsi3_compare0"
2126 [(set (reg:CC_NOOV CC_REGNUM)
2127 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2128 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2130 (set (match_operand:SI 0 "s_register_operand" "=r")
2131 (ior:SI (match_dup 1) (match_dup 2)))]
2133 "orr%?s\\t%0, %1, %2"
2134 [(set_attr "conds" "set")]
2137 (define_insn "*iorsi3_compare0_scratch"
2138 [(set (reg:CC_NOOV CC_REGNUM)
2139 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2140 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2142 (clobber (match_scratch:SI 0 "=r"))]
2144 "orr%?s\\t%0, %1, %2"
2145 [(set_attr "conds" "set")]
2148 (define_insn "xordi3"
2149 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2150 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2151 (match_operand:DI 2 "s_register_operand" "r,r")))]
2152 "TARGET_ARM && !TARGET_IWMMXT"
2154 [(set_attr "length" "8")
2155 (set_attr "predicable" "yes")]
2158 (define_insn "*xordi_zesidi_di"
2159 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2160 (xor:DI (zero_extend:DI
2161 (match_operand:SI 2 "s_register_operand" "r,r"))
2162 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2165 eor%?\\t%Q0, %Q1, %2
2167 [(set_attr "length" "4,8")
2168 (set_attr "predicable" "yes")]
2171 (define_insn "*xordi_sesidi_di"
2172 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2173 (xor:DI (sign_extend:DI
2174 (match_operand:SI 2 "s_register_operand" "r,r"))
2175 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2178 [(set_attr "length" "8")
2179 (set_attr "predicable" "yes")]
2182 (define_expand "xorsi3"
2183 [(set (match_operand:SI 0 "s_register_operand" "")
2184 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2185 (match_operand:SI 2 "arm_rhs_operand" "")))]
2188 if (GET_CODE (operands[2]) == CONST_INT)
2189 operands[2] = force_reg (SImode, operands[2]);
2193 (define_insn "*arm_xorsi3"
2194 [(set (match_operand:SI 0 "s_register_operand" "=r")
2195 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2196 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2198 "eor%?\\t%0, %1, %2"
2199 [(set_attr "predicable" "yes")]
2202 (define_insn "*thumb_xorsi3"
2203 [(set (match_operand:SI 0 "register_operand" "=l")
2204 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2205 (match_operand:SI 2 "register_operand" "l")))]
2208 [(set_attr "length" "2")]
2211 (define_insn "*xorsi3_compare0"
2212 [(set (reg:CC_NOOV CC_REGNUM)
2213 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2214 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2216 (set (match_operand:SI 0 "s_register_operand" "=r")
2217 (xor:SI (match_dup 1) (match_dup 2)))]
2219 "eor%?s\\t%0, %1, %2"
2220 [(set_attr "conds" "set")]
2223 (define_insn "*xorsi3_compare0_scratch"
2224 [(set (reg:CC_NOOV CC_REGNUM)
2225 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2226 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2230 [(set_attr "conds" "set")]
2233 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2234 ; (NOT D) we can sometimes merge the final NOT into one of the following
2238 [(set (match_operand:SI 0 "s_register_operand" "")
2239 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2240 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2241 (match_operand:SI 3 "arm_rhs_operand" "")))
2242 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2244 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2245 (not:SI (match_dup 3))))
2246 (set (match_dup 0) (not:SI (match_dup 4)))]
2250 (define_insn "*andsi_iorsi3_notsi"
2251 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2252 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2253 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2254 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2256 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2257 [(set_attr "length" "8")
2258 (set_attr "predicable" "yes")]
2262 [(set (match_operand:SI 0 "s_register_operand" "")
2263 (match_operator:SI 1 "logical_binary_operator"
2264 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2265 (match_operand:SI 3 "const_int_operand" "")
2266 (match_operand:SI 4 "const_int_operand" ""))
2267 (match_operator:SI 9 "logical_binary_operator"
2268 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2269 (match_operand:SI 6 "const_int_operand" ""))
2270 (match_operand:SI 7 "s_register_operand" "")])]))
2271 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2273 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2274 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2277 [(ashift:SI (match_dup 2) (match_dup 4))
2281 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2284 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2288 [(set (match_operand:SI 0 "s_register_operand" "")
2289 (match_operator:SI 1 "logical_binary_operator"
2290 [(match_operator:SI 9 "logical_binary_operator"
2291 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2292 (match_operand:SI 6 "const_int_operand" ""))
2293 (match_operand:SI 7 "s_register_operand" "")])
2294 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2295 (match_operand:SI 3 "const_int_operand" "")
2296 (match_operand:SI 4 "const_int_operand" ""))]))
2297 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2299 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2300 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2303 [(ashift:SI (match_dup 2) (match_dup 4))
2307 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2310 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2314 [(set (match_operand:SI 0 "s_register_operand" "")
2315 (match_operator:SI 1 "logical_binary_operator"
2316 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2317 (match_operand:SI 3 "const_int_operand" "")
2318 (match_operand:SI 4 "const_int_operand" ""))
2319 (match_operator:SI 9 "logical_binary_operator"
2320 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2321 (match_operand:SI 6 "const_int_operand" ""))
2322 (match_operand:SI 7 "s_register_operand" "")])]))
2323 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2325 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2326 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2329 [(ashift:SI (match_dup 2) (match_dup 4))
2333 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2336 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2340 [(set (match_operand:SI 0 "s_register_operand" "")
2341 (match_operator:SI 1 "logical_binary_operator"
2342 [(match_operator:SI 9 "logical_binary_operator"
2343 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2344 (match_operand:SI 6 "const_int_operand" ""))
2345 (match_operand:SI 7 "s_register_operand" "")])
2346 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2347 (match_operand:SI 3 "const_int_operand" "")
2348 (match_operand:SI 4 "const_int_operand" ""))]))
2349 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2351 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2352 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2355 [(ashift:SI (match_dup 2) (match_dup 4))
2359 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2362 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2366 ;; Minimum and maximum insns
2368 (define_insn "smaxsi3"
2369 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2370 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2371 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2372 (clobber (reg:CC CC_REGNUM))]
2375 cmp\\t%1, %2\;movlt\\t%0, %2
2376 cmp\\t%1, %2\;movge\\t%0, %1
2377 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2378 [(set_attr "conds" "clob")
2379 (set_attr "length" "8,8,12")]
2382 (define_insn "sminsi3"
2383 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2384 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2385 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2386 (clobber (reg:CC CC_REGNUM))]
2389 cmp\\t%1, %2\;movge\\t%0, %2
2390 cmp\\t%1, %2\;movlt\\t%0, %1
2391 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2392 [(set_attr "conds" "clob")
2393 (set_attr "length" "8,8,12")]
2396 (define_insn "umaxsi3"
2397 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2398 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2399 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2400 (clobber (reg:CC CC_REGNUM))]
2403 cmp\\t%1, %2\;movcc\\t%0, %2
2404 cmp\\t%1, %2\;movcs\\t%0, %1
2405 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2406 [(set_attr "conds" "clob")
2407 (set_attr "length" "8,8,12")]
2410 (define_insn "uminsi3"
2411 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2412 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2413 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2414 (clobber (reg:CC CC_REGNUM))]
2417 cmp\\t%1, %2\;movcs\\t%0, %2
2418 cmp\\t%1, %2\;movcc\\t%0, %1
2419 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2420 [(set_attr "conds" "clob")
2421 (set_attr "length" "8,8,12")]
2424 (define_insn "*store_minmaxsi"
2425 [(set (match_operand:SI 0 "memory_operand" "=m")
2426 (match_operator:SI 3 "minmax_operator"
2427 [(match_operand:SI 1 "s_register_operand" "r")
2428 (match_operand:SI 2 "s_register_operand" "r")]))
2429 (clobber (reg:CC CC_REGNUM))]
2432 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2433 operands[1], operands[2]);
2434 output_asm_insn (\"cmp\\t%1, %2\", operands);
2435 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2436 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2439 [(set_attr "conds" "clob")
2440 (set_attr "length" "12")
2441 (set_attr "type" "store1")]
2444 ; Reject the frame pointer in operand[1], since reloading this after
2445 ; it has been eliminated can cause carnage.
2446 (define_insn "*minmax_arithsi"
2447 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2448 (match_operator:SI 4 "shiftable_operator"
2449 [(match_operator:SI 5 "minmax_operator"
2450 [(match_operand:SI 2 "s_register_operand" "r,r")
2451 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2452 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2453 (clobber (reg:CC CC_REGNUM))]
2455 && (GET_CODE (operands[1]) != REG
2456 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2457 && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2460 enum rtx_code code = GET_CODE (operands[4]);
2462 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2463 operands[2], operands[3]);
2464 output_asm_insn (\"cmp\\t%2, %3\", operands);
2465 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2466 if (which_alternative != 0 || operands[3] != const0_rtx
2467 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2468 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2471 [(set_attr "conds" "clob")
2472 (set_attr "length" "12")]
2476 ;; Shift and rotation insns
2478 (define_expand "ashldi3"
2479 [(set (match_operand:DI 0 "s_register_operand" "")
2480 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2481 (match_operand:SI 2 "reg_or_int_operand" "")))]
2484 if (GET_CODE (operands[2]) == CONST_INT)
2486 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2488 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2491 /* Ideally we shouldn't fail here if we could know that operands[1]
2492 ends up already living in an iwmmxt register. Otherwise it's
2493 cheaper to have the alternate code being generated than moving
2494 values to iwmmxt regs and back. */
2497 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2502 (define_insn "arm_ashldi3_1bit"
2503 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2504 (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2506 (clobber (reg:CC CC_REGNUM))]
2508 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2509 [(set_attr "conds" "clob")
2510 (set_attr "length" "8")]
2513 (define_expand "ashlsi3"
2514 [(set (match_operand:SI 0 "s_register_operand" "")
2515 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2516 (match_operand:SI 2 "arm_rhs_operand" "")))]
2519 if (GET_CODE (operands[2]) == CONST_INT
2520 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2522 emit_insn (gen_movsi (operands[0], const0_rtx));
2528 (define_insn "*thumb_ashlsi3"
2529 [(set (match_operand:SI 0 "register_operand" "=l,l")
2530 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2531 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2534 [(set_attr "length" "2")]
2537 (define_expand "ashrdi3"
2538 [(set (match_operand:DI 0 "s_register_operand" "")
2539 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2540 (match_operand:SI 2 "reg_or_int_operand" "")))]
2543 if (GET_CODE (operands[2]) == CONST_INT)
2545 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2547 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2550 /* Ideally we shouldn't fail here if we could know that operands[1]
2551 ends up already living in an iwmmxt register. Otherwise it's
2552 cheaper to have the alternate code being generated than moving
2553 values to iwmmxt regs and back. */
2556 else if (!TARGET_REALLY_IWMMXT)
2561 (define_insn "arm_ashrdi3_1bit"
2562 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2563 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2565 (clobber (reg:CC CC_REGNUM))]
2567 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2568 [(set_attr "conds" "clob")
2569 (set_attr "length" "8")]
2572 (define_expand "ashrsi3"
2573 [(set (match_operand:SI 0 "s_register_operand" "")
2574 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2575 (match_operand:SI 2 "arm_rhs_operand" "")))]
2578 if (GET_CODE (operands[2]) == CONST_INT
2579 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2580 operands[2] = GEN_INT (31);
2584 (define_insn "*thumb_ashrsi3"
2585 [(set (match_operand:SI 0 "register_operand" "=l,l")
2586 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2587 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2590 [(set_attr "length" "2")]
2593 (define_expand "lshrdi3"
2594 [(set (match_operand:DI 0 "s_register_operand" "")
2595 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2596 (match_operand:SI 2 "reg_or_int_operand" "")))]
2599 if (GET_CODE (operands[2]) == CONST_INT)
2601 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2603 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2606 /* Ideally we shouldn't fail here if we could know that operands[1]
2607 ends up already living in an iwmmxt register. Otherwise it's
2608 cheaper to have the alternate code being generated than moving
2609 values to iwmmxt regs and back. */
2612 else if (!TARGET_REALLY_IWMMXT)
2617 (define_insn "arm_lshrdi3_1bit"
2618 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2619 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2621 (clobber (reg:CC CC_REGNUM))]
2623 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2624 [(set_attr "conds" "clob")
2625 (set_attr "length" "8")]
2628 (define_expand "lshrsi3"
2629 [(set (match_operand:SI 0 "s_register_operand" "")
2630 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2631 (match_operand:SI 2 "arm_rhs_operand" "")))]
2634 if (GET_CODE (operands[2]) == CONST_INT
2635 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2637 emit_insn (gen_movsi (operands[0], const0_rtx));
2643 (define_insn "*thumb_lshrsi3"
2644 [(set (match_operand:SI 0 "register_operand" "=l,l")
2645 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2646 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2649 [(set_attr "length" "2")]
2652 (define_expand "rotlsi3"
2653 [(set (match_operand:SI 0 "s_register_operand" "")
2654 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2655 (match_operand:SI 2 "reg_or_int_operand" "")))]
2658 if (GET_CODE (operands[2]) == CONST_INT)
2659 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2662 rtx reg = gen_reg_rtx (SImode);
2663 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2669 (define_expand "rotrsi3"
2670 [(set (match_operand:SI 0 "s_register_operand" "")
2671 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2672 (match_operand:SI 2 "arm_rhs_operand" "")))]
2677 if (GET_CODE (operands[2]) == CONST_INT
2678 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2679 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2681 else /* TARGET_THUMB */
2683 if (GET_CODE (operands [2]) == CONST_INT)
2684 operands [2] = force_reg (SImode, operands[2]);
2689 (define_insn "*thumb_rotrsi3"
2690 [(set (match_operand:SI 0 "register_operand" "=l")
2691 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2692 (match_operand:SI 2 "register_operand" "l")))]
2695 [(set_attr "length" "2")]
2698 (define_insn "*arm_shiftsi3"
2699 [(set (match_operand:SI 0 "s_register_operand" "=r")
2700 (match_operator:SI 3 "shift_operator"
2701 [(match_operand:SI 1 "s_register_operand" "r")
2702 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2705 [(set_attr "predicable" "yes")
2706 (set_attr "shift" "1")
2707 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2708 (const_string "alu_shift")
2709 (const_string "alu_shift_reg")))]
2712 (define_insn "*shiftsi3_compare0"
2713 [(set (reg:CC_NOOV CC_REGNUM)
2714 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2715 [(match_operand:SI 1 "s_register_operand" "r")
2716 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2718 (set (match_operand:SI 0 "s_register_operand" "=r")
2719 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2721 "mov%?s\\t%0, %1%S3"
2722 [(set_attr "conds" "set")
2723 (set_attr "shift" "1")
2724 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2725 (const_string "alu_shift")
2726 (const_string "alu_shift_reg")))]
2729 (define_insn "*shiftsi3_compare0_scratch"
2730 [(set (reg:CC_NOOV CC_REGNUM)
2731 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2732 [(match_operand:SI 1 "s_register_operand" "r")
2733 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2735 (clobber (match_scratch:SI 0 "=r"))]
2737 "mov%?s\\t%0, %1%S3"
2738 [(set_attr "conds" "set")
2739 (set_attr "shift" "1")]
2742 (define_insn "*notsi_shiftsi"
2743 [(set (match_operand:SI 0 "s_register_operand" "=r")
2744 (not:SI (match_operator:SI 3 "shift_operator"
2745 [(match_operand:SI 1 "s_register_operand" "r")
2746 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2749 [(set_attr "predicable" "yes")
2750 (set_attr "shift" "1")
2751 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2752 (const_string "alu_shift")
2753 (const_string "alu_shift_reg")))]
2756 (define_insn "*notsi_shiftsi_compare0"
2757 [(set (reg:CC_NOOV CC_REGNUM)
2758 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2759 [(match_operand:SI 1 "s_register_operand" "r")
2760 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2762 (set (match_operand:SI 0 "s_register_operand" "=r")
2763 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2765 "mvn%?s\\t%0, %1%S3"
2766 [(set_attr "conds" "set")
2767 (set_attr "shift" "1")
2768 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2769 (const_string "alu_shift")
2770 (const_string "alu_shift_reg")))]
2773 (define_insn "*not_shiftsi_compare0_scratch"
2774 [(set (reg:CC_NOOV CC_REGNUM)
2775 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2776 [(match_operand:SI 1 "s_register_operand" "r")
2777 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2779 (clobber (match_scratch:SI 0 "=r"))]
2781 "mvn%?s\\t%0, %1%S3"
2782 [(set_attr "conds" "set")
2783 (set_attr "shift" "1")
2784 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2785 (const_string "alu_shift")
2786 (const_string "alu_shift_reg")))]
2789 ;; We don't really have extzv, but defining this using shifts helps
2790 ;; to reduce register pressure later on.
2792 (define_expand "extzv"
2794 (ashift:SI (match_operand:SI 1 "register_operand" "")
2795 (match_operand:SI 2 "const_int_operand" "")))
2796 (set (match_operand:SI 0 "register_operand" "")
2797 (lshiftrt:SI (match_dup 4)
2798 (match_operand:SI 3 "const_int_operand" "")))]
2802 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2803 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2805 operands[3] = GEN_INT (rshift);
2809 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2813 operands[2] = GEN_INT (lshift);
2814 operands[4] = gen_reg_rtx (SImode);
2819 ;; Unary arithmetic insns
2821 (define_expand "negdi2"
2823 [(set (match_operand:DI 0 "s_register_operand" "")
2824 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2825 (clobber (reg:CC CC_REGNUM))])]
2830 if (GET_CODE (operands[1]) != REG)
2831 operands[1] = force_reg (SImode, operands[1]);
2836 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2837 ;; The second alternative is to allow the common case of a *full* overlap.
2838 (define_insn "*arm_negdi2"
2839 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2840 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2841 (clobber (reg:CC CC_REGNUM))]
2843 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2844 [(set_attr "conds" "clob")
2845 (set_attr "length" "8")]
2848 (define_insn "*thumb_negdi2"
2849 [(set (match_operand:DI 0 "register_operand" "=&l")
2850 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2851 (clobber (reg:CC CC_REGNUM))]
2853 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2854 [(set_attr "length" "6")]
2857 (define_expand "negsi2"
2858 [(set (match_operand:SI 0 "s_register_operand" "")
2859 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2864 (define_insn "*arm_negsi2"
2865 [(set (match_operand:SI 0 "s_register_operand" "=r")
2866 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2868 "rsb%?\\t%0, %1, #0"
2869 [(set_attr "predicable" "yes")]
2872 (define_insn "*thumb_negsi2"
2873 [(set (match_operand:SI 0 "register_operand" "=l")
2874 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2877 [(set_attr "length" "2")]
2880 (define_expand "negsf2"
2881 [(set (match_operand:SF 0 "s_register_operand" "")
2882 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2883 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2887 (define_expand "negdf2"
2888 [(set (match_operand:DF 0 "s_register_operand" "")
2889 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2890 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2893 ;; abssi2 doesn't really clobber the condition codes if a different register
2894 ;; is being set. To keep things simple, assume during rtl manipulations that
2895 ;; it does, but tell the final scan operator the truth. Similarly for
2898 (define_expand "abssi2"
2900 [(set (match_operand:SI 0 "s_register_operand" "")
2901 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2902 (clobber (reg:CC CC_REGNUM))])]
2906 (define_insn "*arm_abssi2"
2907 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2908 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2909 (clobber (reg:CC CC_REGNUM))]
2912 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2913 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2914 [(set_attr "conds" "clob,*")
2915 (set_attr "shift" "1")
2916 ;; predicable can't be set based on the variant, so left as no
2917 (set_attr "length" "8")]
2920 (define_insn "*neg_abssi2"
2921 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2922 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2923 (clobber (reg:CC CC_REGNUM))]
2926 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2927 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2928 [(set_attr "conds" "clob,*")
2929 (set_attr "shift" "1")
2930 ;; predicable can't be set based on the variant, so left as no
2931 (set_attr "length" "8")]
2934 (define_expand "abssf2"
2935 [(set (match_operand:SF 0 "s_register_operand" "")
2936 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
2937 "TARGET_ARM && TARGET_HARD_FLOAT"
2940 (define_expand "absdf2"
2941 [(set (match_operand:DF 0 "s_register_operand" "")
2942 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
2943 "TARGET_ARM && TARGET_HARD_FLOAT"
2946 (define_expand "sqrtsf2"
2947 [(set (match_operand:SF 0 "s_register_operand" "")
2948 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
2949 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2952 (define_expand "sqrtdf2"
2953 [(set (match_operand:DF 0 "s_register_operand" "")
2954 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
2955 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2958 (define_insn_and_split "one_cmpldi2"
2959 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2960 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2963 "TARGET_ARM && reload_completed"
2964 [(set (match_dup 0) (not:SI (match_dup 1)))
2965 (set (match_dup 2) (not:SI (match_dup 3)))]
2968 operands[2] = gen_highpart (SImode, operands[0]);
2969 operands[0] = gen_lowpart (SImode, operands[0]);
2970 operands[3] = gen_highpart (SImode, operands[1]);
2971 operands[1] = gen_lowpart (SImode, operands[1]);
2973 [(set_attr "length" "8")
2974 (set_attr "predicable" "yes")]
2977 (define_expand "one_cmplsi2"
2978 [(set (match_operand:SI 0 "s_register_operand" "")
2979 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2984 (define_insn "*arm_one_cmplsi2"
2985 [(set (match_operand:SI 0 "s_register_operand" "=r")
2986 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
2989 [(set_attr "predicable" "yes")]
2992 (define_insn "*thumb_one_cmplsi2"
2993 [(set (match_operand:SI 0 "register_operand" "=l")
2994 (not:SI (match_operand:SI 1 "register_operand" "l")))]
2997 [(set_attr "length" "2")]
3000 (define_insn "*notsi_compare0"
3001 [(set (reg:CC_NOOV CC_REGNUM)
3002 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3004 (set (match_operand:SI 0 "s_register_operand" "=r")
3005 (not:SI (match_dup 1)))]
3008 [(set_attr "conds" "set")]
3011 (define_insn "*notsi_compare0_scratch"
3012 [(set (reg:CC_NOOV CC_REGNUM)
3013 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3015 (clobber (match_scratch:SI 0 "=r"))]
3018 [(set_attr "conds" "set")]
3021 ;; Fixed <--> Floating conversion insns
3023 (define_expand "floatsisf2"
3024 [(set (match_operand:SF 0 "s_register_operand" "")
3025 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3026 "TARGET_ARM && TARGET_HARD_FLOAT"
3028 if (TARGET_MAVERICK)
3030 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3035 (define_expand "floatsidf2"
3036 [(set (match_operand:DF 0 "s_register_operand" "")
3037 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3038 "TARGET_ARM && TARGET_HARD_FLOAT"
3040 if (TARGET_MAVERICK)
3042 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3047 (define_expand "fix_truncsfsi2"
3048 [(set (match_operand:SI 0 "s_register_operand" "")
3049 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
3050 "TARGET_ARM && TARGET_HARD_FLOAT"
3052 if (TARGET_MAVERICK)
3054 if (!cirrus_fp_register (operands[0], SImode))
3055 operands[0] = force_reg (SImode, operands[0]);
3056 if (!cirrus_fp_register (operands[1], SFmode))
3057 operands[1] = force_reg (SFmode, operands[0]);
3058 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3063 (define_expand "fix_truncdfsi2"
3064 [(set (match_operand:SI 0 "s_register_operand" "")
3065 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
3066 "TARGET_ARM && TARGET_HARD_FLOAT"
3068 if (TARGET_MAVERICK)
3070 if (!cirrus_fp_register (operands[1], DFmode))
3071 operands[1] = force_reg (DFmode, operands[0]);
3072 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3079 (define_expand "truncdfsf2"
3080 [(set (match_operand:SF 0 "s_register_operand" "")
3082 (match_operand:DF 1 "s_register_operand" "")))]
3083 "TARGET_ARM && TARGET_HARD_FLOAT"
3087 ;; Zero and sign extension instructions.
3089 (define_insn "zero_extendsidi2"
3090 [(set (match_operand:DI 0 "s_register_operand" "=r")
3091 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3094 if (REGNO (operands[1])
3095 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3096 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3097 return \"mov%?\\t%R0, #0\";
3099 [(set_attr "length" "8")
3100 (set_attr "predicable" "yes")]
3103 (define_insn "zero_extendqidi2"
3104 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
3105 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3108 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3109 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3110 [(set_attr "length" "8")
3111 (set_attr "predicable" "yes")
3112 (set_attr "type" "*,load_byte")
3113 (set_attr "pool_range" "*,4092")
3114 (set_attr "neg_pool_range" "*,4084")]
3117 (define_insn "extendsidi2"
3118 [(set (match_operand:DI 0 "s_register_operand" "=r")
3119 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3122 if (REGNO (operands[1])
3123 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3124 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3125 return \"mov%?\\t%R0, %Q0, asr #31\";
3127 [(set_attr "length" "8")
3128 (set_attr "shift" "1")
3129 (set_attr "predicable" "yes")]
3132 (define_expand "zero_extendhisi2"
3134 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3136 (set (match_operand:SI 0 "s_register_operand" "")
3137 (lshiftrt:SI (match_dup 2) (const_int 16)))]
3141 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3143 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3144 here because the insn below will generate an LDRH instruction
3145 rather than an LDR instruction, so we cannot get an unaligned
3147 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3148 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3152 if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3154 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3158 if (!s_register_operand (operands[1], HImode))
3159 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3163 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3164 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3168 operands[1] = gen_lowpart (SImode, operands[1]);
3169 operands[2] = gen_reg_rtx (SImode);
3173 (define_insn "*thumb_zero_extendhisi2"
3174 [(set (match_operand:SI 0 "register_operand" "=l")
3175 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3176 "TARGET_THUMB && !arm_arch6"
3178 rtx mem = XEXP (operands[1], 0);
3180 if (GET_CODE (mem) == CONST)
3181 mem = XEXP (mem, 0);
3183 if (GET_CODE (mem) == LABEL_REF)
3184 return \"ldr\\t%0, %1\";
3186 if (GET_CODE (mem) == PLUS)
3188 rtx a = XEXP (mem, 0);
3189 rtx b = XEXP (mem, 1);
3191 /* This can happen due to bugs in reload. */
3192 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3195 ops[0] = operands[0];
3198 output_asm_insn (\"mov %0, %1\", ops);
3200 XEXP (mem, 0) = operands[0];
3203 else if ( GET_CODE (a) == LABEL_REF
3204 && GET_CODE (b) == CONST_INT)
3205 return \"ldr\\t%0, %1\";
3208 return \"ldrh\\t%0, %1\";
3210 [(set_attr "length" "4")
3211 (set_attr "type" "load_byte")
3212 (set_attr "pool_range" "60")]
3215 (define_insn "*thumb_zero_extendhisi2_v6"
3216 [(set (match_operand:SI 0 "register_operand" "=l,l")
3217 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3218 "TARGET_THUMB && arm_arch6"
3222 if (which_alternative == 0)
3223 return \"uxth\\t%0, %1\";
3225 mem = XEXP (operands[1], 0);
3227 if (GET_CODE (mem) == CONST)
3228 mem = XEXP (mem, 0);
3230 if (GET_CODE (mem) == LABEL_REF)
3231 return \"ldr\\t%0, %1\";
3233 if (GET_CODE (mem) == PLUS)
3235 rtx a = XEXP (mem, 0);
3236 rtx b = XEXP (mem, 1);
3238 /* This can happen due to bugs in reload. */
3239 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3242 ops[0] = operands[0];
3245 output_asm_insn (\"mov %0, %1\", ops);
3247 XEXP (mem, 0) = operands[0];
3250 else if ( GET_CODE (a) == LABEL_REF
3251 && GET_CODE (b) == CONST_INT)
3252 return \"ldr\\t%0, %1\";
3255 return \"ldrh\\t%0, %1\";
3257 [(set_attr "length" "2,4")
3258 (set_attr "type" "alu_shift,load_byte")
3259 (set_attr "pool_range" "*,60")]
3262 (define_insn "*arm_zero_extendhisi2"
3263 [(set (match_operand:SI 0 "s_register_operand" "=r")
3264 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3265 "TARGET_ARM && arm_arch4 && !arm_arch6"
3267 [(set_attr "type" "load_byte")
3268 (set_attr "predicable" "yes")
3269 (set_attr "pool_range" "256")
3270 (set_attr "neg_pool_range" "244")]
3273 (define_insn "*arm_zero_extendhisi2_v6"
3274 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3275 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3276 "TARGET_ARM && arm_arch6"
3280 [(set_attr "type" "alu_shift,load_byte")
3281 (set_attr "predicable" "yes")
3282 (set_attr "pool_range" "*,256")
3283 (set_attr "neg_pool_range" "*,244")]
3286 (define_insn "*arm_zero_extendhisi2addsi"
3287 [(set (match_operand:SI 0 "s_register_operand" "=r")
3288 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3289 (match_operand:SI 2 "s_register_operand" "r")))]
3290 "TARGET_ARM && arm_arch6"
3291 "uxtah%?\\t%0, %2, %1"
3292 [(set_attr "type" "alu_shift")
3293 (set_attr "predicable" "yes")]
3297 [(set (match_operand:SI 0 "s_register_operand" "")
3298 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3299 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3300 "TARGET_ARM && (!arm_arch4)"
3301 [(set (match_dup 2) (match_dup 1))
3302 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3304 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3310 [(set (match_operand:SI 0 "s_register_operand" "")
3311 (match_operator:SI 3 "shiftable_operator"
3312 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3313 (match_operand:SI 4 "s_register_operand" "")]))
3314 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3315 "TARGET_ARM && (!arm_arch4)"
3316 [(set (match_dup 2) (match_dup 1))
3319 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3321 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3326 (define_expand "zero_extendqisi2"
3327 [(set (match_operand:SI 0 "s_register_operand" "")
3328 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3331 if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3335 emit_insn (gen_andsi3 (operands[0],
3336 gen_lowpart (SImode, operands[1]),
3339 else /* TARGET_THUMB */
3341 rtx temp = gen_reg_rtx (SImode);
3344 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3345 operands[1] = gen_lowpart (SImode, operands[1]);
3348 ops[1] = operands[1];
3349 ops[2] = GEN_INT (24);
3351 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3352 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3354 ops[0] = operands[0];
3356 ops[2] = GEN_INT (24);
3358 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3359 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3366 (define_insn "*thumb_zero_extendqisi2"
3367 [(set (match_operand:SI 0 "register_operand" "=l")
3368 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3369 "TARGET_THUMB && !arm_arch6"
3371 [(set_attr "length" "2")
3372 (set_attr "type" "load_byte")
3373 (set_attr "pool_range" "32")]
3376 (define_insn "*thumb_zero_extendqisi2_v6"
3377 [(set (match_operand:SI 0 "register_operand" "=l,l")
3378 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3379 "TARGET_THUMB && arm_arch6"
3383 [(set_attr "length" "2,2")
3384 (set_attr "type" "alu_shift,load_byte")
3385 (set_attr "pool_range" "*,32")]
3388 (define_insn "*arm_zero_extendqisi2"
3389 [(set (match_operand:SI 0 "s_register_operand" "=r")
3390 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3391 "TARGET_ARM && !arm_arch6"
3392 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3393 [(set_attr "type" "load_byte")
3394 (set_attr "predicable" "yes")
3395 (set_attr "pool_range" "4096")
3396 (set_attr "neg_pool_range" "4084")]
3399 (define_insn "*arm_zero_extendqisi2_v6"
3400 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3401 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3402 "TARGET_ARM && arm_arch6"
3405 ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3406 [(set_attr "type" "alu_shift,load_byte")
3407 (set_attr "predicable" "yes")
3408 (set_attr "pool_range" "*,4096")
3409 (set_attr "neg_pool_range" "*,4084")]
3412 (define_insn "*arm_zero_extendqisi2addsi"
3413 [(set (match_operand:SI 0 "s_register_operand" "=r")
3414 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3415 (match_operand:SI 2 "s_register_operand" "r")))]
3416 "TARGET_ARM && arm_arch6"
3417 "uxtab%?\\t%0, %2, %1"
3418 [(set_attr "predicable" "yes")
3419 (set_attr "type" "alu_shift")]
3423 [(set (match_operand:SI 0 "s_register_operand" "")
3424 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3425 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3426 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3427 [(set (match_dup 2) (match_dup 1))
3428 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3432 (define_insn "*compareqi_eq0"
3433 [(set (reg:CC_Z CC_REGNUM)
3434 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3438 [(set_attr "conds" "set")]
3441 (define_expand "extendhisi2"
3443 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3445 (set (match_operand:SI 0 "s_register_operand" "")
3446 (ashiftrt:SI (match_dup 2)
3451 if (GET_CODE (operands[1]) == MEM)
3455 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3460 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3461 here because the insn below will generate an LDRH instruction
3462 rather than an LDR instruction, so we cannot get an unaligned
3464 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3465 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3470 if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3472 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3476 if (!s_register_operand (operands[1], HImode))
3477 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3482 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3484 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3485 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3490 operands[1] = gen_lowpart (SImode, operands[1]);
3491 operands[2] = gen_reg_rtx (SImode);
3495 (define_insn "thumb_extendhisi2"
3496 [(set (match_operand:SI 0 "register_operand" "=l")
3497 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3498 (clobber (match_scratch:SI 2 "=&l"))]
3499 "TARGET_THUMB && !arm_arch6"
3503 rtx mem = XEXP (operands[1], 0);
3505 /* This code used to try to use 'V', and fix the address only if it was
3506 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3507 range of QImode offsets, and offsettable_address_p does a QImode
3510 if (GET_CODE (mem) == CONST)
3511 mem = XEXP (mem, 0);
3513 if (GET_CODE (mem) == LABEL_REF)
3514 return \"ldr\\t%0, %1\";
3516 if (GET_CODE (mem) == PLUS)
3518 rtx a = XEXP (mem, 0);
3519 rtx b = XEXP (mem, 1);
3521 if (GET_CODE (a) == LABEL_REF
3522 && GET_CODE (b) == CONST_INT)
3523 return \"ldr\\t%0, %1\";
3525 if (GET_CODE (b) == REG)
3526 return \"ldrsh\\t%0, %1\";
3534 ops[2] = const0_rtx;
3537 if (GET_CODE (ops[1]) != REG)
3543 ops[0] = operands[0];
3544 ops[3] = operands[2];
3545 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3548 [(set_attr "length" "4")
3549 (set_attr "type" "load_byte")
3550 (set_attr "pool_range" "1020")]
3553 ;; We used to have an early-clobber on the scratch register here.
3554 ;; However, there's a bug somewhere in reload which means that this
3555 ;; can be partially ignored during spill allocation if the memory
3556 ;; address also needs reloading; this causes an abort later on when
3557 ;; we try to verify the operands. Fortunately, we don't really need
3558 ;; the early-clobber: we can always use operand 0 if operand 2
3559 ;; overlaps the address.
3560 (define_insn "*thumb_extendhisi2_insn_v6"
3561 [(set (match_operand:SI 0 "register_operand" "=l,l")
3562 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3563 (clobber (match_scratch:SI 2 "=X,l"))]
3564 "TARGET_THUMB && arm_arch6"
3570 if (which_alternative == 0)
3571 return \"sxth\\t%0, %1\";
3573 mem = XEXP (operands[1], 0);
3575 /* This code used to try to use 'V', and fix the address only if it was
3576 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3577 range of QImode offsets, and offsettable_address_p does a QImode
3580 if (GET_CODE (mem) == CONST)
3581 mem = XEXP (mem, 0);
3583 if (GET_CODE (mem) == LABEL_REF)
3584 return \"ldr\\t%0, %1\";
3586 if (GET_CODE (mem) == PLUS)
3588 rtx a = XEXP (mem, 0);
3589 rtx b = XEXP (mem, 1);
3591 if (GET_CODE (a) == LABEL_REF
3592 && GET_CODE (b) == CONST_INT)
3593 return \"ldr\\t%0, %1\";
3595 if (GET_CODE (b) == REG)
3596 return \"ldrsh\\t%0, %1\";
3604 ops[2] = const0_rtx;
3607 if (GET_CODE (ops[1]) != REG)
3613 ops[0] = operands[0];
3614 if (reg_mentioned_p (operands[2], ops[1]))
3617 ops[3] = operands[2];
3618 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3621 [(set_attr "length" "2,4")
3622 (set_attr "type" "alu_shift,load_byte")
3623 (set_attr "pool_range" "*,1020")]
3626 (define_expand "extendhisi2_mem"
3627 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3629 (zero_extend:SI (match_dup 7)))
3630 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3631 (set (match_operand:SI 0 "" "")
3632 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3637 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3639 mem1 = gen_rtx_MEM (QImode, addr);
3640 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3641 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3642 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3643 operands[0] = gen_lowpart (SImode, operands[0]);
3645 operands[2] = gen_reg_rtx (SImode);
3646 operands[3] = gen_reg_rtx (SImode);
3647 operands[6] = gen_reg_rtx (SImode);
3650 if (BYTES_BIG_ENDIAN)
3652 operands[4] = operands[2];
3653 operands[5] = operands[3];
3657 operands[4] = operands[3];
3658 operands[5] = operands[2];
3663 (define_insn "*arm_extendhisi2"
3664 [(set (match_operand:SI 0 "s_register_operand" "=r")
3665 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3666 "TARGET_ARM && arm_arch4 && !arm_arch6"
3668 [(set_attr "type" "load_byte")
3669 (set_attr "predicable" "yes")
3670 (set_attr "pool_range" "256")
3671 (set_attr "neg_pool_range" "244")]
3674 (define_insn "*arm_extendhisi2_v6"
3675 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3676 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3677 "TARGET_ARM && arm_arch6"
3681 [(set_attr "type" "alu_shift,load_byte")
3682 (set_attr "predicable" "yes")
3683 (set_attr "pool_range" "*,256")
3684 (set_attr "neg_pool_range" "*,244")]
3687 (define_insn "*arm_extendhisi2addsi"
3688 [(set (match_operand:SI 0 "s_register_operand" "=r")
3689 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3690 (match_operand:SI 2 "s_register_operand" "r")))]
3691 "TARGET_ARM && arm_arch6"
3692 "sxtah%?\\t%0, %2, %1"
3696 [(set (match_operand:SI 0 "s_register_operand" "")
3697 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3698 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3699 "TARGET_ARM && (!arm_arch4)"
3700 [(set (match_dup 2) (match_dup 1))
3701 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3703 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3709 [(set (match_operand:SI 0 "s_register_operand" "")
3710 (match_operator:SI 3 "shiftable_operator"
3711 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3712 (match_operand:SI 4 "s_register_operand" "")]))
3713 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3714 "TARGET_ARM && (!arm_arch4)"
3715 [(set (match_dup 2) (match_dup 1))
3718 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3719 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3724 (define_expand "extendqihi2"
3726 (ashift:SI (match_operand:QI 1 "general_operand" "")
3728 (set (match_operand:HI 0 "s_register_operand" "")
3729 (ashiftrt:SI (match_dup 2)
3734 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3736 emit_insn (gen_rtx_SET (VOIDmode,
3738 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3741 if (!s_register_operand (operands[1], QImode))
3742 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3743 operands[0] = gen_lowpart (SImode, operands[0]);
3744 operands[1] = gen_lowpart (SImode, operands[1]);
3745 operands[2] = gen_reg_rtx (SImode);
3749 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3750 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3751 (define_insn "*extendqihi_insn"
3752 [(set (match_operand:HI 0 "s_register_operand" "=r")
3753 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3754 "TARGET_ARM && arm_arch4"
3756 /* If the address is invalid, this will split the instruction into two. */
3757 if (bad_signed_byte_operand (operands[1], VOIDmode))
3759 return \"ldr%?sb\\t%0, %1\";
3761 [(set_attr "type" "load_byte")
3762 (set_attr "predicable" "yes")
3763 (set_attr "length" "8")
3764 (set_attr "pool_range" "256")
3765 (set_attr "neg_pool_range" "244")]
3769 [(set (match_operand:HI 0 "s_register_operand" "")
3770 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3771 "TARGET_ARM && arm_arch4 && reload_completed"
3772 [(set (match_dup 3) (match_dup 1))
3773 (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3776 HOST_WIDE_INT offset;
3778 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3779 operands[2] = gen_rtx_MEM (QImode, operands[3]);
3780 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3781 operands[1] = XEXP (operands[1], 0);
3782 if (GET_CODE (operands[1]) == PLUS
3783 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3784 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3785 || const_ok_for_arm (-offset)))
3787 HOST_WIDE_INT low = (offset > 0
3788 ? (offset & 0xff) : -((-offset) & 0xff));
3789 XEXP (operands[2], 0) = plus_constant (operands[3], low);
3790 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3792 /* Ensure the sum is in correct canonical form. */
3793 else if (GET_CODE (operands[1]) == PLUS
3794 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3795 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3796 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3797 XEXP (operands[1], 1),
3798 XEXP (operands[1], 0));
3802 (define_expand "extendqisi2"
3804 (ashift:SI (match_operand:QI 1 "general_operand" "")
3806 (set (match_operand:SI 0 "s_register_operand" "")
3807 (ashiftrt:SI (match_dup 2)
3812 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3814 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3815 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3819 if (!s_register_operand (operands[1], QImode))
3820 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3824 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3825 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3829 operands[1] = gen_lowpart (SImode, operands[1]);
3830 operands[2] = gen_reg_rtx (SImode);
3834 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3835 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3836 (define_insn "*arm_extendqisi"
3837 [(set (match_operand:SI 0 "s_register_operand" "=r")
3838 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3839 "TARGET_ARM && arm_arch4 && !arm_arch6"
3841 /* If the address is invalid, this will split the instruction into two. */
3842 if (bad_signed_byte_operand (operands[1], VOIDmode))
3844 return \"ldr%?sb\\t%0, %1\";
3846 [(set_attr "type" "load_byte")
3847 (set_attr "predicable" "yes")
3848 (set_attr "length" "8")
3849 (set_attr "pool_range" "256")
3850 (set_attr "neg_pool_range" "244")]
3853 (define_insn "*arm_extendqisi_v6"
3854 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3855 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3856 "TARGET_ARM && arm_arch6"
3858 if (which_alternative == 0)
3859 return \"sxtb%?\\t%0, %1\";
3861 /* If the address is invalid, this will split the instruction into two. */
3862 if (bad_signed_byte_operand (operands[1], VOIDmode))
3865 return \"ldr%?sb\\t%0, %1\";
3867 [(set_attr "type" "alu_shift,load_byte")
3868 (set_attr "predicable" "yes")
3869 (set_attr "length" "4,8")
3870 (set_attr "pool_range" "*,256")
3871 (set_attr "neg_pool_range" "*,244")]
3874 (define_insn "*arm_extendqisi2addsi"
3875 [(set (match_operand:SI 0 "s_register_operand" "=r")
3876 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3877 (match_operand:SI 2 "s_register_operand" "r")))]
3878 "TARGET_ARM && arm_arch6"
3879 "sxtab%?\\t%0, %2, %1"
3880 [(set_attr "type" "alu_shift")
3881 (set_attr "predicable" "yes")]
3885 [(set (match_operand:SI 0 "s_register_operand" "")
3886 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3887 "TARGET_ARM && arm_arch4 && reload_completed"
3888 [(set (match_dup 0) (match_dup 1))
3889 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3892 HOST_WIDE_INT offset;
3894 operands[2] = gen_rtx_MEM (QImode, operands[0]);
3895 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3896 operands[1] = XEXP (operands[1], 0);
3897 if (GET_CODE (operands[1]) == PLUS
3898 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3899 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3900 || const_ok_for_arm (-offset)))
3902 HOST_WIDE_INT low = (offset > 0
3903 ? (offset & 0xff) : -((-offset) & 0xff));
3904 XEXP (operands[2], 0) = plus_constant (operands[0], low);
3905 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3907 /* Ensure the sum is in correct canonical form. */
3908 else if (GET_CODE (operands[1]) == PLUS
3909 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3910 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3911 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3912 XEXP (operands[1], 1),
3913 XEXP (operands[1], 0));
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"
3924 rtx mem = XEXP (operands[1], 0);
3926 if (GET_CODE (mem) == CONST)
3927 mem = XEXP (mem, 0);
3929 if (GET_CODE (mem) == LABEL_REF)
3930 return \"ldr\\t%0, %1\";
3932 if (GET_CODE (mem) == PLUS
3933 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3934 return \"ldr\\t%0, %1\";
3936 if (which_alternative == 0)
3937 return \"ldrsb\\t%0, %1\";
3939 ops[0] = operands[0];
3941 if (GET_CODE (mem) == PLUS)
3943 rtx a = XEXP (mem, 0);
3944 rtx b = XEXP (mem, 1);
3949 if (GET_CODE (a) == REG)
3951 if (GET_CODE (b) == REG)
3952 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3953 else if (REGNO (a) == REGNO (ops[0]))
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);
3960 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3962 else if (GET_CODE (b) != REG)
3966 if (REGNO (b) == REGNO (ops[0]))
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);
3973 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3976 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
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);
3985 ops[2] = const0_rtx;
3987 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3991 [(set_attr "length" "2,6")
3992 (set_attr "type" "load_byte,load_byte")
3993 (set_attr "pool_range" "32,32")]
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"
4005 if (which_alternative == 0)
4006 return \"sxtb\\t%0, %1\";
4008 mem = XEXP (operands[1], 0);
4010 if (GET_CODE (mem) == CONST)
4011 mem = XEXP (mem, 0);
4013 if (GET_CODE (mem) == LABEL_REF)
4014 return \"ldr\\t%0, %1\";
4016 if (GET_CODE (mem) == PLUS
4017 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4018 return \"ldr\\t%0, %1\";
4020 if (which_alternative == 0)
4021 return \"ldrsb\\t%0, %1\";
4023 ops[0] = operands[0];
4025 if (GET_CODE (mem) == PLUS)
4027 rtx a = XEXP (mem, 0);
4028 rtx b = XEXP (mem, 1);
4033 if (GET_CODE (a) == REG)
4035 if (GET_CODE (b) == REG)
4036 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4037 else if (REGNO (a) == REGNO (ops[0]))
4039 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4040 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4043 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4045 else if (GET_CODE (b) != REG)
4049 if (REGNO (b) == REGNO (ops[0]))
4051 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4052 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4055 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4058 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4060 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4061 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4066 ops[2] = const0_rtx;
4068 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4072 [(set_attr "length" "2,2,4")
4073 (set_attr "type" "alu_shift,load_byte,load_byte")
4074 (set_attr "pool_range" "*,32,32")]
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"
4084 ;; Move insns (including loads and stores)
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
4089 ;;(define_expand "loadti"
4090 ;; [(set (match_operand:TI 0 "s_register_operand" "")
4091 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4094 ;;(define_expand "storeti"
4095 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4096 ;; (match_operand:TI 1 "s_register_operand" ""))]
4099 ;;(define_expand "movti"
4100 ;; [(set (match_operand:TI 0 "general_operand" "")
4101 ;; (match_operand:TI 1 "general_operand" ""))]
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));
4116 ;; emit_insn (insn);
4120 ;; Recognize garbage generated above.
4123 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4124 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4128 ;; register mem = (which_alternative < 3);
4129 ;; register const char *template;
4131 ;; operands[mem] = XEXP (operands[mem], 0);
4132 ;; switch (which_alternative)
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;
4141 ;; output_asm_insn (template, operands);
4145 (define_expand "movdi"
4146 [(set (match_operand:DI 0 "general_operand" "")
4147 (match_operand:DI 1 "general_operand" ""))]
4152 if (!no_new_pseudos)
4154 if (GET_CODE (operands[0]) != REG)
4155 operands[1] = force_reg (DImode, operands[1]);
4161 (define_insn "*arm_movdi"
4162 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
4163 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
4165 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4168 return (output_move_double (operands));
4170 [(set_attr "length" "8")
4171 (set_attr "type" "*,load2,store2")
4172 (set_attr "pool_range" "*,1020,*")
4173 (set_attr "neg_pool_range" "*,1008,*")]
4176 ;;; ??? This should have alternatives for constants.
4177 ;;; ??? This was originally identical to the movdf_insn pattern.
4178 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4179 ;;; thumb_reorg with a memory reference.
4180 (define_insn "*thumb_movdi_insn"
4181 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4182 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
4184 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4185 && ( register_operand (operands[0], DImode)
4186 || register_operand (operands[1], DImode))"
4189 switch (which_alternative)
4193 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4194 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4195 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4197 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4199 operands[1] = GEN_INT (- INTVAL (operands[1]));
4200 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4202 return \"ldmia\\t%1, {%0, %H0}\";
4204 return \"stmia\\t%0, {%1, %H1}\";
4206 return thumb_load_double_from_address (operands);
4208 operands[2] = gen_rtx_MEM (SImode,
4209 plus_constant (XEXP (operands[0], 0), 4));
4210 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4213 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4214 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4215 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4218 [(set_attr "length" "4,4,6,2,2,6,4,4")
4219 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4220 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4223 (define_expand "movsi"
4224 [(set (match_operand:SI 0 "general_operand" "")
4225 (match_operand:SI 1 "general_operand" ""))]
4230 /* Everything except mem = const or mem = mem can be done easily. */
4231 if (GET_CODE (operands[0]) == MEM)
4232 operands[1] = force_reg (SImode, operands[1]);
4233 if (arm_general_register_operand (operands[0], SImode)
4234 && GET_CODE (operands[1]) == CONST_INT
4235 && !(const_ok_for_arm (INTVAL (operands[1]))
4236 || const_ok_for_arm (~INTVAL (operands[1]))))
4238 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4241 : preserve_subexpressions_p ()));
4245 else /* TARGET_THUMB.... */
4247 if (!no_new_pseudos)
4249 if (GET_CODE (operands[0]) != REG)
4250 operands[1] = force_reg (SImode, operands[1]);
4255 && (CONSTANT_P (operands[1])
4256 || symbol_mentioned_p (operands[1])
4257 || label_mentioned_p (operands[1])))
4258 operands[1] = legitimize_pic_address (operands[1], SImode,
4259 (no_new_pseudos ? operands[0] : 0));
4263 (define_insn "*arm_movsi_insn"
4264 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4265 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
4266 "TARGET_ARM && ! TARGET_IWMMXT
4267 && !(TARGET_HARD_FLOAT && TARGET_VFP)
4268 && ( register_operand (operands[0], SImode)
4269 || register_operand (operands[1], SImode))"
4275 [(set_attr "type" "*,*,load1,store1")
4276 (set_attr "predicable" "yes")
4277 (set_attr "pool_range" "*,*,4096,*")
4278 (set_attr "neg_pool_range" "*,*,4084,*")]
4282 [(set (match_operand:SI 0 "arm_general_register_operand" "")
4283 (match_operand:SI 1 "const_int_operand" ""))]
4285 && (!(const_ok_for_arm (INTVAL (operands[1]))
4286 || const_ok_for_arm (~INTVAL (operands[1]))))"
4287 [(clobber (const_int 0))]
4289 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4295 (define_insn "*thumb_movsi_insn"
4296 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4297 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
4299 && ( register_operand (operands[0], SImode)
4300 || register_operand (operands[1], SImode))"
4311 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4312 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4313 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4317 [(set (match_operand:SI 0 "register_operand" "")
4318 (match_operand:SI 1 "const_int_operand" ""))]
4319 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4320 [(set (match_dup 0) (match_dup 1))
4321 (set (match_dup 0) (neg:SI (match_dup 0)))]
4322 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4326 [(set (match_operand:SI 0 "register_operand" "")
4327 (match_operand:SI 1 "const_int_operand" ""))]
4328 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4329 [(set (match_dup 0) (match_dup 1))
4330 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4333 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4334 unsigned HOST_WIDE_INT mask = 0xff;
4337 for (i = 0; i < 25; i++)
4338 if ((val & (mask << i)) == val)
4341 /* Shouldn't happen, but we don't want to split if the shift is zero. */
4345 operands[1] = GEN_INT (val >> i);
4346 operands[2] = GEN_INT (i);
4350 ;; When generating pic, we need to load the symbol offset into a register.
4351 ;; So that the optimizer does not confuse this with a normal symbol load
4352 ;; we use an unspec. The offset will be loaded from a constant pool entry,
4353 ;; since that is the only type of relocation we can use.
4355 ;; The rather odd constraints on the following are to force reload to leave
4356 ;; the insn alone, and to force the minipool generation pass to then move
4357 ;; the GOT symbol to memory.
4359 (define_insn "pic_load_addr_arm"
4360 [(set (match_operand:SI 0 "s_register_operand" "=r")
4361 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4362 "TARGET_ARM && flag_pic"
4364 [(set_attr "type" "load1")
4365 (set (attr "pool_range") (const_int 4096))
4366 (set (attr "neg_pool_range") (const_int 4084))]
4369 (define_insn "pic_load_addr_thumb"
4370 [(set (match_operand:SI 0 "s_register_operand" "=l")
4371 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4372 "TARGET_THUMB && flag_pic"
4374 [(set_attr "type" "load1")
4375 (set (attr "pool_range") (const_int 1024))]
4378 ;; This variant is used for AOF assembly, since it needs to mention the
4379 ;; pic register in the rtl.
4380 (define_expand "pic_load_addr_based"
4381 [(set (match_operand:SI 0 "s_register_operand" "")
4382 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4383 "TARGET_ARM && flag_pic"
4384 "operands[2] = pic_offset_table_rtx;"
4387 (define_insn "*pic_load_addr_based_insn"
4388 [(set (match_operand:SI 0 "s_register_operand" "=r")
4389 (unspec:SI [(match_operand 1 "" "")
4390 (match_operand 2 "s_register_operand" "r")]
4392 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4394 #ifdef AOF_ASSEMBLER
4395 operands[1] = aof_pic_entry (operands[1]);
4397 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4400 [(set_attr "type" "load1")
4401 (set (attr "pool_range")
4402 (if_then_else (eq_attr "is_thumb" "yes")
4405 (set (attr "neg_pool_range")
4406 (if_then_else (eq_attr "is_thumb" "yes")
4411 (define_insn "pic_add_dot_plus_four"
4412 [(set (match_operand:SI 0 "register_operand" "+r")
4413 (unspec:SI [(plus:SI (match_dup 0)
4414 (const (plus:SI (pc) (const_int 4))))]
4416 (use (label_ref (match_operand 1 "" "")))]
4417 "TARGET_THUMB && flag_pic"
4419 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4420 CODE_LABEL_NUMBER (operands[1]));
4421 return \"add\\t%0, %|pc\";
4423 [(set_attr "length" "2")]
4426 (define_insn "pic_add_dot_plus_eight"
4427 [(set (match_operand:SI 0 "register_operand" "+r")
4428 (unspec:SI [(plus:SI (match_dup 0)
4429 (const (plus:SI (pc) (const_int 8))))]
4431 (use (label_ref (match_operand 1 "" "")))]
4432 "TARGET_ARM && flag_pic"
4434 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4435 CODE_LABEL_NUMBER (operands[1]));
4436 return \"add%?\\t%0, %|pc, %0\";
4438 [(set_attr "predicable" "yes")]
4441 (define_expand "builtin_setjmp_receiver"
4442 [(label_ref (match_operand 0 "" ""))]
4446 arm_finalize_pic (0);
4450 ;; If copying one reg to another we can set the condition codes according to
4451 ;; its value. Such a move is common after a return from subroutine and the
4452 ;; result is being tested against zero.
4454 (define_insn "*movsi_compare0"
4455 [(set (reg:CC CC_REGNUM)
4456 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4458 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4463 sub%?s\\t%0, %1, #0"
4464 [(set_attr "conds" "set")]
4467 ;; Subroutine to store a half word from a register into memory.
4468 ;; Operand 0 is the source register (HImode)
4469 ;; Operand 1 is the destination address in a register (SImode)
4471 ;; In both this routine and the next, we must be careful not to spill
4472 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4473 ;; can generate unrecognizable rtl.
4475 (define_expand "storehi"
4476 [;; store the low byte
4477 (set (match_operand 1 "" "") (match_dup 3))
4478 ;; extract the high byte
4480 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4481 ;; store the high byte
4482 (set (match_dup 4) (match_dup 5))]
4486 rtx op1 = operands[1];
4487 rtx addr = XEXP (op1, 0);
4488 enum rtx_code code = GET_CODE (addr);
4490 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4492 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4494 operands[4] = adjust_address (op1, QImode, 1);
4495 operands[1] = adjust_address (operands[1], QImode, 0);
4496 operands[3] = gen_lowpart (QImode, operands[0]);
4497 operands[0] = gen_lowpart (SImode, operands[0]);
4498 operands[2] = gen_reg_rtx (SImode);
4499 operands[5] = gen_lowpart (QImode, operands[2]);
4503 (define_expand "storehi_bigend"
4504 [(set (match_dup 4) (match_dup 3))
4506 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4507 (set (match_operand 1 "" "") (match_dup 5))]
4511 rtx op1 = operands[1];
4512 rtx addr = XEXP (op1, 0);
4513 enum rtx_code code = GET_CODE (addr);
4515 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4517 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4519 operands[4] = adjust_address (op1, QImode, 1);
4520 operands[1] = adjust_address (operands[1], QImode, 0);
4521 operands[3] = gen_lowpart (QImode, operands[0]);
4522 operands[0] = gen_lowpart (SImode, operands[0]);
4523 operands[2] = gen_reg_rtx (SImode);
4524 operands[5] = gen_lowpart (QImode, operands[2]);
4528 ;; Subroutine to store a half word integer constant into memory.
4529 (define_expand "storeinthi"
4530 [(set (match_operand 0 "" "")
4531 (match_operand 1 "" ""))
4532 (set (match_dup 3) (match_dup 2))]
4536 HOST_WIDE_INT value = INTVAL (operands[1]);
4537 rtx addr = XEXP (operands[0], 0);
4538 rtx op0 = operands[0];
4539 enum rtx_code code = GET_CODE (addr);
4541 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4543 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4545 operands[1] = gen_reg_rtx (SImode);
4546 if (BYTES_BIG_ENDIAN)
4548 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4549 if ((value & 255) == ((value >> 8) & 255))
4550 operands[2] = operands[1];
4553 operands[2] = gen_reg_rtx (SImode);
4554 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4559 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4560 if ((value & 255) == ((value >> 8) & 255))
4561 operands[2] = operands[1];
4564 operands[2] = gen_reg_rtx (SImode);
4565 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4569 operands[3] = adjust_address (op0, QImode, 1);
4570 operands[0] = adjust_address (operands[0], QImode, 0);
4571 operands[2] = gen_lowpart (QImode, operands[2]);
4572 operands[1] = gen_lowpart (QImode, operands[1]);
4576 (define_expand "storehi_single_op"
4577 [(set (match_operand:HI 0 "memory_operand" "")
4578 (match_operand:HI 1 "general_operand" ""))]
4579 "TARGET_ARM && arm_arch4"
4581 if (!s_register_operand (operands[1], HImode))
4582 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4586 (define_expand "movhi"
4587 [(set (match_operand:HI 0 "general_operand" "")
4588 (match_operand:HI 1 "general_operand" ""))]
4593 if (!no_new_pseudos)
4595 if (GET_CODE (operands[0]) == MEM)
4599 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4602 if (GET_CODE (operands[1]) == CONST_INT)
4603 emit_insn (gen_storeinthi (operands[0], operands[1]));
4606 if (GET_CODE (operands[1]) == MEM)
4607 operands[1] = force_reg (HImode, operands[1]);
4608 if (BYTES_BIG_ENDIAN)
4609 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4611 emit_insn (gen_storehi (operands[1], operands[0]));
4615 /* Sign extend a constant, and keep it in an SImode reg. */
4616 else if (GET_CODE (operands[1]) == CONST_INT)
4618 rtx reg = gen_reg_rtx (SImode);
4619 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4621 /* If the constant is already valid, leave it alone. */
4622 if (!const_ok_for_arm (val))
4624 /* If setting all the top bits will make the constant
4625 loadable in a single instruction, then set them.
4626 Otherwise, sign extend the number. */
4628 if (const_ok_for_arm (~(val | ~0xffff)))
4630 else if (val & 0x8000)
4634 emit_insn (gen_movsi (reg, GEN_INT (val)));
4635 operands[1] = gen_lowpart (HImode, reg);
4637 else if (arm_arch4 && !no_new_pseudos && optimize > 0
4638 && GET_CODE (operands[1]) == MEM)
4640 rtx reg = gen_reg_rtx (SImode);
4642 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4643 operands[1] = gen_lowpart (HImode, reg);
4645 else if (!arm_arch4)
4647 /* Note: We do not have to worry about TARGET_MMU_TRAPS
4648 for v4 and up architectures because LDRH instructions will
4649 be used to access the HI values, and these cannot generate
4650 unaligned word access faults in the MMU. */
4651 if (GET_CODE (operands[1]) == MEM)
4653 if (TARGET_MMU_TRAPS)
4656 rtx offset = const0_rtx;
4657 rtx reg = gen_reg_rtx (SImode);
4659 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4660 || (GET_CODE (base) == PLUS
4661 && (GET_CODE (offset = XEXP (base, 1))
4663 && ((INTVAL(offset) & 1) != 1)
4664 && GET_CODE (base = XEXP (base, 0)) == REG))
4665 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4667 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4670 new = gen_rtx_MEM (SImode,
4671 plus_constant (base, new_offset));
4672 MEM_COPY_ATTRIBUTES (new, operands[1]);
4673 emit_insn (gen_movsi (reg, new));
4674 if (((INTVAL (offset) & 2) != 0)
4675 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4677 rtx reg2 = gen_reg_rtx (SImode);
4679 emit_insn (gen_lshrsi3 (reg2, reg,
4685 emit_insn (gen_movhi_bytes (reg, operands[1]));
4687 operands[1] = gen_lowpart (HImode, reg);
4689 else if (BYTES_BIG_ENDIAN)
4692 rtx offset = const0_rtx;
4694 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4695 || (GET_CODE (base) == PLUS
4696 && (GET_CODE (offset = XEXP (base, 1))
4698 && GET_CODE (base = XEXP (base, 0)) == REG))
4699 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4701 rtx reg = gen_reg_rtx (SImode);
4704 if ((INTVAL (offset) & 2) == 2)
4706 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4707 new = gen_rtx_MEM (SImode,
4708 plus_constant (base,
4710 MEM_COPY_ATTRIBUTES (new, operands[1]);
4711 emit_insn (gen_movsi (reg, new));
4715 new = gen_rtx_MEM (SImode,
4716 XEXP (operands[1], 0));
4717 MEM_COPY_ATTRIBUTES (new, operands[1]);
4718 emit_insn (gen_rotated_loadsi (reg, new));
4721 operands[1] = gen_lowpart (HImode, reg);
4725 emit_insn (gen_movhi_bigend (operands[0],
4733 /* Handle loading a large integer during reload. */
4734 else if (GET_CODE (operands[1]) == CONST_INT
4735 && !const_ok_for_arm (INTVAL (operands[1]))
4736 && !const_ok_for_arm (~INTVAL (operands[1])))
4738 /* Writing a constant to memory needs a scratch, which should
4739 be handled with SECONDARY_RELOADs. */
4740 if (GET_CODE (operands[0]) != REG)
4743 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4744 emit_insn (gen_movsi (operands[0], operands[1]));
4748 else /* TARGET_THUMB */
4750 if (!no_new_pseudos)
4752 if (GET_CODE (operands[0]) != REG)
4753 operands[1] = force_reg (HImode, operands[1]);
4755 /* ??? We shouldn't really get invalid addresses here, but this can
4756 happen if we are passed a SP (never OK for HImode/QImode) or
4757 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4758 HImode/QImode) relative address. */
4759 /* ??? This should perhaps be fixed elsewhere, for instance, in
4760 fixup_stack_1, by checking for other kinds of invalid addresses,
4761 e.g. a bare reference to a virtual register. This may confuse the
4762 alpha though, which must handle this case differently. */
4763 if (GET_CODE (operands[0]) == MEM
4764 && !memory_address_p (GET_MODE (operands[0]),
4765 XEXP (operands[0], 0)))
4767 = replace_equiv_address (operands[0],
4768 copy_to_reg (XEXP (operands[0], 0)));
4770 if (GET_CODE (operands[1]) == MEM
4771 && !memory_address_p (GET_MODE (operands[1]),
4772 XEXP (operands[1], 0)))
4774 = replace_equiv_address (operands[1],
4775 copy_to_reg (XEXP (operands[1], 0)));
4777 /* Handle loading a large integer during reload. */
4778 else if (GET_CODE (operands[1]) == CONST_INT
4779 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4781 /* Writing a constant to memory needs a scratch, which should
4782 be handled with SECONDARY_RELOADs. */
4783 if (GET_CODE (operands[0]) != REG)
4786 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4787 emit_insn (gen_movsi (operands[0], operands[1]));
4794 (define_insn "*thumb_movhi_insn"
4795 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4796 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
4798 && ( register_operand (operands[0], HImode)
4799 || register_operand (operands[1], HImode))"
4801 switch (which_alternative)
4803 case 0: return \"add %0, %1, #0\";
4804 case 2: return \"strh %1, %0\";
4805 case 3: return \"mov %0, %1\";
4806 case 4: return \"mov %0, %1\";
4807 case 5: return \"mov %0, %1\";
4810 /* The stack pointer can end up being taken as an index register.
4811 Catch this case here and deal with it. */
4812 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4813 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4814 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4817 ops[0] = operands[0];
4818 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4820 output_asm_insn (\"mov %0, %1\", ops);
4822 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4825 return \"ldrh %0, %1\";
4827 [(set_attr "length" "2,4,2,2,2,2")
4828 (set_attr "type" "*,load1,store1,*,*,*")]
4832 (define_insn "rotated_loadsi"
4833 [(set (match_operand:SI 0 "s_register_operand" "=r")
4834 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4836 "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4841 ops[0] = operands[0];
4842 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4843 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4846 [(set_attr "type" "load1")
4847 (set_attr "predicable" "yes")]
4850 (define_expand "movhi_bytes"
4851 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4853 (zero_extend:SI (match_dup 6)))
4854 (set (match_operand:SI 0 "" "")
4855 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4860 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4862 mem1 = gen_rtx_MEM (QImode, addr);
4863 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4864 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4865 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4866 operands[0] = gen_lowpart (SImode, operands[0]);
4868 operands[2] = gen_reg_rtx (SImode);
4869 operands[3] = gen_reg_rtx (SImode);
4872 if (BYTES_BIG_ENDIAN)
4874 operands[4] = operands[2];
4875 operands[5] = operands[3];
4879 operands[4] = operands[3];
4880 operands[5] = operands[2];
4885 (define_expand "movhi_bigend"
4887 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4890 (ashiftrt:SI (match_dup 2) (const_int 16)))
4891 (set (match_operand:HI 0 "s_register_operand" "")
4895 operands[2] = gen_reg_rtx (SImode);
4896 operands[3] = gen_reg_rtx (SImode);
4897 operands[4] = gen_lowpart (HImode, operands[3]);
4901 ;; Pattern to recognize insn generated default case above
4902 (define_insn "*movhi_insn_arch4"
4903 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4904 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4907 && (GET_CODE (operands[1]) != CONST_INT
4908 || const_ok_for_arm (INTVAL (operands[1]))
4909 || const_ok_for_arm (~INTVAL (operands[1])))"
4911 mov%?\\t%0, %1\\t%@ movhi
4912 mvn%?\\t%0, #%B1\\t%@ movhi
4913 str%?h\\t%1, %0\\t%@ movhi
4914 ldr%?h\\t%0, %1\\t%@ movhi"
4915 [(set_attr "type" "*,*,store1,load1")
4916 (set_attr "predicable" "yes")
4917 (set_attr "pool_range" "*,*,*,256")
4918 (set_attr "neg_pool_range" "*,*,*,244")]
4921 (define_insn "*movhi_insn_littleend"
4922 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4923 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4926 && !BYTES_BIG_ENDIAN
4927 && !TARGET_MMU_TRAPS
4928 && (GET_CODE (operands[1]) != CONST_INT
4929 || const_ok_for_arm (INTVAL (operands[1]))
4930 || const_ok_for_arm (~INTVAL (operands[1])))"
4932 mov%?\\t%0, %1\\t%@ movhi
4933 mvn%?\\t%0, #%B1\\t%@ movhi
4934 ldr%?\\t%0, %1\\t%@ movhi"
4935 [(set_attr "type" "*,*,load1")
4936 (set_attr "predicable" "yes")
4937 (set_attr "pool_range" "4096")
4938 (set_attr "neg_pool_range" "4084")]
4941 (define_insn "*movhi_insn_bigend"
4942 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4943 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4947 && !TARGET_MMU_TRAPS
4948 && (GET_CODE (operands[1]) != CONST_INT
4949 || const_ok_for_arm (INTVAL (operands[1]))
4950 || const_ok_for_arm (~INTVAL (operands[1])))"
4952 mov%?\\t%0, %1\\t%@ movhi
4953 mvn%?\\t%0, #%B1\\t%@ movhi
4954 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4955 [(set_attr "type" "*,*,load1")
4956 (set_attr "predicable" "yes")
4957 (set_attr "length" "4,4,8")
4958 (set_attr "pool_range" "*,*,4092")
4959 (set_attr "neg_pool_range" "*,*,4084")]
4962 (define_insn "*loadhi_si_bigend"
4963 [(set (match_operand:SI 0 "s_register_operand" "=r")
4964 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
4968 && !TARGET_MMU_TRAPS"
4969 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4970 [(set_attr "type" "load1")
4971 (set_attr "predicable" "yes")
4972 (set_attr "pool_range" "4096")
4973 (set_attr "neg_pool_range" "4084")]
4976 (define_insn "*movhi_bytes"
4977 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4978 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4979 "TARGET_ARM && TARGET_MMU_TRAPS"
4981 mov%?\\t%0, %1\\t%@ movhi
4982 mvn%?\\t%0, #%B1\\t%@ movhi"
4983 [(set_attr "predicable" "yes")]
4986 (define_insn "thumb_movhi_clobber"
4987 [(set (match_operand:HI 0 "memory_operand" "=m")
4988 (match_operand:HI 1 "register_operand" "l"))
4989 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4995 ;; We use a DImode scratch because we may occasionally need an additional
4996 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4997 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4998 (define_expand "reload_outhi"
4999 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
5000 (match_operand:HI 1 "s_register_operand" "r")
5001 (match_operand:DI 2 "s_register_operand" "=&l")])]
5004 arm_reload_out_hi (operands);
5006 thumb_reload_out_hi (operands);
5011 (define_expand "reload_inhi"
5012 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
5013 (match_operand:HI 1 "arm_reload_memory_operand" "o")
5014 (match_operand:DI 2 "s_register_operand" "=&r")])]
5015 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
5018 arm_reload_in_hi (operands);
5020 thumb_reload_out_hi (operands);
5024 (define_expand "movqi"
5025 [(set (match_operand:QI 0 "general_operand" "")
5026 (match_operand:QI 1 "general_operand" ""))]
5031 /* Everything except mem = const or mem = mem can be done easily */
5033 if (!no_new_pseudos)
5035 if (GET_CODE (operands[1]) == CONST_INT)
5037 rtx reg = gen_reg_rtx (SImode);
5039 emit_insn (gen_movsi (reg, operands[1]));
5040 operands[1] = gen_lowpart (QImode, reg);
5042 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5044 rtx reg = gen_reg_rtx (SImode);
5046 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5047 operands[1] = gen_lowpart (QImode, reg);
5049 if (GET_CODE (operands[0]) == MEM)
5050 operands[1] = force_reg (QImode, operands[1]);
5053 else /* TARGET_THUMB */
5055 if (!no_new_pseudos)
5057 if (GET_CODE (operands[0]) != REG)
5058 operands[1] = force_reg (QImode, operands[1]);
5060 /* ??? We shouldn't really get invalid addresses here, but this can
5061 happen if we are passed a SP (never OK for HImode/QImode) or
5062 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5063 HImode/QImode) relative address. */
5064 /* ??? This should perhaps be fixed elsewhere, for instance, in
5065 fixup_stack_1, by checking for other kinds of invalid addresses,
5066 e.g. a bare reference to a virtual register. This may confuse the
5067 alpha though, which must handle this case differently. */
5068 if (GET_CODE (operands[0]) == MEM
5069 && !memory_address_p (GET_MODE (operands[0]),
5070 XEXP (operands[0], 0)))
5072 = replace_equiv_address (operands[0],
5073 copy_to_reg (XEXP (operands[0], 0)));
5074 if (GET_CODE (operands[1]) == MEM
5075 && !memory_address_p (GET_MODE (operands[1]),
5076 XEXP (operands[1], 0)))
5078 = replace_equiv_address (operands[1],
5079 copy_to_reg (XEXP (operands[1], 0)));
5081 /* Handle loading a large integer during reload. */
5082 else if (GET_CODE (operands[1]) == CONST_INT
5083 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
5085 /* Writing a constant to memory needs a scratch, which should
5086 be handled with SECONDARY_RELOADs. */
5087 if (GET_CODE (operands[0]) != REG)
5090 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5091 emit_insn (gen_movsi (operands[0], operands[1]));
5099 (define_insn "*arm_movqi_insn"
5100 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5101 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5103 && ( register_operand (operands[0], QImode)
5104 || register_operand (operands[1], QImode))"
5110 [(set_attr "type" "*,*,load1,store1")
5111 (set_attr "predicable" "yes")]
5114 (define_insn "*thumb_movqi_insn"
5115 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5116 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
5118 && ( register_operand (operands[0], QImode)
5119 || register_operand (operands[1], QImode))"
5127 [(set_attr "length" "2")
5128 (set_attr "type" "*,load1,store1,*,*,*")
5129 (set_attr "pool_range" "*,32,*,*,*,*")]
5132 (define_expand "movsf"
5133 [(set (match_operand:SF 0 "general_operand" "")
5134 (match_operand:SF 1 "general_operand" ""))]
5139 if (GET_CODE (operands[0]) == MEM)
5140 operands[1] = force_reg (SFmode, operands[1]);
5142 else /* TARGET_THUMB */
5144 if (!no_new_pseudos)
5146 if (GET_CODE (operands[0]) != REG)
5147 operands[1] = force_reg (SFmode, operands[1]);
5154 [(set (match_operand:SF 0 "nonimmediate_operand" "")
5155 (match_operand:SF 1 "immediate_operand" ""))]
5157 && !(TARGET_HARD_FLOAT && TARGET_FPA)
5159 && GET_CODE (operands[1]) == CONST_DOUBLE"
5160 [(set (match_dup 2) (match_dup 3))]
5162 operands[2] = gen_lowpart (SImode, operands[0]);
5163 operands[3] = gen_lowpart (SImode, operands[1]);
5164 if (operands[2] == 0 || operands[3] == 0)
5169 (define_insn "*arm_movsf_soft_insn"
5170 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5171 (match_operand:SF 1 "general_operand" "r,mE,r"))]
5173 && TARGET_SOFT_FLOAT
5174 && (GET_CODE (operands[0]) != MEM
5175 || register_operand (operands[1], SFmode))"
5178 ldr%?\\t%0, %1\\t%@ float
5179 str%?\\t%1, %0\\t%@ float"
5180 [(set_attr "length" "4,4,4")
5181 (set_attr "predicable" "yes")
5182 (set_attr "type" "*,load1,store1")
5183 (set_attr "pool_range" "*,4096,*")
5184 (set_attr "neg_pool_range" "*,4084,*")]
5187 ;;; ??? This should have alternatives for constants.
5188 (define_insn "*thumb_movsf_insn"
5189 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5190 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
5192 && ( register_operand (operands[0], SFmode)
5193 || register_operand (operands[1], SFmode))"
5202 [(set_attr "length" "2")
5203 (set_attr "type" "*,load1,store1,load1,store1,*,*")
5204 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5207 (define_expand "movdf"
5208 [(set (match_operand:DF 0 "general_operand" "")
5209 (match_operand:DF 1 "general_operand" ""))]
5214 if (GET_CODE (operands[0]) == MEM)
5215 operands[1] = force_reg (DFmode, operands[1]);
5217 else /* TARGET_THUMB */
5219 if (!no_new_pseudos)
5221 if (GET_CODE (operands[0]) != REG)
5222 operands[1] = force_reg (DFmode, operands[1]);
5228 ;; Reloading a df mode value stored in integer regs to memory can require a
5230 (define_expand "reload_outdf"
5231 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5232 (match_operand:DF 1 "s_register_operand" "r")
5233 (match_operand:SI 2 "s_register_operand" "=&r")]
5237 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5240 operands[2] = XEXP (operands[0], 0);
5241 else if (code == POST_INC || code == PRE_DEC)
5243 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5244 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5245 emit_insn (gen_movdi (operands[0], operands[1]));
5248 else if (code == PRE_INC)
5250 rtx reg = XEXP (XEXP (operands[0], 0), 0);
5252 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5255 else if (code == POST_DEC)
5256 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5258 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5259 XEXP (XEXP (operands[0], 0), 1)));
5261 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5264 if (code == POST_DEC)
5265 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5271 (define_insn "*movdf_soft_insn"
5272 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5273 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5274 "TARGET_ARM && TARGET_SOFT_FLOAT
5276 "* return output_move_double (operands);"
5277 [(set_attr "length" "8,8,8")
5278 (set_attr "type" "*,load2,store2")
5279 (set_attr "pool_range" "1020")
5280 (set_attr "neg_pool_range" "1008")]
5283 ;;; ??? This should have alternatives for constants.
5284 ;;; ??? This was originally identical to the movdi_insn pattern.
5285 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5286 ;;; thumb_reorg with a memory reference.
5287 (define_insn "*thumb_movdf_insn"
5288 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5289 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
5291 && ( register_operand (operands[0], DFmode)
5292 || register_operand (operands[1], DFmode))"
5294 switch (which_alternative)
5298 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5299 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5300 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5302 return \"ldmia\\t%1, {%0, %H0}\";
5304 return \"stmia\\t%0, {%1, %H1}\";
5306 return thumb_load_double_from_address (operands);
5308 operands[2] = gen_rtx_MEM (SImode,
5309 plus_constant (XEXP (operands[0], 0), 4));
5310 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5313 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5314 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5315 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5318 [(set_attr "length" "4,2,2,6,4,4")
5319 (set_attr "type" "*,load2,store2,load2,store2,*")
5320 (set_attr "pool_range" "*,*,*,1020,*,*")]
5324 (define_expand "movv2si"
5325 [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5326 (match_operand:V2SI 1 "general_operand" ""))]
5327 "TARGET_REALLY_IWMMXT"
5331 (define_expand "movv4hi"
5332 [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5333 (match_operand:V4HI 1 "general_operand" ""))]
5334 "TARGET_REALLY_IWMMXT"
5338 (define_expand "movv8qi"
5339 [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5340 (match_operand:V8QI 1 "general_operand" ""))]
5341 "TARGET_REALLY_IWMMXT"
5346 ;; load- and store-multiple insns
5347 ;; The arm can load/store any set of registers, provided that they are in
5348 ;; ascending order; but that is beyond GCC so stick with what it knows.
5350 (define_expand "load_multiple"
5351 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5352 (match_operand:SI 1 "" ""))
5353 (use (match_operand:SI 2 "" ""))])]
5356 /* Support only fixed point registers. */
5357 if (GET_CODE (operands[2]) != CONST_INT
5358 || INTVAL (operands[2]) > 14
5359 || INTVAL (operands[2]) < 2
5360 || GET_CODE (operands[1]) != MEM
5361 || GET_CODE (operands[0]) != REG
5362 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5363 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5367 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5368 force_reg (SImode, XEXP (operands[1], 0)),
5369 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5370 MEM_IN_STRUCT_P(operands[1]),
5371 MEM_SCALAR_P (operands[1]));
5375 ;; Load multiple with write-back
5377 (define_insn "*ldmsi_postinc4"
5378 [(match_parallel 0 "load_multiple_operation"
5379 [(set (match_operand:SI 1 "s_register_operand" "=r")
5380 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5382 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5383 (mem:SI (match_dup 2)))
5384 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5385 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5386 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5387 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5388 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5389 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5390 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5391 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5392 [(set_attr "type" "load4")
5393 (set_attr "predicable" "yes")]
5396 (define_insn "*ldmsi_postinc3"
5397 [(match_parallel 0 "load_multiple_operation"
5398 [(set (match_operand:SI 1 "s_register_operand" "=r")
5399 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5401 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5402 (mem:SI (match_dup 2)))
5403 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5404 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5405 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5406 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5407 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5408 "ldm%?ia\\t%1!, {%3, %4, %5}"
5409 [(set_attr "type" "load3")
5410 (set_attr "predicable" "yes")]
5413 (define_insn "*ldmsi_postinc2"
5414 [(match_parallel 0 "load_multiple_operation"
5415 [(set (match_operand:SI 1 "s_register_operand" "=r")
5416 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5418 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5419 (mem:SI (match_dup 2)))
5420 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5421 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5422 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5423 "ldm%?ia\\t%1!, {%3, %4}"
5424 [(set_attr "type" "load2")
5425 (set_attr "predicable" "yes")]
5428 ;; Ordinary load multiple
5430 (define_insn "*ldmsi4"
5431 [(match_parallel 0 "load_multiple_operation"
5432 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5433 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5434 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5435 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5436 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5437 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5438 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5439 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5440 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5441 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5442 [(set_attr "type" "load4")
5443 (set_attr "predicable" "yes")]
5446 (define_insn "*ldmsi3"
5447 [(match_parallel 0 "load_multiple_operation"
5448 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5449 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5450 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5451 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5452 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5453 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5454 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5455 "ldm%?ia\\t%1, {%2, %3, %4}"
5456 [(set_attr "type" "load3")
5457 (set_attr "predicable" "yes")]
5460 (define_insn "*ldmsi2"
5461 [(match_parallel 0 "load_multiple_operation"
5462 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5463 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5464 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5465 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5466 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5467 "ldm%?ia\\t%1, {%2, %3}"
5468 [(set_attr "type" "load2")
5469 (set_attr "predicable" "yes")]
5472 (define_expand "store_multiple"
5473 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5474 (match_operand:SI 1 "" ""))
5475 (use (match_operand:SI 2 "" ""))])]
5478 /* Support only fixed point registers. */
5479 if (GET_CODE (operands[2]) != CONST_INT
5480 || INTVAL (operands[2]) > 14
5481 || INTVAL (operands[2]) < 2
5482 || GET_CODE (operands[1]) != REG
5483 || GET_CODE (operands[0]) != MEM
5484 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5485 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5489 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5490 force_reg (SImode, XEXP (operands[0], 0)),
5491 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5492 MEM_IN_STRUCT_P(operands[0]),
5493 MEM_SCALAR_P (operands[0]));
5497 ;; Store multiple with write-back
5499 (define_insn "*stmsi_postinc4"
5500 [(match_parallel 0 "store_multiple_operation"
5501 [(set (match_operand:SI 1 "s_register_operand" "=r")
5502 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5504 (set (mem:SI (match_dup 2))
5505 (match_operand:SI 3 "arm_hard_register_operand" ""))
5506 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5507 (match_operand:SI 4 "arm_hard_register_operand" ""))
5508 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5509 (match_operand:SI 5 "arm_hard_register_operand" ""))
5510 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5511 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5512 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5513 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5514 [(set_attr "predicable" "yes")
5515 (set_attr "type" "store4")]
5518 (define_insn "*stmsi_postinc3"
5519 [(match_parallel 0 "store_multiple_operation"
5520 [(set (match_operand:SI 1 "s_register_operand" "=r")
5521 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5523 (set (mem:SI (match_dup 2))
5524 (match_operand:SI 3 "arm_hard_register_operand" ""))
5525 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5526 (match_operand:SI 4 "arm_hard_register_operand" ""))
5527 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5528 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5529 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5530 "stm%?ia\\t%1!, {%3, %4, %5}"
5531 [(set_attr "predicable" "yes")
5532 (set_attr "type" "store3")]
5535 (define_insn "*stmsi_postinc2"
5536 [(match_parallel 0 "store_multiple_operation"
5537 [(set (match_operand:SI 1 "s_register_operand" "=r")
5538 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5540 (set (mem:SI (match_dup 2))
5541 (match_operand:SI 3 "arm_hard_register_operand" ""))
5542 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5543 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5544 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5545 "stm%?ia\\t%1!, {%3, %4}"
5546 [(set_attr "predicable" "yes")
5547 (set_attr "type" "store2")]
5550 ;; Ordinary store multiple
5552 (define_insn "*stmsi4"
5553 [(match_parallel 0 "store_multiple_operation"
5554 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5555 (match_operand:SI 2 "arm_hard_register_operand" ""))
5556 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5557 (match_operand:SI 3 "arm_hard_register_operand" ""))
5558 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5559 (match_operand:SI 4 "arm_hard_register_operand" ""))
5560 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5561 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5562 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5563 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5564 [(set_attr "predicable" "yes")
5565 (set_attr "type" "store4")]
5568 (define_insn "*stmsi3"
5569 [(match_parallel 0 "store_multiple_operation"
5570 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5571 (match_operand:SI 2 "arm_hard_register_operand" ""))
5572 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5573 (match_operand:SI 3 "arm_hard_register_operand" ""))
5574 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5575 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5576 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5577 "stm%?ia\\t%1, {%2, %3, %4}"
5578 [(set_attr "predicable" "yes")
5579 (set_attr "type" "store3")]
5582 (define_insn "*stmsi2"
5583 [(match_parallel 0 "store_multiple_operation"
5584 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5585 (match_operand:SI 2 "arm_hard_register_operand" ""))
5586 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5587 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5588 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5589 "stm%?ia\\t%1, {%2, %3}"
5590 [(set_attr "predicable" "yes")
5591 (set_attr "type" "store2")]
5594 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5595 ;; We could let this apply for blocks of less than this, but it clobbers so
5596 ;; many registers that there is then probably a better way.
5598 (define_expand "movstrqi"
5599 [(match_operand:BLK 0 "general_operand" "")
5600 (match_operand:BLK 1 "general_operand" "")
5601 (match_operand:SI 2 "const_int_operand" "")
5602 (match_operand:SI 3 "const_int_operand" "")]
5607 if (arm_gen_movstrqi (operands))
5611 else /* TARGET_THUMB */
5613 if ( INTVAL (operands[3]) != 4
5614 || INTVAL (operands[2]) > 48)
5617 thumb_expand_movstrqi (operands);
5623 ;; Thumb block-move insns
5625 (define_insn "movmem12b"
5626 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5627 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5628 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5629 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5630 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5631 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5632 (set (match_operand:SI 0 "register_operand" "=l")
5633 (plus:SI (match_dup 2) (const_int 12)))
5634 (set (match_operand:SI 1 "register_operand" "=l")
5635 (plus:SI (match_dup 3) (const_int 12)))
5636 (clobber (match_scratch:SI 4 "=&l"))
5637 (clobber (match_scratch:SI 5 "=&l"))
5638 (clobber (match_scratch:SI 6 "=&l"))]
5640 "* return thumb_output_move_mem_multiple (3, operands);"
5641 [(set_attr "length" "4")
5642 ; This isn't entirely accurate... It loads as well, but in terms of
5643 ; scheduling the following insn it is better to consider it as a store
5644 (set_attr "type" "store3")]
5647 (define_insn "movmem8b"
5648 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5649 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5650 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5651 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5652 (set (match_operand:SI 0 "register_operand" "=l")
5653 (plus:SI (match_dup 2) (const_int 8)))
5654 (set (match_operand:SI 1 "register_operand" "=l")
5655 (plus:SI (match_dup 3) (const_int 8)))
5656 (clobber (match_scratch:SI 4 "=&l"))
5657 (clobber (match_scratch:SI 5 "=&l"))]
5659 "* return thumb_output_move_mem_multiple (2, operands);"
5660 [(set_attr "length" "4")
5661 ; This isn't entirely accurate... It loads as well, but in terms of
5662 ; scheduling the following insn it is better to consider it as a store
5663 (set_attr "type" "store2")]
5668 ;; Compare & branch insns
5669 ;; The range calculations are based as follows:
5670 ;; For forward branches, the address calculation returns the address of
5671 ;; the next instruction. This is 2 beyond the branch instruction.
5672 ;; For backward branches, the address calculation returns the address of
5673 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5674 ;; instruction for the shortest sequence, and 4 before the branch instruction
5675 ;; if we have to jump around an unconditional branch.
5676 ;; To the basic branch range the PC offset must be added (this is +4).
5677 ;; So for forward branches we have
5678 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5679 ;; And for backward branches we have
5680 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5682 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5683 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5685 (define_expand "cbranchsi4"
5686 [(set (pc) (if_then_else
5687 (match_operator 0 "arm_comparison_operator"
5688 [(match_operand:SI 1 "s_register_operand" "")
5689 (match_operand:SI 2 "nonmemory_operand" "")])
5690 (label_ref (match_operand 3 "" ""))
5694 if (thumb_cmpneg_operand (operands[2], SImode))
5696 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5697 operands[3], operands[0]));
5700 if (!thumb_cmp_operand (operands[2], SImode))
5701 operands[2] = force_reg (SImode, operands[2]);
5704 (define_insn "*cbranchsi4_insn"
5705 [(set (pc) (if_then_else
5706 (match_operator 0 "arm_comparison_operator"
5707 [(match_operand:SI 1 "s_register_operand" "l,*h")
5708 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5709 (label_ref (match_operand 3 "" ""))
5713 output_asm_insn (\"cmp\\t%1, %2\", operands);
5715 switch (get_attr_length (insn))
5717 case 4: return \"b%d0\\t%l3\";
5718 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5719 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5722 [(set (attr "far_jump")
5724 (eq_attr "length" "8")
5725 (const_string "yes")
5726 (const_string "no")))
5727 (set (attr "length")
5729 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5730 (le (minus (match_dup 3) (pc)) (const_int 256)))
5733 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5734 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5739 (define_insn "cbranchsi4_scratch"
5740 [(set (pc) (if_then_else
5741 (match_operator 4 "arm_comparison_operator"
5742 [(match_operand:SI 1 "s_register_operand" "l,0")
5743 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5744 (label_ref (match_operand 3 "" ""))
5746 (clobber (match_scratch:SI 0 "=l,l"))]
5749 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5751 switch (get_attr_length (insn))
5753 case 4: return \"b%d4\\t%l3\";
5754 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5755 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5758 [(set (attr "far_jump")
5760 (eq_attr "length" "8")
5761 (const_string "yes")
5762 (const_string "no")))
5763 (set (attr "length")
5765 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5766 (le (minus (match_dup 3) (pc)) (const_int 256)))
5769 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5770 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5774 (define_insn "*movsi_cbranchsi4"
5777 (match_operator 3 "arm_comparison_operator"
5778 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5780 (label_ref (match_operand 2 "" ""))
5782 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5786 if (which_alternative == 0)
5787 output_asm_insn (\"cmp\t%0, #0\", operands);
5788 else if (which_alternative == 1)
5789 output_asm_insn (\"sub\t%0, %1, #0\", operands);
5792 output_asm_insn (\"cmp\t%1, #0\", operands);
5793 if (which_alternative == 2)
5794 output_asm_insn (\"mov\t%0, %1\", operands);
5796 output_asm_insn (\"str\t%1, %0\", operands);
5798 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5800 case 4: return \"b%d3\\t%l2\";
5801 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5802 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5805 [(set (attr "far_jump")
5807 (ior (and (gt (symbol_ref ("which_alternative"))
5809 (eq_attr "length" "8"))
5810 (eq_attr "length" "10"))
5811 (const_string "yes")
5812 (const_string "no")))
5813 (set (attr "length")
5815 (le (symbol_ref ("which_alternative"))
5818 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5819 (le (minus (match_dup 2) (pc)) (const_int 256)))
5822 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5823 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5827 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5828 (le (minus (match_dup 2) (pc)) (const_int 256)))
5831 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5832 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5837 (define_insn "*negated_cbranchsi4"
5840 (match_operator 0 "arm_comparison_operator"
5841 [(match_operand:SI 1 "s_register_operand" "l")
5842 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5843 (label_ref (match_operand 3 "" ""))
5847 output_asm_insn (\"cmn\\t%1, %2\", operands);
5848 switch (get_attr_length (insn))
5850 case 4: return \"b%d0\\t%l3\";
5851 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5852 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5855 [(set (attr "far_jump")
5857 (eq_attr "length" "8")
5858 (const_string "yes")
5859 (const_string "no")))
5860 (set (attr "length")
5862 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5863 (le (minus (match_dup 3) (pc)) (const_int 256)))
5866 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5867 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5872 (define_insn "*tbit_cbranch"
5875 (match_operator 0 "equality_operator"
5876 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5878 (match_operand:SI 2 "const_int_operand" "i"))
5880 (label_ref (match_operand 3 "" ""))
5882 (clobber (match_scratch:SI 4 "=l"))]
5887 op[0] = operands[4];
5888 op[1] = operands[1];
5889 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5891 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5892 switch (get_attr_length (insn))
5894 case 4: return \"b%d0\\t%l3\";
5895 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5896 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5899 [(set (attr "far_jump")
5901 (eq_attr "length" "8")
5902 (const_string "yes")
5903 (const_string "no")))
5904 (set (attr "length")
5906 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5907 (le (minus (match_dup 3) (pc)) (const_int 256)))
5910 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5911 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5916 (define_insn "*tstsi3_cbranch"
5919 (match_operator 3 "equality_operator"
5920 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5921 (match_operand:SI 1 "s_register_operand" "l"))
5923 (label_ref (match_operand 2 "" ""))
5928 output_asm_insn (\"tst\\t%0, %1\", operands);
5929 switch (get_attr_length (insn))
5931 case 4: return \"b%d3\\t%l2\";
5932 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5933 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5936 [(set (attr "far_jump")
5938 (eq_attr "length" "8")
5939 (const_string "yes")
5940 (const_string "no")))
5941 (set (attr "length")
5943 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5944 (le (minus (match_dup 2) (pc)) (const_int 256)))
5947 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5948 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5953 (define_insn "*andsi3_cbranch"
5956 (match_operator 5 "equality_operator"
5957 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5958 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5960 (label_ref (match_operand 4 "" ""))
5962 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5963 (and:SI (match_dup 2) (match_dup 3)))
5964 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5968 if (which_alternative == 0)
5969 output_asm_insn (\"and\\t%0, %3\", operands);
5970 else if (which_alternative == 1)
5972 output_asm_insn (\"and\\t%1, %3\", operands);
5973 output_asm_insn (\"mov\\t%0, %1\", operands);
5977 output_asm_insn (\"and\\t%1, %3\", operands);
5978 output_asm_insn (\"str\\t%1, %0\", operands);
5981 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5983 case 4: return \"b%d5\\t%l4\";
5984 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5985 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5988 [(set (attr "far_jump")
5990 (ior (and (eq (symbol_ref ("which_alternative"))
5992 (eq_attr "length" "8"))
5993 (eq_attr "length" "10"))
5994 (const_string "yes")
5995 (const_string "no")))
5996 (set (attr "length")
5998 (eq (symbol_ref ("which_alternative"))
6001 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6002 (le (minus (match_dup 4) (pc)) (const_int 256)))
6005 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6006 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6010 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6011 (le (minus (match_dup 4) (pc)) (const_int 256)))
6014 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6015 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6020 (define_insn "*orrsi3_cbranch_scratch"
6023 (match_operator 4 "equality_operator"
6024 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6025 (match_operand:SI 2 "s_register_operand" "l"))
6027 (label_ref (match_operand 3 "" ""))
6029 (clobber (match_scratch:SI 0 "=l"))]
6033 output_asm_insn (\"orr\\t%0, %2\", operands);
6034 switch (get_attr_length (insn))
6036 case 4: return \"b%d4\\t%l3\";
6037 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6038 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6041 [(set (attr "far_jump")
6043 (eq_attr "length" "8")
6044 (const_string "yes")
6045 (const_string "no")))
6046 (set (attr "length")
6048 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6049 (le (minus (match_dup 3) (pc)) (const_int 256)))
6052 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6053 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6058 (define_insn "*orrsi3_cbranch"
6061 (match_operator 5 "equality_operator"
6062 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6063 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6065 (label_ref (match_operand 4 "" ""))
6067 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6068 (ior:SI (match_dup 2) (match_dup 3)))
6069 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6073 if (which_alternative == 0)
6074 output_asm_insn (\"orr\\t%0, %3\", operands);
6075 else if (which_alternative == 1)
6077 output_asm_insn (\"orr\\t%1, %3\", operands);
6078 output_asm_insn (\"mov\\t%0, %1\", operands);
6082 output_asm_insn (\"orr\\t%1, %3\", operands);
6083 output_asm_insn (\"str\\t%1, %0\", operands);
6086 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6088 case 4: return \"b%d5\\t%l4\";
6089 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6090 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6093 [(set (attr "far_jump")
6095 (ior (and (eq (symbol_ref ("which_alternative"))
6097 (eq_attr "length" "8"))
6098 (eq_attr "length" "10"))
6099 (const_string "yes")
6100 (const_string "no")))
6101 (set (attr "length")
6103 (eq (symbol_ref ("which_alternative"))
6106 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6107 (le (minus (match_dup 4) (pc)) (const_int 256)))
6110 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6111 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6115 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6116 (le (minus (match_dup 4) (pc)) (const_int 256)))
6119 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6120 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6125 (define_insn "*xorsi3_cbranch_scratch"
6128 (match_operator 4 "equality_operator"
6129 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6130 (match_operand:SI 2 "s_register_operand" "l"))
6132 (label_ref (match_operand 3 "" ""))
6134 (clobber (match_scratch:SI 0 "=l"))]
6138 output_asm_insn (\"eor\\t%0, %2\", operands);
6139 switch (get_attr_length (insn))
6141 case 4: return \"b%d4\\t%l3\";
6142 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6143 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6146 [(set (attr "far_jump")
6148 (eq_attr "length" "8")
6149 (const_string "yes")
6150 (const_string "no")))
6151 (set (attr "length")
6153 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6154 (le (minus (match_dup 3) (pc)) (const_int 256)))
6157 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6158 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6163 (define_insn "*xorsi3_cbranch"
6166 (match_operator 5 "equality_operator"
6167 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6168 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6170 (label_ref (match_operand 4 "" ""))
6172 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6173 (xor:SI (match_dup 2) (match_dup 3)))
6174 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6178 if (which_alternative == 0)
6179 output_asm_insn (\"eor\\t%0, %3\", operands);
6180 else if (which_alternative == 1)
6182 output_asm_insn (\"eor\\t%1, %3\", operands);
6183 output_asm_insn (\"mov\\t%0, %1\", operands);
6187 output_asm_insn (\"eor\\t%1, %3\", operands);
6188 output_asm_insn (\"str\\t%1, %0\", operands);
6191 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6193 case 4: return \"b%d5\\t%l4\";
6194 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6195 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6198 [(set (attr "far_jump")
6200 (ior (and (eq (symbol_ref ("which_alternative"))
6202 (eq_attr "length" "8"))
6203 (eq_attr "length" "10"))
6204 (const_string "yes")
6205 (const_string "no")))
6206 (set (attr "length")
6208 (eq (symbol_ref ("which_alternative"))
6211 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6212 (le (minus (match_dup 4) (pc)) (const_int 256)))
6215 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6216 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6220 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6221 (le (minus (match_dup 4) (pc)) (const_int 256)))
6224 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6225 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6230 (define_insn "*bicsi3_cbranch_scratch"
6233 (match_operator 4 "equality_operator"
6234 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6235 (match_operand:SI 1 "s_register_operand" "0"))
6237 (label_ref (match_operand 3 "" ""))
6239 (clobber (match_scratch:SI 0 "=l"))]
6243 output_asm_insn (\"bic\\t%0, %2\", operands);
6244 switch (get_attr_length (insn))
6246 case 4: return \"b%d4\\t%l3\";
6247 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6248 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6251 [(set (attr "far_jump")
6253 (eq_attr "length" "8")
6254 (const_string "yes")
6255 (const_string "no")))
6256 (set (attr "length")
6258 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6259 (le (minus (match_dup 3) (pc)) (const_int 256)))
6262 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6263 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6268 (define_insn "*bicsi3_cbranch"
6271 (match_operator 5 "equality_operator"
6272 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6273 (match_operand:SI 2 "s_register_operand" "0,1,1,1"))
6275 (label_ref (match_operand 4 "" ""))
6277 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6278 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6279 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6283 if (which_alternative == 0)
6284 output_asm_insn (\"bic\\t%0, %3\", operands);
6285 else if (which_alternative == 1)
6287 output_asm_insn (\"bic\\t%1, %3\", operands);
6288 output_asm_insn (\"mov\\t%0, %1\", operands);
6292 output_asm_insn (\"bic\\t%1, %3\", operands);
6293 output_asm_insn (\"str\\t%1, %0\", operands);
6296 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6298 case 4: return \"b%d5\\t%l4\";
6299 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6300 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6303 [(set (attr "far_jump")
6305 (ior (and (eq (symbol_ref ("which_alternative"))
6307 (eq_attr "length" "8"))
6308 (eq_attr "length" "10"))
6309 (const_string "yes")
6310 (const_string "no")))
6311 (set (attr "length")
6313 (eq (symbol_ref ("which_alternative"))
6316 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6317 (le (minus (match_dup 4) (pc)) (const_int 256)))
6320 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6321 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6325 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6326 (le (minus (match_dup 4) (pc)) (const_int 256)))
6329 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6330 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6335 (define_insn "*cbranchne_decr1"
6337 (if_then_else (match_operator 3 "equality_operator"
6338 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6340 (label_ref (match_operand 4 "" ""))
6342 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6343 (plus:SI (match_dup 2) (const_int -1)))
6344 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6349 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6351 VOIDmode, operands[2], const1_rtx);
6352 cond[1] = operands[4];
6354 if (which_alternative == 0)
6355 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6356 else if (which_alternative == 1)
6358 /* We must provide an alternative for a hi reg because reload
6359 cannot handle output reloads on a jump instruction, but we
6360 can't subtract into that. Fortunately a mov from lo to hi
6361 does not clobber the condition codes. */
6362 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6363 output_asm_insn (\"mov\\t%0, %1\", operands);
6367 /* Similarly, but the target is memory. */
6368 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6369 output_asm_insn (\"str\\t%1, %0\", operands);
6372 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6375 output_asm_insn (\"b%d0\\t%l1\", cond);
6378 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6379 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6381 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6382 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6386 [(set (attr "far_jump")
6388 (ior (and (eq (symbol_ref ("which_alternative"))
6390 (eq_attr "length" "8"))
6391 (eq_attr "length" "10"))
6392 (const_string "yes")
6393 (const_string "no")))
6394 (set_attr_alternative "length"
6398 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6399 (le (minus (match_dup 4) (pc)) (const_int 256)))
6402 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6403 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6408 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6409 (le (minus (match_dup 4) (pc)) (const_int 256)))
6412 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6413 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6418 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6419 (le (minus (match_dup 4) (pc)) (const_int 256)))
6422 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6423 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6428 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6429 (le (minus (match_dup 4) (pc)) (const_int 256)))
6432 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6433 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6438 (define_insn "*addsi3_cbranch"
6441 (match_operator 4 "comparison_operator"
6443 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6444 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6446 (label_ref (match_operand 5 "" ""))
6449 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6450 (plus:SI (match_dup 2) (match_dup 3)))
6451 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6453 && (GET_CODE (operands[4]) == EQ
6454 || GET_CODE (operands[4]) == NE
6455 || GET_CODE (operands[4]) == GE
6456 || GET_CODE (operands[4]) == LT)"
6462 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6463 cond[1] = operands[2];
6464 cond[2] = operands[3];
6466 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6467 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6469 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6471 if (which_alternative >= 3
6472 && which_alternative < 4)
6473 output_asm_insn (\"mov\\t%0, %1\", operands);
6474 else if (which_alternative >= 4)
6475 output_asm_insn (\"str\\t%1, %0\", operands);
6477 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6480 return \"b%d4\\t%l5\";
6482 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6484 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6488 [(set (attr "far_jump")
6490 (ior (and (lt (symbol_ref ("which_alternative"))
6492 (eq_attr "length" "8"))
6493 (eq_attr "length" "10"))
6494 (const_string "yes")
6495 (const_string "no")))
6496 (set (attr "length")
6498 (lt (symbol_ref ("which_alternative"))
6501 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6502 (le (minus (match_dup 5) (pc)) (const_int 256)))
6505 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6506 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6510 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6511 (le (minus (match_dup 5) (pc)) (const_int 256)))
6514 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6515 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6520 (define_insn "*addsi3_cbranch_scratch"
6523 (match_operator 3 "comparison_operator"
6525 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6526 (match_operand:SI 2 "reg_or_int_operand" "J,l,I,L"))
6528 (label_ref (match_operand 4 "" ""))
6530 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6532 && (GET_CODE (operands[3]) == EQ
6533 || GET_CODE (operands[3]) == NE
6534 || GET_CODE (operands[3]) == GE
6535 || GET_CODE (operands[3]) == LT)"
6538 switch (which_alternative)
6541 output_asm_insn (\"cmp\t%1, #%n2\", operands);
6544 output_asm_insn (\"cmn\t%1, %2\", operands);
6547 output_asm_insn (\"add\t%0, %1, %2\", operands);
6550 output_asm_insn (\"add\t%0, %0, %2\", operands);
6554 switch (get_attr_length (insn))
6557 return \"b%d3\\t%l4\";
6559 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6561 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6565 [(set (attr "far_jump")
6567 (eq_attr "length" "8")
6568 (const_string "yes")
6569 (const_string "no")))
6570 (set (attr "length")
6572 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6573 (le (minus (match_dup 4) (pc)) (const_int 256)))
6576 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6577 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6582 (define_insn "*subsi3_cbranch"
6585 (match_operator 4 "comparison_operator"
6587 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6588 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6590 (label_ref (match_operand 5 "" ""))
6592 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6593 (minus:SI (match_dup 2) (match_dup 3)))
6594 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6596 && (GET_CODE (operands[4]) == EQ
6597 || GET_CODE (operands[4]) == NE
6598 || GET_CODE (operands[4]) == GE
6599 || GET_CODE (operands[4]) == LT)"
6602 if (which_alternative == 0)
6603 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6604 else if (which_alternative == 1)
6606 /* We must provide an alternative for a hi reg because reload
6607 cannot handle output reloads on a jump instruction, but we
6608 can't subtract into that. Fortunately a mov from lo to hi
6609 does not clobber the condition codes. */
6610 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6611 output_asm_insn (\"mov\\t%0, %1\", operands);
6615 /* Similarly, but the target is memory. */
6616 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6617 output_asm_insn (\"str\\t%1, %0\", operands);
6620 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6623 return \"b%d4\\t%l5\";
6625 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6627 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6631 [(set (attr "far_jump")
6633 (ior (and (eq (symbol_ref ("which_alternative"))
6635 (eq_attr "length" "8"))
6636 (eq_attr "length" "10"))
6637 (const_string "yes")
6638 (const_string "no")))
6639 (set (attr "length")
6641 (eq (symbol_ref ("which_alternative"))
6644 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6645 (le (minus (match_dup 5) (pc)) (const_int 256)))
6648 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6649 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6653 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6654 (le (minus (match_dup 5) (pc)) (const_int 256)))
6657 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6658 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6663 (define_insn "*subsi3_cbranch_scratch"
6666 (match_operator 0 "arm_comparison_operator"
6667 [(minus:SI (match_operand:SI 1 "register_operand" "l")
6668 (match_operand:SI 2 "nonmemory_operand" "l"))
6670 (label_ref (match_operand 3 "" ""))
6673 && (GET_CODE (operands[0]) == EQ
6674 || GET_CODE (operands[0]) == NE
6675 || GET_CODE (operands[0]) == GE
6676 || GET_CODE (operands[0]) == LT)"
6678 output_asm_insn (\"cmp\\t%1, %2\", operands);
6679 switch (get_attr_length (insn))
6681 case 4: return \"b%d0\\t%l3\";
6682 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6683 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6686 [(set (attr "far_jump")
6688 (eq_attr "length" "8")
6689 (const_string "yes")
6690 (const_string "no")))
6691 (set (attr "length")
6693 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6694 (le (minus (match_dup 3) (pc)) (const_int 256)))
6697 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6698 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6703 ;; Comparison and test insns
6705 (define_expand "cmpsi"
6706 [(match_operand:SI 0 "s_register_operand" "")
6707 (match_operand:SI 1 "arm_add_operand" "")]
6710 arm_compare_op0 = operands[0];
6711 arm_compare_op1 = operands[1];
6716 (define_expand "cmpsf"
6717 [(match_operand:SF 0 "s_register_operand" "")
6718 (match_operand:SF 1 "arm_float_compare_operand" "")]
6719 "TARGET_ARM && TARGET_HARD_FLOAT"
6721 arm_compare_op0 = operands[0];
6722 arm_compare_op1 = operands[1];
6727 (define_expand "cmpdf"
6728 [(match_operand:DF 0 "s_register_operand" "")
6729 (match_operand:DF 1 "arm_float_compare_operand" "")]
6730 "TARGET_ARM && TARGET_HARD_FLOAT"
6732 arm_compare_op0 = operands[0];
6733 arm_compare_op1 = operands[1];
6738 (define_insn "*arm_cmpsi_insn"
6739 [(set (reg:CC CC_REGNUM)
6740 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6741 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
6746 [(set_attr "conds" "set")]
6749 (define_insn "*cmpsi_shiftsi"
6750 [(set (reg:CC CC_REGNUM)
6751 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6752 (match_operator:SI 3 "shift_operator"
6753 [(match_operand:SI 1 "s_register_operand" "r")
6754 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
6757 [(set_attr "conds" "set")
6758 (set_attr "shift" "1")
6759 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6760 (const_string "alu_shift")
6761 (const_string "alu_shift_reg")))]
6764 (define_insn "*cmpsi_shiftsi_swp"
6765 [(set (reg:CC_SWP CC_REGNUM)
6766 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6767 [(match_operand:SI 1 "s_register_operand" "r")
6768 (match_operand:SI 2 "reg_or_int_operand" "rM")])
6769 (match_operand:SI 0 "s_register_operand" "r")))]
6772 [(set_attr "conds" "set")
6773 (set_attr "shift" "1")
6774 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6775 (const_string "alu_shift")
6776 (const_string "alu_shift_reg")))]
6779 (define_insn "*cmpsi_neg_shiftsi"
6780 [(set (reg:CC CC_REGNUM)
6781 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6782 (neg:SI (match_operator:SI 3 "shift_operator"
6783 [(match_operand:SI 1 "s_register_operand" "r")
6784 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
6787 [(set_attr "conds" "set")
6788 (set_attr "shift" "1")
6789 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6790 (const_string "alu_shift")
6791 (const_string "alu_shift_reg")))]
6794 ;; Cirrus SF compare instruction
6795 (define_insn "*cirrus_cmpsf"
6796 [(set (reg:CCFP CC_REGNUM)
6797 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6798 (match_operand:SF 1 "cirrus_fp_register" "v")))]
6799 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6800 "cfcmps%?\\tr15, %V0, %V1"
6801 [(set_attr "type" "mav_farith")
6802 (set_attr "cirrus" "compare")]
6805 ;; Cirrus DF compare instruction
6806 (define_insn "*cirrus_cmpdf"
6807 [(set (reg:CCFP CC_REGNUM)
6808 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6809 (match_operand:DF 1 "cirrus_fp_register" "v")))]
6810 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6811 "cfcmpd%?\\tr15, %V0, %V1"
6812 [(set_attr "type" "mav_farith")
6813 (set_attr "cirrus" "compare")]
6816 ;; Cirrus DI compare instruction
6817 (define_expand "cmpdi"
6818 [(match_operand:DI 0 "cirrus_fp_register" "")
6819 (match_operand:DI 1 "cirrus_fp_register" "")]
6820 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6822 arm_compare_op0 = operands[0];
6823 arm_compare_op1 = operands[1];
6827 (define_insn "*cirrus_cmpdi"
6828 [(set (reg:CC CC_REGNUM)
6829 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6830 (match_operand:DI 1 "cirrus_fp_register" "v")))]
6831 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6832 "cfcmp64%?\\tr15, %V0, %V1"
6833 [(set_attr "type" "mav_farith")
6834 (set_attr "cirrus" "compare")]
6837 ; This insn allows redundant compares to be removed by cse, nothing should
6838 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6839 ; is deleted later on. The match_dup will match the mode here, so that
6840 ; mode changes of the condition codes aren't lost by this even though we don't
6841 ; specify what they are.
6843 (define_insn "*deleted_compare"
6844 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6846 "\\t%@ deleted compare"
6847 [(set_attr "conds" "set")
6848 (set_attr "length" "0")]
6852 ;; Conditional branch insns
6854 (define_expand "beq"
6856 (if_then_else (eq (match_dup 1) (const_int 0))
6857 (label_ref (match_operand 0 "" ""))
6860 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6863 (define_expand "bne"
6865 (if_then_else (ne (match_dup 1) (const_int 0))
6866 (label_ref (match_operand 0 "" ""))
6869 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6872 (define_expand "bgt"
6874 (if_then_else (gt (match_dup 1) (const_int 0))
6875 (label_ref (match_operand 0 "" ""))
6878 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6881 (define_expand "ble"
6883 (if_then_else (le (match_dup 1) (const_int 0))
6884 (label_ref (match_operand 0 "" ""))
6887 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6890 (define_expand "bge"
6892 (if_then_else (ge (match_dup 1) (const_int 0))
6893 (label_ref (match_operand 0 "" ""))
6896 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6899 (define_expand "blt"
6901 (if_then_else (lt (match_dup 1) (const_int 0))
6902 (label_ref (match_operand 0 "" ""))
6905 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6908 (define_expand "bgtu"
6910 (if_then_else (gtu (match_dup 1) (const_int 0))
6911 (label_ref (match_operand 0 "" ""))
6914 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6917 (define_expand "bleu"
6919 (if_then_else (leu (match_dup 1) (const_int 0))
6920 (label_ref (match_operand 0 "" ""))
6923 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6926 (define_expand "bgeu"
6928 (if_then_else (geu (match_dup 1) (const_int 0))
6929 (label_ref (match_operand 0 "" ""))
6932 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6935 (define_expand "bltu"
6937 (if_then_else (ltu (match_dup 1) (const_int 0))
6938 (label_ref (match_operand 0 "" ""))
6941 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6944 (define_expand "bunordered"
6946 (if_then_else (unordered (match_dup 1) (const_int 0))
6947 (label_ref (match_operand 0 "" ""))
6949 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6950 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6954 (define_expand "bordered"
6956 (if_then_else (ordered (match_dup 1) (const_int 0))
6957 (label_ref (match_operand 0 "" ""))
6959 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6960 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6964 (define_expand "bungt"
6966 (if_then_else (ungt (match_dup 1) (const_int 0))
6967 (label_ref (match_operand 0 "" ""))
6969 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6970 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6973 (define_expand "bunlt"
6975 (if_then_else (unlt (match_dup 1) (const_int 0))
6976 (label_ref (match_operand 0 "" ""))
6978 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6979 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6982 (define_expand "bunge"
6984 (if_then_else (unge (match_dup 1) (const_int 0))
6985 (label_ref (match_operand 0 "" ""))
6987 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6988 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6991 (define_expand "bunle"
6993 (if_then_else (unle (match_dup 1) (const_int 0))
6994 (label_ref (match_operand 0 "" ""))
6996 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6997 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7000 ;; The following two patterns need two branch instructions, since there is
7001 ;; no single instruction that will handle all cases.
7002 (define_expand "buneq"
7004 (if_then_else (uneq (match_dup 1) (const_int 0))
7005 (label_ref (match_operand 0 "" ""))
7007 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7008 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7011 (define_expand "bltgt"
7013 (if_then_else (ltgt (match_dup 1) (const_int 0))
7014 (label_ref (match_operand 0 "" ""))
7016 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7017 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7021 ;; Patterns to match conditional branch insns.
7024 ; Special pattern to match UNEQ.
7025 (define_insn "*arm_buneq"
7027 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7028 (label_ref (match_operand 0 "" ""))
7030 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7032 if (arm_ccfsm_state != 0)
7035 return \"bvs\\t%l0\;beq\\t%l0\";
7037 [(set_attr "conds" "jump_clob")
7038 (set_attr "length" "8")]
7041 ; Special pattern to match LTGT.
7042 (define_insn "*arm_bltgt"
7044 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7045 (label_ref (match_operand 0 "" ""))
7047 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7049 if (arm_ccfsm_state != 0)
7052 return \"bmi\\t%l0\;bgt\\t%l0\";
7054 [(set_attr "conds" "jump_clob")
7055 (set_attr "length" "8")]
7058 (define_insn "*arm_cond_branch"
7060 (if_then_else (match_operator 1 "arm_comparison_operator"
7061 [(match_operand 2 "cc_register" "") (const_int 0)])
7062 (label_ref (match_operand 0 "" ""))
7066 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7068 arm_ccfsm_state += 2;
7071 return \"b%d1\\t%l0\";
7073 [(set_attr "conds" "use")
7074 (set_attr "type" "branch")]
7077 ; Special pattern to match reversed UNEQ.
7078 (define_insn "*arm_buneq_reversed"
7080 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7082 (label_ref (match_operand 0 "" ""))))]
7083 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7085 if (arm_ccfsm_state != 0)
7088 return \"bmi\\t%l0\;bgt\\t%l0\";
7090 [(set_attr "conds" "jump_clob")
7091 (set_attr "length" "8")]
7094 ; Special pattern to match reversed LTGT.
7095 (define_insn "*arm_bltgt_reversed"
7097 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7099 (label_ref (match_operand 0 "" ""))))]
7100 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7102 if (arm_ccfsm_state != 0)
7105 return \"bvs\\t%l0\;beq\\t%l0\";
7107 [(set_attr "conds" "jump_clob")
7108 (set_attr "length" "8")]
7111 (define_insn "*arm_cond_branch_reversed"
7113 (if_then_else (match_operator 1 "arm_comparison_operator"
7114 [(match_operand 2 "cc_register" "") (const_int 0)])
7116 (label_ref (match_operand 0 "" ""))))]
7119 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7121 arm_ccfsm_state += 2;
7124 return \"b%D1\\t%l0\";
7126 [(set_attr "conds" "use")
7127 (set_attr "type" "branch")]
7134 (define_expand "seq"
7135 [(set (match_operand:SI 0 "s_register_operand" "")
7136 (eq:SI (match_dup 1) (const_int 0)))]
7138 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7141 (define_expand "sne"
7142 [(set (match_operand:SI 0 "s_register_operand" "")
7143 (ne:SI (match_dup 1) (const_int 0)))]
7145 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7148 (define_expand "sgt"
7149 [(set (match_operand:SI 0 "s_register_operand" "")
7150 (gt:SI (match_dup 1) (const_int 0)))]
7152 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7155 (define_expand "sle"
7156 [(set (match_operand:SI 0 "s_register_operand" "")
7157 (le:SI (match_dup 1) (const_int 0)))]
7159 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7162 (define_expand "sge"
7163 [(set (match_operand:SI 0 "s_register_operand" "")
7164 (ge:SI (match_dup 1) (const_int 0)))]
7166 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7169 (define_expand "slt"
7170 [(set (match_operand:SI 0 "s_register_operand" "")
7171 (lt:SI (match_dup 1) (const_int 0)))]
7173 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7176 (define_expand "sgtu"
7177 [(set (match_operand:SI 0 "s_register_operand" "")
7178 (gtu:SI (match_dup 1) (const_int 0)))]
7180 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7183 (define_expand "sleu"
7184 [(set (match_operand:SI 0 "s_register_operand" "")
7185 (leu:SI (match_dup 1) (const_int 0)))]
7187 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7190 (define_expand "sgeu"
7191 [(set (match_operand:SI 0 "s_register_operand" "")
7192 (geu:SI (match_dup 1) (const_int 0)))]
7194 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7197 (define_expand "sltu"
7198 [(set (match_operand:SI 0 "s_register_operand" "")
7199 (ltu:SI (match_dup 1) (const_int 0)))]
7201 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7204 (define_expand "sunordered"
7205 [(set (match_operand:SI 0 "s_register_operand" "")
7206 (unordered:SI (match_dup 1) (const_int 0)))]
7207 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7208 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7212 (define_expand "sordered"
7213 [(set (match_operand:SI 0 "s_register_operand" "")
7214 (ordered:SI (match_dup 1) (const_int 0)))]
7215 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7216 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7220 (define_expand "sungt"
7221 [(set (match_operand:SI 0 "s_register_operand" "")
7222 (ungt:SI (match_dup 1) (const_int 0)))]
7223 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7224 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7228 (define_expand "sunge"
7229 [(set (match_operand:SI 0 "s_register_operand" "")
7230 (unge:SI (match_dup 1) (const_int 0)))]
7231 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7232 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7236 (define_expand "sunlt"
7237 [(set (match_operand:SI 0 "s_register_operand" "")
7238 (unlt:SI (match_dup 1) (const_int 0)))]
7239 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7240 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7244 (define_expand "sunle"
7245 [(set (match_operand:SI 0 "s_register_operand" "")
7246 (unle:SI (match_dup 1) (const_int 0)))]
7247 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7248 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7252 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7253 ;;; simple ARM instructions.
7255 ; (define_expand "suneq"
7256 ; [(set (match_operand:SI 0 "s_register_operand" "")
7257 ; (uneq:SI (match_dup 1) (const_int 0)))]
7258 ; "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7262 ; (define_expand "sltgt"
7263 ; [(set (match_operand:SI 0 "s_register_operand" "")
7264 ; (ltgt:SI (match_dup 1) (const_int 0)))]
7265 ; "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7269 (define_insn "*mov_scc"
7270 [(set (match_operand:SI 0 "s_register_operand" "=r")
7271 (match_operator:SI 1 "arm_comparison_operator"
7272 [(match_operand 2 "cc_register" "") (const_int 0)]))]
7274 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7275 [(set_attr "conds" "use")
7276 (set_attr "length" "8")]
7279 (define_insn "*mov_negscc"
7280 [(set (match_operand:SI 0 "s_register_operand" "=r")
7281 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7282 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7284 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7285 [(set_attr "conds" "use")
7286 (set_attr "length" "8")]
7289 (define_insn "*mov_notscc"
7290 [(set (match_operand:SI 0 "s_register_operand" "=r")
7291 (not:SI (match_operator:SI 1 "arm_comparison_operator"
7292 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7294 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7295 [(set_attr "conds" "use")
7296 (set_attr "length" "8")]
7300 ;; Conditional move insns
7302 (define_expand "movsicc"
7303 [(set (match_operand:SI 0 "s_register_operand" "")
7304 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7305 (match_operand:SI 2 "arm_not_operand" "")
7306 (match_operand:SI 3 "arm_not_operand" "")))]
7310 enum rtx_code code = GET_CODE (operands[1]);
7313 if (code == UNEQ || code == LTGT)
7316 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7317 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7321 (define_expand "movsfcc"
7322 [(set (match_operand:SF 0 "s_register_operand" "")
7323 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7324 (match_operand:SF 2 "s_register_operand" "")
7325 (match_operand:SF 3 "nonmemory_operand" "")))]
7329 enum rtx_code code = GET_CODE (operands[1]);
7332 if (code == UNEQ || code == LTGT)
7335 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
7336 Otherwise, ensure it is a valid FP add operand */
7337 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7338 || (!arm_float_add_operand (operands[3], SFmode)))
7339 operands[3] = force_reg (SFmode, operands[3]);
7341 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7342 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7346 (define_expand "movdfcc"
7347 [(set (match_operand:DF 0 "s_register_operand" "")
7348 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7349 (match_operand:DF 2 "s_register_operand" "")
7350 (match_operand:DF 3 "arm_float_add_operand" "")))]
7351 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7354 enum rtx_code code = GET_CODE (operands[1]);
7357 if (code == UNEQ || code == LTGT)
7360 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7361 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7365 (define_insn "*movsicc_insn"
7366 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7368 (match_operator 3 "arm_comparison_operator"
7369 [(match_operand 4 "cc_register" "") (const_int 0)])
7370 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7371 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7378 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7379 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7380 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7381 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7382 [(set_attr "length" "4,4,4,4,8,8,8,8")
7383 (set_attr "conds" "use")]
7386 (define_insn "*movsfcc_soft_insn"
7387 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7388 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7389 [(match_operand 4 "cc_register" "") (const_int 0)])
7390 (match_operand:SF 1 "s_register_operand" "0,r")
7391 (match_operand:SF 2 "s_register_operand" "r,0")))]
7392 "TARGET_ARM && TARGET_SOFT_FLOAT"
7396 [(set_attr "conds" "use")]
7400 ;; Jump and linkage insns
7402 (define_expand "jump"
7404 (label_ref (match_operand 0 "" "")))]
7409 (define_insn "*arm_jump"
7411 (label_ref (match_operand 0 "" "")))]
7415 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7417 arm_ccfsm_state += 2;
7420 return \"b%?\\t%l0\";
7423 [(set_attr "predicable" "yes")]
7426 (define_insn "*thumb_jump"
7428 (label_ref (match_operand 0 "" "")))]
7431 if (get_attr_length (insn) == 2)
7433 return \"bl\\t%l0\\t%@ far jump\";
7435 [(set (attr "far_jump")
7437 (eq_attr "length" "4")
7438 (const_string "yes")
7439 (const_string "no")))
7440 (set (attr "length")
7442 (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
7443 (le (minus (match_dup 0) (pc)) (const_int 2044)))
7448 (define_expand "call"
7449 [(parallel [(call (match_operand 0 "memory_operand" "")
7450 (match_operand 1 "general_operand" ""))
7451 (use (match_operand 2 "" ""))
7452 (clobber (reg:SI LR_REGNUM))])]
7458 /* In an untyped call, we can get NULL for operand 2. */
7459 if (operands[2] == NULL_RTX)
7460 operands[2] = const0_rtx;
7462 /* This is to decide if we should generate indirect calls by loading the
7463 32 bit address of the callee into a register before performing the
7464 branch and link. operand[2] encodes the long_call/short_call
7465 attribute of the function being called. This attribute is set whenever
7466 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7467 is used, and the short_call attribute can also be set if function is
7468 declared as static or if it has already been defined in the current
7469 compilation unit. See arm.c and arm.h for info about this. The third
7470 parameter to arm_is_longcall_p is used to tell it which pattern
7472 callee = XEXP (operands[0], 0);
7474 if (GET_CODE (callee) != REG
7475 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7476 XEXP (operands[0], 0) = force_reg (Pmode, callee);
7480 (define_insn "*call_reg"
7481 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7482 (match_operand 1 "" ""))
7483 (use (match_operand 2 "" ""))
7484 (clobber (reg:SI LR_REGNUM))]
7487 return output_call (operands);
7489 ;; length is worst case, normally it is only two
7490 [(set_attr "length" "12")
7491 (set_attr "type" "call")]
7494 (define_insn "*call_mem"
7495 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7496 (match_operand 1 "" ""))
7497 (use (match_operand 2 "" ""))
7498 (clobber (reg:SI LR_REGNUM))]
7501 return output_call_mem (operands);
7503 [(set_attr "length" "12")
7504 (set_attr "type" "call")]
7507 (define_insn "*call_indirect"
7508 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7509 (match_operand 1 "" ""))
7510 (use (match_operand 2 "" ""))
7511 (clobber (reg:SI LR_REGNUM))]
7515 if (TARGET_CALLER_INTERWORKING)
7516 return \"bl\\t%__interwork_call_via_%0\";
7518 return \"bl\\t%__call_via_%0\";
7520 [(set_attr "type" "call")]
7523 (define_insn "*call_value_indirect"
7524 [(set (match_operand 0 "" "")
7525 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7526 (match_operand 2 "" "")))
7527 (use (match_operand 3 "" ""))
7528 (clobber (reg:SI LR_REGNUM))]
7532 if (TARGET_CALLER_INTERWORKING)
7533 return \"bl\\t%__interwork_call_via_%1\";
7535 return \"bl\\t%__call_via_%1\";
7537 [(set_attr "type" "call")]
7540 (define_expand "call_value"
7541 [(parallel [(set (match_operand 0 "" "")
7542 (call (match_operand 1 "memory_operand" "")
7543 (match_operand 2 "general_operand" "")))
7544 (use (match_operand 3 "" ""))
7545 (clobber (reg:SI LR_REGNUM))])]
7549 rtx callee = XEXP (operands[1], 0);
7551 /* In an untyped call, we can get NULL for operand 2. */
7552 if (operands[3] == 0)
7553 operands[3] = const0_rtx;
7555 /* See the comment in define_expand \"call\". */
7556 if (GET_CODE (callee) != REG
7557 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7558 XEXP (operands[1], 0) = force_reg (Pmode, callee);
7562 (define_insn "*call_value_reg"
7563 [(set (match_operand 0 "" "")
7564 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7565 (match_operand 2 "" "")))
7566 (use (match_operand 3 "" ""))
7567 (clobber (reg:SI LR_REGNUM))]
7570 return output_call (&operands[1]);
7572 [(set_attr "length" "12")
7573 (set_attr "type" "call")]
7576 (define_insn "*call_value_mem"
7577 [(set (match_operand 0 "" "")
7578 (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7579 (match_operand 2 "" "")))
7580 (use (match_operand 3 "" ""))
7581 (clobber (reg:SI LR_REGNUM))]
7582 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7584 return output_call_mem (&operands[1]);
7586 [(set_attr "length" "12")
7587 (set_attr "type" "call")]
7590 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7591 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7593 (define_insn "*call_symbol"
7594 [(call (mem:SI (match_operand:SI 0 "" ""))
7595 (match_operand 1 "" ""))
7596 (use (match_operand 2 "" ""))
7597 (clobber (reg:SI LR_REGNUM))]
7599 && (GET_CODE (operands[0]) == SYMBOL_REF)
7600 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7603 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7605 [(set_attr "type" "call")]
7608 (define_insn "*call_value_symbol"
7609 [(set (match_operand 0 "s_register_operand" "")
7610 (call (mem:SI (match_operand:SI 1 "" ""))
7611 (match_operand:SI 2 "" "")))
7612 (use (match_operand 3 "" ""))
7613 (clobber (reg:SI LR_REGNUM))]
7615 && (GET_CODE (operands[1]) == SYMBOL_REF)
7616 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7619 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7621 [(set_attr "type" "call")]
7624 (define_insn "*call_insn"
7625 [(call (mem:SI (match_operand:SI 0 "" ""))
7626 (match_operand:SI 1 "" ""))
7627 (use (match_operand 2 "" ""))
7628 (clobber (reg:SI LR_REGNUM))]
7630 && GET_CODE (operands[0]) == SYMBOL_REF
7631 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7633 [(set_attr "length" "4")
7634 (set_attr "type" "call")]
7637 (define_insn "*call_value_insn"
7638 [(set (match_operand 0 "register_operand" "")
7639 (call (mem:SI (match_operand 1 "" ""))
7640 (match_operand 2 "" "")))
7641 (use (match_operand 3 "" ""))
7642 (clobber (reg:SI LR_REGNUM))]
7644 && GET_CODE (operands[1]) == SYMBOL_REF
7645 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7647 [(set_attr "length" "4")
7648 (set_attr "type" "call")]
7651 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7652 (define_expand "sibcall"
7653 [(parallel [(call (match_operand 0 "memory_operand" "")
7654 (match_operand 1 "general_operand" ""))
7656 (use (match_operand 2 "" ""))])]
7660 if (operands[2] == NULL_RTX)
7661 operands[2] = const0_rtx;
7665 (define_expand "sibcall_value"
7666 [(parallel [(set (match_operand 0 "register_operand" "")
7667 (call (match_operand 1 "memory_operand" "")
7668 (match_operand 2 "general_operand" "")))
7670 (use (match_operand 3 "" ""))])]
7674 if (operands[3] == NULL_RTX)
7675 operands[3] = const0_rtx;
7679 (define_insn "*sibcall_insn"
7680 [(call (mem:SI (match_operand:SI 0 "" "X"))
7681 (match_operand 1 "" ""))
7683 (use (match_operand 2 "" ""))]
7684 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7686 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7688 [(set_attr "type" "call")]
7691 (define_insn "*sibcall_value_insn"
7692 [(set (match_operand 0 "s_register_operand" "")
7693 (call (mem:SI (match_operand:SI 1 "" "X"))
7694 (match_operand 2 "" "")))
7696 (use (match_operand 3 "" ""))]
7697 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7699 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7701 [(set_attr "type" "call")]
7704 ;; Often the return insn will be the same as loading from memory, so set attr
7705 (define_insn "return"
7707 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7710 if (arm_ccfsm_state == 2)
7712 arm_ccfsm_state += 2;
7715 return output_return_instruction (const_true_rtx, TRUE, FALSE);
7717 [(set_attr "type" "load1")
7718 (set_attr "length" "12")
7719 (set_attr "predicable" "yes")]
7722 (define_insn "*cond_return"
7724 (if_then_else (match_operator 0 "arm_comparison_operator"
7725 [(match_operand 1 "cc_register" "") (const_int 0)])
7728 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7731 if (arm_ccfsm_state == 2)
7733 arm_ccfsm_state += 2;
7736 return output_return_instruction (operands[0], TRUE, FALSE);
7738 [(set_attr "conds" "use")
7739 (set_attr "length" "12")
7740 (set_attr "type" "load1")]
7743 (define_insn "*cond_return_inverted"
7745 (if_then_else (match_operator 0 "arm_comparison_operator"
7746 [(match_operand 1 "cc_register" "") (const_int 0)])
7749 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7752 if (arm_ccfsm_state == 2)
7754 arm_ccfsm_state += 2;
7757 return output_return_instruction (operands[0], TRUE, TRUE);
7759 [(set_attr "conds" "use")
7760 (set_attr "type" "load1")]
7763 ;; Generate a sequence of instructions to determine if the processor is
7764 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7767 (define_expand "return_addr_mask"
7769 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7771 (set (match_operand:SI 0 "s_register_operand" "")
7772 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7774 (const_int 67108860)))] ; 0x03fffffc
7777 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7780 (define_insn "*check_arch2"
7781 [(set (match_operand:CC_NOOV 0 "cc_register" "")
7782 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7785 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7786 [(set_attr "length" "8")
7787 (set_attr "conds" "set")]
7790 ;; Call subroutine returning any type.
7792 (define_expand "untyped_call"
7793 [(parallel [(call (match_operand 0 "" "")
7795 (match_operand 1 "" "")
7796 (match_operand 2 "" "")])]
7802 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
7804 for (i = 0; i < XVECLEN (operands[2], 0); i++)
7806 rtx set = XVECEXP (operands[2], 0, i);
7808 emit_move_insn (SET_DEST (set), SET_SRC (set));
7811 /* The optimizer does not know that the call sets the function value
7812 registers we stored in the result block. We avoid problems by
7813 claiming that all hard registers are used and clobbered at this
7815 emit_insn (gen_blockage ());
7821 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7822 ;; all of memory. This blocks insns from being moved across this point.
7824 (define_insn "blockage"
7825 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7828 [(set_attr "length" "0")
7829 (set_attr "type" "block")]
7832 (define_expand "casesi"
7833 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
7834 (match_operand:SI 1 "const_int_operand" "") ; lower bound
7835 (match_operand:SI 2 "const_int_operand" "") ; total range
7836 (match_operand:SI 3 "" "") ; table label
7837 (match_operand:SI 4 "" "")] ; Out of range label
7842 if (operands[1] != const0_rtx)
7844 reg = gen_reg_rtx (SImode);
7846 emit_insn (gen_addsi3 (reg, operands[0],
7847 GEN_INT (-INTVAL (operands[1]))));
7851 if (!const_ok_for_arm (INTVAL (operands[2])))
7852 operands[2] = force_reg (SImode, operands[2]);
7854 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7860 ;; The USE in this pattern is needed to tell flow analysis that this is
7861 ;; a CASESI insn. It has no other purpose.
7862 (define_insn "casesi_internal"
7863 [(parallel [(set (pc)
7865 (leu (match_operand:SI 0 "s_register_operand" "r")
7866 (match_operand:SI 1 "arm_rhs_operand" "rI"))
7867 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7868 (label_ref (match_operand 2 "" ""))))
7869 (label_ref (match_operand 3 "" ""))))
7870 (clobber (reg:CC CC_REGNUM))
7871 (use (label_ref (match_dup 2)))])]
7875 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
7876 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
7878 [(set_attr "conds" "clob")
7879 (set_attr "length" "12")]
7882 (define_expand "indirect_jump"
7884 (match_operand:SI 0 "s_register_operand" ""))]
7889 (define_insn "*arm_indirect_jump"
7891 (match_operand:SI 0 "s_register_operand" "r"))]
7893 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
7894 [(set_attr "predicable" "yes")]
7897 ;; Although not supported by the define_expand above,
7898 ;; cse/combine may generate this form.
7899 (define_insn "*load_indirect_jump"
7901 (match_operand:SI 0 "memory_operand" "m"))]
7903 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
7904 [(set_attr "type" "load1")
7905 (set_attr "pool_range" "4096")
7906 (set_attr "neg_pool_range" "4084")
7907 (set_attr "predicable" "yes")]
7910 (define_insn "*thumb_indirect_jump"
7912 (match_operand:SI 0 "register_operand" "l*r"))]
7915 [(set_attr "conds" "clob")
7916 (set_attr "length" "2")]
7927 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
7928 return \"mov\\tr8, r8\";
7930 [(set (attr "length")
7931 (if_then_else (eq_attr "is_thumb" "yes")
7937 ;; Patterns to allow combination of arithmetic, cond code and shifts
7939 (define_insn "*arith_shiftsi"
7940 [(set (match_operand:SI 0 "s_register_operand" "=r")
7941 (match_operator:SI 1 "shiftable_operator"
7942 [(match_operator:SI 3 "shift_operator"
7943 [(match_operand:SI 4 "s_register_operand" "r")
7944 (match_operand:SI 5 "reg_or_int_operand" "rI")])
7945 (match_operand:SI 2 "s_register_operand" "r")]))]
7947 "%i1%?\\t%0, %2, %4%S3"
7948 [(set_attr "predicable" "yes")
7949 (set_attr "shift" "4")
7950 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7951 (const_string "alu_shift")
7952 (const_string "alu_shift_reg")))]
7956 [(set (match_operand:SI 0 "s_register_operand" "")
7957 (match_operator:SI 1 "shiftable_operator"
7958 [(match_operator:SI 2 "shiftable_operator"
7959 [(match_operator:SI 3 "shift_operator"
7960 [(match_operand:SI 4 "s_register_operand" "")
7961 (match_operand:SI 5 "reg_or_int_operand" "")])
7962 (match_operand:SI 6 "s_register_operand" "")])
7963 (match_operand:SI 7 "arm_rhs_operand" "")]))
7964 (clobber (match_operand:SI 8 "s_register_operand" ""))]
7967 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7970 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
7973 (define_insn "*arith_shiftsi_compare0"
7974 [(set (reg:CC_NOOV CC_REGNUM)
7975 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7976 [(match_operator:SI 3 "shift_operator"
7977 [(match_operand:SI 4 "s_register_operand" "r")
7978 (match_operand:SI 5 "reg_or_int_operand" "rI")])
7979 (match_operand:SI 2 "s_register_operand" "r")])
7981 (set (match_operand:SI 0 "s_register_operand" "=r")
7982 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7985 "%i1%?s\\t%0, %2, %4%S3"
7986 [(set_attr "conds" "set")
7987 (set_attr "shift" "4")
7988 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7989 (const_string "alu_shift")
7990 (const_string "alu_shift_reg")))]
7993 (define_insn "*arith_shiftsi_compare0_scratch"
7994 [(set (reg:CC_NOOV CC_REGNUM)
7995 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7996 [(match_operator:SI 3 "shift_operator"
7997 [(match_operand:SI 4 "s_register_operand" "r")
7998 (match_operand:SI 5 "reg_or_int_operand" "rI")])
7999 (match_operand:SI 2 "s_register_operand" "r")])
8001 (clobber (match_scratch:SI 0 "=r"))]
8003 "%i1%?s\\t%0, %2, %4%S3"
8004 [(set_attr "conds" "set")
8005 (set_attr "shift" "4")
8006 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8007 (const_string "alu_shift")
8008 (const_string "alu_shift_reg")))]
8011 (define_insn "*sub_shiftsi"
8012 [(set (match_operand:SI 0 "s_register_operand" "=r")
8013 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8014 (match_operator:SI 2 "shift_operator"
8015 [(match_operand:SI 3 "s_register_operand" "r")
8016 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8018 "sub%?\\t%0, %1, %3%S2"
8019 [(set_attr "predicable" "yes")
8020 (set_attr "shift" "3")
8021 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8022 (const_string "alu_shift")
8023 (const_string "alu_shift_reg")))]
8026 (define_insn "*sub_shiftsi_compare0"
8027 [(set (reg:CC_NOOV CC_REGNUM)
8029 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8030 (match_operator:SI 2 "shift_operator"
8031 [(match_operand:SI 3 "s_register_operand" "r")
8032 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8034 (set (match_operand:SI 0 "s_register_operand" "=r")
8035 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8038 "sub%?s\\t%0, %1, %3%S2"
8039 [(set_attr "conds" "set")
8040 (set_attr "shift" "3")
8041 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8042 (const_string "alu_shift")
8043 (const_string "alu_shift_reg")))]
8046 (define_insn "*sub_shiftsi_compare0_scratch"
8047 [(set (reg:CC_NOOV CC_REGNUM)
8049 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8050 (match_operator:SI 2 "shift_operator"
8051 [(match_operand:SI 3 "s_register_operand" "r")
8052 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8054 (clobber (match_scratch:SI 0 "=r"))]
8056 "sub%?s\\t%0, %1, %3%S2"
8057 [(set_attr "conds" "set")
8058 (set_attr "shift" "3")
8059 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8060 (const_string "alu_shift")
8061 (const_string "alu_shift_reg")))]
8066 (define_insn "*and_scc"
8067 [(set (match_operand:SI 0 "s_register_operand" "=r")
8068 (and:SI (match_operator:SI 1 "arm_comparison_operator"
8069 [(match_operand 3 "cc_register" "") (const_int 0)])
8070 (match_operand:SI 2 "s_register_operand" "r")))]
8072 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8073 [(set_attr "conds" "use")
8074 (set_attr "length" "8")]
8077 (define_insn "*ior_scc"
8078 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8079 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8080 [(match_operand 3 "cc_register" "") (const_int 0)])
8081 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8085 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8086 [(set_attr "conds" "use")
8087 (set_attr "length" "4,8")]
8090 (define_insn "*compare_scc"
8091 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8092 (match_operator:SI 1 "arm_comparison_operator"
8093 [(match_operand:SI 2 "s_register_operand" "r,r")
8094 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8095 (clobber (reg:CC CC_REGNUM))]
8098 if (operands[3] == const0_rtx)
8100 if (GET_CODE (operands[1]) == LT)
8101 return \"mov\\t%0, %2, lsr #31\";
8103 if (GET_CODE (operands[1]) == GE)
8104 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8106 if (GET_CODE (operands[1]) == EQ)
8107 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8110 if (GET_CODE (operands[1]) == NE)
8112 if (which_alternative == 1)
8113 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8114 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8116 if (which_alternative == 1)
8117 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8119 output_asm_insn (\"cmp\\t%2, %3\", operands);
8120 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8122 [(set_attr "conds" "clob")
8123 (set_attr "length" "12")]
8126 (define_insn "*cond_move"
8127 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8128 (if_then_else:SI (match_operator 3 "equality_operator"
8129 [(match_operator 4 "arm_comparison_operator"
8130 [(match_operand 5 "cc_register" "") (const_int 0)])
8132 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8133 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8136 if (GET_CODE (operands[3]) == NE)
8138 if (which_alternative != 1)
8139 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8140 if (which_alternative != 0)
8141 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8144 if (which_alternative != 0)
8145 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8146 if (which_alternative != 1)
8147 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8150 [(set_attr "conds" "use")
8151 (set_attr "length" "4,4,8")]
8154 (define_insn "*cond_arith"
8155 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8156 (match_operator:SI 5 "shiftable_operator"
8157 [(match_operator:SI 4 "arm_comparison_operator"
8158 [(match_operand:SI 2 "s_register_operand" "r,r")
8159 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8160 (match_operand:SI 1 "s_register_operand" "0,?r")]))
8161 (clobber (reg:CC CC_REGNUM))]
8164 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8165 return \"%i5\\t%0, %1, %2, lsr #31\";
8167 output_asm_insn (\"cmp\\t%2, %3\", operands);
8168 if (GET_CODE (operands[5]) == AND)
8169 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8170 else if (GET_CODE (operands[5]) == MINUS)
8171 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8172 else if (which_alternative != 0)
8173 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8174 return \"%i5%d4\\t%0, %1, #1\";
8176 [(set_attr "conds" "clob")
8177 (set_attr "length" "12")]
8180 (define_insn "*cond_sub"
8181 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8182 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8183 (match_operator:SI 4 "arm_comparison_operator"
8184 [(match_operand:SI 2 "s_register_operand" "r,r")
8185 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8186 (clobber (reg:CC CC_REGNUM))]
8189 output_asm_insn (\"cmp\\t%2, %3\", operands);
8190 if (which_alternative != 0)
8191 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8192 return \"sub%d4\\t%0, %1, #1\";
8194 [(set_attr "conds" "clob")
8195 (set_attr "length" "8,12")]
8198 (define_insn "*cmp_ite0"
8199 [(set (match_operand 6 "dominant_cc_register" "")
8202 (match_operator 4 "arm_comparison_operator"
8203 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8204 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8205 (match_operator:SI 5 "arm_comparison_operator"
8206 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8207 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8213 static const char * const opcodes[4][2] =
8215 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8216 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8217 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8218 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8219 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8220 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8221 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8222 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8225 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8227 return opcodes[which_alternative][swap];
8229 [(set_attr "conds" "set")
8230 (set_attr "length" "8")]
8233 (define_insn "*cmp_ite1"
8234 [(set (match_operand 6 "dominant_cc_register" "")
8237 (match_operator 4 "arm_comparison_operator"
8238 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8239 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8240 (match_operator:SI 5 "arm_comparison_operator"
8241 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8242 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8248 static const char * const opcodes[4][2] =
8250 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8251 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8252 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8253 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8254 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8255 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8256 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8257 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8260 comparison_dominates_p (GET_CODE (operands[5]),
8261 reverse_condition (GET_CODE (operands[4])));
8263 return opcodes[which_alternative][swap];
8265 [(set_attr "conds" "set")
8266 (set_attr "length" "8")]
8269 (define_insn "*cmp_and"
8270 [(set (match_operand 6 "dominant_cc_register" "")
8273 (match_operator 4 "arm_comparison_operator"
8274 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8275 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8276 (match_operator:SI 5 "arm_comparison_operator"
8277 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8278 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8283 static const char *const opcodes[4][2] =
8285 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8286 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8287 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8288 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8289 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8290 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8291 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8292 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8295 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8297 return opcodes[which_alternative][swap];
8299 [(set_attr "conds" "set")
8300 (set_attr "predicable" "no")
8301 (set_attr "length" "8")]
8304 (define_insn "*cmp_ior"
8305 [(set (match_operand 6 "dominant_cc_register" "")
8308 (match_operator 4 "arm_comparison_operator"
8309 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8310 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8311 (match_operator:SI 5 "arm_comparison_operator"
8312 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8313 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8318 static const char *const opcodes[4][2] =
8320 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8321 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8322 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8323 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8324 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8325 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8326 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8327 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8330 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8332 return opcodes[which_alternative][swap];
8335 [(set_attr "conds" "set")
8336 (set_attr "length" "8")]
8339 (define_insn_and_split "*ior_scc_scc"
8340 [(set (match_operand:SI 0 "s_register_operand" "=r")
8341 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8342 [(match_operand:SI 1 "s_register_operand" "r")
8343 (match_operand:SI 2 "arm_add_operand" "rIL")])
8344 (match_operator:SI 6 "arm_comparison_operator"
8345 [(match_operand:SI 4 "s_register_operand" "r")
8346 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8347 (clobber (reg:CC CC_REGNUM))]
8349 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8352 "TARGET_ARM && reload_completed"
8356 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8357 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8359 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8361 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8364 [(set_attr "conds" "clob")
8365 (set_attr "length" "16")])
8367 ; If the above pattern is followed by a CMP insn, then the compare is
8368 ; redundant, since we can rework the conditional instruction that follows.
8369 (define_insn_and_split "*ior_scc_scc_cmp"
8370 [(set (match_operand 0 "dominant_cc_register" "")
8371 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8372 [(match_operand:SI 1 "s_register_operand" "r")
8373 (match_operand:SI 2 "arm_add_operand" "rIL")])
8374 (match_operator:SI 6 "arm_comparison_operator"
8375 [(match_operand:SI 4 "s_register_operand" "r")
8376 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8378 (set (match_operand:SI 7 "s_register_operand" "=r")
8379 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8380 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8383 "TARGET_ARM && reload_completed"
8387 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8388 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8390 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8392 [(set_attr "conds" "set")
8393 (set_attr "length" "16")])
8395 (define_insn_and_split "*and_scc_scc"
8396 [(set (match_operand:SI 0 "s_register_operand" "=r")
8397 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8398 [(match_operand:SI 1 "s_register_operand" "r")
8399 (match_operand:SI 2 "arm_add_operand" "rIL")])
8400 (match_operator:SI 6 "arm_comparison_operator"
8401 [(match_operand:SI 4 "s_register_operand" "r")
8402 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8403 (clobber (reg:CC CC_REGNUM))]
8405 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8408 "TARGET_ARM && reload_completed
8409 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8414 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8415 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8417 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8419 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8422 [(set_attr "conds" "clob")
8423 (set_attr "length" "16")])
8425 ; If the above pattern is followed by a CMP insn, then the compare is
8426 ; redundant, since we can rework the conditional instruction that follows.
8427 (define_insn_and_split "*and_scc_scc_cmp"
8428 [(set (match_operand 0 "dominant_cc_register" "")
8429 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8430 [(match_operand:SI 1 "s_register_operand" "r")
8431 (match_operand:SI 2 "arm_add_operand" "rIL")])
8432 (match_operator:SI 6 "arm_comparison_operator"
8433 [(match_operand:SI 4 "s_register_operand" "r")
8434 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8436 (set (match_operand:SI 7 "s_register_operand" "=r")
8437 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8438 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8441 "TARGET_ARM && reload_completed"
8445 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8446 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8448 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8450 [(set_attr "conds" "set")
8451 (set_attr "length" "16")])
8453 ;; If there is no dominance in the comparison, then we can still save an
8454 ;; instruction in the AND case, since we can know that the second compare
8455 ;; need only zero the value if false (if true, then the value is already
8457 (define_insn_and_split "*and_scc_scc_nodom"
8458 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8459 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8460 [(match_operand:SI 1 "s_register_operand" "r,r,0")
8461 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8462 (match_operator:SI 6 "arm_comparison_operator"
8463 [(match_operand:SI 4 "s_register_operand" "r,r,r")
8464 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8465 (clobber (reg:CC CC_REGNUM))]
8467 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8470 "TARGET_ARM && reload_completed"
8471 [(parallel [(set (match_dup 0)
8472 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8473 (clobber (reg:CC CC_REGNUM))])
8474 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8476 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8479 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8480 operands[4], operands[5]),
8482 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8484 [(set_attr "conds" "clob")
8485 (set_attr "length" "20")])
8488 [(set (reg:CC_NOOV CC_REGNUM)
8489 (compare:CC_NOOV (ior:SI
8490 (and:SI (match_operand:SI 0 "s_register_operand" "")
8492 (match_operator:SI 1 "comparison_operator"
8493 [(match_operand:SI 2 "s_register_operand" "")
8494 (match_operand:SI 3 "arm_add_operand" "")]))
8496 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8499 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8501 (set (reg:CC_NOOV CC_REGNUM)
8502 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8507 [(set (reg:CC_NOOV CC_REGNUM)
8508 (compare:CC_NOOV (ior:SI
8509 (match_operator:SI 1 "comparison_operator"
8510 [(match_operand:SI 2 "s_register_operand" "")
8511 (match_operand:SI 3 "arm_add_operand" "")])
8512 (and:SI (match_operand:SI 0 "s_register_operand" "")
8515 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8518 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8520 (set (reg:CC_NOOV CC_REGNUM)
8521 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8525 (define_insn "*negscc"
8526 [(set (match_operand:SI 0 "s_register_operand" "=r")
8527 (neg:SI (match_operator 3 "arm_comparison_operator"
8528 [(match_operand:SI 1 "s_register_operand" "r")
8529 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8530 (clobber (reg:CC CC_REGNUM))]
8533 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8534 return \"mov\\t%0, %1, asr #31\";
8536 if (GET_CODE (operands[3]) == NE)
8537 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8539 if (GET_CODE (operands[3]) == GT)
8540 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8542 output_asm_insn (\"cmp\\t%1, %2\", operands);
8543 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8544 return \"mvn%d3\\t%0, #0\";
8546 [(set_attr "conds" "clob")
8547 (set_attr "length" "12")]
8550 (define_insn "movcond"
8551 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8553 (match_operator 5 "arm_comparison_operator"
8554 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8555 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8556 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8557 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8558 (clobber (reg:CC CC_REGNUM))]
8561 if (GET_CODE (operands[5]) == LT
8562 && (operands[4] == const0_rtx))
8564 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8566 if (operands[2] == const0_rtx)
8567 return \"and\\t%0, %1, %3, asr #31\";
8568 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8570 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8572 if (operands[1] == const0_rtx)
8573 return \"bic\\t%0, %2, %3, asr #31\";
8574 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8576 /* The only case that falls through to here is when both ops 1 & 2
8580 if (GET_CODE (operands[5]) == GE
8581 && (operands[4] == const0_rtx))
8583 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8585 if (operands[2] == const0_rtx)
8586 return \"bic\\t%0, %1, %3, asr #31\";
8587 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8589 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8591 if (operands[1] == const0_rtx)
8592 return \"and\\t%0, %2, %3, asr #31\";
8593 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8595 /* The only case that falls through to here is when both ops 1 & 2
8598 if (GET_CODE (operands[4]) == CONST_INT
8599 && !const_ok_for_arm (INTVAL (operands[4])))
8600 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8602 output_asm_insn (\"cmp\\t%3, %4\", operands);
8603 if (which_alternative != 0)
8604 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8605 if (which_alternative != 1)
8606 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8609 [(set_attr "conds" "clob")
8610 (set_attr "length" "8,8,12")]
8613 (define_insn "*ifcompare_plus_move"
8614 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8615 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8616 [(match_operand:SI 4 "s_register_operand" "r,r")
8617 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8619 (match_operand:SI 2 "s_register_operand" "r,r")
8620 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8621 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8622 (clobber (reg:CC CC_REGNUM))]
8625 [(set_attr "conds" "clob")
8626 (set_attr "length" "8,12")]
8629 (define_insn "*if_plus_move"
8630 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8632 (match_operator 4 "arm_comparison_operator"
8633 [(match_operand 5 "cc_register" "") (const_int 0)])
8635 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8636 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8637 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8641 sub%d4\\t%0, %2, #%n3
8642 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8643 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8644 [(set_attr "conds" "use")
8645 (set_attr "length" "4,4,8,8")
8646 (set_attr "type" "*,*,*,*")]
8649 (define_insn "*ifcompare_move_plus"
8650 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8651 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8652 [(match_operand:SI 4 "s_register_operand" "r,r")
8653 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8654 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8656 (match_operand:SI 2 "s_register_operand" "r,r")
8657 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8658 (clobber (reg:CC CC_REGNUM))]
8661 [(set_attr "conds" "clob")
8662 (set_attr "length" "8,12")]
8665 (define_insn "*if_move_plus"
8666 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8668 (match_operator 4 "arm_comparison_operator"
8669 [(match_operand 5 "cc_register" "") (const_int 0)])
8670 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8672 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8673 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8677 sub%D4\\t%0, %2, #%n3
8678 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8679 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8680 [(set_attr "conds" "use")
8681 (set_attr "length" "4,4,8,8")
8682 (set_attr "type" "*,*,*,*")]
8685 (define_insn "*ifcompare_arith_arith"
8686 [(set (match_operand:SI 0 "s_register_operand" "=r")
8687 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8688 [(match_operand:SI 5 "s_register_operand" "r")
8689 (match_operand:SI 6 "arm_add_operand" "rIL")])
8690 (match_operator:SI 8 "shiftable_operator"
8691 [(match_operand:SI 1 "s_register_operand" "r")
8692 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8693 (match_operator:SI 7 "shiftable_operator"
8694 [(match_operand:SI 3 "s_register_operand" "r")
8695 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8696 (clobber (reg:CC CC_REGNUM))]
8699 [(set_attr "conds" "clob")
8700 (set_attr "length" "12")]
8703 (define_insn "*if_arith_arith"
8704 [(set (match_operand:SI 0 "s_register_operand" "=r")
8705 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8706 [(match_operand 8 "cc_register" "") (const_int 0)])
8707 (match_operator:SI 6 "shiftable_operator"
8708 [(match_operand:SI 1 "s_register_operand" "r")
8709 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8710 (match_operator:SI 7 "shiftable_operator"
8711 [(match_operand:SI 3 "s_register_operand" "r")
8712 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8714 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8715 [(set_attr "conds" "use")
8716 (set_attr "length" "8")]
8719 (define_insn "*ifcompare_arith_move"
8720 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8721 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8722 [(match_operand:SI 2 "s_register_operand" "r,r")
8723 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8724 (match_operator:SI 7 "shiftable_operator"
8725 [(match_operand:SI 4 "s_register_operand" "r,r")
8726 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8727 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8728 (clobber (reg:CC CC_REGNUM))]
8731 /* If we have an operation where (op x 0) is the identity operation and
8732 the conditional operator is LT or GE and we are comparing against zero and
8733 everything is in registers then we can do this in two instructions. */
8734 if (operands[3] == const0_rtx
8735 && GET_CODE (operands[7]) != AND
8736 && GET_CODE (operands[5]) == REG
8737 && GET_CODE (operands[1]) == REG
8738 && REGNO (operands[1]) == REGNO (operands[4])
8739 && REGNO (operands[4]) != REGNO (operands[0]))
8741 if (GET_CODE (operands[6]) == LT)
8742 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8743 else if (GET_CODE (operands[6]) == GE)
8744 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8746 if (GET_CODE (operands[3]) == CONST_INT
8747 && !const_ok_for_arm (INTVAL (operands[3])))
8748 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8750 output_asm_insn (\"cmp\\t%2, %3\", operands);
8751 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8752 if (which_alternative != 0)
8753 return \"mov%D6\\t%0, %1\";
8756 [(set_attr "conds" "clob")
8757 (set_attr "length" "8,12")]
8760 (define_insn "*if_arith_move"
8761 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8762 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8763 [(match_operand 6 "cc_register" "") (const_int 0)])
8764 (match_operator:SI 5 "shiftable_operator"
8765 [(match_operand:SI 2 "s_register_operand" "r,r")
8766 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8767 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8771 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8772 [(set_attr "conds" "use")
8773 (set_attr "length" "4,8")
8774 (set_attr "type" "*,*")]
8777 (define_insn "*ifcompare_move_arith"
8778 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8779 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8780 [(match_operand:SI 4 "s_register_operand" "r,r")
8781 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8782 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8783 (match_operator:SI 7 "shiftable_operator"
8784 [(match_operand:SI 2 "s_register_operand" "r,r")
8785 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8786 (clobber (reg:CC CC_REGNUM))]
8789 /* If we have an operation where (op x 0) is the identity operation and
8790 the conditional operator is LT or GE and we are comparing against zero and
8791 everything is in registers then we can do this in two instructions */
8792 if (operands[5] == const0_rtx
8793 && GET_CODE (operands[7]) != AND
8794 && GET_CODE (operands[3]) == REG
8795 && GET_CODE (operands[1]) == REG
8796 && REGNO (operands[1]) == REGNO (operands[2])
8797 && REGNO (operands[2]) != REGNO (operands[0]))
8799 if (GET_CODE (operands[6]) == GE)
8800 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8801 else if (GET_CODE (operands[6]) == LT)
8802 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8805 if (GET_CODE (operands[5]) == CONST_INT
8806 && !const_ok_for_arm (INTVAL (operands[5])))
8807 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8809 output_asm_insn (\"cmp\\t%4, %5\", operands);
8811 if (which_alternative != 0)
8812 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8813 return \"%I7%D6\\t%0, %2, %3\";
8815 [(set_attr "conds" "clob")
8816 (set_attr "length" "8,12")]
8819 (define_insn "*if_move_arith"
8820 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8822 (match_operator 4 "arm_comparison_operator"
8823 [(match_operand 6 "cc_register" "") (const_int 0)])
8824 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8825 (match_operator:SI 5 "shiftable_operator"
8826 [(match_operand:SI 2 "s_register_operand" "r,r")
8827 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8831 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8832 [(set_attr "conds" "use")
8833 (set_attr "length" "4,8")
8834 (set_attr "type" "*,*")]
8837 (define_insn "*ifcompare_move_not"
8838 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8840 (match_operator 5 "arm_comparison_operator"
8841 [(match_operand:SI 3 "s_register_operand" "r,r")
8842 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8843 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8845 (match_operand:SI 2 "s_register_operand" "r,r"))))
8846 (clobber (reg:CC CC_REGNUM))]
8849 [(set_attr "conds" "clob")
8850 (set_attr "length" "8,12")]
8853 (define_insn "*if_move_not"
8854 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8856 (match_operator 4 "arm_comparison_operator"
8857 [(match_operand 3 "cc_register" "") (const_int 0)])
8858 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8859 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8863 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8864 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8865 [(set_attr "conds" "use")
8866 (set_attr "length" "4,8,8")]
8869 (define_insn "*ifcompare_not_move"
8870 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8872 (match_operator 5 "arm_comparison_operator"
8873 [(match_operand:SI 3 "s_register_operand" "r,r")
8874 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8876 (match_operand:SI 2 "s_register_operand" "r,r"))
8877 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8878 (clobber (reg:CC CC_REGNUM))]
8881 [(set_attr "conds" "clob")
8882 (set_attr "length" "8,12")]
8885 (define_insn "*if_not_move"
8886 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8888 (match_operator 4 "arm_comparison_operator"
8889 [(match_operand 3 "cc_register" "") (const_int 0)])
8890 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8891 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8895 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
8896 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8897 [(set_attr "conds" "use")
8898 (set_attr "length" "4,8,8")]
8901 (define_insn "*ifcompare_shift_move"
8902 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8904 (match_operator 6 "arm_comparison_operator"
8905 [(match_operand:SI 4 "s_register_operand" "r,r")
8906 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8907 (match_operator:SI 7 "shift_operator"
8908 [(match_operand:SI 2 "s_register_operand" "r,r")
8909 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
8910 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8911 (clobber (reg:CC CC_REGNUM))]
8914 [(set_attr "conds" "clob")
8915 (set_attr "length" "8,12")]
8918 (define_insn "*if_shift_move"
8919 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8921 (match_operator 5 "arm_comparison_operator"
8922 [(match_operand 6 "cc_register" "") (const_int 0)])
8923 (match_operator:SI 4 "shift_operator"
8924 [(match_operand:SI 2 "s_register_operand" "r,r,r")
8925 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
8926 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8930 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
8931 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8932 [(set_attr "conds" "use")
8933 (set_attr "shift" "2")
8934 (set_attr "length" "4,8,8")
8935 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8936 (const_string "alu_shift")
8937 (const_string "alu_shift_reg")))]
8940 (define_insn "*ifcompare_move_shift"
8941 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8943 (match_operator 6 "arm_comparison_operator"
8944 [(match_operand:SI 4 "s_register_operand" "r,r")
8945 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8946 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8947 (match_operator:SI 7 "shift_operator"
8948 [(match_operand:SI 2 "s_register_operand" "r,r")
8949 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
8950 (clobber (reg:CC CC_REGNUM))]
8953 [(set_attr "conds" "clob")
8954 (set_attr "length" "8,12")]
8957 (define_insn "*if_move_shift"
8958 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8960 (match_operator 5 "arm_comparison_operator"
8961 [(match_operand 6 "cc_register" "") (const_int 0)])
8962 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8963 (match_operator:SI 4 "shift_operator"
8964 [(match_operand:SI 2 "s_register_operand" "r,r,r")
8965 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
8969 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
8970 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8971 [(set_attr "conds" "use")
8972 (set_attr "shift" "2")
8973 (set_attr "length" "4,8,8")
8974 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8975 (const_string "alu_shift")
8976 (const_string "alu_shift_reg")))]
8979 (define_insn "*ifcompare_shift_shift"
8980 [(set (match_operand:SI 0 "s_register_operand" "=r")
8982 (match_operator 7 "arm_comparison_operator"
8983 [(match_operand:SI 5 "s_register_operand" "r")
8984 (match_operand:SI 6 "arm_add_operand" "rIL")])
8985 (match_operator:SI 8 "shift_operator"
8986 [(match_operand:SI 1 "s_register_operand" "r")
8987 (match_operand:SI 2 "arm_rhs_operand" "rM")])
8988 (match_operator:SI 9 "shift_operator"
8989 [(match_operand:SI 3 "s_register_operand" "r")
8990 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
8991 (clobber (reg:CC CC_REGNUM))]
8994 [(set_attr "conds" "clob")
8995 (set_attr "length" "12")]
8998 (define_insn "*if_shift_shift"
8999 [(set (match_operand:SI 0 "s_register_operand" "=r")
9001 (match_operator 5 "arm_comparison_operator"
9002 [(match_operand 8 "cc_register" "") (const_int 0)])
9003 (match_operator:SI 6 "shift_operator"
9004 [(match_operand:SI 1 "s_register_operand" "r")
9005 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9006 (match_operator:SI 7 "shift_operator"
9007 [(match_operand:SI 3 "s_register_operand" "r")
9008 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9010 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9011 [(set_attr "conds" "use")
9012 (set_attr "shift" "1")
9013 (set_attr "length" "8")
9014 (set (attr "type") (if_then_else
9015 (and (match_operand 2 "const_int_operand" "")
9016 (match_operand 4 "const_int_operand" ""))
9017 (const_string "alu_shift")
9018 (const_string "alu_shift_reg")))]
9021 (define_insn "*ifcompare_not_arith"
9022 [(set (match_operand:SI 0 "s_register_operand" "=r")
9024 (match_operator 6 "arm_comparison_operator"
9025 [(match_operand:SI 4 "s_register_operand" "r")
9026 (match_operand:SI 5 "arm_add_operand" "rIL")])
9027 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9028 (match_operator:SI 7 "shiftable_operator"
9029 [(match_operand:SI 2 "s_register_operand" "r")
9030 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9031 (clobber (reg:CC CC_REGNUM))]
9034 [(set_attr "conds" "clob")
9035 (set_attr "length" "12")]
9038 (define_insn "*if_not_arith"
9039 [(set (match_operand:SI 0 "s_register_operand" "=r")
9041 (match_operator 5 "arm_comparison_operator"
9042 [(match_operand 4 "cc_register" "") (const_int 0)])
9043 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9044 (match_operator:SI 6 "shiftable_operator"
9045 [(match_operand:SI 2 "s_register_operand" "r")
9046 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9048 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9049 [(set_attr "conds" "use")
9050 (set_attr "length" "8")]
9053 (define_insn "*ifcompare_arith_not"
9054 [(set (match_operand:SI 0 "s_register_operand" "=r")
9056 (match_operator 6 "arm_comparison_operator"
9057 [(match_operand:SI 4 "s_register_operand" "r")
9058 (match_operand:SI 5 "arm_add_operand" "rIL")])
9059 (match_operator:SI 7 "shiftable_operator"
9060 [(match_operand:SI 2 "s_register_operand" "r")
9061 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9062 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9063 (clobber (reg:CC CC_REGNUM))]
9066 [(set_attr "conds" "clob")
9067 (set_attr "length" "12")]
9070 (define_insn "*if_arith_not"
9071 [(set (match_operand:SI 0 "s_register_operand" "=r")
9073 (match_operator 5 "arm_comparison_operator"
9074 [(match_operand 4 "cc_register" "") (const_int 0)])
9075 (match_operator:SI 6 "shiftable_operator"
9076 [(match_operand:SI 2 "s_register_operand" "r")
9077 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9078 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9080 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9081 [(set_attr "conds" "use")
9082 (set_attr "length" "8")]
9085 (define_insn "*ifcompare_neg_move"
9086 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9088 (match_operator 5 "arm_comparison_operator"
9089 [(match_operand:SI 3 "s_register_operand" "r,r")
9090 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9091 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9092 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9093 (clobber (reg:CC CC_REGNUM))]
9096 [(set_attr "conds" "clob")
9097 (set_attr "length" "8,12")]
9100 (define_insn "*if_neg_move"
9101 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9103 (match_operator 4 "arm_comparison_operator"
9104 [(match_operand 3 "cc_register" "") (const_int 0)])
9105 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9106 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9110 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9111 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9112 [(set_attr "conds" "use")
9113 (set_attr "length" "4,8,8")]
9116 (define_insn "*ifcompare_move_neg"
9117 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9119 (match_operator 5 "arm_comparison_operator"
9120 [(match_operand:SI 3 "s_register_operand" "r,r")
9121 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9122 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9123 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9124 (clobber (reg:CC CC_REGNUM))]
9127 [(set_attr "conds" "clob")
9128 (set_attr "length" "8,12")]
9131 (define_insn "*if_move_neg"
9132 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9134 (match_operator 4 "arm_comparison_operator"
9135 [(match_operand 3 "cc_register" "") (const_int 0)])
9136 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9137 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9141 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9142 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9143 [(set_attr "conds" "use")
9144 (set_attr "length" "4,8,8")]
9147 (define_insn "*arith_adjacentmem"
9148 [(set (match_operand:SI 0 "s_register_operand" "=r")
9149 (match_operator:SI 1 "shiftable_operator"
9150 [(match_operand:SI 2 "memory_operand" "m")
9151 (match_operand:SI 3 "memory_operand" "m")]))
9152 (clobber (match_scratch:SI 4 "=r"))]
9153 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9158 int val1 = 0, val2 = 0;
9160 if (REGNO (operands[0]) > REGNO (operands[4]))
9162 ldm[1] = operands[4];
9163 ldm[2] = operands[0];
9167 ldm[1] = operands[0];
9168 ldm[2] = operands[4];
9170 if (GET_CODE (XEXP (operands[2], 0)) != REG)
9171 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
9172 if (GET_CODE (XEXP (operands[3], 0)) != REG)
9173 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9174 arith[0] = operands[0];
9175 arith[3] = operands[1];
9189 ldm[0] = ops[0] = operands[4];
9190 ops[1] = XEXP (XEXP (operands[2], 0), 0);
9191 ops[2] = XEXP (XEXP (operands[2], 0), 1);
9192 output_add_immediate (ops);
9194 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9196 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9200 ldm[0] = XEXP (operands[3], 0);
9202 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9204 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9208 ldm[0] = XEXP (operands[2], 0);
9210 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9212 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9214 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9217 [(set_attr "length" "12")
9218 (set_attr "predicable" "yes")
9219 (set_attr "type" "load1")]
9222 ;; the arm can support extended pre-inc instructions
9224 ;; In all these cases, we use operands 0 and 1 for the register being
9225 ;; incremented because those are the operands that local-alloc will
9226 ;; tie and these are the pair most likely to be tieable (and the ones
9227 ;; that will benefit the most).
9229 ;; We reject the frame pointer if it occurs anywhere in these patterns since
9230 ;; elimination will cause too many headaches.
9232 (define_insn "*strqi_preinc"
9233 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9234 (match_operand:SI 2 "index_operand" "rJ")))
9235 (match_operand:QI 3 "s_register_operand" "r"))
9236 (set (match_operand:SI 0 "s_register_operand" "=r")
9237 (plus:SI (match_dup 1) (match_dup 2)))]
9239 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9240 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9241 && (GET_CODE (operands[2]) != REG
9242 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9243 "str%?b\\t%3, [%0, %2]!"
9244 [(set_attr "type" "store1")
9245 (set_attr "predicable" "yes")]
9248 (define_insn "*strqi_predec"
9249 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9250 (match_operand:SI 2 "s_register_operand" "r")))
9251 (match_operand:QI 3 "s_register_operand" "r"))
9252 (set (match_operand:SI 0 "s_register_operand" "=r")
9253 (minus:SI (match_dup 1) (match_dup 2)))]
9255 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9256 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9257 && (GET_CODE (operands[2]) != REG
9258 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9259 "str%?b\\t%3, [%0, -%2]!"
9260 [(set_attr "type" "store1")
9261 (set_attr "predicable" "yes")]
9264 (define_insn "*loadqi_preinc"
9265 [(set (match_operand:QI 3 "s_register_operand" "=r")
9266 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9267 (match_operand:SI 2 "index_operand" "rJ"))))
9268 (set (match_operand:SI 0 "s_register_operand" "=r")
9269 (plus:SI (match_dup 1) (match_dup 2)))]
9271 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9272 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9273 && (GET_CODE (operands[2]) != REG
9274 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9275 "ldr%?b\\t%3, [%0, %2]!"
9276 [(set_attr "type" "load_byte")
9277 (set_attr "predicable" "yes")]
9280 (define_insn "*loadqi_predec"
9281 [(set (match_operand:QI 3 "s_register_operand" "=r")
9282 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9283 (match_operand:SI 2 "s_register_operand" "r"))))
9284 (set (match_operand:SI 0 "s_register_operand" "=r")
9285 (minus:SI (match_dup 1) (match_dup 2)))]
9287 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9288 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9289 && (GET_CODE (operands[2]) != REG
9290 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9291 "ldr%?b\\t%3, [%0, -%2]!"
9292 [(set_attr "type" "load_byte")
9293 (set_attr "predicable" "yes")]
9296 (define_insn "*loadqisi_preinc"
9297 [(set (match_operand:SI 3 "s_register_operand" "=r")
9299 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9300 (match_operand:SI 2 "index_operand" "rJ")))))
9301 (set (match_operand:SI 0 "s_register_operand" "=r")
9302 (plus:SI (match_dup 1) (match_dup 2)))]
9304 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9305 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9306 && (GET_CODE (operands[2]) != REG
9307 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9308 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
9309 [(set_attr "type" "load_byte")
9310 (set_attr "predicable" "yes")]
9313 (define_insn "*loadqisi_predec"
9314 [(set (match_operand:SI 3 "s_register_operand" "=r")
9316 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9317 (match_operand:SI 2 "s_register_operand" "r")))))
9318 (set (match_operand:SI 0 "s_register_operand" "=r")
9319 (minus:SI (match_dup 1) (match_dup 2)))]
9321 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9322 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9323 && (GET_CODE (operands[2]) != REG
9324 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9325 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
9326 [(set_attr "type" "load_byte")
9327 (set_attr "predicable" "yes")]
9330 (define_insn "*strsi_preinc"
9331 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9332 (match_operand:SI 2 "index_operand" "rJ")))
9333 (match_operand:SI 3 "s_register_operand" "r"))
9334 (set (match_operand:SI 0 "s_register_operand" "=r")
9335 (plus:SI (match_dup 1) (match_dup 2)))]
9337 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9338 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9339 && (GET_CODE (operands[2]) != REG
9340 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9341 "str%?\\t%3, [%0, %2]!"
9342 [(set_attr "type" "store1")
9343 (set_attr "predicable" "yes")]
9346 (define_insn "*strsi_predec"
9347 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9348 (match_operand:SI 2 "s_register_operand" "r")))
9349 (match_operand:SI 3 "s_register_operand" "r"))
9350 (set (match_operand:SI 0 "s_register_operand" "=r")
9351 (minus:SI (match_dup 1) (match_dup 2)))]
9353 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9354 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9355 && (GET_CODE (operands[2]) != REG
9356 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9357 "str%?\\t%3, [%0, -%2]!"
9358 [(set_attr "type" "store1")
9359 (set_attr "predicable" "yes")]
9362 (define_insn "*loadsi_preinc"
9363 [(set (match_operand:SI 3 "s_register_operand" "=r")
9364 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9365 (match_operand:SI 2 "index_operand" "rJ"))))
9366 (set (match_operand:SI 0 "s_register_operand" "=r")
9367 (plus:SI (match_dup 1) (match_dup 2)))]
9369 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9370 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9371 && (GET_CODE (operands[2]) != REG
9372 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9373 "ldr%?\\t%3, [%0, %2]!"
9374 [(set_attr "type" "load1")
9375 (set_attr "predicable" "yes")]
9378 (define_insn "*loadsi_predec"
9379 [(set (match_operand:SI 3 "s_register_operand" "=r")
9380 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9381 (match_operand:SI 2 "s_register_operand" "r"))))
9382 (set (match_operand:SI 0 "s_register_operand" "=r")
9383 (minus:SI (match_dup 1) (match_dup 2)))]
9385 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9386 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9387 && (GET_CODE (operands[2]) != REG
9388 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9389 "ldr%?\\t%3, [%0, -%2]!"
9390 [(set_attr "type" "load1")
9391 (set_attr "predicable" "yes")]
9394 (define_insn "*loadhi_preinc"
9395 [(set (match_operand:HI 3 "s_register_operand" "=r")
9396 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9397 (match_operand:SI 2 "index_operand" "rJ"))))
9398 (set (match_operand:SI 0 "s_register_operand" "=r")
9399 (plus:SI (match_dup 1) (match_dup 2)))]
9401 && !BYTES_BIG_ENDIAN
9402 && !TARGET_MMU_TRAPS
9404 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9405 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9406 && (GET_CODE (operands[2]) != REG
9407 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9408 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
9409 [(set_attr "type" "load_byte")
9410 (set_attr "predicable" "yes")]
9413 (define_insn "*loadhi_predec"
9414 [(set (match_operand:HI 3 "s_register_operand" "=r")
9415 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9416 (match_operand:SI 2 "s_register_operand" "r"))))
9417 (set (match_operand:SI 0 "s_register_operand" "=r")
9418 (minus:SI (match_dup 1) (match_dup 2)))]
9420 && !BYTES_BIG_ENDIAN
9421 && !TARGET_MMU_TRAPS
9423 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9424 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9425 && (GET_CODE (operands[2]) != REG
9426 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9427 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
9428 [(set_attr "type" "load_byte")
9429 (set_attr "predicable" "yes")]
9432 (define_insn "*strqi_shiftpreinc"
9433 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9434 [(match_operand:SI 3 "s_register_operand" "r")
9435 (match_operand:SI 4 "const_shift_operand" "n")])
9436 (match_operand:SI 1 "s_register_operand" "0")))
9437 (match_operand:QI 5 "s_register_operand" "r"))
9438 (set (match_operand:SI 0 "s_register_operand" "=r")
9439 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9442 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9443 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9444 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9445 "str%?b\\t%5, [%0, %3%S2]!"
9446 [(set_attr "type" "store1")
9447 (set_attr "predicable" "yes")]
9450 (define_insn "*strqi_shiftpredec"
9451 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9452 (match_operator:SI 2 "shift_operator"
9453 [(match_operand:SI 3 "s_register_operand" "r")
9454 (match_operand:SI 4 "const_shift_operand" "n")])))
9455 (match_operand:QI 5 "s_register_operand" "r"))
9456 (set (match_operand:SI 0 "s_register_operand" "=r")
9457 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9460 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9461 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9462 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9463 "str%?b\\t%5, [%0, -%3%S2]!"
9464 [(set_attr "type" "store1")
9465 (set_attr "predicable" "yes")]
9468 (define_insn "*loadqi_shiftpreinc"
9469 [(set (match_operand:QI 5 "s_register_operand" "=r")
9470 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9471 [(match_operand:SI 3 "s_register_operand" "r")
9472 (match_operand:SI 4 "const_shift_operand" "n")])
9473 (match_operand:SI 1 "s_register_operand" "0"))))
9474 (set (match_operand:SI 0 "s_register_operand" "=r")
9475 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9478 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9479 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9480 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9481 "ldr%?b\\t%5, [%0, %3%S2]!"
9482 [(set_attr "type" "load_byte")
9483 (set_attr "predicable" "yes")]
9486 (define_insn "*loadqi_shiftpredec"
9487 [(set (match_operand:QI 5 "s_register_operand" "=r")
9488 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9489 (match_operator:SI 2 "shift_operator"
9490 [(match_operand:SI 3 "s_register_operand" "r")
9491 (match_operand:SI 4 "const_shift_operand" "n")]))))
9492 (set (match_operand:SI 0 "s_register_operand" "=r")
9493 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9496 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9497 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9498 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9499 "ldr%?b\\t%5, [%0, -%3%S2]!"
9500 [(set_attr "type" "load_byte")
9501 (set_attr "predicable" "yes")]
9504 (define_insn "*strsi_shiftpreinc"
9505 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9506 [(match_operand:SI 3 "s_register_operand" "r")
9507 (match_operand:SI 4 "const_shift_operand" "n")])
9508 (match_operand:SI 1 "s_register_operand" "0")))
9509 (match_operand:SI 5 "s_register_operand" "r"))
9510 (set (match_operand:SI 0 "s_register_operand" "=r")
9511 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9514 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9515 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9516 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9517 "str%?\\t%5, [%0, %3%S2]!"
9518 [(set_attr "type" "store1")
9519 (set_attr "predicable" "yes")]
9522 (define_insn "*strsi_shiftpredec"
9523 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9524 (match_operator:SI 2 "shift_operator"
9525 [(match_operand:SI 3 "s_register_operand" "r")
9526 (match_operand:SI 4 "const_shift_operand" "n")])))
9527 (match_operand:SI 5 "s_register_operand" "r"))
9528 (set (match_operand:SI 0 "s_register_operand" "=r")
9529 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9532 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9533 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9534 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9535 "str%?\\t%5, [%0, -%3%S2]!"
9536 [(set_attr "type" "store1")
9537 (set_attr "predicable" "yes")]
9540 (define_insn "*loadsi_shiftpreinc"
9541 [(set (match_operand:SI 5 "s_register_operand" "=r")
9542 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9543 [(match_operand:SI 3 "s_register_operand" "r")
9544 (match_operand:SI 4 "const_shift_operand" "n")])
9545 (match_operand:SI 1 "s_register_operand" "0"))))
9546 (set (match_operand:SI 0 "s_register_operand" "=r")
9547 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9550 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9551 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9552 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9553 "ldr%?\\t%5, [%0, %3%S2]!"
9554 [(set_attr "type" "load1")
9555 (set_attr "predicable" "yes")]
9558 (define_insn "*loadsi_shiftpredec"
9559 [(set (match_operand:SI 5 "s_register_operand" "=r")
9560 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9561 (match_operator:SI 2 "shift_operator"
9562 [(match_operand:SI 3 "s_register_operand" "r")
9563 (match_operand:SI 4 "const_shift_operand" "n")]))))
9564 (set (match_operand:SI 0 "s_register_operand" "=r")
9565 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9568 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9569 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9570 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9571 "ldr%?\\t%5, [%0, -%3%S2]!"
9572 [(set_attr "type" "load1")
9573 (set_attr "predicable" "yes")])
9575 (define_insn "*loadhi_shiftpreinc"
9576 [(set (match_operand:HI 5 "s_register_operand" "=r")
9577 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
9578 [(match_operand:SI 3 "s_register_operand" "r")
9579 (match_operand:SI 4 "const_shift_operand" "n")])
9580 (match_operand:SI 1 "s_register_operand" "0"))))
9581 (set (match_operand:SI 0 "s_register_operand" "=r")
9582 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9585 && !BYTES_BIG_ENDIAN
9586 && !TARGET_MMU_TRAPS
9588 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9589 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9590 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9591 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
9592 [(set_attr "type" "load_byte")
9593 (set_attr "predicable" "yes")]
9596 (define_insn "*loadhi_shiftpredec"
9597 [(set (match_operand:HI 5 "s_register_operand" "=r")
9598 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9599 (match_operator:SI 2 "shift_operator"
9600 [(match_operand:SI 3 "s_register_operand" "r")
9601 (match_operand:SI 4 "const_shift_operand" "n")]))))
9602 (set (match_operand:SI 0 "s_register_operand" "=r")
9603 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9606 && !BYTES_BIG_ENDIAN
9607 && !TARGET_MMU_TRAPS
9609 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9610 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9611 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9612 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
9613 [(set_attr "type" "load_byte")
9614 (set_attr "predicable" "yes")]
9617 ; It can also support extended post-inc expressions, but combine doesn't
9619 ; It doesn't seem worth adding peepholes for anything but the most common
9620 ; cases since, unlike combine, the increment must immediately follow the load
9621 ; for this pattern to match.
9622 ; We must watch to see that the source/destination register isn't also the
9623 ; same as the base address register, and that if the index is a register,
9624 ; that it is not the same as the base address register. In such cases the
9625 ; instruction that we would generate would have UNPREDICTABLE behavior so
9629 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9630 (match_operand:QI 2 "s_register_operand" "r"))
9632 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9634 && (REGNO (operands[2]) != REGNO (operands[0]))
9635 && (GET_CODE (operands[1]) != REG
9636 || (REGNO (operands[1]) != REGNO (operands[0])))"
9637 "str%?b\\t%2, [%0], %1"
9641 [(set (match_operand:QI 0 "s_register_operand" "=r")
9642 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9644 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9646 && REGNO (operands[0]) != REGNO(operands[1])
9647 && (GET_CODE (operands[2]) != REG
9648 || REGNO(operands[0]) != REGNO (operands[2]))"
9649 "ldr%?b\\t%0, [%1], %2"
9653 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9654 (match_operand:SI 2 "s_register_operand" "r"))
9656 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9658 && (REGNO (operands[2]) != REGNO (operands[0]))
9659 && (GET_CODE (operands[1]) != REG
9660 || (REGNO (operands[1]) != REGNO (operands[0])))"
9661 "str%?\\t%2, [%0], %1"
9665 [(set (match_operand:HI 0 "s_register_operand" "=r")
9666 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
9668 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9670 && !BYTES_BIG_ENDIAN
9671 && !TARGET_MMU_TRAPS
9673 && REGNO (operands[0]) != REGNO(operands[1])
9674 && (GET_CODE (operands[2]) != REG
9675 || REGNO(operands[0]) != REGNO (operands[2]))"
9676 "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
9680 [(set (match_operand:SI 0 "s_register_operand" "=r")
9681 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9683 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9685 && REGNO (operands[0]) != REGNO(operands[1])
9686 && (GET_CODE (operands[2]) != REG
9687 || REGNO(operands[0]) != REGNO (operands[2]))"
9688 "ldr%?\\t%0, [%1], %2"
9692 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9693 (match_operand:SI 1 "index_operand" "rJ")))
9694 (match_operand:QI 2 "s_register_operand" "r"))
9695 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9697 && (REGNO (operands[2]) != REGNO (operands[0]))
9698 && (GET_CODE (operands[1]) != REG
9699 || (REGNO (operands[1]) != REGNO (operands[0])))"
9700 "str%?b\\t%2, [%0, %1]!"
9704 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9705 [(match_operand:SI 0 "s_register_operand" "r")
9706 (match_operand:SI 1 "const_int_operand" "n")])
9707 (match_operand:SI 2 "s_register_operand" "+r")))
9708 (match_operand:QI 3 "s_register_operand" "r"))
9709 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9712 && (REGNO (operands[3]) != REGNO (operands[2]))
9713 && (REGNO (operands[0]) != REGNO (operands[2]))"
9714 "str%?b\\t%3, [%2, %0%S4]!"
9717 ; This pattern is never tried by combine, so do it as a peephole
9720 [(set (match_operand:SI 0 "s_register_operand" "")
9721 (match_operand:SI 1 "s_register_operand" ""))
9722 (set (reg:CC CC_REGNUM)
9723 (compare:CC (match_dup 1) (const_int 0)))]
9725 && (!(TARGET_HARD_FLOAT && TARGET_MAVERICK)
9726 || (!cirrus_fp_register (operands[0], SImode)
9727 && !cirrus_fp_register (operands[1], SImode)))
9729 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9730 (set (match_dup 0) (match_dup 1))])]
9734 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9735 ; reversed, check that the memory references aren't volatile.
9738 [(set (match_operand:SI 0 "s_register_operand" "=r")
9739 (match_operand:SI 4 "memory_operand" "m"))
9740 (set (match_operand:SI 1 "s_register_operand" "=r")
9741 (match_operand:SI 5 "memory_operand" "m"))
9742 (set (match_operand:SI 2 "s_register_operand" "=r")
9743 (match_operand:SI 6 "memory_operand" "m"))
9744 (set (match_operand:SI 3 "s_register_operand" "=r")
9745 (match_operand:SI 7 "memory_operand" "m"))]
9746 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9748 return emit_ldm_seq (operands, 4);
9753 [(set (match_operand:SI 0 "s_register_operand" "=r")
9754 (match_operand:SI 3 "memory_operand" "m"))
9755 (set (match_operand:SI 1 "s_register_operand" "=r")
9756 (match_operand:SI 4 "memory_operand" "m"))
9757 (set (match_operand:SI 2 "s_register_operand" "=r")
9758 (match_operand:SI 5 "memory_operand" "m"))]
9759 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9761 return emit_ldm_seq (operands, 3);
9766 [(set (match_operand:SI 0 "s_register_operand" "=r")
9767 (match_operand:SI 2 "memory_operand" "m"))
9768 (set (match_operand:SI 1 "s_register_operand" "=r")
9769 (match_operand:SI 3 "memory_operand" "m"))]
9770 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9772 return emit_ldm_seq (operands, 2);
9777 [(set (match_operand:SI 4 "memory_operand" "=m")
9778 (match_operand:SI 0 "s_register_operand" "r"))
9779 (set (match_operand:SI 5 "memory_operand" "=m")
9780 (match_operand:SI 1 "s_register_operand" "r"))
9781 (set (match_operand:SI 6 "memory_operand" "=m")
9782 (match_operand:SI 2 "s_register_operand" "r"))
9783 (set (match_operand:SI 7 "memory_operand" "=m")
9784 (match_operand:SI 3 "s_register_operand" "r"))]
9785 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9787 return emit_stm_seq (operands, 4);
9792 [(set (match_operand:SI 3 "memory_operand" "=m")
9793 (match_operand:SI 0 "s_register_operand" "r"))
9794 (set (match_operand:SI 4 "memory_operand" "=m")
9795 (match_operand:SI 1 "s_register_operand" "r"))
9796 (set (match_operand:SI 5 "memory_operand" "=m")
9797 (match_operand:SI 2 "s_register_operand" "r"))]
9798 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9800 return emit_stm_seq (operands, 3);
9805 [(set (match_operand:SI 2 "memory_operand" "=m")
9806 (match_operand:SI 0 "s_register_operand" "r"))
9807 (set (match_operand:SI 3 "memory_operand" "=m")
9808 (match_operand:SI 1 "s_register_operand" "r"))]
9809 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9811 return emit_stm_seq (operands, 2);
9816 [(set (match_operand:SI 0 "s_register_operand" "")
9817 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9819 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9820 [(match_operand:SI 3 "s_register_operand" "")
9821 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9822 (clobber (match_operand:SI 5 "s_register_operand" ""))]
9824 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9825 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9830 ;; This split can be used because CC_Z mode implies that the following
9831 ;; branch will be an equality, or an unsigned inequality, so the sign
9832 ;; extension is not needed.
9835 [(set (reg:CC_Z CC_REGNUM)
9837 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9839 (match_operand 1 "const_int_operand" "")))
9840 (clobber (match_scratch:SI 2 ""))]
9842 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9843 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9844 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9845 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9847 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9851 (define_expand "prologue"
9852 [(clobber (const_int 0))]
9855 arm_expand_prologue ();
9857 thumb_expand_prologue ();
9862 (define_expand "epilogue"
9863 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9867 thumb_expand_epilogue ();
9868 else if (USE_RETURN_INSN (FALSE))
9870 emit_jump_insn (gen_return ());
9873 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9875 gen_rtx_RETURN (VOIDmode)),
9881 ;; Note - although unspec_volatile's USE all hard registers,
9882 ;; USEs are ignored after relaod has completed. Thus we need
9883 ;; to add an unspec of the link register to ensure that flow
9884 ;; does not think that it is unused by the sibcall branch that
9885 ;; will replace the standard function epilogue.
9886 (define_insn "sibcall_epilogue"
9887 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9888 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9891 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9892 return output_return_instruction (const_true_rtx, FALSE, FALSE);
9893 return arm_output_epilogue (next_nonnote_insn (insn));
9895 ;; Length is absolute worst case
9896 [(set_attr "length" "44")
9897 (set_attr "type" "block")
9898 ;; We don't clobber the conditions, but the potential length of this
9899 ;; operation is sufficient to make conditionalizing the sequence
9900 ;; unlikely to be profitable.
9901 (set_attr "conds" "clob")]
9904 (define_insn "*epilogue_insns"
9905 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9909 return arm_output_epilogue (NULL);
9910 else /* TARGET_THUMB */
9911 return thumb_unexpanded_epilogue ();
9913 ; Length is absolute worst case
9914 [(set_attr "length" "44")
9915 (set_attr "type" "block")
9916 ;; We don't clobber the conditions, but the potential length of this
9917 ;; operation is sufficient to make conditionalizing the sequence
9918 ;; unlikely to be profitable.
9919 (set_attr "conds" "clob")]
9922 (define_expand "eh_epilogue"
9923 [(use (match_operand:SI 0 "register_operand" ""))
9924 (use (match_operand:SI 1 "register_operand" ""))
9925 (use (match_operand:SI 2 "register_operand" ""))]
9929 cfun->machine->eh_epilogue_sp_ofs = operands[1];
9930 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9932 rtx ra = gen_rtx_REG (Pmode, 2);
9934 emit_move_insn (ra, operands[2]);
9937 /* This is a hack -- we may have crystalized the function type too
9939 cfun->machine->func_type = 0;
9943 ;; This split is only used during output to reduce the number of patterns
9944 ;; that need assembler instructions adding to them. We allowed the setting
9945 ;; of the conditions to be implicit during rtl generation so that
9946 ;; the conditional compare patterns would work. However this conflicts to
9947 ;; some extent with the conditional data operations, so we have to split them
9951 [(set (match_operand:SI 0 "s_register_operand" "")
9952 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9953 [(match_operand 2 "" "") (match_operand 3 "" "")])
9955 (match_operand 4 "" "")))
9956 (clobber (reg:CC CC_REGNUM))]
9957 "TARGET_ARM && reload_completed"
9958 [(set (match_dup 5) (match_dup 6))
9959 (cond_exec (match_dup 7)
9960 (set (match_dup 0) (match_dup 4)))]
9963 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9964 operands[2], operands[3]);
9965 enum rtx_code rc = GET_CODE (operands[1]);
9967 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9968 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9969 if (mode == CCFPmode || mode == CCFPEmode)
9970 rc = reverse_condition_maybe_unordered (rc);
9972 rc = reverse_condition (rc);
9974 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9979 [(set (match_operand:SI 0 "s_register_operand" "")
9980 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9981 [(match_operand 2 "" "") (match_operand 3 "" "")])
9982 (match_operand 4 "" "")
9984 (clobber (reg:CC CC_REGNUM))]
9985 "TARGET_ARM && reload_completed"
9986 [(set (match_dup 5) (match_dup 6))
9987 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9988 (set (match_dup 0) (match_dup 4)))]
9991 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9992 operands[2], operands[3]);
9994 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9995 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10000 [(set (match_operand:SI 0 "s_register_operand" "")
10001 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10002 [(match_operand 2 "" "") (match_operand 3 "" "")])
10003 (match_operand 4 "" "")
10004 (match_operand 5 "" "")))
10005 (clobber (reg:CC CC_REGNUM))]
10006 "TARGET_ARM && reload_completed"
10007 [(set (match_dup 6) (match_dup 7))
10008 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10009 (set (match_dup 0) (match_dup 4)))
10010 (cond_exec (match_dup 8)
10011 (set (match_dup 0) (match_dup 5)))]
10014 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10015 operands[2], operands[3]);
10016 enum rtx_code rc = GET_CODE (operands[1]);
10018 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10019 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10020 if (mode == CCFPmode || mode == CCFPEmode)
10021 rc = reverse_condition_maybe_unordered (rc);
10023 rc = reverse_condition (rc);
10025 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10030 [(set (match_operand:SI 0 "s_register_operand" "")
10031 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10032 [(match_operand:SI 2 "s_register_operand" "")
10033 (match_operand:SI 3 "arm_add_operand" "")])
10034 (match_operand:SI 4 "arm_rhs_operand" "")
10036 (match_operand:SI 5 "s_register_operand" ""))))
10037 (clobber (reg:CC CC_REGNUM))]
10038 "TARGET_ARM && reload_completed"
10039 [(set (match_dup 6) (match_dup 7))
10040 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10041 (set (match_dup 0) (match_dup 4)))
10042 (cond_exec (match_dup 8)
10043 (set (match_dup 0) (not:SI (match_dup 5))))]
10046 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10047 operands[2], operands[3]);
10048 enum rtx_code rc = GET_CODE (operands[1]);
10050 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10051 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10052 if (mode == CCFPmode || mode == CCFPEmode)
10053 rc = reverse_condition_maybe_unordered (rc);
10055 rc = reverse_condition (rc);
10057 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10061 (define_insn "*cond_move_not"
10062 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10063 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10064 [(match_operand 3 "cc_register" "") (const_int 0)])
10065 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10067 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10071 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10072 [(set_attr "conds" "use")
10073 (set_attr "length" "4,8")]
10076 ;; The next two patterns occur when an AND operation is followed by a
10077 ;; scc insn sequence
10079 (define_insn "*sign_extract_onebit"
10080 [(set (match_operand:SI 0 "s_register_operand" "=r")
10081 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10083 (match_operand:SI 2 "const_int_operand" "n")))
10084 (clobber (reg:CC CC_REGNUM))]
10087 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10088 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10089 return \"mvnne\\t%0, #0\";
10091 [(set_attr "conds" "clob")
10092 (set_attr "length" "8")]
10095 (define_insn "*not_signextract_onebit"
10096 [(set (match_operand:SI 0 "s_register_operand" "=r")
10098 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10100 (match_operand:SI 2 "const_int_operand" "n"))))
10101 (clobber (reg:CC CC_REGNUM))]
10104 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10105 output_asm_insn (\"tst\\t%1, %2\", operands);
10106 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10107 return \"movne\\t%0, #0\";
10109 [(set_attr "conds" "clob")
10110 (set_attr "length" "12")]
10113 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
10114 ;; expressions. For simplicity, the first register is also in the unspec
10116 (define_insn "*push_multi"
10117 [(match_parallel 2 "multi_register_push"
10118 [(set (match_operand:BLK 0 "memory_operand" "=m")
10119 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10120 UNSPEC_PUSH_MULT))])]
10124 int num_saves = XVECLEN (operands[2], 0);
10126 /* For the StrongARM at least it is faster to
10127 use STR to store only a single register. */
10128 if (num_saves == 1)
10129 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10135 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10137 for (i = 1; i < num_saves; i++)
10139 strcat (pattern, \", %|\");
10141 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10144 strcat (pattern, \"}\");
10145 output_asm_insn (pattern, operands);
10150 [(set_attr "type" "store4")]
10153 (define_insn "stack_tie"
10154 [(set (mem:BLK (scratch))
10155 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10156 (match_operand:SI 1 "s_register_operand" "r")]
10160 [(set_attr "length" "0")]
10163 ;; Similarly for the floating point registers
10164 (define_insn "*push_fp_multi"
10165 [(match_parallel 2 "multi_register_push"
10166 [(set (match_operand:BLK 0 "memory_operand" "=m")
10167 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10168 UNSPEC_PUSH_MULT))])]
10169 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
10174 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10175 output_asm_insn (pattern, operands);
10178 [(set_attr "type" "f_store")]
10181 ;; Special patterns for dealing with the constant pool
10183 (define_insn "align_4"
10184 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10187 assemble_align (32);
10192 (define_insn "align_8"
10193 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10194 "TARGET_REALLY_IWMMXT"
10196 assemble_align (64);
10201 (define_insn "consttable_end"
10202 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10205 making_const_table = FALSE;
10210 (define_insn "consttable_1"
10211 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10214 making_const_table = TRUE;
10215 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10216 assemble_zeros (3);
10219 [(set_attr "length" "4")]
10222 (define_insn "consttable_2"
10223 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10226 making_const_table = TRUE;
10227 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10228 assemble_zeros (2);
10231 [(set_attr "length" "4")]
10234 (define_insn "consttable_4"
10235 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10239 making_const_table = TRUE;
10240 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10245 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10246 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10250 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10255 [(set_attr "length" "4")]
10258 (define_insn "consttable_8"
10259 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10263 making_const_table = TRUE;
10264 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10269 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10270 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10274 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10279 [(set_attr "length" "8")]
10282 ;; Miscellaneous Thumb patterns
10284 (define_expand "tablejump"
10285 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10286 (use (label_ref (match_operand 1 "" "")))])]
10291 /* Hopefully, CSE will eliminate this copy. */
10292 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10293 rtx reg2 = gen_reg_rtx (SImode);
10295 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10296 operands[0] = reg2;
10301 (define_insn "*thumb_tablejump"
10302 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10303 (use (label_ref (match_operand 1 "" "")))]
10306 [(set_attr "length" "2")]
10309 ;; V5 Instructions,
10311 (define_insn "clzsi2"
10312 [(set (match_operand:SI 0 "s_register_operand" "=r")
10313 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10314 "TARGET_ARM && arm_arch5"
10316 [(set_attr "predicable" "yes")])
10318 (define_expand "ffssi2"
10319 [(set (match_operand:SI 0 "s_register_operand" "")
10320 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10321 "TARGET_ARM && arm_arch5"
10326 t1 = gen_reg_rtx (SImode);
10327 t2 = gen_reg_rtx (SImode);
10328 t3 = gen_reg_rtx (SImode);
10330 emit_insn (gen_negsi2 (t1, operands[1]));
10331 emit_insn (gen_andsi3 (t2, operands[1], t1));
10332 emit_insn (gen_clzsi2 (t3, t2));
10333 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10338 (define_expand "ctzsi2"
10339 [(set (match_operand:SI 0 "s_register_operand" "")
10340 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10341 "TARGET_ARM && arm_arch5"
10346 t1 = gen_reg_rtx (SImode);
10347 t2 = gen_reg_rtx (SImode);
10348 t3 = gen_reg_rtx (SImode);
10350 emit_insn (gen_negsi2 (t1, operands[1]));
10351 emit_insn (gen_andsi3 (t2, operands[1], t1));
10352 emit_insn (gen_clzsi2 (t3, t2));
10353 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10358 ;; V5E instructions.
10360 (define_insn "prefetch"
10361 [(prefetch (match_operand:SI 0 "address_operand" "p")
10362 (match_operand:SI 1 "" "")
10363 (match_operand:SI 2 "" ""))]
10364 "TARGET_ARM && arm_arch5e"
10367 ;; General predication pattern
10370 [(match_operator 0 "arm_comparison_operator"
10371 [(match_operand 1 "cc_register" "")
10377 (define_insn "prologue_use"
10378 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10380 "%@ %0 needed for prologue"
10383 ;; Load the FPA co-processor patterns
10385 ;; Load the Maverick co-processor patterns
10386 (include "cirrus.md")
10387 ;; Load the Intel Wireless Multimedia Extension patterns
10388 (include "iwmmxt.md")
10389 ;; Load the VFP co-processor patterns