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, 2005, 2006, 2007, 2008, 2009, 2010
4 ;; Free Software Foundation, Inc.
5 ;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
6 ;; and Martin Simmons (@harleqn.co.uk).
7 ;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
9 ;; This file is part of GCC.
11 ;; GCC is free software; you can redistribute it and/or modify it
12 ;; under the terms of the GNU General Public License as published
13 ;; by the Free Software Foundation; either version 3, or (at your
14 ;; option) any later version.
16 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
17 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
19 ;; License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GCC; see the file COPYING3. If not see
23 ;; <http://www.gnu.org/licenses/>.
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
28 ;;---------------------------------------------------------------------------
33 [(R0_REGNUM 0) ; First CORE register
34 (R1_REGNUM 1) ; Second CORE register
35 (IP_REGNUM 12) ; Scratch register
36 (SP_REGNUM 13) ; Stack pointer
37 (LR_REGNUM 14) ; Return address register
38 (PC_REGNUM 15) ; Program counter
39 (CC_REGNUM 24) ; Condition code pseudo register
40 (LAST_ARM_REGNUM 15) ;
41 (FPA_F0_REGNUM 16) ; FIRST_FPA_REGNUM
42 (FPA_F7_REGNUM 23) ; LAST_FPA_REGNUM
45 ;; 3rd operand to select_dominance_cc_mode
52 ;; conditional compare combination
63 ;; Note: sin and cos are no-longer used.
64 ;; Unspec enumerators for Neon are defined in neon.md.
66 (define_c_enum "unspec" [
67 UNSPEC_SIN ; `sin' operation (MODE_FLOAT):
68 ; operand 0 is the result,
69 ; operand 1 the parameter.
70 UNPSEC_COS ; `cos' operation (MODE_FLOAT):
71 ; operand 0 is the result,
72 ; operand 1 the parameter.
73 UNSPEC_PUSH_MULT ; `push multiple' operation:
74 ; operand 0 is the first register,
75 ; subsequent registers are in parallel (use ...)
77 UNSPEC_PIC_SYM ; A symbol that has been treated properly for pic
78 ; usage, that is, we will add the pic_register
79 ; value to it before trying to dereference it.
80 UNSPEC_PIC_BASE ; Add PC and all but the last operand together,
81 ; The last operand is the number of a PIC_LABEL
82 ; that points at the containing instruction.
83 UNSPEC_PRLG_STK ; A special barrier that prevents frame accesses
84 ; being scheduled before the stack adjustment insn.
85 UNSPEC_PROLOGUE_USE ; As USE insns are not meaningful after reload,
86 ; this unspec is used to prevent the deletion of
87 ; instructions setting registers for EH handling
88 ; and stack frame generation. Operand 0 is the
90 UNSPEC_CHECK_ARCH ; Set CCs to indicate 26-bit or 32-bit mode.
91 UNSPEC_WSHUFH ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
92 UNSPEC_WACC ; Used by the intrinsic form of the iWMMXt WACC instruction.
93 UNSPEC_TMOVMSK ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
94 UNSPEC_WSAD ; Used by the intrinsic form of the iWMMXt WSAD instruction.
95 UNSPEC_WSADZ ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
96 UNSPEC_WMACS ; Used by the intrinsic form of the iWMMXt WMACS instruction.
97 UNSPEC_WMACU ; Used by the intrinsic form of the iWMMXt WMACU instruction.
98 UNSPEC_WMACSZ ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
99 UNSPEC_WMACUZ ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
100 UNSPEC_CLRDI ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
101 UNSPEC_WMADDS ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
102 UNSPEC_WMADDU ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
103 UNSPEC_TLS ; A symbol that has been treated properly for TLS usage.
104 UNSPEC_PIC_LABEL ; A label used for PIC access that does not appear in the
105 ; instruction stream.
106 UNSPEC_PIC_OFFSET ; A symbolic 12-bit OFFSET that has been treated
107 ; correctly for PIC usage.
108 UNSPEC_GOTSYM_OFF ; The offset of the start of the GOT from a
109 ; a given symbolic address.
110 UNSPEC_THUMB1_CASESI ; A Thumb1 compressed dispatch-table call.
111 UNSPEC_RBIT ; rbit operation.
112 UNSPEC_SYMBOL_OFFSET ; The offset of the start of the symbol from
113 ; another symbolic address.
114 UNSPEC_MEMORY_BARRIER ; Represent a memory barrier.
117 ;; UNSPEC_VOLATILE Usage:
119 (define_c_enum "unspecv" [
120 VUNSPEC_BLOCKAGE ; `blockage' insn to prevent scheduling across an
122 VUNSPEC_EPILOGUE ; `epilogue' insn, used to represent any part of the
123 ; instruction epilogue sequence that isn't expanded
124 ; into normal RTL. Used for both normal and sibcall
126 VUNSPEC_THUMB1_INTERWORK ; `prologue_thumb1_interwork' insn, used to swap
127 ; modes from arm to thumb.
128 VUNSPEC_ALIGN ; `align' insn. Used at the head of a minipool table
129 ; for inlined constants.
130 VUNSPEC_POOL_END ; `end-of-table'. Used to mark the end of a minipool
132 VUNSPEC_POOL_1 ; `pool-entry(1)'. An entry in the constant pool for
134 VUNSPEC_POOL_2 ; `pool-entry(2)'. An entry in the constant pool for
136 VUNSPEC_POOL_4 ; `pool-entry(4)'. An entry in the constant pool for
138 VUNSPEC_POOL_8 ; `pool-entry(8)'. An entry in the constant pool for
140 VUNSPEC_POOL_16 ; `pool-entry(16)'. An entry in the constant pool for
142 VUNSPEC_TMRC ; Used by the iWMMXt TMRC instruction.
143 VUNSPEC_TMCR ; Used by the iWMMXt TMCR instruction.
144 VUNSPEC_ALIGN8 ; 8-byte alignment version of VUNSPEC_ALIGN
145 VUNSPEC_WCMP_EQ ; Used by the iWMMXt WCMPEQ instructions
146 VUNSPEC_WCMP_GTU ; Used by the iWMMXt WCMPGTU instructions
147 VUNSPEC_WCMP_GT ; Used by the iwMMXT WCMPGT instructions
148 VUNSPEC_EH_RETURN ; Use to override the return address for exception
150 VUNSPEC_SYNC_COMPARE_AND_SWAP ; Represent an atomic compare swap.
151 VUNSPEC_SYNC_LOCK ; Represent a sync_lock_test_and_set.
152 VUNSPEC_SYNC_OP ; Represent a sync_<op>
153 VUNSPEC_SYNC_NEW_OP ; Represent a sync_new_<op>
154 VUNSPEC_SYNC_OLD_OP ; Represent a sync_old_<op>
157 ;;---------------------------------------------------------------------------
160 ;; Processor type. This is created automatically from arm-cores.def.
161 (include "arm-tune.md")
163 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
164 ; generating ARM code. This is used to control the length of some insn
165 ; patterns that share the same RTL in both ARM and Thumb code.
166 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
168 ; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
169 (define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
171 ; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
172 (define_attr "is_thumb1" "no,yes" (const (symbol_ref "thumb1_code")))
174 ;; Operand number of an input operand that is shifted. Zero if the
175 ;; given instruction does not shift one of its input operands.
176 (define_attr "shift" "" (const_int 0))
178 ; Floating Point Unit. If we only have floating point emulation, then there
179 ; is no point in scheduling the floating point insns. (Well, for best
180 ; performance we should try and group them together).
181 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
182 (const (symbol_ref "arm_fpu_attr")))
184 (define_attr "sync_result" "none,0,1,2,3,4,5" (const_string "none"))
185 (define_attr "sync_memory" "none,0,1,2,3,4,5" (const_string "none"))
186 (define_attr "sync_required_value" "none,0,1,2,3,4,5" (const_string "none"))
187 (define_attr "sync_new_value" "none,0,1,2,3,4,5" (const_string "none"))
188 (define_attr "sync_t1" "none,0,1,2,3,4,5" (const_string "none"))
189 (define_attr "sync_t2" "none,0,1,2,3,4,5" (const_string "none"))
190 (define_attr "sync_release_barrier" "yes,no" (const_string "yes"))
191 (define_attr "sync_op" "none,add,sub,ior,xor,and,nand"
192 (const_string "none"))
194 ; LENGTH of an instruction (in bytes)
195 (define_attr "length" ""
196 (cond [(not (eq_attr "sync_memory" "none"))
197 (symbol_ref "arm_sync_loop_insns (insn, operands) * 4")
200 ; The architecture which supports the instruction (or alternative).
201 ; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
202 ; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
203 ; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
204 ; arm_arch6. This attribute is used to compute attribute "enabled",
205 ; use type "any" to enable an alternative in all cases.
206 (define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,onlya8,nota8"
207 (const_string "any"))
209 (define_attr "arch_enabled" "no,yes"
210 (cond [(eq_attr "arch" "any")
213 (and (eq_attr "arch" "a")
214 (match_test "TARGET_ARM"))
217 (and (eq_attr "arch" "t")
218 (match_test "TARGET_THUMB"))
221 (and (eq_attr "arch" "t1")
222 (match_test "TARGET_THUMB1"))
225 (and (eq_attr "arch" "t2")
226 (match_test "TARGET_THUMB2"))
229 (and (eq_attr "arch" "32")
230 (match_test "TARGET_32BIT"))
233 (and (eq_attr "arch" "v6")
234 (match_test "TARGET_32BIT && arm_arch6"))
237 (and (eq_attr "arch" "nov6")
238 (match_test "TARGET_32BIT && !arm_arch6"))
241 (and (eq_attr "arch" "onlya8")
242 (eq_attr "tune" "cortexa8"))
245 (and (eq_attr "arch" "nota8")
246 (not (eq_attr "tune" "cortexa8")))
247 (const_string "yes")]
248 (const_string "no")))
250 ; Allows an insn to disable certain alternatives for reasons other than
252 (define_attr "insn_enabled" "no,yes"
253 (const_string "yes"))
255 ; Enable all alternatives that are both arch_enabled and insn_enabled.
256 (define_attr "enabled" "no,yes"
257 (if_then_else (eq_attr "insn_enabled" "yes")
258 (if_then_else (eq_attr "arch_enabled" "yes")
261 (const_string "no")))
263 ; POOL_RANGE is how far away from a constant pool entry that this insn
264 ; can be placed. If the distance is zero, then this insn will never
265 ; reference the pool.
266 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
267 ; before its address.
268 (define_attr "arm_pool_range" "" (const_int 0))
269 (define_attr "thumb2_pool_range" "" (const_int 0))
270 (define_attr "arm_neg_pool_range" "" (const_int 0))
271 (define_attr "thumb2_neg_pool_range" "" (const_int 0))
273 (define_attr "pool_range" ""
274 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
275 (attr "arm_pool_range")))
276 (define_attr "neg_pool_range" ""
277 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
278 (attr "arm_neg_pool_range")))
280 ; An assembler sequence may clobber the condition codes without us knowing.
281 ; If such an insn references the pool, then we have no way of knowing how,
282 ; so use the most conservative value for pool_range.
283 (define_asm_attributes
284 [(set_attr "conds" "clob")
285 (set_attr "length" "4")
286 (set_attr "pool_range" "250")])
288 ;; The instruction used to implement a particular pattern. This
289 ;; information is used by pipeline descriptions to provide accurate
290 ;; scheduling information.
293 "mov,mvn,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,smmla,umaal,smlald,smlsld,clz,mrs,msr,xtab,sdiv,udiv,other"
294 (const_string "other"))
296 ; TYPE attribute is used to detect floating point instructions which, if
297 ; running on a co-processor can run in parallel with other, basic instructions
298 ; If write-buffer scheduling is enabled then it can also be used in the
299 ; scheduling of writes.
301 ; Classification of each insn
302 ; Note: vfp.md has different meanings for some of these, and some further
303 ; types as well. See that file for details.
304 ; alu any alu instruction that doesn't hit memory or fp
305 ; regs or have a shifted source operand
306 ; alu_shift any data instruction that doesn't hit memory or fp
307 ; regs, but has a source operand shifted by a constant
308 ; alu_shift_reg any data instruction that doesn't hit memory or fp
309 ; regs, but has a source operand shifted by a register value
310 ; mult a multiply instruction
311 ; block blockage insn, this blocks all functional units
312 ; float a floating point arithmetic operation (subject to expansion)
313 ; fdivd DFmode floating point division
314 ; fdivs SFmode floating point division
315 ; fmul Floating point multiply
316 ; ffmul Fast floating point multiply
317 ; farith Floating point arithmetic (4 cycle)
318 ; ffarith Fast floating point arithmetic (2 cycle)
319 ; float_em a floating point arithmetic operation that is normally emulated
320 ; even on a machine with an fpa.
321 ; f_fpa_load a floating point load from memory. Only for the FPA.
322 ; f_fpa_store a floating point store to memory. Only for the FPA.
323 ; f_load[sd] A single/double load from memory. Used for VFP unit.
324 ; f_store[sd] A single/double store to memory. Used for VFP unit.
325 ; f_flag a transfer of co-processor flags to the CPSR
326 ; f_mem_r a transfer of a floating point register to a real reg via mem
327 ; r_mem_f the reverse of f_mem_r
328 ; f_2_r fast transfer float to arm (no memory needed)
329 ; r_2_f fast transfer arm to float
330 ; f_cvt convert floating<->integral
332 ; call a subroutine call
333 ; load_byte load byte(s) from memory to arm registers
334 ; load1 load 1 word from memory to arm registers
335 ; load2 load 2 words from memory to arm registers
336 ; load3 load 3 words from memory to arm registers
337 ; load4 load 4 words from memory to arm registers
338 ; store store 1 word to memory from arm registers
339 ; store2 store 2 words
340 ; store3 store 3 words
341 ; store4 store 4 (or more) words
342 ; Additions for Cirrus Maverick co-processor:
343 ; mav_farith Floating point arithmetic (4 cycle)
344 ; mav_dmult Double multiplies (7 cycle)
348 "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,fmuls,fmuld,fmacs,fmacd,ffmul,farith,ffarith,f_flag,float_em,f_fpa_load,f_fpa_store,f_loads,f_loadd,f_stores,f_stored,f_mem_r,r_mem_f,f_2_r,r_2_f,f_cvt,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult,fconsts,fconstd,fadds,faddd,ffariths,ffarithd,fcmps,fcmpd,fcpys"
350 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
351 (const_string "mult")
352 (const_string "alu")))
354 ; Load scheduling, set from the arm_ld_sched variable
355 ; initialized by arm_option_override()
356 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
358 ;; Classification of NEON instructions for scheduling purposes.
359 ;; Do not set this attribute and the "type" attribute together in
360 ;; any one instruction pattern.
361 (define_attr "neon_type"
372 neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
373 neon_mul_qqq_8_16_32_ddd_32,\
374 neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
375 neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
377 neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
378 neon_mla_qqq_32_qqd_32_scalar,\
379 neon_mul_ddd_16_scalar_32_16_long_scalar,\
380 neon_mul_qqd_32_scalar,\
381 neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
386 neon_vqshl_vrshl_vqrshl_qqq,\
388 neon_fp_vadd_ddd_vabs_dd,\
389 neon_fp_vadd_qqq_vabs_qq,\
395 neon_fp_vmla_ddd_scalar,\
396 neon_fp_vmla_qqq_scalar,\
397 neon_fp_vrecps_vrsqrts_ddd,\
398 neon_fp_vrecps_vrsqrts_qqq,\
406 neon_vld2_2_regs_vld1_vld2_all_lanes,\
409 neon_vst1_1_2_regs_vst2_2_regs,\
411 neon_vst2_4_regs_vst3_vst4,\
413 neon_vld1_vld2_lane,\
414 neon_vld3_vld4_lane,\
415 neon_vst1_vst2_lane,\
416 neon_vst3_vst4_lane,\
417 neon_vld3_vld4_all_lanes,\
425 (const_string "none"))
427 ; condition codes: this one is used by final_prescan_insn to speed up
428 ; conditionalizing instructions. It saves having to scan the rtl to see if
429 ; it uses or alters the condition codes.
431 ; USE means that the condition codes are used by the insn in the process of
432 ; outputting code, this means (at present) that we can't use the insn in
435 ; SET means that the purpose of the insn is to set the condition codes in a
436 ; well defined manner.
438 ; CLOB means that the condition codes are altered in an undefined manner, if
439 ; they are altered at all
441 ; UNCONDITIONAL means the instruction can not be conditionally executed and
442 ; that the instruction does not use or alter the condition codes.
444 ; NOCOND means that the instruction does not use or alter the condition
445 ; codes but can be converted into a conditionally exectuted instruction.
447 (define_attr "conds" "use,set,clob,unconditional,nocond"
449 (ior (eq_attr "is_thumb1" "yes")
450 (eq_attr "type" "call"))
451 (const_string "clob")
452 (if_then_else (eq_attr "neon_type" "none")
453 (const_string "nocond")
454 (const_string "unconditional"))))
456 ; Predicable means that the insn can be conditionally executed based on
457 ; an automatically added predicate (additional patterns are generated by
458 ; gen...). We default to 'no' because no Thumb patterns match this rule
459 ; and not all ARM patterns do.
460 (define_attr "predicable" "no,yes" (const_string "no"))
462 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
463 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
464 ; suffer blockages enough to warrant modelling this (and it can adversely
465 ; affect the schedule).
466 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
468 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
469 ; to stall the processor. Used with model_wbuf above.
470 (define_attr "write_conflict" "no,yes"
471 (if_then_else (eq_attr "type"
472 "block,float_em,f_fpa_load,f_fpa_store,f_mem_r,r_mem_f,call,load1")
474 (const_string "no")))
476 ; Classify the insns into those that take one cycle and those that take more
477 ; than one on the main cpu execution unit.
478 (define_attr "core_cycles" "single,multi"
479 (if_then_else (eq_attr "type"
480 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
481 (const_string "single")
482 (const_string "multi")))
484 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
485 ;; distant label. Only applicable to Thumb code.
486 (define_attr "far_jump" "yes,no" (const_string "no"))
489 ;; The number of machine instructions this pattern expands to.
490 ;; Used for Thumb-2 conditional execution.
491 (define_attr "ce_count" "" (const_int 1))
493 ;;---------------------------------------------------------------------------
496 (include "iterators.md")
498 ;;---------------------------------------------------------------------------
501 (include "predicates.md")
502 (include "constraints.md")
504 ;;---------------------------------------------------------------------------
505 ;; Pipeline descriptions
507 (define_attr "tune_cortexr4" "yes,no"
509 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
511 (const_string "no"))))
513 ;; True if the generic scheduling description should be used.
515 (define_attr "generic_sched" "yes,no"
517 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa5,cortexa8,cortexa9,cortexm4")
518 (eq_attr "tune_cortexr4" "yes"))
520 (const_string "yes"))))
522 (define_attr "generic_vfp" "yes,no"
524 (and (eq_attr "fpu" "vfp")
525 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa8,cortexa9,cortexm4")
526 (eq_attr "tune_cortexr4" "no"))
528 (const_string "no"))))
530 (include "arm-generic.md")
531 (include "arm926ejs.md")
532 (include "arm1020e.md")
533 (include "arm1026ejs.md")
534 (include "arm1136jfs.md")
536 (include "fa606te.md")
537 (include "fa626te.md")
538 (include "fmp626.md")
539 (include "fa726te.md")
540 (include "cortex-a5.md")
541 (include "cortex-a8.md")
542 (include "cortex-a9.md")
543 (include "cortex-r4.md")
544 (include "cortex-r4f.md")
545 (include "cortex-m4.md")
546 (include "cortex-m4-fpu.md")
550 ;;---------------------------------------------------------------------------
555 ;; Note: For DImode insns, there is normally no reason why operands should
556 ;; not be in the same register, what we don't want is for something being
557 ;; written to partially overlap something that is an input.
558 ;; Cirrus 64bit additions should not be split because we have a native
559 ;; 64bit addition instructions.
561 (define_expand "adddi3"
563 [(set (match_operand:DI 0 "s_register_operand" "")
564 (plus:DI (match_operand:DI 1 "s_register_operand" "")
565 (match_operand:DI 2 "s_register_operand" "")))
566 (clobber (reg:CC CC_REGNUM))])]
569 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
571 if (!cirrus_fp_register (operands[0], DImode))
572 operands[0] = force_reg (DImode, operands[0]);
573 if (!cirrus_fp_register (operands[1], DImode))
574 operands[1] = force_reg (DImode, operands[1]);
575 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
581 if (GET_CODE (operands[1]) != REG)
582 operands[1] = force_reg (DImode, operands[1]);
583 if (GET_CODE (operands[2]) != REG)
584 operands[2] = force_reg (DImode, operands[2]);
589 (define_insn "*thumb1_adddi3"
590 [(set (match_operand:DI 0 "register_operand" "=l")
591 (plus:DI (match_operand:DI 1 "register_operand" "%0")
592 (match_operand:DI 2 "register_operand" "l")))
593 (clobber (reg:CC CC_REGNUM))
596 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
597 [(set_attr "length" "4")]
600 (define_insn_and_split "*arm_adddi3"
601 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
602 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
603 (match_operand:DI 2 "s_register_operand" "r, 0")))
604 (clobber (reg:CC CC_REGNUM))]
605 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK) && !TARGET_NEON"
607 "TARGET_32BIT && reload_completed
608 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
609 [(parallel [(set (reg:CC_C CC_REGNUM)
610 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
612 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
613 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
614 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
617 operands[3] = gen_highpart (SImode, operands[0]);
618 operands[0] = gen_lowpart (SImode, operands[0]);
619 operands[4] = gen_highpart (SImode, operands[1]);
620 operands[1] = gen_lowpart (SImode, operands[1]);
621 operands[5] = gen_highpart (SImode, operands[2]);
622 operands[2] = gen_lowpart (SImode, operands[2]);
624 [(set_attr "conds" "clob")
625 (set_attr "length" "8")]
628 (define_insn_and_split "*adddi_sesidi_di"
629 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
630 (plus:DI (sign_extend:DI
631 (match_operand:SI 2 "s_register_operand" "r,r"))
632 (match_operand:DI 1 "s_register_operand" "0,r")))
633 (clobber (reg:CC CC_REGNUM))]
634 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
636 "TARGET_32BIT && reload_completed"
637 [(parallel [(set (reg:CC_C CC_REGNUM)
638 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
640 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
641 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
644 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
647 operands[3] = gen_highpart (SImode, operands[0]);
648 operands[0] = gen_lowpart (SImode, operands[0]);
649 operands[4] = gen_highpart (SImode, operands[1]);
650 operands[1] = gen_lowpart (SImode, operands[1]);
651 operands[2] = gen_lowpart (SImode, operands[2]);
653 [(set_attr "conds" "clob")
654 (set_attr "length" "8")]
657 (define_insn_and_split "*adddi_zesidi_di"
658 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
659 (plus:DI (zero_extend:DI
660 (match_operand:SI 2 "s_register_operand" "r,r"))
661 (match_operand:DI 1 "s_register_operand" "0,r")))
662 (clobber (reg:CC CC_REGNUM))]
663 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
665 "TARGET_32BIT && reload_completed"
666 [(parallel [(set (reg:CC_C CC_REGNUM)
667 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
669 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
670 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
671 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
674 operands[3] = gen_highpart (SImode, operands[0]);
675 operands[0] = gen_lowpart (SImode, operands[0]);
676 operands[4] = gen_highpart (SImode, operands[1]);
677 operands[1] = gen_lowpart (SImode, operands[1]);
678 operands[2] = gen_lowpart (SImode, operands[2]);
680 [(set_attr "conds" "clob")
681 (set_attr "length" "8")]
684 (define_expand "addsi3"
685 [(set (match_operand:SI 0 "s_register_operand" "")
686 (plus:SI (match_operand:SI 1 "s_register_operand" "")
687 (match_operand:SI 2 "reg_or_int_operand" "")))]
690 if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
692 arm_split_constant (PLUS, SImode, NULL_RTX,
693 INTVAL (operands[2]), operands[0], operands[1],
694 optimize && can_create_pseudo_p ());
700 ; If there is a scratch available, this will be faster than synthesizing the
703 [(match_scratch:SI 3 "r")
704 (set (match_operand:SI 0 "arm_general_register_operand" "")
705 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
706 (match_operand:SI 2 "const_int_operand" "")))]
708 !(const_ok_for_arm (INTVAL (operands[2]))
709 || const_ok_for_arm (-INTVAL (operands[2])))
710 && const_ok_for_arm (~INTVAL (operands[2]))"
711 [(set (match_dup 3) (match_dup 2))
712 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
716 ;; The r/r/k alternative is required when reloading the address
717 ;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
718 ;; put the duplicated register first, and not try the commutative version.
719 (define_insn_and_split "*arm_addsi3"
720 [(set (match_operand:SI 0 "s_register_operand" "=r, k,r,r, k, r, k,r, k, r")
721 (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,k,r,rk,k, rk,k,rk,k, rk")
722 (match_operand:SI 2 "reg_or_int_operand" "rI,rI,k,Pj,Pj,L, L,PJ,PJ,?n")))]
732 subw%?\\t%0, %1, #%n2
733 subw%?\\t%0, %1, #%n2
736 && GET_CODE (operands[2]) == CONST_INT
737 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
738 && (reload_completed || !arm_eliminable_register (operands[1]))"
739 [(clobber (const_int 0))]
741 arm_split_constant (PLUS, SImode, curr_insn,
742 INTVAL (operands[2]), operands[0],
746 [(set_attr "length" "4,4,4,4,4,4,4,4,4,16")
747 (set_attr "predicable" "yes")
748 (set_attr "arch" "*,*,*,t2,t2,*,*,t2,t2,*")]
751 (define_insn_and_split "*thumb1_addsi3"
752 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,k,l,l,l")
753 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,k,k,0,l,k")
754 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,M,O,Pa,Pb,Pc")))]
757 static const char * const asms[] =
759 \"add\\t%0, %0, %2\",
760 \"sub\\t%0, %0, #%n2\",
761 \"add\\t%0, %1, %2\",
762 \"add\\t%0, %0, %2\",
763 \"add\\t%0, %0, %2\",
764 \"add\\t%0, %1, %2\",
765 \"add\\t%0, %1, %2\",
770 if ((which_alternative == 2 || which_alternative == 6)
771 && GET_CODE (operands[2]) == CONST_INT
772 && INTVAL (operands[2]) < 0)
773 return \"sub\\t%0, %1, #%n2\";
774 return asms[which_alternative];
776 "&& reload_completed && CONST_INT_P (operands[2])
777 && ((operands[1] != stack_pointer_rtx
778 && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255))
779 || (operands[1] == stack_pointer_rtx
780 && INTVAL (operands[2]) > 1020))"
781 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
782 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
784 HOST_WIDE_INT offset = INTVAL (operands[2]);
785 if (operands[1] == stack_pointer_rtx)
791 else if (offset < -255)
794 operands[3] = GEN_INT (offset);
795 operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
797 [(set_attr "length" "2,2,2,2,2,2,2,4,4,4")]
800 ;; Reloading and elimination of the frame pointer can
801 ;; sometimes cause this optimization to be missed.
803 [(set (match_operand:SI 0 "arm_general_register_operand" "")
804 (match_operand:SI 1 "const_int_operand" ""))
806 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
808 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
809 && (INTVAL (operands[1]) & 3) == 0"
810 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
814 (define_insn "addsi3_compare0"
815 [(set (reg:CC_NOOV CC_REGNUM)
817 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
818 (match_operand:SI 2 "arm_add_operand" "rI,L"))
820 (set (match_operand:SI 0 "s_register_operand" "=r,r")
821 (plus:SI (match_dup 1) (match_dup 2)))]
825 sub%.\\t%0, %1, #%n2"
826 [(set_attr "conds" "set")]
829 (define_insn "*addsi3_compare0_scratch"
830 [(set (reg:CC_NOOV CC_REGNUM)
832 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
833 (match_operand:SI 1 "arm_add_operand" "rI,L"))
839 [(set_attr "conds" "set")]
842 (define_insn "*compare_negsi_si"
843 [(set (reg:CC_Z CC_REGNUM)
845 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
846 (match_operand:SI 1 "s_register_operand" "r")))]
849 [(set_attr "conds" "set")]
852 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
853 ;; addend is a constant.
854 (define_insn "*cmpsi2_addneg"
855 [(set (reg:CC CC_REGNUM)
857 (match_operand:SI 1 "s_register_operand" "r,r")
858 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
859 (set (match_operand:SI 0 "s_register_operand" "=r,r")
860 (plus:SI (match_dup 1)
861 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
862 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
865 sub%.\\t%0, %1, #%n3"
866 [(set_attr "conds" "set")]
869 ;; Convert the sequence
871 ;; cmn rd, #1 (equivalent to cmp rd, #-1)
875 ;; bcs dest ((unsigned)rn >= 1)
876 ;; similarly for the beq variant using bcc.
877 ;; This is a common looping idiom (while (n--))
879 [(set (match_operand:SI 0 "arm_general_register_operand" "")
880 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
882 (set (match_operand 2 "cc_register" "")
883 (compare (match_dup 0) (const_int -1)))
885 (if_then_else (match_operator 3 "equality_operator"
886 [(match_dup 2) (const_int 0)])
887 (match_operand 4 "" "")
888 (match_operand 5 "" "")))]
889 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
893 (match_dup 1) (const_int 1)))
894 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
896 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
899 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
900 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
903 operands[2], const0_rtx);"
906 ;; The next four insns work because they compare the result with one of
907 ;; the operands, and we know that the use of the condition code is
908 ;; either GEU or LTU, so we can use the carry flag from the addition
909 ;; instead of doing the compare a second time.
910 (define_insn "*addsi3_compare_op1"
911 [(set (reg:CC_C CC_REGNUM)
913 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
914 (match_operand:SI 2 "arm_add_operand" "rI,L"))
916 (set (match_operand:SI 0 "s_register_operand" "=r,r")
917 (plus:SI (match_dup 1) (match_dup 2)))]
921 sub%.\\t%0, %1, #%n2"
922 [(set_attr "conds" "set")]
925 (define_insn "*addsi3_compare_op2"
926 [(set (reg:CC_C CC_REGNUM)
928 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
929 (match_operand:SI 2 "arm_add_operand" "rI,L"))
931 (set (match_operand:SI 0 "s_register_operand" "=r,r")
932 (plus:SI (match_dup 1) (match_dup 2)))]
936 sub%.\\t%0, %1, #%n2"
937 [(set_attr "conds" "set")]
940 (define_insn "*compare_addsi2_op0"
941 [(set (reg:CC_C CC_REGNUM)
943 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
944 (match_operand:SI 1 "arm_add_operand" "rI,L"))
950 [(set_attr "conds" "set")]
953 (define_insn "*compare_addsi2_op1"
954 [(set (reg:CC_C CC_REGNUM)
956 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
957 (match_operand:SI 1 "arm_add_operand" "rI,L"))
963 [(set_attr "conds" "set")]
966 (define_insn "*addsi3_carryin_<optab>"
967 [(set (match_operand:SI 0 "s_register_operand" "=r")
968 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
969 (match_operand:SI 2 "arm_rhs_operand" "rI"))
970 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
973 [(set_attr "conds" "use")]
976 (define_insn "*addsi3_carryin_alt2_<optab>"
977 [(set (match_operand:SI 0 "s_register_operand" "=r")
978 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
979 (match_operand:SI 1 "s_register_operand" "%r"))
980 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
983 [(set_attr "conds" "use")]
986 (define_insn "*addsi3_carryin_shift_<optab>"
987 [(set (match_operand:SI 0 "s_register_operand" "=r")
989 (match_operator:SI 2 "shift_operator"
990 [(match_operand:SI 3 "s_register_operand" "r")
991 (match_operand:SI 4 "reg_or_int_operand" "rM")])
992 (match_operand:SI 1 "s_register_operand" "r"))
993 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
995 "adc%?\\t%0, %1, %3%S2"
996 [(set_attr "conds" "use")
997 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
998 (const_string "alu_shift")
999 (const_string "alu_shift_reg")))]
1002 (define_insn "*addsi3_carryin_clobercc_<optab>"
1003 [(set (match_operand:SI 0 "s_register_operand" "=r")
1004 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
1005 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1006 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
1007 (clobber (reg:CC CC_REGNUM))]
1009 "adc%.\\t%0, %1, %2"
1010 [(set_attr "conds" "set")]
1013 (define_expand "incscc"
1014 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1015 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
1016 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
1017 (match_operand:SI 1 "s_register_operand" "0,?r")))]
1022 (define_insn "*arm_incscc"
1023 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1024 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
1025 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
1026 (match_operand:SI 1 "s_register_operand" "0,?r")))]
1030 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
1031 [(set_attr "conds" "use")
1032 (set_attr "length" "4,8")]
1035 ; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
1037 [(set (match_operand:SI 0 "s_register_operand" "")
1038 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1039 (match_operand:SI 2 "s_register_operand" ""))
1041 (clobber (match_operand:SI 3 "s_register_operand" ""))]
1043 [(set (match_dup 3) (match_dup 1))
1044 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1046 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1049 (define_expand "addsf3"
1050 [(set (match_operand:SF 0 "s_register_operand" "")
1051 (plus:SF (match_operand:SF 1 "s_register_operand" "")
1052 (match_operand:SF 2 "arm_float_add_operand" "")))]
1053 "TARGET_32BIT && TARGET_HARD_FLOAT"
1056 && !cirrus_fp_register (operands[2], SFmode))
1057 operands[2] = force_reg (SFmode, operands[2]);
1060 (define_expand "adddf3"
1061 [(set (match_operand:DF 0 "s_register_operand" "")
1062 (plus:DF (match_operand:DF 1 "s_register_operand" "")
1063 (match_operand:DF 2 "arm_float_add_operand" "")))]
1064 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1067 && !cirrus_fp_register (operands[2], DFmode))
1068 operands[2] = force_reg (DFmode, operands[2]);
1071 (define_expand "subdi3"
1073 [(set (match_operand:DI 0 "s_register_operand" "")
1074 (minus:DI (match_operand:DI 1 "s_register_operand" "")
1075 (match_operand:DI 2 "s_register_operand" "")))
1076 (clobber (reg:CC CC_REGNUM))])]
1079 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
1081 && cirrus_fp_register (operands[0], DImode)
1082 && cirrus_fp_register (operands[1], DImode))
1084 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
1090 if (GET_CODE (operands[1]) != REG)
1091 operands[1] = force_reg (DImode, operands[1]);
1092 if (GET_CODE (operands[2]) != REG)
1093 operands[2] = force_reg (DImode, operands[2]);
1098 (define_insn "*arm_subdi3"
1099 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
1100 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1101 (match_operand:DI 2 "s_register_operand" "r,0,0")))
1102 (clobber (reg:CC CC_REGNUM))]
1103 "TARGET_32BIT && !TARGET_NEON"
1104 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
1105 [(set_attr "conds" "clob")
1106 (set_attr "length" "8")]
1109 (define_insn "*thumb_subdi3"
1110 [(set (match_operand:DI 0 "register_operand" "=l")
1111 (minus:DI (match_operand:DI 1 "register_operand" "0")
1112 (match_operand:DI 2 "register_operand" "l")))
1113 (clobber (reg:CC CC_REGNUM))]
1115 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
1116 [(set_attr "length" "4")]
1119 (define_insn "*subdi_di_zesidi"
1120 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1121 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
1123 (match_operand:SI 2 "s_register_operand" "r,r"))))
1124 (clobber (reg:CC CC_REGNUM))]
1126 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1127 [(set_attr "conds" "clob")
1128 (set_attr "length" "8")]
1131 (define_insn "*subdi_di_sesidi"
1132 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1133 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
1135 (match_operand:SI 2 "s_register_operand" "r,r"))))
1136 (clobber (reg:CC CC_REGNUM))]
1138 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
1139 [(set_attr "conds" "clob")
1140 (set_attr "length" "8")]
1143 (define_insn "*subdi_zesidi_di"
1144 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1145 (minus:DI (zero_extend:DI
1146 (match_operand:SI 2 "s_register_operand" "r,r"))
1147 (match_operand:DI 1 "s_register_operand" "0,r")))
1148 (clobber (reg:CC CC_REGNUM))]
1150 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1151 [(set_attr "conds" "clob")
1152 (set_attr "length" "8")]
1155 (define_insn "*subdi_sesidi_di"
1156 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1157 (minus:DI (sign_extend:DI
1158 (match_operand:SI 2 "s_register_operand" "r,r"))
1159 (match_operand:DI 1 "s_register_operand" "0,r")))
1160 (clobber (reg:CC CC_REGNUM))]
1162 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1163 [(set_attr "conds" "clob")
1164 (set_attr "length" "8")]
1167 (define_insn "*subdi_zesidi_zesidi"
1168 [(set (match_operand:DI 0 "s_register_operand" "=r")
1169 (minus:DI (zero_extend:DI
1170 (match_operand:SI 1 "s_register_operand" "r"))
1172 (match_operand:SI 2 "s_register_operand" "r"))))
1173 (clobber (reg:CC CC_REGNUM))]
1175 "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1176 [(set_attr "conds" "clob")
1177 (set_attr "length" "8")]
1180 (define_expand "subsi3"
1181 [(set (match_operand:SI 0 "s_register_operand" "")
1182 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1183 (match_operand:SI 2 "s_register_operand" "")))]
1186 if (GET_CODE (operands[1]) == CONST_INT)
1190 arm_split_constant (MINUS, SImode, NULL_RTX,
1191 INTVAL (operands[1]), operands[0],
1192 operands[2], optimize && can_create_pseudo_p ());
1195 else /* TARGET_THUMB1 */
1196 operands[1] = force_reg (SImode, operands[1]);
1201 (define_insn "thumb1_subsi3_insn"
1202 [(set (match_operand:SI 0 "register_operand" "=l")
1203 (minus:SI (match_operand:SI 1 "register_operand" "l")
1204 (match_operand:SI 2 "reg_or_int_operand" "lPd")))]
1207 [(set_attr "length" "2")
1208 (set_attr "conds" "set")])
1210 ; ??? Check Thumb-2 split length
1211 (define_insn_and_split "*arm_subsi3_insn"
1212 [(set (match_operand:SI 0 "s_register_operand" "=r,r,rk,r,r")
1213 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,k,?n,r")
1214 (match_operand:SI 2 "reg_or_int_operand" "r,rI,r, r,?n")))]
1222 "&& ((GET_CODE (operands[1]) == CONST_INT
1223 && !const_ok_for_arm (INTVAL (operands[1])))
1224 || (GET_CODE (operands[2]) == CONST_INT
1225 && !const_ok_for_arm (INTVAL (operands[2]))))"
1226 [(clobber (const_int 0))]
1228 arm_split_constant (MINUS, SImode, curr_insn,
1229 INTVAL (operands[1]), operands[0], operands[2], 0);
1232 [(set_attr "length" "4,4,4,16,16")
1233 (set_attr "predicable" "yes")]
1237 [(match_scratch:SI 3 "r")
1238 (set (match_operand:SI 0 "arm_general_register_operand" "")
1239 (minus:SI (match_operand:SI 1 "const_int_operand" "")
1240 (match_operand:SI 2 "arm_general_register_operand" "")))]
1242 && !const_ok_for_arm (INTVAL (operands[1]))
1243 && const_ok_for_arm (~INTVAL (operands[1]))"
1244 [(set (match_dup 3) (match_dup 1))
1245 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1249 (define_insn "*subsi3_compare0"
1250 [(set (reg:CC_NOOV CC_REGNUM)
1252 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1253 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1255 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1256 (minus:SI (match_dup 1) (match_dup 2)))]
1261 [(set_attr "conds" "set")]
1264 (define_insn "*subsi3_compare"
1265 [(set (reg:CC CC_REGNUM)
1266 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,I")
1267 (match_operand:SI 2 "arm_rhs_operand" "rI,r")))
1268 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1269 (minus:SI (match_dup 1) (match_dup 2)))]
1274 [(set_attr "conds" "set")]
1277 (define_expand "decscc"
1278 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1279 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1280 (match_operator:SI 2 "arm_comparison_operator"
1281 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1286 (define_insn "*arm_decscc"
1287 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1288 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1289 (match_operator:SI 2 "arm_comparison_operator"
1290 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1294 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1295 [(set_attr "conds" "use")
1296 (set_attr "length" "*,8")]
1299 (define_expand "subsf3"
1300 [(set (match_operand:SF 0 "s_register_operand" "")
1301 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1302 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1303 "TARGET_32BIT && TARGET_HARD_FLOAT"
1305 if (TARGET_MAVERICK)
1307 if (!cirrus_fp_register (operands[1], SFmode))
1308 operands[1] = force_reg (SFmode, operands[1]);
1309 if (!cirrus_fp_register (operands[2], SFmode))
1310 operands[2] = force_reg (SFmode, operands[2]);
1314 (define_expand "subdf3"
1315 [(set (match_operand:DF 0 "s_register_operand" "")
1316 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1317 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1318 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1320 if (TARGET_MAVERICK)
1322 if (!cirrus_fp_register (operands[1], DFmode))
1323 operands[1] = force_reg (DFmode, operands[1]);
1324 if (!cirrus_fp_register (operands[2], DFmode))
1325 operands[2] = force_reg (DFmode, operands[2]);
1330 ;; Multiplication insns
1332 (define_expand "mulsi3"
1333 [(set (match_operand:SI 0 "s_register_operand" "")
1334 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1335 (match_operand:SI 1 "s_register_operand" "")))]
1340 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1341 (define_insn "*arm_mulsi3"
1342 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1343 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1344 (match_operand:SI 1 "s_register_operand" "%0,r")))]
1345 "TARGET_32BIT && !arm_arch6"
1346 "mul%?\\t%0, %2, %1"
1347 [(set_attr "insn" "mul")
1348 (set_attr "predicable" "yes")]
1351 (define_insn "*arm_mulsi3_v6"
1352 [(set (match_operand:SI 0 "s_register_operand" "=r")
1353 (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1354 (match_operand:SI 2 "s_register_operand" "r")))]
1355 "TARGET_32BIT && arm_arch6"
1356 "mul%?\\t%0, %1, %2"
1357 [(set_attr "insn" "mul")
1358 (set_attr "predicable" "yes")]
1361 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1362 ; 1 and 2; are the same, because reload will make operand 0 match
1363 ; operand 1 without realizing that this conflicts with operand 2. We fix
1364 ; this by adding another alternative to match this case, and then `reload'
1365 ; it ourselves. This alternative must come first.
1366 (define_insn "*thumb_mulsi3"
1367 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1368 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1369 (match_operand:SI 2 "register_operand" "l,l,l")))]
1370 "TARGET_THUMB1 && !arm_arch6"
1372 if (which_alternative < 2)
1373 return \"mov\\t%0, %1\;mul\\t%0, %2\";
1375 return \"mul\\t%0, %2\";
1377 [(set_attr "length" "4,4,2")
1378 (set_attr "insn" "mul")]
1381 (define_insn "*thumb_mulsi3_v6"
1382 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
1383 (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1384 (match_operand:SI 2 "register_operand" "l,0,0")))]
1385 "TARGET_THUMB1 && arm_arch6"
1390 [(set_attr "length" "2")
1391 (set_attr "insn" "mul")]
1394 (define_insn "*mulsi3_compare0"
1395 [(set (reg:CC_NOOV CC_REGNUM)
1396 (compare:CC_NOOV (mult:SI
1397 (match_operand:SI 2 "s_register_operand" "r,r")
1398 (match_operand:SI 1 "s_register_operand" "%0,r"))
1400 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1401 (mult:SI (match_dup 2) (match_dup 1)))]
1402 "TARGET_ARM && !arm_arch6"
1403 "mul%.\\t%0, %2, %1"
1404 [(set_attr "conds" "set")
1405 (set_attr "insn" "muls")]
1408 (define_insn "*mulsi3_compare0_v6"
1409 [(set (reg:CC_NOOV CC_REGNUM)
1410 (compare:CC_NOOV (mult:SI
1411 (match_operand:SI 2 "s_register_operand" "r")
1412 (match_operand:SI 1 "s_register_operand" "r"))
1414 (set (match_operand:SI 0 "s_register_operand" "=r")
1415 (mult:SI (match_dup 2) (match_dup 1)))]
1416 "TARGET_ARM && arm_arch6 && optimize_size"
1417 "mul%.\\t%0, %2, %1"
1418 [(set_attr "conds" "set")
1419 (set_attr "insn" "muls")]
1422 (define_insn "*mulsi_compare0_scratch"
1423 [(set (reg:CC_NOOV CC_REGNUM)
1424 (compare:CC_NOOV (mult:SI
1425 (match_operand:SI 2 "s_register_operand" "r,r")
1426 (match_operand:SI 1 "s_register_operand" "%0,r"))
1428 (clobber (match_scratch:SI 0 "=&r,&r"))]
1429 "TARGET_ARM && !arm_arch6"
1430 "mul%.\\t%0, %2, %1"
1431 [(set_attr "conds" "set")
1432 (set_attr "insn" "muls")]
1435 (define_insn "*mulsi_compare0_scratch_v6"
1436 [(set (reg:CC_NOOV CC_REGNUM)
1437 (compare:CC_NOOV (mult:SI
1438 (match_operand:SI 2 "s_register_operand" "r")
1439 (match_operand:SI 1 "s_register_operand" "r"))
1441 (clobber (match_scratch:SI 0 "=r"))]
1442 "TARGET_ARM && arm_arch6 && optimize_size"
1443 "mul%.\\t%0, %2, %1"
1444 [(set_attr "conds" "set")
1445 (set_attr "insn" "muls")]
1448 ;; Unnamed templates to match MLA instruction.
1450 (define_insn "*mulsi3addsi"
1451 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1453 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1454 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1455 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
1456 "TARGET_32BIT && !arm_arch6"
1457 "mla%?\\t%0, %2, %1, %3"
1458 [(set_attr "insn" "mla")
1459 (set_attr "predicable" "yes")]
1462 (define_insn "*mulsi3addsi_v6"
1463 [(set (match_operand:SI 0 "s_register_operand" "=r")
1465 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1466 (match_operand:SI 1 "s_register_operand" "r"))
1467 (match_operand:SI 3 "s_register_operand" "r")))]
1468 "TARGET_32BIT && arm_arch6"
1469 "mla%?\\t%0, %2, %1, %3"
1470 [(set_attr "insn" "mla")
1471 (set_attr "predicable" "yes")]
1474 (define_insn "*mulsi3addsi_compare0"
1475 [(set (reg:CC_NOOV CC_REGNUM)
1478 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1479 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1480 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
1482 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1483 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1485 "TARGET_ARM && arm_arch6"
1486 "mla%.\\t%0, %2, %1, %3"
1487 [(set_attr "conds" "set")
1488 (set_attr "insn" "mlas")]
1491 (define_insn "*mulsi3addsi_compare0_v6"
1492 [(set (reg:CC_NOOV CC_REGNUM)
1495 (match_operand:SI 2 "s_register_operand" "r")
1496 (match_operand:SI 1 "s_register_operand" "r"))
1497 (match_operand:SI 3 "s_register_operand" "r"))
1499 (set (match_operand:SI 0 "s_register_operand" "=r")
1500 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1502 "TARGET_ARM && arm_arch6 && optimize_size"
1503 "mla%.\\t%0, %2, %1, %3"
1504 [(set_attr "conds" "set")
1505 (set_attr "insn" "mlas")]
1508 (define_insn "*mulsi3addsi_compare0_scratch"
1509 [(set (reg:CC_NOOV CC_REGNUM)
1512 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1513 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1514 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1516 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1517 "TARGET_ARM && !arm_arch6"
1518 "mla%.\\t%0, %2, %1, %3"
1519 [(set_attr "conds" "set")
1520 (set_attr "insn" "mlas")]
1523 (define_insn "*mulsi3addsi_compare0_scratch_v6"
1524 [(set (reg:CC_NOOV CC_REGNUM)
1527 (match_operand:SI 2 "s_register_operand" "r")
1528 (match_operand:SI 1 "s_register_operand" "r"))
1529 (match_operand:SI 3 "s_register_operand" "r"))
1531 (clobber (match_scratch:SI 0 "=r"))]
1532 "TARGET_ARM && arm_arch6 && optimize_size"
1533 "mla%.\\t%0, %2, %1, %3"
1534 [(set_attr "conds" "set")
1535 (set_attr "insn" "mlas")]
1538 (define_insn "*mulsi3subsi"
1539 [(set (match_operand:SI 0 "s_register_operand" "=r")
1541 (match_operand:SI 3 "s_register_operand" "r")
1542 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1543 (match_operand:SI 1 "s_register_operand" "r"))))]
1544 "TARGET_32BIT && arm_arch_thumb2"
1545 "mls%?\\t%0, %2, %1, %3"
1546 [(set_attr "insn" "mla")
1547 (set_attr "predicable" "yes")]
1550 (define_expand "maddsidi4"
1551 [(set (match_operand:DI 0 "s_register_operand" "")
1554 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1555 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1556 (match_operand:DI 3 "s_register_operand" "")))]
1557 "TARGET_32BIT && arm_arch3m"
1560 (define_insn "*mulsidi3adddi"
1561 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1564 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1565 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1566 (match_operand:DI 1 "s_register_operand" "0")))]
1567 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1568 "smlal%?\\t%Q0, %R0, %3, %2"
1569 [(set_attr "insn" "smlal")
1570 (set_attr "predicable" "yes")]
1573 (define_insn "*mulsidi3adddi_v6"
1574 [(set (match_operand:DI 0 "s_register_operand" "=r")
1577 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1578 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1579 (match_operand:DI 1 "s_register_operand" "0")))]
1580 "TARGET_32BIT && arm_arch6"
1581 "smlal%?\\t%Q0, %R0, %3, %2"
1582 [(set_attr "insn" "smlal")
1583 (set_attr "predicable" "yes")]
1586 ;; 32x32->64 widening multiply.
1587 ;; As with mulsi3, the only difference between the v3-5 and v6+
1588 ;; versions of these patterns is the requirement that the output not
1589 ;; overlap the inputs, but that still means we have to have a named
1590 ;; expander and two different starred insns.
1592 (define_expand "mulsidi3"
1593 [(set (match_operand:DI 0 "s_register_operand" "")
1595 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1596 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1597 "TARGET_32BIT && arm_arch3m"
1601 (define_insn "*mulsidi3_nov6"
1602 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1604 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1605 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1606 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1607 "smull%?\\t%Q0, %R0, %1, %2"
1608 [(set_attr "insn" "smull")
1609 (set_attr "predicable" "yes")]
1612 (define_insn "*mulsidi3_v6"
1613 [(set (match_operand:DI 0 "s_register_operand" "=r")
1615 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1616 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1617 "TARGET_32BIT && arm_arch6"
1618 "smull%?\\t%Q0, %R0, %1, %2"
1619 [(set_attr "insn" "smull")
1620 (set_attr "predicable" "yes")]
1623 (define_expand "umulsidi3"
1624 [(set (match_operand:DI 0 "s_register_operand" "")
1626 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1627 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1628 "TARGET_32BIT && arm_arch3m"
1632 (define_insn "*umulsidi3_nov6"
1633 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1635 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1636 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1637 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1638 "umull%?\\t%Q0, %R0, %1, %2"
1639 [(set_attr "insn" "umull")
1640 (set_attr "predicable" "yes")]
1643 (define_insn "*umulsidi3_v6"
1644 [(set (match_operand:DI 0 "s_register_operand" "=r")
1646 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1647 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1648 "TARGET_32BIT && arm_arch6"
1649 "umull%?\\t%Q0, %R0, %1, %2"
1650 [(set_attr "insn" "umull")
1651 (set_attr "predicable" "yes")]
1654 (define_expand "umaddsidi4"
1655 [(set (match_operand:DI 0 "s_register_operand" "")
1658 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1659 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1660 (match_operand:DI 3 "s_register_operand" "")))]
1661 "TARGET_32BIT && arm_arch3m"
1664 (define_insn "*umulsidi3adddi"
1665 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1668 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1669 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1670 (match_operand:DI 1 "s_register_operand" "0")))]
1671 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1672 "umlal%?\\t%Q0, %R0, %3, %2"
1673 [(set_attr "insn" "umlal")
1674 (set_attr "predicable" "yes")]
1677 (define_insn "*umulsidi3adddi_v6"
1678 [(set (match_operand:DI 0 "s_register_operand" "=r")
1681 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1682 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1683 (match_operand:DI 1 "s_register_operand" "0")))]
1684 "TARGET_32BIT && arm_arch6"
1685 "umlal%?\\t%Q0, %R0, %3, %2"
1686 [(set_attr "insn" "umlal")
1687 (set_attr "predicable" "yes")]
1690 (define_expand "smulsi3_highpart"
1692 [(set (match_operand:SI 0 "s_register_operand" "")
1696 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1697 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1699 (clobber (match_scratch:SI 3 ""))])]
1700 "TARGET_32BIT && arm_arch3m"
1704 (define_insn "*smulsi3_highpart_nov6"
1705 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1709 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
1710 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1712 (clobber (match_scratch:SI 3 "=&r,&r"))]
1713 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1714 "smull%?\\t%3, %0, %2, %1"
1715 [(set_attr "insn" "smull")
1716 (set_attr "predicable" "yes")]
1719 (define_insn "*smulsi3_highpart_v6"
1720 [(set (match_operand:SI 0 "s_register_operand" "=r")
1724 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1725 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1727 (clobber (match_scratch:SI 3 "=r"))]
1728 "TARGET_32BIT && arm_arch6"
1729 "smull%?\\t%3, %0, %2, %1"
1730 [(set_attr "insn" "smull")
1731 (set_attr "predicable" "yes")]
1734 (define_expand "umulsi3_highpart"
1736 [(set (match_operand:SI 0 "s_register_operand" "")
1740 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1741 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1743 (clobber (match_scratch:SI 3 ""))])]
1744 "TARGET_32BIT && arm_arch3m"
1748 (define_insn "*umulsi3_highpart_nov6"
1749 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1753 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
1754 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1756 (clobber (match_scratch:SI 3 "=&r,&r"))]
1757 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1758 "umull%?\\t%3, %0, %2, %1"
1759 [(set_attr "insn" "umull")
1760 (set_attr "predicable" "yes")]
1763 (define_insn "*umulsi3_highpart_v6"
1764 [(set (match_operand:SI 0 "s_register_operand" "=r")
1768 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1769 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1771 (clobber (match_scratch:SI 3 "=r"))]
1772 "TARGET_32BIT && arm_arch6"
1773 "umull%?\\t%3, %0, %2, %1"
1774 [(set_attr "insn" "umull")
1775 (set_attr "predicable" "yes")]
1778 (define_insn "mulhisi3"
1779 [(set (match_operand:SI 0 "s_register_operand" "=r")
1780 (mult:SI (sign_extend:SI
1781 (match_operand:HI 1 "s_register_operand" "%r"))
1783 (match_operand:HI 2 "s_register_operand" "r"))))]
1784 "TARGET_DSP_MULTIPLY"
1785 "smulbb%?\\t%0, %1, %2"
1786 [(set_attr "insn" "smulxy")
1787 (set_attr "predicable" "yes")]
1790 (define_insn "*mulhisi3tb"
1791 [(set (match_operand:SI 0 "s_register_operand" "=r")
1792 (mult:SI (ashiftrt:SI
1793 (match_operand:SI 1 "s_register_operand" "r")
1796 (match_operand:HI 2 "s_register_operand" "r"))))]
1797 "TARGET_DSP_MULTIPLY"
1798 "smultb%?\\t%0, %1, %2"
1799 [(set_attr "insn" "smulxy")
1800 (set_attr "predicable" "yes")]
1803 (define_insn "*mulhisi3bt"
1804 [(set (match_operand:SI 0 "s_register_operand" "=r")
1805 (mult:SI (sign_extend:SI
1806 (match_operand:HI 1 "s_register_operand" "r"))
1808 (match_operand:SI 2 "s_register_operand" "r")
1810 "TARGET_DSP_MULTIPLY"
1811 "smulbt%?\\t%0, %1, %2"
1812 [(set_attr "insn" "smulxy")
1813 (set_attr "predicable" "yes")]
1816 (define_insn "*mulhisi3tt"
1817 [(set (match_operand:SI 0 "s_register_operand" "=r")
1818 (mult:SI (ashiftrt:SI
1819 (match_operand:SI 1 "s_register_operand" "r")
1822 (match_operand:SI 2 "s_register_operand" "r")
1824 "TARGET_DSP_MULTIPLY"
1825 "smultt%?\\t%0, %1, %2"
1826 [(set_attr "insn" "smulxy")
1827 (set_attr "predicable" "yes")]
1830 (define_insn "maddhisi4"
1831 [(set (match_operand:SI 0 "s_register_operand" "=r")
1832 (plus:SI (mult:SI (sign_extend:SI
1833 (match_operand:HI 1 "s_register_operand" "r"))
1835 (match_operand:HI 2 "s_register_operand" "r")))
1836 (match_operand:SI 3 "s_register_operand" "r")))]
1837 "TARGET_DSP_MULTIPLY"
1838 "smlabb%?\\t%0, %1, %2, %3"
1839 [(set_attr "insn" "smlaxy")
1840 (set_attr "predicable" "yes")]
1843 ;; Note: there is no maddhisi4ibt because this one is canonical form
1844 (define_insn "*maddhisi4tb"
1845 [(set (match_operand:SI 0 "s_register_operand" "=r")
1846 (plus:SI (mult:SI (ashiftrt:SI
1847 (match_operand:SI 1 "s_register_operand" "r")
1850 (match_operand:HI 2 "s_register_operand" "r")))
1851 (match_operand:SI 3 "s_register_operand" "r")))]
1852 "TARGET_DSP_MULTIPLY"
1853 "smlatb%?\\t%0, %1, %2, %3"
1854 [(set_attr "insn" "smlaxy")
1855 (set_attr "predicable" "yes")]
1858 (define_insn "*maddhisi4tt"
1859 [(set (match_operand:SI 0 "s_register_operand" "=r")
1860 (plus:SI (mult:SI (ashiftrt:SI
1861 (match_operand:SI 1 "s_register_operand" "r")
1864 (match_operand:SI 2 "s_register_operand" "r")
1866 (match_operand:SI 3 "s_register_operand" "r")))]
1867 "TARGET_DSP_MULTIPLY"
1868 "smlatt%?\\t%0, %1, %2, %3"
1869 [(set_attr "insn" "smlaxy")
1870 (set_attr "predicable" "yes")]
1873 (define_insn "maddhidi4"
1874 [(set (match_operand:DI 0 "s_register_operand" "=r")
1876 (mult:DI (sign_extend:DI
1877 (match_operand:HI 1 "s_register_operand" "r"))
1879 (match_operand:HI 2 "s_register_operand" "r")))
1880 (match_operand:DI 3 "s_register_operand" "0")))]
1881 "TARGET_DSP_MULTIPLY"
1882 "smlalbb%?\\t%Q0, %R0, %1, %2"
1883 [(set_attr "insn" "smlalxy")
1884 (set_attr "predicable" "yes")])
1886 ;; Note: there is no maddhidi4ibt because this one is canonical form
1887 (define_insn "*maddhidi4tb"
1888 [(set (match_operand:DI 0 "s_register_operand" "=r")
1890 (mult:DI (sign_extend:DI
1892 (match_operand:SI 1 "s_register_operand" "r")
1895 (match_operand:HI 2 "s_register_operand" "r")))
1896 (match_operand:DI 3 "s_register_operand" "0")))]
1897 "TARGET_DSP_MULTIPLY"
1898 "smlaltb%?\\t%Q0, %R0, %1, %2"
1899 [(set_attr "insn" "smlalxy")
1900 (set_attr "predicable" "yes")])
1902 (define_insn "*maddhidi4tt"
1903 [(set (match_operand:DI 0 "s_register_operand" "=r")
1905 (mult:DI (sign_extend:DI
1907 (match_operand:SI 1 "s_register_operand" "r")
1911 (match_operand:SI 2 "s_register_operand" "r")
1913 (match_operand:DI 3 "s_register_operand" "0")))]
1914 "TARGET_DSP_MULTIPLY"
1915 "smlaltt%?\\t%Q0, %R0, %1, %2"
1916 [(set_attr "insn" "smlalxy")
1917 (set_attr "predicable" "yes")])
1919 (define_expand "mulsf3"
1920 [(set (match_operand:SF 0 "s_register_operand" "")
1921 (mult:SF (match_operand:SF 1 "s_register_operand" "")
1922 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1923 "TARGET_32BIT && TARGET_HARD_FLOAT"
1926 && !cirrus_fp_register (operands[2], SFmode))
1927 operands[2] = force_reg (SFmode, operands[2]);
1930 (define_expand "muldf3"
1931 [(set (match_operand:DF 0 "s_register_operand" "")
1932 (mult:DF (match_operand:DF 1 "s_register_operand" "")
1933 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1934 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1937 && !cirrus_fp_register (operands[2], DFmode))
1938 operands[2] = force_reg (DFmode, operands[2]);
1943 (define_expand "divsf3"
1944 [(set (match_operand:SF 0 "s_register_operand" "")
1945 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1946 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1947 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1950 (define_expand "divdf3"
1951 [(set (match_operand:DF 0 "s_register_operand" "")
1952 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1953 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1954 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
1959 (define_expand "modsf3"
1960 [(set (match_operand:SF 0 "s_register_operand" "")
1961 (mod:SF (match_operand:SF 1 "s_register_operand" "")
1962 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1963 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
1966 (define_expand "moddf3"
1967 [(set (match_operand:DF 0 "s_register_operand" "")
1968 (mod:DF (match_operand:DF 1 "s_register_operand" "")
1969 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1970 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
1973 ;; Boolean and,ior,xor insns
1975 ;; Split up double word logical operations
1977 ;; Split up simple DImode logical operations. Simply perform the logical
1978 ;; operation on the upper and lower halves of the registers.
1980 [(set (match_operand:DI 0 "s_register_operand" "")
1981 (match_operator:DI 6 "logical_binary_operator"
1982 [(match_operand:DI 1 "s_register_operand" "")
1983 (match_operand:DI 2 "s_register_operand" "")]))]
1984 "TARGET_32BIT && reload_completed
1985 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
1986 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1987 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1988 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1991 operands[3] = gen_highpart (SImode, operands[0]);
1992 operands[0] = gen_lowpart (SImode, operands[0]);
1993 operands[4] = gen_highpart (SImode, operands[1]);
1994 operands[1] = gen_lowpart (SImode, operands[1]);
1995 operands[5] = gen_highpart (SImode, operands[2]);
1996 operands[2] = gen_lowpart (SImode, operands[2]);
2001 [(set (match_operand:DI 0 "s_register_operand" "")
2002 (match_operator:DI 6 "logical_binary_operator"
2003 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2004 (match_operand:DI 1 "s_register_operand" "")]))]
2005 "TARGET_32BIT && reload_completed"
2006 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2007 (set (match_dup 3) (match_op_dup:SI 6
2008 [(ashiftrt:SI (match_dup 2) (const_int 31))
2012 operands[3] = gen_highpart (SImode, operands[0]);
2013 operands[0] = gen_lowpart (SImode, operands[0]);
2014 operands[4] = gen_highpart (SImode, operands[1]);
2015 operands[1] = gen_lowpart (SImode, operands[1]);
2016 operands[5] = gen_highpart (SImode, operands[2]);
2017 operands[2] = gen_lowpart (SImode, operands[2]);
2021 ;; The zero extend of operand 2 means we can just copy the high part of
2022 ;; operand1 into operand0.
2024 [(set (match_operand:DI 0 "s_register_operand" "")
2026 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2027 (match_operand:DI 1 "s_register_operand" "")))]
2028 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
2029 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
2030 (set (match_dup 3) (match_dup 4))]
2033 operands[4] = gen_highpart (SImode, operands[1]);
2034 operands[3] = gen_highpart (SImode, operands[0]);
2035 operands[0] = gen_lowpart (SImode, operands[0]);
2036 operands[1] = gen_lowpart (SImode, operands[1]);
2040 ;; The zero extend of operand 2 means we can just copy the high part of
2041 ;; operand1 into operand0.
2043 [(set (match_operand:DI 0 "s_register_operand" "")
2045 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2046 (match_operand:DI 1 "s_register_operand" "")))]
2047 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
2048 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
2049 (set (match_dup 3) (match_dup 4))]
2052 operands[4] = gen_highpart (SImode, operands[1]);
2053 operands[3] = gen_highpart (SImode, operands[0]);
2054 operands[0] = gen_lowpart (SImode, operands[0]);
2055 operands[1] = gen_lowpart (SImode, operands[1]);
2059 (define_expand "anddi3"
2060 [(set (match_operand:DI 0 "s_register_operand" "")
2061 (and:DI (match_operand:DI 1 "s_register_operand" "")
2062 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
2067 (define_insn "*anddi3_insn"
2068 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2069 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2070 (match_operand:DI 2 "s_register_operand" "r,r")))]
2071 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
2073 [(set_attr "length" "8")]
2076 (define_insn_and_split "*anddi_zesidi_di"
2077 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2078 (and:DI (zero_extend:DI
2079 (match_operand:SI 2 "s_register_operand" "r,r"))
2080 (match_operand:DI 1 "s_register_operand" "0,r")))]
2083 "TARGET_32BIT && reload_completed"
2084 ; The zero extend of operand 2 clears the high word of the output
2086 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2087 (set (match_dup 3) (const_int 0))]
2090 operands[3] = gen_highpart (SImode, operands[0]);
2091 operands[0] = gen_lowpart (SImode, operands[0]);
2092 operands[1] = gen_lowpart (SImode, operands[1]);
2094 [(set_attr "length" "8")]
2097 (define_insn "*anddi_sesdi_di"
2098 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2099 (and:DI (sign_extend:DI
2100 (match_operand:SI 2 "s_register_operand" "r,r"))
2101 (match_operand:DI 1 "s_register_operand" "0,r")))]
2104 [(set_attr "length" "8")]
2107 (define_expand "andsi3"
2108 [(set (match_operand:SI 0 "s_register_operand" "")
2109 (and:SI (match_operand:SI 1 "s_register_operand" "")
2110 (match_operand:SI 2 "reg_or_int_operand" "")))]
2115 if (GET_CODE (operands[2]) == CONST_INT)
2117 if (INTVAL (operands[2]) == 255 && arm_arch6)
2119 operands[1] = convert_to_mode (QImode, operands[1], 1);
2120 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2124 arm_split_constant (AND, SImode, NULL_RTX,
2125 INTVAL (operands[2]), operands[0],
2127 optimize && can_create_pseudo_p ());
2132 else /* TARGET_THUMB1 */
2134 if (GET_CODE (operands[2]) != CONST_INT)
2136 rtx tmp = force_reg (SImode, operands[2]);
2137 if (rtx_equal_p (operands[0], operands[1]))
2141 operands[2] = operands[1];
2149 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
2151 operands[2] = force_reg (SImode,
2152 GEN_INT (~INTVAL (operands[2])));
2154 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
2159 for (i = 9; i <= 31; i++)
2161 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2163 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2167 else if ((((HOST_WIDE_INT) 1) << i) - 1
2168 == ~INTVAL (operands[2]))
2170 rtx shift = GEN_INT (i);
2171 rtx reg = gen_reg_rtx (SImode);
2173 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2174 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2180 operands[2] = force_reg (SImode, operands[2]);
2186 ; ??? Check split length for Thumb-2
2187 (define_insn_and_split "*arm_andsi3_insn"
2188 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2189 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2190 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
2194 bic%?\\t%0, %1, #%B2
2197 && GET_CODE (operands[2]) == CONST_INT
2198 && !(const_ok_for_arm (INTVAL (operands[2]))
2199 || const_ok_for_arm (~INTVAL (operands[2])))"
2200 [(clobber (const_int 0))]
2202 arm_split_constant (AND, SImode, curr_insn,
2203 INTVAL (operands[2]), operands[0], operands[1], 0);
2206 [(set_attr "length" "4,4,16")
2207 (set_attr "predicable" "yes")]
2210 (define_insn "*thumb1_andsi3_insn"
2211 [(set (match_operand:SI 0 "register_operand" "=l")
2212 (and:SI (match_operand:SI 1 "register_operand" "%0")
2213 (match_operand:SI 2 "register_operand" "l")))]
2216 [(set_attr "length" "2")
2217 (set_attr "conds" "set")])
2219 (define_insn "*andsi3_compare0"
2220 [(set (reg:CC_NOOV CC_REGNUM)
2222 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
2223 (match_operand:SI 2 "arm_not_operand" "rI,K"))
2225 (set (match_operand:SI 0 "s_register_operand" "=r,r")
2226 (and:SI (match_dup 1) (match_dup 2)))]
2230 bic%.\\t%0, %1, #%B2"
2231 [(set_attr "conds" "set")]
2234 (define_insn "*andsi3_compare0_scratch"
2235 [(set (reg:CC_NOOV CC_REGNUM)
2237 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
2238 (match_operand:SI 1 "arm_not_operand" "rI,K"))
2240 (clobber (match_scratch:SI 2 "=X,r"))]
2244 bic%.\\t%2, %0, #%B1"
2245 [(set_attr "conds" "set")]
2248 (define_insn "*zeroextractsi_compare0_scratch"
2249 [(set (reg:CC_NOOV CC_REGNUM)
2250 (compare:CC_NOOV (zero_extract:SI
2251 (match_operand:SI 0 "s_register_operand" "r")
2252 (match_operand 1 "const_int_operand" "n")
2253 (match_operand 2 "const_int_operand" "n"))
2256 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2257 && INTVAL (operands[1]) > 0
2258 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2259 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
2261 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2262 << INTVAL (operands[2]));
2263 output_asm_insn (\"tst%?\\t%0, %1\", operands);
2266 [(set_attr "conds" "set")]
2269 (define_insn_and_split "*ne_zeroextractsi"
2270 [(set (match_operand:SI 0 "s_register_operand" "=r")
2271 (ne:SI (zero_extract:SI
2272 (match_operand:SI 1 "s_register_operand" "r")
2273 (match_operand:SI 2 "const_int_operand" "n")
2274 (match_operand:SI 3 "const_int_operand" "n"))
2276 (clobber (reg:CC CC_REGNUM))]
2278 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2279 && INTVAL (operands[2]) > 0
2280 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2281 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2284 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2285 && INTVAL (operands[2]) > 0
2286 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2287 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2288 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2289 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2291 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2293 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2294 (match_dup 0) (const_int 1)))]
2296 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2297 << INTVAL (operands[3]));
2299 [(set_attr "conds" "clob")
2300 (set (attr "length")
2301 (if_then_else (eq_attr "is_thumb" "yes")
2306 (define_insn_and_split "*ne_zeroextractsi_shifted"
2307 [(set (match_operand:SI 0 "s_register_operand" "=r")
2308 (ne:SI (zero_extract:SI
2309 (match_operand:SI 1 "s_register_operand" "r")
2310 (match_operand:SI 2 "const_int_operand" "n")
2313 (clobber (reg:CC CC_REGNUM))]
2317 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2318 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2320 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2322 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2323 (match_dup 0) (const_int 1)))]
2325 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2327 [(set_attr "conds" "clob")
2328 (set_attr "length" "8")]
2331 (define_insn_and_split "*ite_ne_zeroextractsi"
2332 [(set (match_operand:SI 0 "s_register_operand" "=r")
2333 (if_then_else:SI (ne (zero_extract:SI
2334 (match_operand:SI 1 "s_register_operand" "r")
2335 (match_operand:SI 2 "const_int_operand" "n")
2336 (match_operand:SI 3 "const_int_operand" "n"))
2338 (match_operand:SI 4 "arm_not_operand" "rIK")
2340 (clobber (reg:CC CC_REGNUM))]
2342 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2343 && INTVAL (operands[2]) > 0
2344 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2345 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2346 && !reg_overlap_mentioned_p (operands[0], operands[4])"
2349 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2350 && INTVAL (operands[2]) > 0
2351 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2352 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2353 && !reg_overlap_mentioned_p (operands[0], operands[4])"
2354 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2355 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2357 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2359 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2360 (match_dup 0) (match_dup 4)))]
2362 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2363 << INTVAL (operands[3]));
2365 [(set_attr "conds" "clob")
2366 (set_attr "length" "8")]
2369 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2370 [(set (match_operand:SI 0 "s_register_operand" "=r")
2371 (if_then_else:SI (ne (zero_extract:SI
2372 (match_operand:SI 1 "s_register_operand" "r")
2373 (match_operand:SI 2 "const_int_operand" "n")
2376 (match_operand:SI 3 "arm_not_operand" "rIK")
2378 (clobber (reg:CC CC_REGNUM))]
2379 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2381 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2382 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2383 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2385 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2387 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2388 (match_dup 0) (match_dup 3)))]
2390 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2392 [(set_attr "conds" "clob")
2393 (set_attr "length" "8")]
2397 [(set (match_operand:SI 0 "s_register_operand" "")
2398 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2399 (match_operand:SI 2 "const_int_operand" "")
2400 (match_operand:SI 3 "const_int_operand" "")))
2401 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2403 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2404 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2406 HOST_WIDE_INT temp = INTVAL (operands[2]);
2408 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2409 operands[3] = GEN_INT (32 - temp);
2413 ;; ??? Use Thumb-2 has bitfield insert/extract instructions.
2415 [(set (match_operand:SI 0 "s_register_operand" "")
2416 (match_operator:SI 1 "shiftable_operator"
2417 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2418 (match_operand:SI 3 "const_int_operand" "")
2419 (match_operand:SI 4 "const_int_operand" ""))
2420 (match_operand:SI 5 "s_register_operand" "")]))
2421 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2423 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2426 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2429 HOST_WIDE_INT temp = INTVAL (operands[3]);
2431 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2432 operands[4] = GEN_INT (32 - temp);
2437 [(set (match_operand:SI 0 "s_register_operand" "")
2438 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2439 (match_operand:SI 2 "const_int_operand" "")
2440 (match_operand:SI 3 "const_int_operand" "")))]
2442 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2443 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2445 HOST_WIDE_INT temp = INTVAL (operands[2]);
2447 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2448 operands[3] = GEN_INT (32 - temp);
2453 [(set (match_operand:SI 0 "s_register_operand" "")
2454 (match_operator:SI 1 "shiftable_operator"
2455 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2456 (match_operand:SI 3 "const_int_operand" "")
2457 (match_operand:SI 4 "const_int_operand" ""))
2458 (match_operand:SI 5 "s_register_operand" "")]))
2459 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2461 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2464 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2467 HOST_WIDE_INT temp = INTVAL (operands[3]);
2469 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2470 operands[4] = GEN_INT (32 - temp);
2474 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
2475 ;;; represented by the bitfield, then this will produce incorrect results.
2476 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
2477 ;;; which have a real bit-field insert instruction, the truncation happens
2478 ;;; in the bit-field insert instruction itself. Since arm does not have a
2479 ;;; bit-field insert instruction, we would have to emit code here to truncate
2480 ;;; the value before we insert. This loses some of the advantage of having
2481 ;;; this insv pattern, so this pattern needs to be reevalutated.
2483 (define_expand "insv"
2484 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
2485 (match_operand:SI 1 "general_operand" "")
2486 (match_operand:SI 2 "general_operand" ""))
2487 (match_operand:SI 3 "reg_or_int_operand" ""))]
2488 "TARGET_ARM || arm_arch_thumb2"
2491 int start_bit = INTVAL (operands[2]);
2492 int width = INTVAL (operands[1]);
2493 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2494 rtx target, subtarget;
2496 if (arm_arch_thumb2)
2498 bool use_bfi = TRUE;
2500 if (GET_CODE (operands[3]) == CONST_INT)
2502 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2506 emit_insn (gen_insv_zero (operands[0], operands[1],
2511 /* See if the set can be done with a single orr instruction. */
2512 if (val == mask && const_ok_for_arm (val << start_bit))
2518 if (GET_CODE (operands[3]) != REG)
2519 operands[3] = force_reg (SImode, operands[3]);
2521 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2527 target = copy_rtx (operands[0]);
2528 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2529 subreg as the final target. */
2530 if (GET_CODE (target) == SUBREG)
2532 subtarget = gen_reg_rtx (SImode);
2533 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2534 < GET_MODE_SIZE (SImode))
2535 target = SUBREG_REG (target);
2540 if (GET_CODE (operands[3]) == CONST_INT)
2542 /* Since we are inserting a known constant, we may be able to
2543 reduce the number of bits that we have to clear so that
2544 the mask becomes simple. */
2545 /* ??? This code does not check to see if the new mask is actually
2546 simpler. It may not be. */
2547 rtx op1 = gen_reg_rtx (SImode);
2548 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2549 start of this pattern. */
2550 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2551 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2553 emit_insn (gen_andsi3 (op1, operands[0],
2554 gen_int_mode (~mask2, SImode)));
2555 emit_insn (gen_iorsi3 (subtarget, op1,
2556 gen_int_mode (op3_value << start_bit, SImode)));
2558 else if (start_bit == 0
2559 && !(const_ok_for_arm (mask)
2560 || const_ok_for_arm (~mask)))
2562 /* A Trick, since we are setting the bottom bits in the word,
2563 we can shift operand[3] up, operand[0] down, OR them together
2564 and rotate the result back again. This takes 3 insns, and
2565 the third might be mergeable into another op. */
2566 /* The shift up copes with the possibility that operand[3] is
2567 wider than the bitfield. */
2568 rtx op0 = gen_reg_rtx (SImode);
2569 rtx op1 = gen_reg_rtx (SImode);
2571 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2572 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2573 emit_insn (gen_iorsi3 (op1, op1, op0));
2574 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2576 else if ((width + start_bit == 32)
2577 && !(const_ok_for_arm (mask)
2578 || const_ok_for_arm (~mask)))
2580 /* Similar trick, but slightly less efficient. */
2582 rtx op0 = gen_reg_rtx (SImode);
2583 rtx op1 = gen_reg_rtx (SImode);
2585 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2586 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2587 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2588 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2592 rtx op0 = gen_int_mode (mask, SImode);
2593 rtx op1 = gen_reg_rtx (SImode);
2594 rtx op2 = gen_reg_rtx (SImode);
2596 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2598 rtx tmp = gen_reg_rtx (SImode);
2600 emit_insn (gen_movsi (tmp, op0));
2604 /* Mask out any bits in operand[3] that are not needed. */
2605 emit_insn (gen_andsi3 (op1, operands[3], op0));
2607 if (GET_CODE (op0) == CONST_INT
2608 && (const_ok_for_arm (mask << start_bit)
2609 || const_ok_for_arm (~(mask << start_bit))))
2611 op0 = gen_int_mode (~(mask << start_bit), SImode);
2612 emit_insn (gen_andsi3 (op2, operands[0], op0));
2616 if (GET_CODE (op0) == CONST_INT)
2618 rtx tmp = gen_reg_rtx (SImode);
2620 emit_insn (gen_movsi (tmp, op0));
2625 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
2627 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2631 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
2633 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2636 if (subtarget != target)
2638 /* If TARGET is still a SUBREG, then it must be wider than a word,
2639 so we must be careful only to set the subword we were asked to. */
2640 if (GET_CODE (target) == SUBREG)
2641 emit_move_insn (target, subtarget);
2643 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2650 (define_insn "insv_zero"
2651 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2652 (match_operand:SI 1 "const_int_operand" "M")
2653 (match_operand:SI 2 "const_int_operand" "M"))
2657 [(set_attr "length" "4")
2658 (set_attr "predicable" "yes")]
2661 (define_insn "insv_t2"
2662 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2663 (match_operand:SI 1 "const_int_operand" "M")
2664 (match_operand:SI 2 "const_int_operand" "M"))
2665 (match_operand:SI 3 "s_register_operand" "r"))]
2667 "bfi%?\t%0, %3, %2, %1"
2668 [(set_attr "length" "4")
2669 (set_attr "predicable" "yes")]
2672 ; constants for op 2 will never be given to these patterns.
2673 (define_insn_and_split "*anddi_notdi_di"
2674 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2675 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2676 (match_operand:DI 2 "s_register_operand" "r,0")))]
2679 "TARGET_32BIT && reload_completed
2680 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2681 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2682 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2683 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2686 operands[3] = gen_highpart (SImode, operands[0]);
2687 operands[0] = gen_lowpart (SImode, operands[0]);
2688 operands[4] = gen_highpart (SImode, operands[1]);
2689 operands[1] = gen_lowpart (SImode, operands[1]);
2690 operands[5] = gen_highpart (SImode, operands[2]);
2691 operands[2] = gen_lowpart (SImode, operands[2]);
2693 [(set_attr "length" "8")
2694 (set_attr "predicable" "yes")]
2697 (define_insn_and_split "*anddi_notzesidi_di"
2698 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2699 (and:DI (not:DI (zero_extend:DI
2700 (match_operand:SI 2 "s_register_operand" "r,r")))
2701 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2704 bic%?\\t%Q0, %Q1, %2
2706 ; (not (zero_extend ...)) allows us to just copy the high word from
2707 ; operand1 to operand0.
2710 && operands[0] != operands[1]"
2711 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2712 (set (match_dup 3) (match_dup 4))]
2715 operands[3] = gen_highpart (SImode, operands[0]);
2716 operands[0] = gen_lowpart (SImode, operands[0]);
2717 operands[4] = gen_highpart (SImode, operands[1]);
2718 operands[1] = gen_lowpart (SImode, operands[1]);
2720 [(set_attr "length" "4,8")
2721 (set_attr "predicable" "yes")]
2724 (define_insn_and_split "*anddi_notsesidi_di"
2725 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2726 (and:DI (not:DI (sign_extend:DI
2727 (match_operand:SI 2 "s_register_operand" "r,r")))
2728 (match_operand:DI 1 "s_register_operand" "0,r")))]
2731 "TARGET_32BIT && reload_completed"
2732 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2733 (set (match_dup 3) (and:SI (not:SI
2734 (ashiftrt:SI (match_dup 2) (const_int 31)))
2738 operands[3] = gen_highpart (SImode, operands[0]);
2739 operands[0] = gen_lowpart (SImode, operands[0]);
2740 operands[4] = gen_highpart (SImode, operands[1]);
2741 operands[1] = gen_lowpart (SImode, operands[1]);
2743 [(set_attr "length" "8")
2744 (set_attr "predicable" "yes")]
2747 (define_insn "andsi_notsi_si"
2748 [(set (match_operand:SI 0 "s_register_operand" "=r")
2749 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2750 (match_operand:SI 1 "s_register_operand" "r")))]
2752 "bic%?\\t%0, %1, %2"
2753 [(set_attr "predicable" "yes")]
2756 (define_insn "thumb1_bicsi3"
2757 [(set (match_operand:SI 0 "register_operand" "=l")
2758 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2759 (match_operand:SI 2 "register_operand" "0")))]
2762 [(set_attr "length" "2")
2763 (set_attr "conds" "set")])
2765 (define_insn "andsi_not_shiftsi_si"
2766 [(set (match_operand:SI 0 "s_register_operand" "=r")
2767 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2768 [(match_operand:SI 2 "s_register_operand" "r")
2769 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2770 (match_operand:SI 1 "s_register_operand" "r")))]
2772 "bic%?\\t%0, %1, %2%S4"
2773 [(set_attr "predicable" "yes")
2774 (set_attr "shift" "2")
2775 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2776 (const_string "alu_shift")
2777 (const_string "alu_shift_reg")))]
2780 (define_insn "*andsi_notsi_si_compare0"
2781 [(set (reg:CC_NOOV CC_REGNUM)
2783 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2784 (match_operand:SI 1 "s_register_operand" "r"))
2786 (set (match_operand:SI 0 "s_register_operand" "=r")
2787 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2789 "bic%.\\t%0, %1, %2"
2790 [(set_attr "conds" "set")]
2793 (define_insn "*andsi_notsi_si_compare0_scratch"
2794 [(set (reg:CC_NOOV CC_REGNUM)
2796 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2797 (match_operand:SI 1 "s_register_operand" "r"))
2799 (clobber (match_scratch:SI 0 "=r"))]
2801 "bic%.\\t%0, %1, %2"
2802 [(set_attr "conds" "set")]
2805 (define_expand "iordi3"
2806 [(set (match_operand:DI 0 "s_register_operand" "")
2807 (ior:DI (match_operand:DI 1 "s_register_operand" "")
2808 (match_operand:DI 2 "neon_logic_op2" "")))]
2813 (define_insn "*iordi3_insn"
2814 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2815 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2816 (match_operand:DI 2 "s_register_operand" "r,r")))]
2817 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
2819 [(set_attr "length" "8")
2820 (set_attr "predicable" "yes")]
2823 (define_insn "*iordi_zesidi_di"
2824 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2825 (ior:DI (zero_extend:DI
2826 (match_operand:SI 2 "s_register_operand" "r,r"))
2827 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2830 orr%?\\t%Q0, %Q1, %2
2832 [(set_attr "length" "4,8")
2833 (set_attr "predicable" "yes")]
2836 (define_insn "*iordi_sesidi_di"
2837 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2838 (ior:DI (sign_extend:DI
2839 (match_operand:SI 2 "s_register_operand" "r,r"))
2840 (match_operand:DI 1 "s_register_operand" "0,r")))]
2843 [(set_attr "length" "8")
2844 (set_attr "predicable" "yes")]
2847 (define_expand "iorsi3"
2848 [(set (match_operand:SI 0 "s_register_operand" "")
2849 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2850 (match_operand:SI 2 "reg_or_int_operand" "")))]
2853 if (GET_CODE (operands[2]) == CONST_INT)
2857 arm_split_constant (IOR, SImode, NULL_RTX,
2858 INTVAL (operands[2]), operands[0], operands[1],
2859 optimize && can_create_pseudo_p ());
2862 else /* TARGET_THUMB1 */
2864 rtx tmp = force_reg (SImode, operands[2]);
2865 if (rtx_equal_p (operands[0], operands[1]))
2869 operands[2] = operands[1];
2877 (define_insn_and_split "*iorsi3_insn"
2878 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2879 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
2880 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
2884 orn%?\\t%0, %1, #%B2
2887 && GET_CODE (operands[2]) == CONST_INT
2888 && !(const_ok_for_arm (INTVAL (operands[2]))
2889 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
2890 [(clobber (const_int 0))]
2892 arm_split_constant (IOR, SImode, curr_insn,
2893 INTVAL (operands[2]), operands[0], operands[1], 0);
2896 [(set_attr "length" "4,4,16")
2897 (set_attr "arch" "32,t2,32")
2898 (set_attr "predicable" "yes")])
2900 (define_insn "*thumb1_iorsi3_insn"
2901 [(set (match_operand:SI 0 "register_operand" "=l")
2902 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2903 (match_operand:SI 2 "register_operand" "l")))]
2906 [(set_attr "length" "2")
2907 (set_attr "conds" "set")])
2910 [(match_scratch:SI 3 "r")
2911 (set (match_operand:SI 0 "arm_general_register_operand" "")
2912 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2913 (match_operand:SI 2 "const_int_operand" "")))]
2915 && !const_ok_for_arm (INTVAL (operands[2]))
2916 && const_ok_for_arm (~INTVAL (operands[2]))"
2917 [(set (match_dup 3) (match_dup 2))
2918 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2922 (define_insn "*iorsi3_compare0"
2923 [(set (reg:CC_NOOV CC_REGNUM)
2924 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2925 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2927 (set (match_operand:SI 0 "s_register_operand" "=r")
2928 (ior:SI (match_dup 1) (match_dup 2)))]
2930 "orr%.\\t%0, %1, %2"
2931 [(set_attr "conds" "set")]
2934 (define_insn "*iorsi3_compare0_scratch"
2935 [(set (reg:CC_NOOV CC_REGNUM)
2936 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2937 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2939 (clobber (match_scratch:SI 0 "=r"))]
2941 "orr%.\\t%0, %1, %2"
2942 [(set_attr "conds" "set")]
2945 (define_expand "xordi3"
2946 [(set (match_operand:DI 0 "s_register_operand" "")
2947 (xor:DI (match_operand:DI 1 "s_register_operand" "")
2948 (match_operand:DI 2 "s_register_operand" "")))]
2953 (define_insn "*xordi3_insn"
2954 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2955 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2956 (match_operand:DI 2 "s_register_operand" "r,r")))]
2957 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
2959 [(set_attr "length" "8")
2960 (set_attr "predicable" "yes")]
2963 (define_insn "*xordi_zesidi_di"
2964 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2965 (xor:DI (zero_extend:DI
2966 (match_operand:SI 2 "s_register_operand" "r,r"))
2967 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2970 eor%?\\t%Q0, %Q1, %2
2972 [(set_attr "length" "4,8")
2973 (set_attr "predicable" "yes")]
2976 (define_insn "*xordi_sesidi_di"
2977 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2978 (xor:DI (sign_extend:DI
2979 (match_operand:SI 2 "s_register_operand" "r,r"))
2980 (match_operand:DI 1 "s_register_operand" "0,r")))]
2983 [(set_attr "length" "8")
2984 (set_attr "predicable" "yes")]
2987 (define_expand "xorsi3"
2988 [(set (match_operand:SI 0 "s_register_operand" "")
2989 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2990 (match_operand:SI 2 "reg_or_int_operand" "")))]
2992 "if (GET_CODE (operands[2]) == CONST_INT)
2996 arm_split_constant (XOR, SImode, NULL_RTX,
2997 INTVAL (operands[2]), operands[0], operands[1],
2998 optimize && can_create_pseudo_p ());
3001 else /* TARGET_THUMB1 */
3003 rtx tmp = force_reg (SImode, operands[2]);
3004 if (rtx_equal_p (operands[0], operands[1]))
3008 operands[2] = operands[1];
3015 (define_insn "*arm_xorsi3"
3016 [(set (match_operand:SI 0 "s_register_operand" "=r")
3017 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
3018 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
3020 "eor%?\\t%0, %1, %2"
3021 [(set_attr "predicable" "yes")]
3024 (define_insn "*thumb1_xorsi3_insn"
3025 [(set (match_operand:SI 0 "register_operand" "=l")
3026 (xor:SI (match_operand:SI 1 "register_operand" "%0")
3027 (match_operand:SI 2 "register_operand" "l")))]
3030 [(set_attr "length" "2")
3031 (set_attr "conds" "set")])
3033 (define_insn "*xorsi3_compare0"
3034 [(set (reg:CC_NOOV CC_REGNUM)
3035 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
3036 (match_operand:SI 2 "arm_rhs_operand" "rI"))
3038 (set (match_operand:SI 0 "s_register_operand" "=r")
3039 (xor:SI (match_dup 1) (match_dup 2)))]
3041 "eor%.\\t%0, %1, %2"
3042 [(set_attr "conds" "set")]
3045 (define_insn "*xorsi3_compare0_scratch"
3046 [(set (reg:CC_NOOV CC_REGNUM)
3047 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
3048 (match_operand:SI 1 "arm_rhs_operand" "rI"))
3052 [(set_attr "conds" "set")]
3055 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3056 ; (NOT D) we can sometimes merge the final NOT into one of the following
3060 [(set (match_operand:SI 0 "s_register_operand" "")
3061 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3062 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3063 (match_operand:SI 3 "arm_rhs_operand" "")))
3064 (clobber (match_operand:SI 4 "s_register_operand" ""))]
3066 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3067 (not:SI (match_dup 3))))
3068 (set (match_dup 0) (not:SI (match_dup 4)))]
3072 (define_insn "*andsi_iorsi3_notsi"
3073 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
3074 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
3075 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3076 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
3078 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3079 [(set_attr "length" "8")
3080 (set_attr "ce_count" "2")
3081 (set_attr "predicable" "yes")]
3084 ; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3085 ; insns are available?
3087 [(set (match_operand:SI 0 "s_register_operand" "")
3088 (match_operator:SI 1 "logical_binary_operator"
3089 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3090 (match_operand:SI 3 "const_int_operand" "")
3091 (match_operand:SI 4 "const_int_operand" ""))
3092 (match_operator:SI 9 "logical_binary_operator"
3093 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3094 (match_operand:SI 6 "const_int_operand" ""))
3095 (match_operand:SI 7 "s_register_operand" "")])]))
3096 (clobber (match_operand:SI 8 "s_register_operand" ""))]
3098 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3099 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3102 [(ashift:SI (match_dup 2) (match_dup 4))
3106 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3109 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3113 [(set (match_operand:SI 0 "s_register_operand" "")
3114 (match_operator:SI 1 "logical_binary_operator"
3115 [(match_operator:SI 9 "logical_binary_operator"
3116 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3117 (match_operand:SI 6 "const_int_operand" ""))
3118 (match_operand:SI 7 "s_register_operand" "")])
3119 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3120 (match_operand:SI 3 "const_int_operand" "")
3121 (match_operand:SI 4 "const_int_operand" ""))]))
3122 (clobber (match_operand:SI 8 "s_register_operand" ""))]
3124 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3125 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3128 [(ashift:SI (match_dup 2) (match_dup 4))
3132 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3135 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3139 [(set (match_operand:SI 0 "s_register_operand" "")
3140 (match_operator:SI 1 "logical_binary_operator"
3141 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3142 (match_operand:SI 3 "const_int_operand" "")
3143 (match_operand:SI 4 "const_int_operand" ""))
3144 (match_operator:SI 9 "logical_binary_operator"
3145 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3146 (match_operand:SI 6 "const_int_operand" ""))
3147 (match_operand:SI 7 "s_register_operand" "")])]))
3148 (clobber (match_operand:SI 8 "s_register_operand" ""))]
3150 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3151 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3154 [(ashift:SI (match_dup 2) (match_dup 4))
3158 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3161 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3165 [(set (match_operand:SI 0 "s_register_operand" "")
3166 (match_operator:SI 1 "logical_binary_operator"
3167 [(match_operator:SI 9 "logical_binary_operator"
3168 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3169 (match_operand:SI 6 "const_int_operand" ""))
3170 (match_operand:SI 7 "s_register_operand" "")])
3171 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3172 (match_operand:SI 3 "const_int_operand" "")
3173 (match_operand:SI 4 "const_int_operand" ""))]))
3174 (clobber (match_operand:SI 8 "s_register_operand" ""))]
3176 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3177 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3180 [(ashift:SI (match_dup 2) (match_dup 4))
3184 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3187 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3191 ;; Minimum and maximum insns
3193 (define_expand "smaxsi3"
3195 (set (match_operand:SI 0 "s_register_operand" "")
3196 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3197 (match_operand:SI 2 "arm_rhs_operand" "")))
3198 (clobber (reg:CC CC_REGNUM))])]
3201 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
3203 /* No need for a clobber of the condition code register here. */
3204 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3205 gen_rtx_SMAX (SImode, operands[1],
3211 (define_insn "*smax_0"
3212 [(set (match_operand:SI 0 "s_register_operand" "=r")
3213 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3216 "bic%?\\t%0, %1, %1, asr #31"
3217 [(set_attr "predicable" "yes")]
3220 (define_insn "*smax_m1"
3221 [(set (match_operand:SI 0 "s_register_operand" "=r")
3222 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3225 "orr%?\\t%0, %1, %1, asr #31"
3226 [(set_attr "predicable" "yes")]
3229 (define_insn "*arm_smax_insn"
3230 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3231 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3232 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
3233 (clobber (reg:CC CC_REGNUM))]
3236 cmp\\t%1, %2\;movlt\\t%0, %2
3237 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3238 [(set_attr "conds" "clob")
3239 (set_attr "length" "8,12")]
3242 (define_expand "sminsi3"
3244 (set (match_operand:SI 0 "s_register_operand" "")
3245 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3246 (match_operand:SI 2 "arm_rhs_operand" "")))
3247 (clobber (reg:CC CC_REGNUM))])]
3250 if (operands[2] == const0_rtx)
3252 /* No need for a clobber of the condition code register here. */
3253 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3254 gen_rtx_SMIN (SImode, operands[1],
3260 (define_insn "*smin_0"
3261 [(set (match_operand:SI 0 "s_register_operand" "=r")
3262 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3265 "and%?\\t%0, %1, %1, asr #31"
3266 [(set_attr "predicable" "yes")]
3269 (define_insn "*arm_smin_insn"
3270 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3271 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3272 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
3273 (clobber (reg:CC CC_REGNUM))]
3276 cmp\\t%1, %2\;movge\\t%0, %2
3277 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3278 [(set_attr "conds" "clob")
3279 (set_attr "length" "8,12")]
3282 (define_expand "umaxsi3"
3284 (set (match_operand:SI 0 "s_register_operand" "")
3285 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3286 (match_operand:SI 2 "arm_rhs_operand" "")))
3287 (clobber (reg:CC CC_REGNUM))])]
3292 (define_insn "*arm_umaxsi3"
3293 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3294 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3295 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3296 (clobber (reg:CC CC_REGNUM))]
3299 cmp\\t%1, %2\;movcc\\t%0, %2
3300 cmp\\t%1, %2\;movcs\\t%0, %1
3301 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3302 [(set_attr "conds" "clob")
3303 (set_attr "length" "8,8,12")]
3306 (define_expand "uminsi3"
3308 (set (match_operand:SI 0 "s_register_operand" "")
3309 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3310 (match_operand:SI 2 "arm_rhs_operand" "")))
3311 (clobber (reg:CC CC_REGNUM))])]
3316 (define_insn "*arm_uminsi3"
3317 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3318 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3319 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3320 (clobber (reg:CC CC_REGNUM))]
3323 cmp\\t%1, %2\;movcs\\t%0, %2
3324 cmp\\t%1, %2\;movcc\\t%0, %1
3325 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3326 [(set_attr "conds" "clob")
3327 (set_attr "length" "8,8,12")]
3330 (define_insn "*store_minmaxsi"
3331 [(set (match_operand:SI 0 "memory_operand" "=m")
3332 (match_operator:SI 3 "minmax_operator"
3333 [(match_operand:SI 1 "s_register_operand" "r")
3334 (match_operand:SI 2 "s_register_operand" "r")]))
3335 (clobber (reg:CC CC_REGNUM))]
3338 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3339 operands[1], operands[2]);
3340 output_asm_insn (\"cmp\\t%1, %2\", operands);
3342 output_asm_insn (\"ite\t%d3\", operands);
3343 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3344 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3347 [(set_attr "conds" "clob")
3348 (set (attr "length")
3349 (if_then_else (eq_attr "is_thumb" "yes")
3352 (set_attr "type" "store1")]
3355 ; Reject the frame pointer in operand[1], since reloading this after
3356 ; it has been eliminated can cause carnage.
3357 (define_insn "*minmax_arithsi"
3358 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3359 (match_operator:SI 4 "shiftable_operator"
3360 [(match_operator:SI 5 "minmax_operator"
3361 [(match_operand:SI 2 "s_register_operand" "r,r")
3362 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3363 (match_operand:SI 1 "s_register_operand" "0,?r")]))
3364 (clobber (reg:CC CC_REGNUM))]
3365 "TARGET_32BIT && !arm_eliminable_register (operands[1])"
3368 enum rtx_code code = GET_CODE (operands[4]);
3371 if (which_alternative != 0 || operands[3] != const0_rtx
3372 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
3377 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3378 operands[2], operands[3]);
3379 output_asm_insn (\"cmp\\t%2, %3\", operands);
3383 output_asm_insn (\"ite\\t%d5\", operands);
3385 output_asm_insn (\"it\\t%d5\", operands);
3387 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
3389 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3392 [(set_attr "conds" "clob")
3393 (set (attr "length")
3394 (if_then_else (eq_attr "is_thumb" "yes")
3400 ;; Shift and rotation insns
3402 (define_expand "ashldi3"
3403 [(set (match_operand:DI 0 "s_register_operand" "")
3404 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
3405 (match_operand:SI 2 "reg_or_int_operand" "")))]
3408 if (GET_CODE (operands[2]) == CONST_INT)
3410 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3412 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3415 /* Ideally we shouldn't fail here if we could know that operands[1]
3416 ends up already living in an iwmmxt register. Otherwise it's
3417 cheaper to have the alternate code being generated than moving
3418 values to iwmmxt regs and back. */
3421 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
3426 (define_insn "arm_ashldi3_1bit"
3427 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
3428 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
3430 (clobber (reg:CC CC_REGNUM))]
3432 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3433 [(set_attr "conds" "clob")
3434 (set_attr "length" "8")]
3437 (define_expand "ashlsi3"
3438 [(set (match_operand:SI 0 "s_register_operand" "")
3439 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3440 (match_operand:SI 2 "arm_rhs_operand" "")))]
3443 if (GET_CODE (operands[2]) == CONST_INT
3444 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3446 emit_insn (gen_movsi (operands[0], const0_rtx));
3452 (define_insn "*thumb1_ashlsi3"
3453 [(set (match_operand:SI 0 "register_operand" "=l,l")
3454 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3455 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3458 [(set_attr "length" "2")
3459 (set_attr "conds" "set")])
3461 (define_expand "ashrdi3"
3462 [(set (match_operand:DI 0 "s_register_operand" "")
3463 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3464 (match_operand:SI 2 "reg_or_int_operand" "")))]
3467 if (GET_CODE (operands[2]) == CONST_INT)
3469 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3471 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3474 /* Ideally we shouldn't fail here if we could know that operands[1]
3475 ends up already living in an iwmmxt register. Otherwise it's
3476 cheaper to have the alternate code being generated than moving
3477 values to iwmmxt regs and back. */
3480 else if (!TARGET_REALLY_IWMMXT)
3485 (define_insn "arm_ashrdi3_1bit"
3486 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
3487 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
3489 (clobber (reg:CC CC_REGNUM))]
3491 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3492 [(set_attr "conds" "clob")
3493 (set_attr "insn" "mov")
3494 (set_attr "length" "8")]
3497 (define_expand "ashrsi3"
3498 [(set (match_operand:SI 0 "s_register_operand" "")
3499 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3500 (match_operand:SI 2 "arm_rhs_operand" "")))]
3503 if (GET_CODE (operands[2]) == CONST_INT
3504 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3505 operands[2] = GEN_INT (31);
3509 (define_insn "*thumb1_ashrsi3"
3510 [(set (match_operand:SI 0 "register_operand" "=l,l")
3511 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3512 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3515 [(set_attr "length" "2")
3516 (set_attr "conds" "set")])
3518 (define_expand "lshrdi3"
3519 [(set (match_operand:DI 0 "s_register_operand" "")
3520 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3521 (match_operand:SI 2 "reg_or_int_operand" "")))]
3524 if (GET_CODE (operands[2]) == CONST_INT)
3526 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3528 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3531 /* Ideally we shouldn't fail here if we could know that operands[1]
3532 ends up already living in an iwmmxt register. Otherwise it's
3533 cheaper to have the alternate code being generated than moving
3534 values to iwmmxt regs and back. */
3537 else if (!TARGET_REALLY_IWMMXT)
3542 (define_insn "arm_lshrdi3_1bit"
3543 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
3544 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
3546 (clobber (reg:CC CC_REGNUM))]
3548 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3549 [(set_attr "conds" "clob")
3550 (set_attr "insn" "mov")
3551 (set_attr "length" "8")]
3554 (define_expand "lshrsi3"
3555 [(set (match_operand:SI 0 "s_register_operand" "")
3556 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3557 (match_operand:SI 2 "arm_rhs_operand" "")))]
3560 if (GET_CODE (operands[2]) == CONST_INT
3561 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3563 emit_insn (gen_movsi (operands[0], const0_rtx));
3569 (define_insn "*thumb1_lshrsi3"
3570 [(set (match_operand:SI 0 "register_operand" "=l,l")
3571 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3572 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3575 [(set_attr "length" "2")
3576 (set_attr "conds" "set")])
3578 (define_expand "rotlsi3"
3579 [(set (match_operand:SI 0 "s_register_operand" "")
3580 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3581 (match_operand:SI 2 "reg_or_int_operand" "")))]
3584 if (GET_CODE (operands[2]) == CONST_INT)
3585 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3588 rtx reg = gen_reg_rtx (SImode);
3589 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3595 (define_expand "rotrsi3"
3596 [(set (match_operand:SI 0 "s_register_operand" "")
3597 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3598 (match_operand:SI 2 "arm_rhs_operand" "")))]
3603 if (GET_CODE (operands[2]) == CONST_INT
3604 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3605 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3607 else /* TARGET_THUMB1 */
3609 if (GET_CODE (operands [2]) == CONST_INT)
3610 operands [2] = force_reg (SImode, operands[2]);
3615 (define_insn "*thumb1_rotrsi3"
3616 [(set (match_operand:SI 0 "register_operand" "=l")
3617 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3618 (match_operand:SI 2 "register_operand" "l")))]
3621 [(set_attr "length" "2")]
3624 (define_insn "*arm_shiftsi3"
3625 [(set (match_operand:SI 0 "s_register_operand" "=r")
3626 (match_operator:SI 3 "shift_operator"
3627 [(match_operand:SI 1 "s_register_operand" "r")
3628 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
3630 "* return arm_output_shift(operands, 0);"
3631 [(set_attr "predicable" "yes")
3632 (set_attr "shift" "1")
3633 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3634 (const_string "alu_shift")
3635 (const_string "alu_shift_reg")))]
3638 (define_insn "*shiftsi3_compare0"
3639 [(set (reg:CC_NOOV CC_REGNUM)
3640 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3641 [(match_operand:SI 1 "s_register_operand" "r")
3642 (match_operand:SI 2 "arm_rhs_operand" "rM")])
3644 (set (match_operand:SI 0 "s_register_operand" "=r")
3645 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
3647 "* return arm_output_shift(operands, 1);"
3648 [(set_attr "conds" "set")
3649 (set_attr "shift" "1")
3650 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3651 (const_string "alu_shift")
3652 (const_string "alu_shift_reg")))]
3655 (define_insn "*shiftsi3_compare0_scratch"
3656 [(set (reg:CC_NOOV CC_REGNUM)
3657 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3658 [(match_operand:SI 1 "s_register_operand" "r")
3659 (match_operand:SI 2 "arm_rhs_operand" "rM")])
3661 (clobber (match_scratch:SI 0 "=r"))]
3663 "* return arm_output_shift(operands, 1);"
3664 [(set_attr "conds" "set")
3665 (set_attr "shift" "1")]
3668 (define_insn "*not_shiftsi"
3669 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3670 (not:SI (match_operator:SI 3 "shift_operator"
3671 [(match_operand:SI 1 "s_register_operand" "r,r")
3672 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3675 [(set_attr "predicable" "yes")
3676 (set_attr "shift" "1")
3677 (set_attr "insn" "mvn")
3678 (set_attr "arch" "32,a")
3679 (set_attr "type" "alu_shift,alu_shift_reg")])
3681 (define_insn "*not_shiftsi_compare0"
3682 [(set (reg:CC_NOOV CC_REGNUM)
3684 (not:SI (match_operator:SI 3 "shift_operator"
3685 [(match_operand:SI 1 "s_register_operand" "r,r")
3686 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3688 (set (match_operand:SI 0 "s_register_operand" "=r,r")
3689 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
3692 [(set_attr "conds" "set")
3693 (set_attr "shift" "1")
3694 (set_attr "insn" "mvn")
3695 (set_attr "arch" "32,a")
3696 (set_attr "type" "alu_shift,alu_shift_reg")])
3698 (define_insn "*not_shiftsi_compare0_scratch"
3699 [(set (reg:CC_NOOV CC_REGNUM)
3701 (not:SI (match_operator:SI 3 "shift_operator"
3702 [(match_operand:SI 1 "s_register_operand" "r,r")
3703 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3705 (clobber (match_scratch:SI 0 "=r,r"))]
3708 [(set_attr "conds" "set")
3709 (set_attr "shift" "1")
3710 (set_attr "insn" "mvn")
3711 (set_attr "arch" "32,a")
3712 (set_attr "type" "alu_shift,alu_shift_reg")])
3714 ;; We don't really have extzv, but defining this using shifts helps
3715 ;; to reduce register pressure later on.
3717 (define_expand "extzv"
3719 (ashift:SI (match_operand:SI 1 "register_operand" "")
3720 (match_operand:SI 2 "const_int_operand" "")))
3721 (set (match_operand:SI 0 "register_operand" "")
3722 (lshiftrt:SI (match_dup 4)
3723 (match_operand:SI 3 "const_int_operand" "")))]
3724 "TARGET_THUMB1 || arm_arch_thumb2"
3727 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3728 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3730 if (arm_arch_thumb2)
3732 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3737 operands[3] = GEN_INT (rshift);
3741 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3745 operands[2] = GEN_INT (lshift);
3746 operands[4] = gen_reg_rtx (SImode);
3751 [(set (match_operand:SI 0 "s_register_operand" "=r")
3752 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3753 (match_operand:SI 2 "const_int_operand" "M")
3754 (match_operand:SI 3 "const_int_operand" "M")))]
3756 "sbfx%?\t%0, %1, %3, %2"
3757 [(set_attr "length" "4")
3758 (set_attr "predicable" "yes")]
3761 (define_insn "extzv_t2"
3762 [(set (match_operand:SI 0 "s_register_operand" "=r")
3763 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3764 (match_operand:SI 2 "const_int_operand" "M")
3765 (match_operand:SI 3 "const_int_operand" "M")))]
3767 "ubfx%?\t%0, %1, %3, %2"
3768 [(set_attr "length" "4")
3769 (set_attr "predicable" "yes")]
3773 ;; Division instructions
3774 (define_insn "divsi3"
3775 [(set (match_operand:SI 0 "s_register_operand" "=r")
3776 (div:SI (match_operand:SI 1 "s_register_operand" "r")
3777 (match_operand:SI 2 "s_register_operand" "r")))]
3779 "sdiv%?\t%0, %1, %2"
3780 [(set_attr "predicable" "yes")
3781 (set_attr "insn" "sdiv")]
3784 (define_insn "udivsi3"
3785 [(set (match_operand:SI 0 "s_register_operand" "=r")
3786 (udiv:SI (match_operand:SI 1 "s_register_operand" "r")
3787 (match_operand:SI 2 "s_register_operand" "r")))]
3789 "udiv%?\t%0, %1, %2"
3790 [(set_attr "predicable" "yes")
3791 (set_attr "insn" "udiv")]
3795 ;; Unary arithmetic insns
3797 (define_expand "negdi2"
3799 [(set (match_operand:DI 0 "s_register_operand" "")
3800 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
3801 (clobber (reg:CC CC_REGNUM))])]
3806 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
3807 ;; The first alternative allows the common case of a *full* overlap.
3808 (define_insn "*arm_negdi2"
3809 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
3810 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
3811 (clobber (reg:CC CC_REGNUM))]
3813 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
3814 [(set_attr "conds" "clob")
3815 (set_attr "length" "8")]
3818 (define_insn "*thumb1_negdi2"
3819 [(set (match_operand:DI 0 "register_operand" "=&l")
3820 (neg:DI (match_operand:DI 1 "register_operand" "l")))
3821 (clobber (reg:CC CC_REGNUM))]
3823 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3824 [(set_attr "length" "6")]
3827 (define_expand "negsi2"
3828 [(set (match_operand:SI 0 "s_register_operand" "")
3829 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3834 (define_insn "*arm_negsi2"
3835 [(set (match_operand:SI 0 "s_register_operand" "=r")
3836 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
3838 "rsb%?\\t%0, %1, #0"
3839 [(set_attr "predicable" "yes")]
3842 (define_insn "*thumb1_negsi2"
3843 [(set (match_operand:SI 0 "register_operand" "=l")
3844 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
3847 [(set_attr "length" "2")]
3850 (define_expand "negsf2"
3851 [(set (match_operand:SF 0 "s_register_operand" "")
3852 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
3853 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3857 (define_expand "negdf2"
3858 [(set (match_operand:DF 0 "s_register_operand" "")
3859 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
3860 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
3863 ;; abssi2 doesn't really clobber the condition codes if a different register
3864 ;; is being set. To keep things simple, assume during rtl manipulations that
3865 ;; it does, but tell the final scan operator the truth. Similarly for
3868 (define_expand "abssi2"
3870 [(set (match_operand:SI 0 "s_register_operand" "")
3871 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3872 (clobber (match_dup 2))])]
3876 operands[2] = gen_rtx_SCRATCH (SImode);
3878 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3881 (define_insn "*arm_abssi2"
3882 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3883 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3884 (clobber (reg:CC CC_REGNUM))]
3887 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3888 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3889 [(set_attr "conds" "clob,*")
3890 (set_attr "shift" "1")
3891 ;; predicable can't be set based on the variant, so left as no
3892 (set_attr "length" "8")]
3895 (define_insn_and_split "*thumb1_abssi2"
3896 [(set (match_operand:SI 0 "s_register_operand" "=l")
3897 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3898 (clobber (match_scratch:SI 2 "=&l"))]
3901 "TARGET_THUMB1 && reload_completed"
3902 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3903 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3904 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3906 [(set_attr "length" "6")]
3909 (define_insn "*arm_neg_abssi2"
3910 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3911 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3912 (clobber (reg:CC CC_REGNUM))]
3915 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3916 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3917 [(set_attr "conds" "clob,*")
3918 (set_attr "shift" "1")
3919 ;; predicable can't be set based on the variant, so left as no
3920 (set_attr "length" "8")]
3923 (define_insn_and_split "*thumb1_neg_abssi2"
3924 [(set (match_operand:SI 0 "s_register_operand" "=l")
3925 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3926 (clobber (match_scratch:SI 2 "=&l"))]
3929 "TARGET_THUMB1 && reload_completed"
3930 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3931 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3932 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3934 [(set_attr "length" "6")]
3937 (define_expand "abssf2"
3938 [(set (match_operand:SF 0 "s_register_operand" "")
3939 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3940 "TARGET_32BIT && TARGET_HARD_FLOAT"
3943 (define_expand "absdf2"
3944 [(set (match_operand:DF 0 "s_register_operand" "")
3945 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3946 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
3949 (define_expand "sqrtsf2"
3950 [(set (match_operand:SF 0 "s_register_operand" "")
3951 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3952 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3955 (define_expand "sqrtdf2"
3956 [(set (match_operand:DF 0 "s_register_operand" "")
3957 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3958 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
3961 (define_insn_and_split "one_cmpldi2"
3962 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3963 (not:DI (match_operand:DI 1 "s_register_operand" "0,r")))]
3966 "TARGET_32BIT && reload_completed"
3967 [(set (match_dup 0) (not:SI (match_dup 1)))
3968 (set (match_dup 2) (not:SI (match_dup 3)))]
3971 operands[2] = gen_highpart (SImode, operands[0]);
3972 operands[0] = gen_lowpart (SImode, operands[0]);
3973 operands[3] = gen_highpart (SImode, operands[1]);
3974 operands[1] = gen_lowpart (SImode, operands[1]);
3976 [(set_attr "length" "8")
3977 (set_attr "predicable" "yes")]
3980 (define_expand "one_cmplsi2"
3981 [(set (match_operand:SI 0 "s_register_operand" "")
3982 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3987 (define_insn "*arm_one_cmplsi2"
3988 [(set (match_operand:SI 0 "s_register_operand" "=r")
3989 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
3992 [(set_attr "predicable" "yes")
3993 (set_attr "insn" "mvn")]
3996 (define_insn "*thumb1_one_cmplsi2"
3997 [(set (match_operand:SI 0 "register_operand" "=l")
3998 (not:SI (match_operand:SI 1 "register_operand" "l")))]
4001 [(set_attr "length" "2")
4002 (set_attr "insn" "mvn")]
4005 (define_insn "*notsi_compare0"
4006 [(set (reg:CC_NOOV CC_REGNUM)
4007 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4009 (set (match_operand:SI 0 "s_register_operand" "=r")
4010 (not:SI (match_dup 1)))]
4013 [(set_attr "conds" "set")
4014 (set_attr "insn" "mvn")]
4017 (define_insn "*notsi_compare0_scratch"
4018 [(set (reg:CC_NOOV CC_REGNUM)
4019 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4021 (clobber (match_scratch:SI 0 "=r"))]
4024 [(set_attr "conds" "set")
4025 (set_attr "insn" "mvn")]
4028 ;; Fixed <--> Floating conversion insns
4030 (define_expand "floatsihf2"
4031 [(set (match_operand:HF 0 "general_operand" "")
4032 (float:HF (match_operand:SI 1 "general_operand" "")))]
4036 rtx op1 = gen_reg_rtx (SFmode);
4037 expand_float (op1, operands[1], 0);
4038 op1 = convert_to_mode (HFmode, op1, 0);
4039 emit_move_insn (operands[0], op1);
4044 (define_expand "floatdihf2"
4045 [(set (match_operand:HF 0 "general_operand" "")
4046 (float:HF (match_operand:DI 1 "general_operand" "")))]
4050 rtx op1 = gen_reg_rtx (SFmode);
4051 expand_float (op1, operands[1], 0);
4052 op1 = convert_to_mode (HFmode, op1, 0);
4053 emit_move_insn (operands[0], op1);
4058 (define_expand "floatsisf2"
4059 [(set (match_operand:SF 0 "s_register_operand" "")
4060 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
4061 "TARGET_32BIT && TARGET_HARD_FLOAT"
4063 if (TARGET_MAVERICK)
4065 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
4070 (define_expand "floatsidf2"
4071 [(set (match_operand:DF 0 "s_register_operand" "")
4072 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
4073 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4075 if (TARGET_MAVERICK)
4077 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
4082 (define_expand "fix_trunchfsi2"
4083 [(set (match_operand:SI 0 "general_operand" "")
4084 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4088 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4089 expand_fix (operands[0], op1, 0);
4094 (define_expand "fix_trunchfdi2"
4095 [(set (match_operand:DI 0 "general_operand" "")
4096 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4100 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4101 expand_fix (operands[0], op1, 0);
4106 (define_expand "fix_truncsfsi2"
4107 [(set (match_operand:SI 0 "s_register_operand" "")
4108 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
4109 "TARGET_32BIT && TARGET_HARD_FLOAT"
4111 if (TARGET_MAVERICK)
4113 if (!cirrus_fp_register (operands[0], SImode))
4114 operands[0] = force_reg (SImode, operands[0]);
4115 if (!cirrus_fp_register (operands[1], SFmode))
4116 operands[1] = force_reg (SFmode, operands[0]);
4117 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
4122 (define_expand "fix_truncdfsi2"
4123 [(set (match_operand:SI 0 "s_register_operand" "")
4124 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
4125 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4127 if (TARGET_MAVERICK)
4129 if (!cirrus_fp_register (operands[1], DFmode))
4130 operands[1] = force_reg (DFmode, operands[0]);
4131 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
4138 (define_expand "truncdfsf2"
4139 [(set (match_operand:SF 0 "s_register_operand" "")
4141 (match_operand:DF 1 "s_register_operand" "")))]
4142 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4146 /* DFmode -> HFmode conversions have to go through SFmode. */
4147 (define_expand "truncdfhf2"
4148 [(set (match_operand:HF 0 "general_operand" "")
4150 (match_operand:DF 1 "general_operand" "")))]
4155 op1 = convert_to_mode (SFmode, operands[1], 0);
4156 op1 = convert_to_mode (HFmode, op1, 0);
4157 emit_move_insn (operands[0], op1);
4162 ;; Zero and sign extension instructions.
4164 (define_insn "zero_extend<mode>di2"
4165 [(set (match_operand:DI 0 "s_register_operand" "=r")
4166 (zero_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4167 "<qhs_extenddi_cstr>")))]
4168 "TARGET_32BIT <qhs_zextenddi_cond>"
4170 [(set_attr "length" "8")
4171 (set_attr "ce_count" "2")
4172 (set_attr "predicable" "yes")]
4175 (define_insn "extend<mode>di2"
4176 [(set (match_operand:DI 0 "s_register_operand" "=r")
4177 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4178 "<qhs_extenddi_cstr>")))]
4179 "TARGET_32BIT <qhs_sextenddi_cond>"
4181 [(set_attr "length" "8")
4182 (set_attr "ce_count" "2")
4183 (set_attr "shift" "1")
4184 (set_attr "predicable" "yes")]
4187 ;; Splits for all extensions to DImode
4189 [(set (match_operand:DI 0 "s_register_operand" "")
4190 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
4192 [(set (match_dup 0) (match_dup 1))]
4194 rtx lo_part = gen_lowpart (SImode, operands[0]);
4195 enum machine_mode src_mode = GET_MODE (operands[1]);
4197 if (REG_P (operands[0])
4198 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4199 emit_clobber (operands[0]);
4200 if (!REG_P (lo_part) || src_mode != SImode
4201 || !rtx_equal_p (lo_part, operands[1]))
4203 if (src_mode == SImode)
4204 emit_move_insn (lo_part, operands[1]);
4206 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4207 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4208 operands[1] = lo_part;
4210 operands[0] = gen_highpart (SImode, operands[0]);
4211 operands[1] = const0_rtx;
4215 [(set (match_operand:DI 0 "s_register_operand" "")
4216 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
4218 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4220 rtx lo_part = gen_lowpart (SImode, operands[0]);
4221 enum machine_mode src_mode = GET_MODE (operands[1]);
4223 if (REG_P (operands[0])
4224 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4225 emit_clobber (operands[0]);
4227 if (!REG_P (lo_part) || src_mode != SImode
4228 || !rtx_equal_p (lo_part, operands[1]))
4230 if (src_mode == SImode)
4231 emit_move_insn (lo_part, operands[1]);
4233 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4234 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4235 operands[1] = lo_part;
4237 operands[0] = gen_highpart (SImode, operands[0]);
4240 (define_expand "zero_extendhisi2"
4241 [(set (match_operand:SI 0 "s_register_operand" "")
4242 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
4245 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
4247 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4250 if (!arm_arch6 && !MEM_P (operands[1]))
4252 rtx t = gen_lowpart (SImode, operands[1]);
4253 rtx tmp = gen_reg_rtx (SImode);
4254 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4255 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4261 [(set (match_operand:SI 0 "s_register_operand" "")
4262 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
4263 "!TARGET_THUMB2 && !arm_arch6"
4264 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4265 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4267 operands[2] = gen_lowpart (SImode, operands[1]);
4270 (define_insn "*thumb1_zero_extendhisi2"
4271 [(set (match_operand:SI 0 "register_operand" "=l,l")
4272 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
4277 if (which_alternative == 0 && arm_arch6)
4278 return "uxth\t%0, %1";
4279 if (which_alternative == 0)
4282 mem = XEXP (operands[1], 0);
4284 if (GET_CODE (mem) == CONST)
4285 mem = XEXP (mem, 0);
4287 if (GET_CODE (mem) == PLUS)
4289 rtx a = XEXP (mem, 0);
4291 /* This can happen due to bugs in reload. */
4292 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4295 ops[0] = operands[0];
4298 output_asm_insn ("mov\t%0, %1", ops);
4300 XEXP (mem, 0) = operands[0];
4304 return "ldrh\t%0, %1";
4306 [(set_attr_alternative "length"
4307 [(if_then_else (eq_attr "is_arch6" "yes")
4308 (const_int 2) (const_int 4))
4310 (set_attr "type" "alu_shift,load_byte")]
4313 (define_insn "*arm_zero_extendhisi2"
4314 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4315 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4316 "TARGET_ARM && arm_arch4 && !arm_arch6"
4320 [(set_attr "type" "alu_shift,load_byte")
4321 (set_attr "predicable" "yes")]
4324 (define_insn "*arm_zero_extendhisi2_v6"
4325 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4326 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4327 "TARGET_ARM && arm_arch6"
4331 [(set_attr "type" "alu_shift,load_byte")
4332 (set_attr "predicable" "yes")]
4335 (define_insn "*arm_zero_extendhisi2addsi"
4336 [(set (match_operand:SI 0 "s_register_operand" "=r")
4337 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4338 (match_operand:SI 2 "s_register_operand" "r")))]
4340 "uxtah%?\\t%0, %2, %1"
4341 [(set_attr "type" "alu_shift")
4342 (set_attr "predicable" "yes")]
4345 (define_expand "zero_extendqisi2"
4346 [(set (match_operand:SI 0 "s_register_operand" "")
4347 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4350 if (TARGET_ARM && !arm_arch6 && GET_CODE (operands[1]) != MEM)
4352 emit_insn (gen_andsi3 (operands[0],
4353 gen_lowpart (SImode, operands[1]),
4357 if (!arm_arch6 && !MEM_P (operands[1]))
4359 rtx t = gen_lowpart (SImode, operands[1]);
4360 rtx tmp = gen_reg_rtx (SImode);
4361 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4362 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
4368 [(set (match_operand:SI 0 "s_register_operand" "")
4369 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
4371 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4372 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
4374 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4377 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
4382 (define_insn "*thumb1_zero_extendqisi2"
4383 [(set (match_operand:SI 0 "register_operand" "=l,l")
4384 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
4385 "TARGET_THUMB1 && !arm_arch6"
4389 [(set_attr "length" "4,2")
4390 (set_attr "type" "alu_shift,load_byte")
4391 (set_attr "pool_range" "*,32")]
4394 (define_insn "*thumb1_zero_extendqisi2_v6"
4395 [(set (match_operand:SI 0 "register_operand" "=l,l")
4396 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
4397 "TARGET_THUMB1 && arm_arch6"
4401 [(set_attr "length" "2")
4402 (set_attr "type" "alu_shift,load_byte")]
4405 (define_insn "*arm_zero_extendqisi2"
4406 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4407 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4408 "TARGET_ARM && !arm_arch6"
4411 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4412 [(set_attr "length" "8,4")
4413 (set_attr "type" "alu_shift,load_byte")
4414 (set_attr "predicable" "yes")]
4417 (define_insn "*arm_zero_extendqisi2_v6"
4418 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4419 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4420 "TARGET_ARM && arm_arch6"
4423 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4424 [(set_attr "type" "alu_shift,load_byte")
4425 (set_attr "predicable" "yes")]
4428 (define_insn "*arm_zero_extendqisi2addsi"
4429 [(set (match_operand:SI 0 "s_register_operand" "=r")
4430 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4431 (match_operand:SI 2 "s_register_operand" "r")))]
4433 "uxtab%?\\t%0, %2, %1"
4434 [(set_attr "predicable" "yes")
4435 (set_attr "insn" "xtab")
4436 (set_attr "type" "alu_shift")]
4440 [(set (match_operand:SI 0 "s_register_operand" "")
4441 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4442 (clobber (match_operand:SI 2 "s_register_operand" ""))]
4443 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
4444 [(set (match_dup 2) (match_dup 1))
4445 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4450 [(set (match_operand:SI 0 "s_register_operand" "")
4451 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4452 (clobber (match_operand:SI 2 "s_register_operand" ""))]
4453 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
4454 [(set (match_dup 2) (match_dup 1))
4455 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4461 [(set (match_operand:SI 0 "s_register_operand" "")
4462 (ior_xor:SI (and:SI (ashift:SI
4463 (match_operand:SI 1 "s_register_operand" "")
4464 (match_operand:SI 2 "const_int_operand" ""))
4465 (match_operand:SI 3 "const_int_operand" ""))
4467 (match_operator 5 "subreg_lowpart_operator"
4468 [(match_operand:SI 4 "s_register_operand" "")]))))]
4470 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
4471 == (GET_MODE_MASK (GET_MODE (operands[5]))
4472 & (GET_MODE_MASK (GET_MODE (operands[5]))
4473 << (INTVAL (operands[2])))))"
4474 [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
4476 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4477 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4480 (define_insn "*compareqi_eq0"
4481 [(set (reg:CC_Z CC_REGNUM)
4482 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
4486 [(set_attr "conds" "set")]
4489 (define_expand "extendhisi2"
4490 [(set (match_operand:SI 0 "s_register_operand" "")
4491 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
4496 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4499 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
4501 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4505 if (!arm_arch6 && !MEM_P (operands[1]))
4507 rtx t = gen_lowpart (SImode, operands[1]);
4508 rtx tmp = gen_reg_rtx (SImode);
4509 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4510 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
4517 [(set (match_operand:SI 0 "register_operand" "")
4518 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
4519 (clobber (match_scratch:SI 2 ""))])]
4521 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4522 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4524 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4527 ;; We used to have an early-clobber on the scratch register here.
4528 ;; However, there's a bug somewhere in reload which means that this
4529 ;; can be partially ignored during spill allocation if the memory
4530 ;; address also needs reloading; this causes us to die later on when
4531 ;; we try to verify the operands. Fortunately, we don't really need
4532 ;; the early-clobber: we can always use operand 0 if operand 2
4533 ;; overlaps the address.
4534 (define_insn "thumb1_extendhisi2"
4535 [(set (match_operand:SI 0 "register_operand" "=l,l")
4536 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4537 (clobber (match_scratch:SI 2 "=X,l"))]
4544 if (which_alternative == 0 && !arm_arch6)
4546 if (which_alternative == 0)
4547 return \"sxth\\t%0, %1\";
4549 mem = XEXP (operands[1], 0);
4551 /* This code used to try to use 'V', and fix the address only if it was
4552 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4553 range of QImode offsets, and offsettable_address_p does a QImode
4556 if (GET_CODE (mem) == CONST)
4557 mem = XEXP (mem, 0);
4559 if (GET_CODE (mem) == LABEL_REF)
4560 return \"ldr\\t%0, %1\";
4562 if (GET_CODE (mem) == PLUS)
4564 rtx a = XEXP (mem, 0);
4565 rtx b = XEXP (mem, 1);
4567 if (GET_CODE (a) == LABEL_REF
4568 && GET_CODE (b) == CONST_INT)
4569 return \"ldr\\t%0, %1\";
4571 if (GET_CODE (b) == REG)
4572 return \"ldrsh\\t%0, %1\";
4580 ops[2] = const0_rtx;
4583 gcc_assert (GET_CODE (ops[1]) == REG);
4585 ops[0] = operands[0];
4586 if (reg_mentioned_p (operands[2], ops[1]))
4589 ops[3] = operands[2];
4590 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4593 [(set_attr_alternative "length"
4594 [(if_then_else (eq_attr "is_arch6" "yes")
4595 (const_int 2) (const_int 4))
4597 (set_attr "type" "alu_shift,load_byte")
4598 (set_attr "pool_range" "*,1020")]
4601 ;; This pattern will only be used when ldsh is not available
4602 (define_expand "extendhisi2_mem"
4603 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4605 (zero_extend:SI (match_dup 7)))
4606 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4607 (set (match_operand:SI 0 "" "")
4608 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
4613 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4615 mem1 = change_address (operands[1], QImode, addr);
4616 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
4617 operands[0] = gen_lowpart (SImode, operands[0]);
4619 operands[2] = gen_reg_rtx (SImode);
4620 operands[3] = gen_reg_rtx (SImode);
4621 operands[6] = gen_reg_rtx (SImode);
4624 if (BYTES_BIG_ENDIAN)
4626 operands[4] = operands[2];
4627 operands[5] = operands[3];
4631 operands[4] = operands[3];
4632 operands[5] = operands[2];
4638 [(set (match_operand:SI 0 "register_operand" "")
4639 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
4641 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4642 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4644 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4647 (define_insn "*arm_extendhisi2"
4648 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4649 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4650 "TARGET_ARM && arm_arch4 && !arm_arch6"
4654 [(set_attr "length" "8,4")
4655 (set_attr "type" "alu_shift,load_byte")
4656 (set_attr "predicable" "yes")
4657 (set_attr "pool_range" "*,256")
4658 (set_attr "neg_pool_range" "*,244")]
4661 ;; ??? Check Thumb-2 pool range
4662 (define_insn "*arm_extendhisi2_v6"
4663 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4664 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4665 "TARGET_32BIT && arm_arch6"
4669 [(set_attr "type" "alu_shift,load_byte")
4670 (set_attr "predicable" "yes")
4671 (set_attr "pool_range" "*,256")
4672 (set_attr "neg_pool_range" "*,244")]
4675 (define_insn "*arm_extendhisi2addsi"
4676 [(set (match_operand:SI 0 "s_register_operand" "=r")
4677 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4678 (match_operand:SI 2 "s_register_operand" "r")))]
4680 "sxtah%?\\t%0, %2, %1"
4683 (define_expand "extendqihi2"
4685 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
4687 (set (match_operand:HI 0 "s_register_operand" "")
4688 (ashiftrt:SI (match_dup 2)
4693 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4695 emit_insn (gen_rtx_SET (VOIDmode,
4697 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4700 if (!s_register_operand (operands[1], QImode))
4701 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4702 operands[0] = gen_lowpart (SImode, operands[0]);
4703 operands[1] = gen_lowpart (SImode, operands[1]);
4704 operands[2] = gen_reg_rtx (SImode);
4708 (define_insn "*arm_extendqihi_insn"
4709 [(set (match_operand:HI 0 "s_register_operand" "=r")
4710 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
4711 "TARGET_ARM && arm_arch4"
4712 "ldr%(sb%)\\t%0, %1"
4713 [(set_attr "type" "load_byte")
4714 (set_attr "predicable" "yes")
4715 (set_attr "pool_range" "256")
4716 (set_attr "neg_pool_range" "244")]
4719 (define_expand "extendqisi2"
4720 [(set (match_operand:SI 0 "s_register_operand" "")
4721 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
4724 if (!arm_arch4 && MEM_P (operands[1]))
4725 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4727 if (!arm_arch6 && !MEM_P (operands[1]))
4729 rtx t = gen_lowpart (SImode, operands[1]);
4730 rtx tmp = gen_reg_rtx (SImode);
4731 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4732 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
4738 [(set (match_operand:SI 0 "register_operand" "")
4739 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
4741 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4742 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
4744 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4747 (define_insn "*arm_extendqisi"
4748 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4749 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
4750 "TARGET_ARM && arm_arch4 && !arm_arch6"
4754 [(set_attr "length" "8,4")
4755 (set_attr "type" "alu_shift,load_byte")
4756 (set_attr "predicable" "yes")
4757 (set_attr "pool_range" "*,256")
4758 (set_attr "neg_pool_range" "*,244")]
4761 (define_insn "*arm_extendqisi_v6"
4762 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4764 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
4765 "TARGET_ARM && arm_arch6"
4769 [(set_attr "type" "alu_shift,load_byte")
4770 (set_attr "predicable" "yes")
4771 (set_attr "pool_range" "*,256")
4772 (set_attr "neg_pool_range" "*,244")]
4775 (define_insn "*arm_extendqisi2addsi"
4776 [(set (match_operand:SI 0 "s_register_operand" "=r")
4777 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4778 (match_operand:SI 2 "s_register_operand" "r")))]
4780 "sxtab%?\\t%0, %2, %1"
4781 [(set_attr "type" "alu_shift")
4782 (set_attr "insn" "xtab")
4783 (set_attr "predicable" "yes")]
4787 [(set (match_operand:SI 0 "register_operand" "")
4788 (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))]
4789 "TARGET_THUMB1 && reload_completed"
4790 [(set (match_dup 0) (match_dup 2))
4791 (set (match_dup 0) (sign_extend:SI (match_dup 3)))]
4793 rtx addr = XEXP (operands[1], 0);
4795 if (GET_CODE (addr) == CONST)
4796 addr = XEXP (addr, 0);
4798 if (GET_CODE (addr) == PLUS
4799 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
4800 /* No split necessary. */
4803 if (GET_CODE (addr) == PLUS
4804 && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1)))
4807 if (reg_overlap_mentioned_p (operands[0], addr))
4809 rtx t = gen_lowpart (QImode, operands[0]);
4810 emit_move_insn (t, operands[1]);
4811 emit_insn (gen_thumb1_extendqisi2 (operands[0], t));
4817 addr = gen_rtx_PLUS (Pmode, addr, operands[0]);
4818 operands[2] = const0_rtx;
4820 else if (GET_CODE (addr) != PLUS)
4822 else if (REG_P (XEXP (addr, 0)))
4824 operands[2] = XEXP (addr, 1);
4825 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]);
4829 operands[2] = XEXP (addr, 0);
4830 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]);
4833 operands[3] = change_address (operands[1], QImode, addr);
4837 [(set (match_operand:SI 0 "register_operand" "")
4838 (plus:SI (match_dup 0) (match_operand 1 "const_int_operand")))
4839 (set (match_operand:SI 2 "register_operand" "") (const_int 0))
4840 (set (match_operand:SI 3 "register_operand" "")
4841 (sign_extend:SI (match_operand:QI 4 "memory_operand" "")))]
4843 && GET_CODE (XEXP (operands[4], 0)) == PLUS
4844 && rtx_equal_p (operands[0], XEXP (XEXP (operands[4], 0), 0))
4845 && rtx_equal_p (operands[2], XEXP (XEXP (operands[4], 0), 1))
4846 && (peep2_reg_dead_p (3, operands[0])
4847 || rtx_equal_p (operands[0], operands[3]))
4848 && (peep2_reg_dead_p (3, operands[2])
4849 || rtx_equal_p (operands[2], operands[3]))"
4850 [(set (match_dup 2) (match_dup 1))
4851 (set (match_dup 3) (sign_extend:SI (match_dup 4)))]
4853 rtx addr = gen_rtx_PLUS (Pmode, operands[0], operands[2]);
4854 operands[4] = change_address (operands[4], QImode, addr);
4857 (define_insn "thumb1_extendqisi2"
4858 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4859 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
4864 if (which_alternative == 0 && arm_arch6)
4865 return "sxtb\\t%0, %1";
4866 if (which_alternative == 0)
4869 addr = XEXP (operands[1], 0);
4870 if (GET_CODE (addr) == PLUS
4871 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
4872 return "ldrsb\\t%0, %1";
4876 [(set_attr_alternative "length"
4877 [(if_then_else (eq_attr "is_arch6" "yes")
4878 (const_int 2) (const_int 4))
4880 (if_then_else (eq_attr "is_arch6" "yes")
4881 (const_int 4) (const_int 6))])
4882 (set_attr "type" "alu_shift,load_byte,load_byte")]
4885 (define_expand "extendsfdf2"
4886 [(set (match_operand:DF 0 "s_register_operand" "")
4887 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
4888 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4892 /* HFmode -> DFmode conversions have to go through SFmode. */
4893 (define_expand "extendhfdf2"
4894 [(set (match_operand:DF 0 "general_operand" "")
4895 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
4900 op1 = convert_to_mode (SFmode, operands[1], 0);
4901 op1 = convert_to_mode (DFmode, op1, 0);
4902 emit_insn (gen_movdf (operands[0], op1));
4907 ;; Move insns (including loads and stores)
4909 ;; XXX Just some ideas about movti.
4910 ;; I don't think these are a good idea on the arm, there just aren't enough
4912 ;;(define_expand "loadti"
4913 ;; [(set (match_operand:TI 0 "s_register_operand" "")
4914 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4917 ;;(define_expand "storeti"
4918 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4919 ;; (match_operand:TI 1 "s_register_operand" ""))]
4922 ;;(define_expand "movti"
4923 ;; [(set (match_operand:TI 0 "general_operand" "")
4924 ;; (match_operand:TI 1 "general_operand" ""))]
4930 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4931 ;; operands[1] = copy_to_reg (operands[1]);
4932 ;; if (GET_CODE (operands[0]) == MEM)
4933 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4934 ;; else if (GET_CODE (operands[1]) == MEM)
4935 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4939 ;; emit_insn (insn);
4943 ;; Recognize garbage generated above.
4946 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4947 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4951 ;; register mem = (which_alternative < 3);
4952 ;; register const char *template;
4954 ;; operands[mem] = XEXP (operands[mem], 0);
4955 ;; switch (which_alternative)
4957 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4958 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4959 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4960 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4961 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4962 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
4964 ;; output_asm_insn (template, operands);
4968 (define_expand "movdi"
4969 [(set (match_operand:DI 0 "general_operand" "")
4970 (match_operand:DI 1 "general_operand" ""))]
4973 if (can_create_pseudo_p ())
4975 if (GET_CODE (operands[0]) != REG)
4976 operands[1] = force_reg (DImode, operands[1]);
4981 (define_insn "*arm_movdi"
4982 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4983 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
4985 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4987 && ( register_operand (operands[0], DImode)
4988 || register_operand (operands[1], DImode))"
4990 switch (which_alternative)
4997 return output_move_double (operands, true, NULL);
5000 [(set_attr "length" "8,12,16,8,8")
5001 (set_attr "type" "*,*,*,load2,store2")
5002 (set_attr "arm_pool_range" "*,*,*,1020,*")
5003 (set_attr "arm_neg_pool_range" "*,*,*,1008,*")
5004 (set_attr "thumb2_pool_range" "*,*,*,4096,*")
5005 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
5009 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5010 (match_operand:ANY64 1 "const_double_operand" ""))]
5013 && (arm_const_double_inline_cost (operands[1])
5014 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
5017 arm_split_constant (SET, SImode, curr_insn,
5018 INTVAL (gen_lowpart (SImode, operands[1])),
5019 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5020 arm_split_constant (SET, SImode, curr_insn,
5021 INTVAL (gen_highpart_mode (SImode,
5022 GET_MODE (operands[0]),
5024 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5029 ; If optimizing for size, or if we have load delay slots, then
5030 ; we want to split the constant into two separate operations.
5031 ; In both cases this may split a trivial part into a single data op
5032 ; leaving a single complex constant to load. We can also get longer
5033 ; offsets in a LDR which means we get better chances of sharing the pool
5034 ; entries. Finally, we can normally do a better job of scheduling
5035 ; LDR instructions than we can with LDM.
5036 ; This pattern will only match if the one above did not.
5038 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5039 (match_operand:ANY64 1 "const_double_operand" ""))]
5040 "TARGET_ARM && reload_completed
5041 && arm_const_double_by_parts (operands[1])"
5042 [(set (match_dup 0) (match_dup 1))
5043 (set (match_dup 2) (match_dup 3))]
5045 operands[2] = gen_highpart (SImode, operands[0]);
5046 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5048 operands[0] = gen_lowpart (SImode, operands[0]);
5049 operands[1] = gen_lowpart (SImode, operands[1]);
5054 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5055 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5056 "TARGET_EITHER && reload_completed"
5057 [(set (match_dup 0) (match_dup 1))
5058 (set (match_dup 2) (match_dup 3))]
5060 operands[2] = gen_highpart (SImode, operands[0]);
5061 operands[3] = gen_highpart (SImode, operands[1]);
5062 operands[0] = gen_lowpart (SImode, operands[0]);
5063 operands[1] = gen_lowpart (SImode, operands[1]);
5065 /* Handle a partial overlap. */
5066 if (rtx_equal_p (operands[0], operands[3]))
5068 rtx tmp0 = operands[0];
5069 rtx tmp1 = operands[1];
5071 operands[0] = operands[2];
5072 operands[1] = operands[3];
5079 ;; We can't actually do base+index doubleword loads if the index and
5080 ;; destination overlap. Split here so that we at least have chance to
5083 [(set (match_operand:DI 0 "s_register_operand" "")
5084 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5085 (match_operand:SI 2 "s_register_operand" ""))))]
5087 && reg_overlap_mentioned_p (operands[0], operands[1])
5088 && reg_overlap_mentioned_p (operands[0], operands[2])"
5090 (plus:SI (match_dup 1)
5093 (mem:DI (match_dup 4)))]
5095 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5099 ;;; ??? This should have alternatives for constants.
5100 ;;; ??? This was originally identical to the movdf_insn pattern.
5101 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
5102 ;;; thumb_reorg with a memory reference.
5103 (define_insn "*thumb1_movdi_insn"
5104 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
5105 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
5107 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
5108 && ( register_operand (operands[0], DImode)
5109 || register_operand (operands[1], DImode))"
5112 switch (which_alternative)
5116 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5117 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5118 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5120 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
5122 operands[1] = GEN_INT (- INTVAL (operands[1]));
5123 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
5125 return \"ldmia\\t%1, {%0, %H0}\";
5127 return \"stmia\\t%0, {%1, %H1}\";
5129 return thumb_load_double_from_address (operands);
5131 operands[2] = gen_rtx_MEM (SImode,
5132 plus_constant (XEXP (operands[0], 0), 4));
5133 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5136 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5137 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5138 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5141 [(set_attr "length" "4,4,6,2,2,6,4,4")
5142 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
5143 (set_attr "insn" "*,mov,*,*,*,*,*,mov")
5144 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
5147 (define_expand "movsi"
5148 [(set (match_operand:SI 0 "general_operand" "")
5149 (match_operand:SI 1 "general_operand" ""))]
5153 rtx base, offset, tmp;
5157 /* Everything except mem = const or mem = mem can be done easily. */
5158 if (GET_CODE (operands[0]) == MEM)
5159 operands[1] = force_reg (SImode, operands[1]);
5160 if (arm_general_register_operand (operands[0], SImode)
5161 && GET_CODE (operands[1]) == CONST_INT
5162 && !(const_ok_for_arm (INTVAL (operands[1]))
5163 || const_ok_for_arm (~INTVAL (operands[1]))))
5165 arm_split_constant (SET, SImode, NULL_RTX,
5166 INTVAL (operands[1]), operands[0], NULL_RTX,
5167 optimize && can_create_pseudo_p ());
5171 if (TARGET_USE_MOVT && !target_word_relocations
5172 && GET_CODE (operands[1]) == SYMBOL_REF
5173 && !flag_pic && !arm_tls_referenced_p (operands[1]))
5175 arm_emit_movpair (operands[0], operands[1]);
5179 else /* TARGET_THUMB1... */
5181 if (can_create_pseudo_p ())
5183 if (GET_CODE (operands[0]) != REG)
5184 operands[1] = force_reg (SImode, operands[1]);
5188 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5190 split_const (operands[1], &base, &offset);
5191 if (GET_CODE (base) == SYMBOL_REF
5192 && !offset_within_block_p (base, INTVAL (offset)))
5194 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5195 emit_move_insn (tmp, base);
5196 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5201 /* Recognize the case where operand[1] is a reference to thread-local
5202 data and load its address to a register. */
5203 if (arm_tls_referenced_p (operands[1]))
5205 rtx tmp = operands[1];
5208 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5210 addend = XEXP (XEXP (tmp, 0), 1);
5211 tmp = XEXP (XEXP (tmp, 0), 0);
5214 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5215 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5217 tmp = legitimize_tls_address (tmp,
5218 !can_create_pseudo_p () ? operands[0] : 0);
5221 tmp = gen_rtx_PLUS (SImode, tmp, addend);
5222 tmp = force_operand (tmp, operands[0]);
5227 && (CONSTANT_P (operands[1])
5228 || symbol_mentioned_p (operands[1])
5229 || label_mentioned_p (operands[1])))
5230 operands[1] = legitimize_pic_address (operands[1], SImode,
5231 (!can_create_pseudo_p ()
5238 ;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5239 ;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5240 ;; so this does not matter.
5241 (define_insn "*arm_movt"
5242 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5243 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5244 (match_operand:SI 2 "general_operand" "i")))]
5246 "movt%?\t%0, #:upper16:%c2"
5247 [(set_attr "predicable" "yes")
5248 (set_attr "length" "4")]
5251 (define_insn "*arm_movsi_insn"
5252 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
5253 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
5254 "TARGET_ARM && ! TARGET_IWMMXT
5255 && !(TARGET_HARD_FLOAT && TARGET_VFP)
5256 && ( register_operand (operands[0], SImode)
5257 || register_operand (operands[1], SImode))"
5265 [(set_attr "type" "*,*,*,*,load1,store1")
5266 (set_attr "insn" "mov,mov,mvn,mov,*,*")
5267 (set_attr "predicable" "yes")
5268 (set_attr "pool_range" "*,*,*,*,4096,*")
5269 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
5273 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5274 (match_operand:SI 1 "const_int_operand" ""))]
5276 && (!(const_ok_for_arm (INTVAL (operands[1]))
5277 || const_ok_for_arm (~INTVAL (operands[1]))))"
5278 [(clobber (const_int 0))]
5280 arm_split_constant (SET, SImode, NULL_RTX,
5281 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
5286 (define_insn "*thumb1_movsi_insn"
5287 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*l*h*k")
5288 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*l*h*k"))]
5290 && ( register_operand (operands[0], SImode)
5291 || register_operand (operands[1], SImode))"
5302 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
5303 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
5304 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")
5305 (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")])
5308 [(set (match_operand:SI 0 "register_operand" "")
5309 (match_operand:SI 1 "const_int_operand" ""))]
5310 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
5311 [(set (match_dup 2) (match_dup 1))
5312 (set (match_dup 0) (neg:SI (match_dup 2)))]
5315 operands[1] = GEN_INT (- INTVAL (operands[1]));
5316 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5321 [(set (match_operand:SI 0 "register_operand" "")
5322 (match_operand:SI 1 "const_int_operand" ""))]
5323 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
5324 [(set (match_dup 2) (match_dup 1))
5325 (set (match_dup 0) (ashift:SI (match_dup 2) (match_dup 3)))]
5328 unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
5329 unsigned HOST_WIDE_INT mask = 0xff;
5332 for (i = 0; i < 25; i++)
5333 if ((val & (mask << i)) == val)
5336 /* Don't split if the shift is zero. */
5340 operands[1] = GEN_INT (val >> i);
5341 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5342 operands[3] = GEN_INT (i);
5346 ;; When generating pic, we need to load the symbol offset into a register.
5347 ;; So that the optimizer does not confuse this with a normal symbol load
5348 ;; we use an unspec. The offset will be loaded from a constant pool entry,
5349 ;; since that is the only type of relocation we can use.
5351 ;; Wrap calculation of the whole PIC address in a single pattern for the
5352 ;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5353 ;; a PIC address involves two loads from memory, so we want to CSE it
5354 ;; as often as possible.
5355 ;; This pattern will be split into one of the pic_load_addr_* patterns
5356 ;; and a move after GCSE optimizations.
5358 ;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5359 (define_expand "calculate_pic_address"
5360 [(set (match_operand:SI 0 "register_operand" "")
5361 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5362 (unspec:SI [(match_operand:SI 2 "" "")]
5367 ;; Split calculate_pic_address into pic_load_addr_* and a move.
5369 [(set (match_operand:SI 0 "register_operand" "")
5370 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5371 (unspec:SI [(match_operand:SI 2 "" "")]
5374 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5375 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5376 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5379 ;; The rather odd constraints on the following are to force reload to leave
5380 ;; the insn alone, and to force the minipool generation pass to then move
5381 ;; the GOT symbol to memory.
5383 (define_insn "pic_load_addr_32bit"
5384 [(set (match_operand:SI 0 "s_register_operand" "=r")
5385 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5386 "TARGET_32BIT && flag_pic"
5388 [(set_attr "type" "load1")
5389 (set_attr "pool_range" "4096")
5390 (set (attr "neg_pool_range")
5391 (if_then_else (eq_attr "is_thumb" "no")
5396 (define_insn "pic_load_addr_thumb1"
5397 [(set (match_operand:SI 0 "s_register_operand" "=l")
5398 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5399 "TARGET_THUMB1 && flag_pic"
5401 [(set_attr "type" "load1")
5402 (set (attr "pool_range") (const_int 1024))]
5405 (define_insn "pic_add_dot_plus_four"
5406 [(set (match_operand:SI 0 "register_operand" "=r")
5407 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5409 (match_operand 2 "" "")]
5413 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5414 INTVAL (operands[2]));
5415 return \"add\\t%0, %|pc\";
5417 [(set_attr "length" "2")]
5420 (define_insn "pic_add_dot_plus_eight"
5421 [(set (match_operand:SI 0 "register_operand" "=r")
5422 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5424 (match_operand 2 "" "")]
5428 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5429 INTVAL (operands[2]));
5430 return \"add%?\\t%0, %|pc, %1\";
5432 [(set_attr "predicable" "yes")]
5435 (define_insn "tls_load_dot_plus_eight"
5436 [(set (match_operand:SI 0 "register_operand" "=r")
5437 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5439 (match_operand 2 "" "")]
5443 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5444 INTVAL (operands[2]));
5445 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5447 [(set_attr "predicable" "yes")]
5450 ;; PIC references to local variables can generate pic_add_dot_plus_eight
5451 ;; followed by a load. These sequences can be crunched down to
5452 ;; tls_load_dot_plus_eight by a peephole.
5455 [(set (match_operand:SI 0 "register_operand" "")
5456 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5458 (match_operand 1 "" "")]
5460 (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
5461 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
5463 (mem:SI (unspec:SI [(match_dup 3)
5470 (define_insn "pic_offset_arm"
5471 [(set (match_operand:SI 0 "register_operand" "=r")
5472 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5473 (unspec:SI [(match_operand:SI 2 "" "X")]
5474 UNSPEC_PIC_OFFSET))))]
5475 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5476 "ldr%?\\t%0, [%1,%2]"
5477 [(set_attr "type" "load1")]
5480 (define_expand "builtin_setjmp_receiver"
5481 [(label_ref (match_operand 0 "" ""))]
5485 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5487 if (arm_pic_register != INVALID_REGNUM)
5488 arm_load_pic_register (1UL << 3);
5492 ;; If copying one reg to another we can set the condition codes according to
5493 ;; its value. Such a move is common after a return from subroutine and the
5494 ;; result is being tested against zero.
5496 (define_insn "*movsi_compare0"
5497 [(set (reg:CC CC_REGNUM)
5498 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5500 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5506 [(set_attr "conds" "set")]
5509 ;; Subroutine to store a half word from a register into memory.
5510 ;; Operand 0 is the source register (HImode)
5511 ;; Operand 1 is the destination address in a register (SImode)
5513 ;; In both this routine and the next, we must be careful not to spill
5514 ;; a memory address of reg+large_const into a separate PLUS insn, since this
5515 ;; can generate unrecognizable rtl.
5517 (define_expand "storehi"
5518 [;; store the low byte
5519 (set (match_operand 1 "" "") (match_dup 3))
5520 ;; extract the high byte
5522 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
5523 ;; store the high byte
5524 (set (match_dup 4) (match_dup 5))]
5528 rtx op1 = operands[1];
5529 rtx addr = XEXP (op1, 0);
5530 enum rtx_code code = GET_CODE (addr);
5532 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5534 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
5536 operands[4] = adjust_address (op1, QImode, 1);
5537 operands[1] = adjust_address (operands[1], QImode, 0);
5538 operands[3] = gen_lowpart (QImode, operands[0]);
5539 operands[0] = gen_lowpart (SImode, operands[0]);
5540 operands[2] = gen_reg_rtx (SImode);
5541 operands[5] = gen_lowpart (QImode, operands[2]);
5545 (define_expand "storehi_bigend"
5546 [(set (match_dup 4) (match_dup 3))
5548 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
5549 (set (match_operand 1 "" "") (match_dup 5))]
5553 rtx op1 = operands[1];
5554 rtx addr = XEXP (op1, 0);
5555 enum rtx_code code = GET_CODE (addr);
5557 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5559 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
5561 operands[4] = adjust_address (op1, QImode, 1);
5562 operands[1] = adjust_address (operands[1], QImode, 0);
5563 operands[3] = gen_lowpart (QImode, operands[0]);
5564 operands[0] = gen_lowpart (SImode, operands[0]);
5565 operands[2] = gen_reg_rtx (SImode);
5566 operands[5] = gen_lowpart (QImode, operands[2]);
5570 ;; Subroutine to store a half word integer constant into memory.
5571 (define_expand "storeinthi"
5572 [(set (match_operand 0 "" "")
5573 (match_operand 1 "" ""))
5574 (set (match_dup 3) (match_dup 2))]
5578 HOST_WIDE_INT value = INTVAL (operands[1]);
5579 rtx addr = XEXP (operands[0], 0);
5580 rtx op0 = operands[0];
5581 enum rtx_code code = GET_CODE (addr);
5583 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5585 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
5587 operands[1] = gen_reg_rtx (SImode);
5588 if (BYTES_BIG_ENDIAN)
5590 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5591 if ((value & 255) == ((value >> 8) & 255))
5592 operands[2] = operands[1];
5595 operands[2] = gen_reg_rtx (SImode);
5596 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5601 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5602 if ((value & 255) == ((value >> 8) & 255))
5603 operands[2] = operands[1];
5606 operands[2] = gen_reg_rtx (SImode);
5607 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5611 operands[3] = adjust_address (op0, QImode, 1);
5612 operands[0] = adjust_address (operands[0], QImode, 0);
5613 operands[2] = gen_lowpart (QImode, operands[2]);
5614 operands[1] = gen_lowpart (QImode, operands[1]);
5618 (define_expand "storehi_single_op"
5619 [(set (match_operand:HI 0 "memory_operand" "")
5620 (match_operand:HI 1 "general_operand" ""))]
5621 "TARGET_32BIT && arm_arch4"
5623 if (!s_register_operand (operands[1], HImode))
5624 operands[1] = copy_to_mode_reg (HImode, operands[1]);
5628 (define_expand "movhi"
5629 [(set (match_operand:HI 0 "general_operand" "")
5630 (match_operand:HI 1 "general_operand" ""))]
5635 if (can_create_pseudo_p ())
5637 if (GET_CODE (operands[0]) == MEM)
5641 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5644 if (GET_CODE (operands[1]) == CONST_INT)
5645 emit_insn (gen_storeinthi (operands[0], operands[1]));
5648 if (GET_CODE (operands[1]) == MEM)
5649 operands[1] = force_reg (HImode, operands[1]);
5650 if (BYTES_BIG_ENDIAN)
5651 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5653 emit_insn (gen_storehi (operands[1], operands[0]));
5657 /* Sign extend a constant, and keep it in an SImode reg. */
5658 else if (GET_CODE (operands[1]) == CONST_INT)
5660 rtx reg = gen_reg_rtx (SImode);
5661 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5663 /* If the constant is already valid, leave it alone. */
5664 if (!const_ok_for_arm (val))
5666 /* If setting all the top bits will make the constant
5667 loadable in a single instruction, then set them.
5668 Otherwise, sign extend the number. */
5670 if (const_ok_for_arm (~(val | ~0xffff)))
5672 else if (val & 0x8000)
5676 emit_insn (gen_movsi (reg, GEN_INT (val)));
5677 operands[1] = gen_lowpart (HImode, reg);
5679 else if (arm_arch4 && optimize && can_create_pseudo_p ()
5680 && GET_CODE (operands[1]) == MEM)
5682 rtx reg = gen_reg_rtx (SImode);
5684 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5685 operands[1] = gen_lowpart (HImode, reg);
5687 else if (!arm_arch4)
5689 if (GET_CODE (operands[1]) == MEM)
5692 rtx offset = const0_rtx;
5693 rtx reg = gen_reg_rtx (SImode);
5695 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5696 || (GET_CODE (base) == PLUS
5697 && (GET_CODE (offset = XEXP (base, 1))
5699 && ((INTVAL(offset) & 1) != 1)
5700 && GET_CODE (base = XEXP (base, 0)) == REG))
5701 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
5705 new_rtx = widen_memory_access (operands[1], SImode,
5706 ((INTVAL (offset) & ~3)
5707 - INTVAL (offset)));
5708 emit_insn (gen_movsi (reg, new_rtx));
5709 if (((INTVAL (offset) & 2) != 0)
5710 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5712 rtx reg2 = gen_reg_rtx (SImode);
5714 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5719 emit_insn (gen_movhi_bytes (reg, operands[1]));
5721 operands[1] = gen_lowpart (HImode, reg);
5725 /* Handle loading a large integer during reload. */
5726 else if (GET_CODE (operands[1]) == CONST_INT
5727 && !const_ok_for_arm (INTVAL (operands[1]))
5728 && !const_ok_for_arm (~INTVAL (operands[1])))
5730 /* Writing a constant to memory needs a scratch, which should
5731 be handled with SECONDARY_RELOADs. */
5732 gcc_assert (GET_CODE (operands[0]) == REG);
5734 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5735 emit_insn (gen_movsi (operands[0], operands[1]));
5739 else if (TARGET_THUMB2)
5741 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
5742 if (can_create_pseudo_p ())
5744 if (GET_CODE (operands[0]) != REG)
5745 operands[1] = force_reg (HImode, operands[1]);
5746 /* Zero extend a constant, and keep it in an SImode reg. */
5747 else if (GET_CODE (operands[1]) == CONST_INT)
5749 rtx reg = gen_reg_rtx (SImode);
5750 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5752 emit_insn (gen_movsi (reg, GEN_INT (val)));
5753 operands[1] = gen_lowpart (HImode, reg);
5757 else /* TARGET_THUMB1 */
5759 if (can_create_pseudo_p ())
5761 if (GET_CODE (operands[1]) == CONST_INT)
5763 rtx reg = gen_reg_rtx (SImode);
5765 emit_insn (gen_movsi (reg, operands[1]));
5766 operands[1] = gen_lowpart (HImode, reg);
5769 /* ??? We shouldn't really get invalid addresses here, but this can
5770 happen if we are passed a SP (never OK for HImode/QImode) or
5771 virtual register (also rejected as illegitimate for HImode/QImode)
5772 relative address. */
5773 /* ??? This should perhaps be fixed elsewhere, for instance, in
5774 fixup_stack_1, by checking for other kinds of invalid addresses,
5775 e.g. a bare reference to a virtual register. This may confuse the
5776 alpha though, which must handle this case differently. */
5777 if (GET_CODE (operands[0]) == MEM
5778 && !memory_address_p (GET_MODE (operands[0]),
5779 XEXP (operands[0], 0)))
5781 = replace_equiv_address (operands[0],
5782 copy_to_reg (XEXP (operands[0], 0)));
5784 if (GET_CODE (operands[1]) == MEM
5785 && !memory_address_p (GET_MODE (operands[1]),
5786 XEXP (operands[1], 0)))
5788 = replace_equiv_address (operands[1],
5789 copy_to_reg (XEXP (operands[1], 0)));
5791 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5793 rtx reg = gen_reg_rtx (SImode);
5795 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5796 operands[1] = gen_lowpart (HImode, reg);
5799 if (GET_CODE (operands[0]) == MEM)
5800 operands[1] = force_reg (HImode, operands[1]);
5802 else if (GET_CODE (operands[1]) == CONST_INT
5803 && !satisfies_constraint_I (operands[1]))
5805 /* Handle loading a large integer during reload. */
5807 /* Writing a constant to memory needs a scratch, which should
5808 be handled with SECONDARY_RELOADs. */
5809 gcc_assert (GET_CODE (operands[0]) == REG);
5811 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5812 emit_insn (gen_movsi (operands[0], operands[1]));
5819 (define_insn "*thumb1_movhi_insn"
5820 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5821 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
5823 && ( register_operand (operands[0], HImode)
5824 || register_operand (operands[1], HImode))"
5826 switch (which_alternative)
5828 case 0: return \"add %0, %1, #0\";
5829 case 2: return \"strh %1, %0\";
5830 case 3: return \"mov %0, %1\";
5831 case 4: return \"mov %0, %1\";
5832 case 5: return \"mov %0, %1\";
5833 default: gcc_unreachable ();
5835 /* The stack pointer can end up being taken as an index register.
5836 Catch this case here and deal with it. */
5837 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
5838 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
5839 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
5842 ops[0] = operands[0];
5843 ops[1] = XEXP (XEXP (operands[1], 0), 0);
5845 output_asm_insn (\"mov %0, %1\", ops);
5847 XEXP (XEXP (operands[1], 0), 0) = operands[0];
5850 return \"ldrh %0, %1\";
5852 [(set_attr "length" "2,4,2,2,2,2")
5853 (set_attr "type" "*,load1,store1,*,*,*")
5854 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
5857 (define_expand "movhi_bytes"
5858 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
5860 (zero_extend:SI (match_dup 6)))
5861 (set (match_operand:SI 0 "" "")
5862 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
5867 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5869 mem1 = change_address (operands[1], QImode, addr);
5870 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
5871 operands[0] = gen_lowpart (SImode, operands[0]);
5873 operands[2] = gen_reg_rtx (SImode);
5874 operands[3] = gen_reg_rtx (SImode);
5877 if (BYTES_BIG_ENDIAN)
5879 operands[4] = operands[2];
5880 operands[5] = operands[3];
5884 operands[4] = operands[3];
5885 operands[5] = operands[2];
5890 (define_expand "movhi_bigend"
5892 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5895 (ashiftrt:SI (match_dup 2) (const_int 16)))
5896 (set (match_operand:HI 0 "s_register_operand" "")
5900 operands[2] = gen_reg_rtx (SImode);
5901 operands[3] = gen_reg_rtx (SImode);
5902 operands[4] = gen_lowpart (HImode, operands[3]);
5906 ;; Pattern to recognize insn generated default case above
5907 (define_insn "*movhi_insn_arch4"
5908 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
5909 (match_operand:HI 1 "general_operand" "rI,K,r,mi"))]
5912 && (register_operand (operands[0], HImode)
5913 || register_operand (operands[1], HImode))"
5915 mov%?\\t%0, %1\\t%@ movhi
5916 mvn%?\\t%0, #%B1\\t%@ movhi
5917 str%(h%)\\t%1, %0\\t%@ movhi
5918 ldr%(h%)\\t%0, %1\\t%@ movhi"
5919 [(set_attr "type" "*,*,store1,load1")
5920 (set_attr "predicable" "yes")
5921 (set_attr "insn" "mov,mvn,*,*")
5922 (set_attr "pool_range" "*,*,*,256")
5923 (set_attr "neg_pool_range" "*,*,*,244")]
5926 (define_insn "*movhi_bytes"
5927 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5928 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
5931 mov%?\\t%0, %1\\t%@ movhi
5932 mvn%?\\t%0, #%B1\\t%@ movhi"
5933 [(set_attr "predicable" "yes")
5934 (set_attr "insn" "mov,mvn")]
5937 (define_expand "thumb_movhi_clobber"
5938 [(set (match_operand:HI 0 "memory_operand" "")
5939 (match_operand:HI 1 "register_operand" ""))
5940 (clobber (match_operand:DI 2 "register_operand" ""))]
5943 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5944 && REGNO (operands[1]) <= LAST_LO_REGNUM)
5946 emit_insn (gen_movhi (operands[0], operands[1]));
5949 /* XXX Fixme, need to handle other cases here as well. */
5954 ;; We use a DImode scratch because we may occasionally need an additional
5955 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
5956 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
5957 (define_expand "reload_outhi"
5958 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
5959 (match_operand:HI 1 "s_register_operand" "r")
5960 (match_operand:DI 2 "s_register_operand" "=&l")])]
5963 arm_reload_out_hi (operands);
5965 thumb_reload_out_hi (operands);
5970 (define_expand "reload_inhi"
5971 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
5972 (match_operand:HI 1 "arm_reload_memory_operand" "o")
5973 (match_operand:DI 2 "s_register_operand" "=&r")])]
5977 arm_reload_in_hi (operands);
5979 thumb_reload_out_hi (operands);
5983 (define_expand "movqi"
5984 [(set (match_operand:QI 0 "general_operand" "")
5985 (match_operand:QI 1 "general_operand" ""))]
5988 /* Everything except mem = const or mem = mem can be done easily */
5990 if (can_create_pseudo_p ())
5992 if (GET_CODE (operands[1]) == CONST_INT)
5994 rtx reg = gen_reg_rtx (SImode);
5996 /* For thumb we want an unsigned immediate, then we are more likely
5997 to be able to use a movs insn. */
5999 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6001 emit_insn (gen_movsi (reg, operands[1]));
6002 operands[1] = gen_lowpart (QImode, reg);
6007 /* ??? We shouldn't really get invalid addresses here, but this can
6008 happen if we are passed a SP (never OK for HImode/QImode) or
6009 virtual register (also rejected as illegitimate for HImode/QImode)
6010 relative address. */
6011 /* ??? This should perhaps be fixed elsewhere, for instance, in
6012 fixup_stack_1, by checking for other kinds of invalid addresses,
6013 e.g. a bare reference to a virtual register. This may confuse the
6014 alpha though, which must handle this case differently. */
6015 if (GET_CODE (operands[0]) == MEM
6016 && !memory_address_p (GET_MODE (operands[0]),
6017 XEXP (operands[0], 0)))
6019 = replace_equiv_address (operands[0],
6020 copy_to_reg (XEXP (operands[0], 0)));
6021 if (GET_CODE (operands[1]) == MEM
6022 && !memory_address_p (GET_MODE (operands[1]),
6023 XEXP (operands[1], 0)))
6025 = replace_equiv_address (operands[1],
6026 copy_to_reg (XEXP (operands[1], 0)));
6029 if (GET_CODE (operands[1]) == MEM && optimize > 0)
6031 rtx reg = gen_reg_rtx (SImode);
6033 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6034 operands[1] = gen_lowpart (QImode, reg);
6037 if (GET_CODE (operands[0]) == MEM)
6038 operands[1] = force_reg (QImode, operands[1]);
6040 else if (TARGET_THUMB
6041 && GET_CODE (operands[1]) == CONST_INT
6042 && !satisfies_constraint_I (operands[1]))
6044 /* Handle loading a large integer during reload. */
6046 /* Writing a constant to memory needs a scratch, which should
6047 be handled with SECONDARY_RELOADs. */
6048 gcc_assert (GET_CODE (operands[0]) == REG);
6050 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6051 emit_insn (gen_movsi (operands[0], operands[1]));
6058 (define_insn "*arm_movqi_insn"
6059 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,l,Uu,r,m")
6060 (match_operand:QI 1 "general_operand" "rI,K,Uu,l,m,r"))]
6062 && ( register_operand (operands[0], QImode)
6063 || register_operand (operands[1], QImode))"
6071 [(set_attr "type" "*,*,load1,store1,load1,store1")
6072 (set_attr "insn" "mov,mvn,*,*,*,*")
6073 (set_attr "predicable" "yes")
6074 (set_attr "arch" "any,any,t2,t2,any,any")
6075 (set_attr "length" "4,4,2,2,4,4")]
6078 (define_insn "*thumb1_movqi_insn"
6079 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
6080 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
6082 && ( register_operand (operands[0], QImode)
6083 || register_operand (operands[1], QImode))"
6091 [(set_attr "length" "2")
6092 (set_attr "type" "*,load1,store1,*,*,*")
6093 (set_attr "insn" "*,*,*,mov,mov,mov")
6094 (set_attr "pool_range" "*,32,*,*,*,*")
6095 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
6098 (define_expand "movhf"
6099 [(set (match_operand:HF 0 "general_operand" "")
6100 (match_operand:HF 1 "general_operand" ""))]
6105 if (GET_CODE (operands[0]) == MEM)
6106 operands[1] = force_reg (HFmode, operands[1]);
6108 else /* TARGET_THUMB1 */
6110 if (can_create_pseudo_p ())
6112 if (GET_CODE (operands[0]) != REG)
6113 operands[1] = force_reg (HFmode, operands[1]);
6119 (define_insn "*arm32_movhf"
6120 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6121 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
6122 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
6123 && ( s_register_operand (operands[0], HFmode)
6124 || s_register_operand (operands[1], HFmode))"
6126 switch (which_alternative)
6128 case 0: /* ARM register from memory */
6129 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
6130 case 1: /* memory from ARM register */
6131 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
6132 case 2: /* ARM register from ARM register */
6133 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6134 case 3: /* ARM register from constant */
6140 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
6141 bits = real_to_target (NULL, &r, HFmode);
6142 ops[0] = operands[0];
6143 ops[1] = GEN_INT (bits);
6144 ops[2] = GEN_INT (bits & 0xff00);
6145 ops[3] = GEN_INT (bits & 0x00ff);
6147 if (arm_arch_thumb2)
6148 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6150 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6157 [(set_attr "conds" "unconditional")
6158 (set_attr "type" "load1,store1,*,*")
6159 (set_attr "insn" "*,*,mov,mov")
6160 (set_attr "length" "4,4,4,8")
6161 (set_attr "predicable" "yes")]
6164 (define_insn "*thumb1_movhf"
6165 [(set (match_operand:HF 0 "nonimmediate_operand" "=l,l,m,*r,*h")
6166 (match_operand:HF 1 "general_operand" "l,mF,l,*h,*r"))]
6168 && ( s_register_operand (operands[0], HFmode)
6169 || s_register_operand (operands[1], HFmode))"
6171 switch (which_alternative)
6176 gcc_assert (GET_CODE(operands[1]) == MEM);
6177 addr = XEXP (operands[1], 0);
6178 if (GET_CODE (addr) == LABEL_REF
6179 || (GET_CODE (addr) == CONST
6180 && GET_CODE (XEXP (addr, 0)) == PLUS
6181 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
6182 && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT))
6184 /* Constant pool entry. */
6185 return \"ldr\\t%0, %1\";
6187 return \"ldrh\\t%0, %1\";
6189 case 2: return \"strh\\t%1, %0\";
6190 default: return \"mov\\t%0, %1\";
6193 [(set_attr "length" "2")
6194 (set_attr "type" "*,load1,store1,*,*")
6195 (set_attr "insn" "mov,*,*,mov,mov")
6196 (set_attr "pool_range" "*,1020,*,*,*")
6197 (set_attr "conds" "clob,nocond,nocond,nocond,nocond")])
6199 (define_expand "movsf"
6200 [(set (match_operand:SF 0 "general_operand" "")
6201 (match_operand:SF 1 "general_operand" ""))]
6206 if (GET_CODE (operands[0]) == MEM)
6207 operands[1] = force_reg (SFmode, operands[1]);
6209 else /* TARGET_THUMB1 */
6211 if (can_create_pseudo_p ())
6213 if (GET_CODE (operands[0]) != REG)
6214 operands[1] = force_reg (SFmode, operands[1]);
6220 ;; Transform a floating-point move of a constant into a core register into
6221 ;; an SImode operation.
6223 [(set (match_operand:SF 0 "arm_general_register_operand" "")
6224 (match_operand:SF 1 "immediate_operand" ""))]
6227 && GET_CODE (operands[1]) == CONST_DOUBLE"
6228 [(set (match_dup 2) (match_dup 3))]
6230 operands[2] = gen_lowpart (SImode, operands[0]);
6231 operands[3] = gen_lowpart (SImode, operands[1]);
6232 if (operands[2] == 0 || operands[3] == 0)
6237 (define_insn "*arm_movsf_soft_insn"
6238 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6239 (match_operand:SF 1 "general_operand" "r,mE,r"))]
6241 && TARGET_SOFT_FLOAT
6242 && (GET_CODE (operands[0]) != MEM
6243 || register_operand (operands[1], SFmode))"
6246 ldr%?\\t%0, %1\\t%@ float
6247 str%?\\t%1, %0\\t%@ float"
6248 [(set_attr "predicable" "yes")
6249 (set_attr "type" "*,load1,store1")
6250 (set_attr "insn" "mov,*,*")
6251 (set_attr "pool_range" "*,4096,*")
6252 (set_attr "arm_neg_pool_range" "*,4084,*")
6253 (set_attr "thumb2_neg_pool_range" "*,0,*")]
6256 ;;; ??? This should have alternatives for constants.
6257 (define_insn "*thumb1_movsf_insn"
6258 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
6259 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
6261 && ( register_operand (operands[0], SFmode)
6262 || register_operand (operands[1], SFmode))"
6271 [(set_attr "length" "2")
6272 (set_attr "type" "*,load1,store1,load1,store1,*,*")
6273 (set_attr "pool_range" "*,*,*,1020,*,*,*")
6274 (set_attr "insn" "*,*,*,*,*,mov,mov")
6275 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,nocond,nocond")]
6278 (define_expand "movdf"
6279 [(set (match_operand:DF 0 "general_operand" "")
6280 (match_operand:DF 1 "general_operand" ""))]
6285 if (GET_CODE (operands[0]) == MEM)
6286 operands[1] = force_reg (DFmode, operands[1]);
6288 else /* TARGET_THUMB */
6290 if (can_create_pseudo_p ())
6292 if (GET_CODE (operands[0]) != REG)
6293 operands[1] = force_reg (DFmode, operands[1]);
6299 ;; Reloading a df mode value stored in integer regs to memory can require a
6301 (define_expand "reload_outdf"
6302 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
6303 (match_operand:DF 1 "s_register_operand" "r")
6304 (match_operand:SI 2 "s_register_operand" "=&r")]
6308 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
6311 operands[2] = XEXP (operands[0], 0);
6312 else if (code == POST_INC || code == PRE_DEC)
6314 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6315 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6316 emit_insn (gen_movdi (operands[0], operands[1]));
6319 else if (code == PRE_INC)
6321 rtx reg = XEXP (XEXP (operands[0], 0), 0);
6323 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6326 else if (code == POST_DEC)
6327 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6329 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6330 XEXP (XEXP (operands[0], 0), 1)));
6332 emit_insn (gen_rtx_SET (VOIDmode,
6333 replace_equiv_address (operands[0], operands[2]),
6336 if (code == POST_DEC)
6337 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6343 (define_insn "*movdf_soft_insn"
6344 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6345 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
6346 "TARGET_32BIT && TARGET_SOFT_FLOAT
6347 && ( register_operand (operands[0], DFmode)
6348 || register_operand (operands[1], DFmode))"
6350 switch (which_alternative)
6357 return output_move_double (operands, true, NULL);
6360 [(set_attr "length" "8,12,16,8,8")
6361 (set_attr "type" "*,*,*,load2,store2")
6362 (set_attr "pool_range" "*,*,*,1020,*")
6363 (set_attr "arm_neg_pool_range" "*,*,*,1008,*")
6364 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
6367 ;;; ??? This should have alternatives for constants.
6368 ;;; ??? This was originally identical to the movdi_insn pattern.
6369 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
6370 ;;; thumb_reorg with a memory reference.
6371 (define_insn "*thumb_movdf_insn"
6372 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
6373 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
6375 && ( register_operand (operands[0], DFmode)
6376 || register_operand (operands[1], DFmode))"
6378 switch (which_alternative)
6382 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6383 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6384 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6386 return \"ldmia\\t%1, {%0, %H0}\";
6388 return \"stmia\\t%0, {%1, %H1}\";
6390 return thumb_load_double_from_address (operands);
6392 operands[2] = gen_rtx_MEM (SImode,
6393 plus_constant (XEXP (operands[0], 0), 4));
6394 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6397 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6398 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6399 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6402 [(set_attr "length" "4,2,2,6,4,4")
6403 (set_attr "type" "*,load2,store2,load2,store2,*")
6404 (set_attr "insn" "*,*,*,*,*,mov")
6405 (set_attr "pool_range" "*,*,*,1020,*,*")]
6408 (define_expand "movxf"
6409 [(set (match_operand:XF 0 "general_operand" "")
6410 (match_operand:XF 1 "general_operand" ""))]
6411 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
6413 if (GET_CODE (operands[0]) == MEM)
6414 operands[1] = force_reg (XFmode, operands[1]);
6420 ;; load- and store-multiple insns
6421 ;; The arm can load/store any set of registers, provided that they are in
6422 ;; ascending order, but these expanders assume a contiguous set.
6424 (define_expand "load_multiple"
6425 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6426 (match_operand:SI 1 "" ""))
6427 (use (match_operand:SI 2 "" ""))])]
6430 HOST_WIDE_INT offset = 0;
6432 /* Support only fixed point registers. */
6433 if (GET_CODE (operands[2]) != CONST_INT
6434 || INTVAL (operands[2]) > 14
6435 || INTVAL (operands[2]) < 2
6436 || GET_CODE (operands[1]) != MEM
6437 || GET_CODE (operands[0]) != REG
6438 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6439 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
6443 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6444 INTVAL (operands[2]),
6445 force_reg (SImode, XEXP (operands[1], 0)),
6446 FALSE, operands[1], &offset);
6449 (define_expand "store_multiple"
6450 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6451 (match_operand:SI 1 "" ""))
6452 (use (match_operand:SI 2 "" ""))])]
6455 HOST_WIDE_INT offset = 0;
6457 /* Support only fixed point registers. */
6458 if (GET_CODE (operands[2]) != CONST_INT
6459 || INTVAL (operands[2]) > 14
6460 || INTVAL (operands[2]) < 2
6461 || GET_CODE (operands[1]) != REG
6462 || GET_CODE (operands[0]) != MEM
6463 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6464 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
6468 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6469 INTVAL (operands[2]),
6470 force_reg (SImode, XEXP (operands[0], 0)),
6471 FALSE, operands[0], &offset);
6475 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
6476 ;; We could let this apply for blocks of less than this, but it clobbers so
6477 ;; many registers that there is then probably a better way.
6479 (define_expand "movmemqi"
6480 [(match_operand:BLK 0 "general_operand" "")
6481 (match_operand:BLK 1 "general_operand" "")
6482 (match_operand:SI 2 "const_int_operand" "")
6483 (match_operand:SI 3 "const_int_operand" "")]
6488 if (arm_gen_movmemqi (operands))
6492 else /* TARGET_THUMB1 */
6494 if ( INTVAL (operands[3]) != 4
6495 || INTVAL (operands[2]) > 48)
6498 thumb_expand_movmemqi (operands);
6504 ;; Thumb block-move insns
6506 (define_insn "movmem12b"
6507 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6508 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6509 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6510 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6511 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6512 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6513 (set (match_operand:SI 0 "register_operand" "=l")
6514 (plus:SI (match_dup 2) (const_int 12)))
6515 (set (match_operand:SI 1 "register_operand" "=l")
6516 (plus:SI (match_dup 3) (const_int 12)))
6517 (clobber (match_scratch:SI 4 "=&l"))
6518 (clobber (match_scratch:SI 5 "=&l"))
6519 (clobber (match_scratch:SI 6 "=&l"))]
6521 "* return thumb_output_move_mem_multiple (3, operands);"
6522 [(set_attr "length" "4")
6523 ; This isn't entirely accurate... It loads as well, but in terms of
6524 ; scheduling the following insn it is better to consider it as a store
6525 (set_attr "type" "store3")]
6528 (define_insn "movmem8b"
6529 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6530 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6531 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6532 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6533 (set (match_operand:SI 0 "register_operand" "=l")
6534 (plus:SI (match_dup 2) (const_int 8)))
6535 (set (match_operand:SI 1 "register_operand" "=l")
6536 (plus:SI (match_dup 3) (const_int 8)))
6537 (clobber (match_scratch:SI 4 "=&l"))
6538 (clobber (match_scratch:SI 5 "=&l"))]
6540 "* return thumb_output_move_mem_multiple (2, operands);"
6541 [(set_attr "length" "4")
6542 ; This isn't entirely accurate... It loads as well, but in terms of
6543 ; scheduling the following insn it is better to consider it as a store
6544 (set_attr "type" "store2")]
6549 ;; Compare & branch insns
6550 ;; The range calculations are based as follows:
6551 ;; For forward branches, the address calculation returns the address of
6552 ;; the next instruction. This is 2 beyond the branch instruction.
6553 ;; For backward branches, the address calculation returns the address of
6554 ;; the first instruction in this pattern (cmp). This is 2 before the branch
6555 ;; instruction for the shortest sequence, and 4 before the branch instruction
6556 ;; if we have to jump around an unconditional branch.
6557 ;; To the basic branch range the PC offset must be added (this is +4).
6558 ;; So for forward branches we have
6559 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6560 ;; And for backward branches we have
6561 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6563 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6564 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
6566 (define_expand "cbranchsi4"
6567 [(set (pc) (if_then_else
6568 (match_operator 0 "arm_comparison_operator"
6569 [(match_operand:SI 1 "s_register_operand" "")
6570 (match_operand:SI 2 "nonmemory_operand" "")])
6571 (label_ref (match_operand 3 "" ""))
6573 "TARGET_THUMB1 || TARGET_32BIT"
6577 if (!arm_add_operand (operands[2], SImode))
6578 operands[2] = force_reg (SImode, operands[2]);
6579 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6583 if (thumb1_cmpneg_operand (operands[2], SImode))
6585 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6586 operands[3], operands[0]));
6589 if (!thumb1_cmp_operand (operands[2], SImode))
6590 operands[2] = force_reg (SImode, operands[2]);
6593 ;; A pattern to recognize a special situation and optimize for it.
6594 ;; On the thumb, zero-extension from memory is preferrable to sign-extension
6595 ;; due to the available addressing modes. Hence, convert a signed comparison
6596 ;; with zero into an unsigned comparison with 127 if possible.
6597 (define_expand "cbranchqi4"
6598 [(set (pc) (if_then_else
6599 (match_operator 0 "lt_ge_comparison_operator"
6600 [(match_operand:QI 1 "memory_operand" "")
6601 (match_operand:QI 2 "const0_operand" "")])
6602 (label_ref (match_operand 3 "" ""))
6607 xops[1] = gen_reg_rtx (SImode);
6608 emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
6609 xops[2] = GEN_INT (127);
6610 xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
6611 VOIDmode, xops[1], xops[2]);
6612 xops[3] = operands[3];
6613 emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
6617 (define_expand "cbranchsf4"
6618 [(set (pc) (if_then_else
6619 (match_operator 0 "arm_comparison_operator"
6620 [(match_operand:SF 1 "s_register_operand" "")
6621 (match_operand:SF 2 "arm_float_compare_operand" "")])
6622 (label_ref (match_operand 3 "" ""))
6624 "TARGET_32BIT && TARGET_HARD_FLOAT"
6625 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6626 operands[3])); DONE;"
6629 (define_expand "cbranchdf4"
6630 [(set (pc) (if_then_else
6631 (match_operator 0 "arm_comparison_operator"
6632 [(match_operand:DF 1 "s_register_operand" "")
6633 (match_operand:DF 2 "arm_float_compare_operand" "")])
6634 (label_ref (match_operand 3 "" ""))
6636 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
6637 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6638 operands[3])); DONE;"
6641 (define_expand "cbranchdi4"
6642 [(set (pc) (if_then_else
6643 (match_operator 0 "arm_comparison_operator"
6644 [(match_operand:DI 1 "cmpdi_operand" "")
6645 (match_operand:DI 2 "cmpdi_operand" "")])
6646 (label_ref (match_operand 3 "" ""))
6650 rtx swap = NULL_RTX;
6651 enum rtx_code code = GET_CODE (operands[0]);
6653 /* We should not have two constants. */
6654 gcc_assert (GET_MODE (operands[1]) == DImode
6655 || GET_MODE (operands[2]) == DImode);
6657 /* Flip unimplemented DImode comparisons to a form that
6658 arm_gen_compare_reg can handle. */
6662 swap = gen_rtx_LT (VOIDmode, operands[2], operands[1]); break;
6664 swap = gen_rtx_GE (VOIDmode, operands[2], operands[1]); break;
6666 swap = gen_rtx_LTU (VOIDmode, operands[2], operands[1]); break;
6668 swap = gen_rtx_GEU (VOIDmode, operands[2], operands[1]); break;
6673 emit_jump_insn (gen_cbranch_cc (swap, operands[2], operands[1],
6676 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6682 (define_insn "cbranchsi4_insn"
6683 [(set (pc) (if_then_else
6684 (match_operator 0 "arm_comparison_operator"
6685 [(match_operand:SI 1 "s_register_operand" "l,l*h")
6686 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
6687 (label_ref (match_operand 3 "" ""))
6691 rtx t = cfun->machine->thumb1_cc_insn;
6694 if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
6695 || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2]))
6697 if (cfun->machine->thumb1_cc_mode == CC_NOOVmode)
6699 if (!noov_comparison_operator (operands[0], VOIDmode))
6702 else if (cfun->machine->thumb1_cc_mode != CCmode)
6707 output_asm_insn ("cmp\t%1, %2", operands);
6708 cfun->machine->thumb1_cc_insn = insn;
6709 cfun->machine->thumb1_cc_op0 = operands[1];
6710 cfun->machine->thumb1_cc_op1 = operands[2];
6711 cfun->machine->thumb1_cc_mode = CCmode;
6714 /* Ensure we emit the right type of condition code on the jump. */
6715 XEXP (operands[0], 0) = gen_rtx_REG (cfun->machine->thumb1_cc_mode,
6718 switch (get_attr_length (insn))
6720 case 4: return \"b%d0\\t%l3\";
6721 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6722 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6725 [(set (attr "far_jump")
6727 (eq_attr "length" "8")
6728 (const_string "yes")
6729 (const_string "no")))
6730 (set (attr "length")
6732 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6733 (le (minus (match_dup 3) (pc)) (const_int 256)))
6736 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6737 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6742 (define_insn "cbranchsi4_scratch"
6743 [(set (pc) (if_then_else
6744 (match_operator 4 "arm_comparison_operator"
6745 [(match_operand:SI 1 "s_register_operand" "l,0")
6746 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
6747 (label_ref (match_operand 3 "" ""))
6749 (clobber (match_scratch:SI 0 "=l,l"))]
6752 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6754 switch (get_attr_length (insn))
6756 case 4: return \"b%d4\\t%l3\";
6757 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6758 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6761 [(set (attr "far_jump")
6763 (eq_attr "length" "8")
6764 (const_string "yes")
6765 (const_string "no")))
6766 (set (attr "length")
6768 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6769 (le (minus (match_dup 3) (pc)) (const_int 256)))
6772 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6773 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6778 ;; Two peepholes to generate subtract of 0 instead of a move if the
6779 ;; condition codes will be useful.
6781 [(set (match_operand:SI 0 "low_register_operand" "")
6782 (match_operand:SI 1 "low_register_operand" ""))
6784 (if_then_else (match_operator 2 "arm_comparison_operator"
6785 [(match_dup 1) (const_int 0)])
6786 (label_ref (match_operand 3 "" ""))
6789 [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
6791 (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
6792 (label_ref (match_dup 3))
6796 ;; Sigh! This variant shouldn't be needed, but combine often fails to
6797 ;; merge cases like this because the op1 is a hard register in
6798 ;; arm_class_likely_spilled_p.
6800 [(set (match_operand:SI 0 "low_register_operand" "")
6801 (match_operand:SI 1 "low_register_operand" ""))
6803 (if_then_else (match_operator 2 "arm_comparison_operator"
6804 [(match_dup 0) (const_int 0)])
6805 (label_ref (match_operand 3 "" ""))
6808 [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
6810 (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
6811 (label_ref (match_dup 3))
6815 (define_insn "*negated_cbranchsi4"
6818 (match_operator 0 "equality_operator"
6819 [(match_operand:SI 1 "s_register_operand" "l")
6820 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
6821 (label_ref (match_operand 3 "" ""))
6825 output_asm_insn (\"cmn\\t%1, %2\", operands);
6826 switch (get_attr_length (insn))
6828 case 4: return \"b%d0\\t%l3\";
6829 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6830 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6833 [(set (attr "far_jump")
6835 (eq_attr "length" "8")
6836 (const_string "yes")
6837 (const_string "no")))
6838 (set (attr "length")
6840 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6841 (le (minus (match_dup 3) (pc)) (const_int 256)))
6844 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6845 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6850 (define_insn "*tbit_cbranch"
6853 (match_operator 0 "equality_operator"
6854 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6856 (match_operand:SI 2 "const_int_operand" "i"))
6858 (label_ref (match_operand 3 "" ""))
6860 (clobber (match_scratch:SI 4 "=l"))]
6865 op[0] = operands[4];
6866 op[1] = operands[1];
6867 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6869 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6870 switch (get_attr_length (insn))
6872 case 4: return \"b%d0\\t%l3\";
6873 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6874 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6877 [(set (attr "far_jump")
6879 (eq_attr "length" "8")
6880 (const_string "yes")
6881 (const_string "no")))
6882 (set (attr "length")
6884 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6885 (le (minus (match_dup 3) (pc)) (const_int 256)))
6888 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6889 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6894 (define_insn "*tlobits_cbranch"
6897 (match_operator 0 "equality_operator"
6898 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6899 (match_operand:SI 2 "const_int_operand" "i")
6902 (label_ref (match_operand 3 "" ""))
6904 (clobber (match_scratch:SI 4 "=l"))]
6909 op[0] = operands[4];
6910 op[1] = operands[1];
6911 op[2] = GEN_INT (32 - INTVAL (operands[2]));
6913 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6914 switch (get_attr_length (insn))
6916 case 4: return \"b%d0\\t%l3\";
6917 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6918 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6921 [(set (attr "far_jump")
6923 (eq_attr "length" "8")
6924 (const_string "yes")
6925 (const_string "no")))
6926 (set (attr "length")
6928 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6929 (le (minus (match_dup 3) (pc)) (const_int 256)))
6932 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6933 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6938 (define_insn "*tstsi3_cbranch"
6941 (match_operator 3 "equality_operator"
6942 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6943 (match_operand:SI 1 "s_register_operand" "l"))
6945 (label_ref (match_operand 2 "" ""))
6950 output_asm_insn (\"tst\\t%0, %1\", operands);
6951 switch (get_attr_length (insn))
6953 case 4: return \"b%d3\\t%l2\";
6954 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6955 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6958 [(set (attr "far_jump")
6960 (eq_attr "length" "8")
6961 (const_string "yes")
6962 (const_string "no")))
6963 (set (attr "length")
6965 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6966 (le (minus (match_dup 2) (pc)) (const_int 256)))
6969 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6970 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6975 (define_insn "*cbranchne_decr1"
6977 (if_then_else (match_operator 3 "equality_operator"
6978 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6980 (label_ref (match_operand 4 "" ""))
6982 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6983 (plus:SI (match_dup 2) (const_int -1)))
6984 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6989 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6991 VOIDmode, operands[2], const1_rtx);
6992 cond[1] = operands[4];
6994 if (which_alternative == 0)
6995 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6996 else if (which_alternative == 1)
6998 /* We must provide an alternative for a hi reg because reload
6999 cannot handle output reloads on a jump instruction, but we
7000 can't subtract into that. Fortunately a mov from lo to hi
7001 does not clobber the condition codes. */
7002 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7003 output_asm_insn (\"mov\\t%0, %1\", operands);
7007 /* Similarly, but the target is memory. */
7008 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7009 output_asm_insn (\"str\\t%1, %0\", operands);
7012 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7015 output_asm_insn (\"b%d0\\t%l1\", cond);
7018 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
7019 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
7021 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
7022 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7026 [(set (attr "far_jump")
7028 (ior (and (eq (symbol_ref ("which_alternative"))
7030 (eq_attr "length" "8"))
7031 (eq_attr "length" "10"))
7032 (const_string "yes")
7033 (const_string "no")))
7034 (set_attr_alternative "length"
7038 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7039 (le (minus (match_dup 4) (pc)) (const_int 256)))
7042 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7043 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7048 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7049 (le (minus (match_dup 4) (pc)) (const_int 256)))
7052 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7053 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7058 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7059 (le (minus (match_dup 4) (pc)) (const_int 256)))
7062 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7063 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7068 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7069 (le (minus (match_dup 4) (pc)) (const_int 256)))
7072 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7073 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7078 (define_insn "*addsi3_cbranch"
7081 (match_operator 4 "arm_comparison_operator"
7083 (match_operand:SI 2 "s_register_operand" "%0,l,*l,1,1,1")
7084 (match_operand:SI 3 "reg_or_int_operand" "IJ,lL,*l,lIJ,lIJ,lIJ"))
7086 (label_ref (match_operand 5 "" ""))
7089 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
7090 (plus:SI (match_dup 2) (match_dup 3)))
7091 (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
7093 && (GET_CODE (operands[4]) == EQ
7094 || GET_CODE (operands[4]) == NE
7095 || GET_CODE (operands[4]) == GE
7096 || GET_CODE (operands[4]) == LT)"
7101 cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
7102 cond[1] = operands[2];
7103 cond[2] = operands[3];
7105 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
7106 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
7108 output_asm_insn (\"add\\t%0, %1, %2\", cond);
7110 if (which_alternative >= 2
7111 && which_alternative < 4)
7112 output_asm_insn (\"mov\\t%0, %1\", operands);
7113 else if (which_alternative >= 4)
7114 output_asm_insn (\"str\\t%1, %0\", operands);
7116 switch (get_attr_length (insn) - ((which_alternative >= 2) ? 2 : 0))
7119 return \"b%d4\\t%l5\";
7121 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7123 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7127 [(set (attr "far_jump")
7129 (ior (and (lt (symbol_ref ("which_alternative"))
7131 (eq_attr "length" "8"))
7132 (eq_attr "length" "10"))
7133 (const_string "yes")
7134 (const_string "no")))
7135 (set (attr "length")
7137 (lt (symbol_ref ("which_alternative"))
7140 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7141 (le (minus (match_dup 5) (pc)) (const_int 256)))
7144 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7145 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7149 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7150 (le (minus (match_dup 5) (pc)) (const_int 256)))
7153 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7154 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7159 (define_insn "*addsi3_cbranch_scratch"
7162 (match_operator 3 "arm_comparison_operator"
7164 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
7165 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
7167 (label_ref (match_operand 4 "" ""))
7169 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
7171 && (GET_CODE (operands[3]) == EQ
7172 || GET_CODE (operands[3]) == NE
7173 || GET_CODE (operands[3]) == GE
7174 || GET_CODE (operands[3]) == LT)"
7177 switch (which_alternative)
7180 output_asm_insn (\"cmp\t%1, #%n2\", operands);
7183 output_asm_insn (\"cmn\t%1, %2\", operands);
7186 if (INTVAL (operands[2]) < 0)
7187 output_asm_insn (\"sub\t%0, %1, %2\", operands);
7189 output_asm_insn (\"add\t%0, %1, %2\", operands);
7192 if (INTVAL (operands[2]) < 0)
7193 output_asm_insn (\"sub\t%0, %0, %2\", operands);
7195 output_asm_insn (\"add\t%0, %0, %2\", operands);
7199 switch (get_attr_length (insn))
7202 return \"b%d3\\t%l4\";
7204 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7206 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7210 [(set (attr "far_jump")
7212 (eq_attr "length" "8")
7213 (const_string "yes")
7214 (const_string "no")))
7215 (set (attr "length")
7217 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7218 (le (minus (match_dup 4) (pc)) (const_int 256)))
7221 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7222 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7228 ;; Comparison and test insns
7230 (define_insn "*arm_cmpsi_insn"
7231 [(set (reg:CC CC_REGNUM)
7232 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r")
7233 (match_operand:SI 1 "arm_add_operand" "Py,r,rI,L")))]
7240 [(set_attr "conds" "set")
7241 (set_attr "arch" "t2,t2,any,any")
7242 (set_attr "length" "2,2,4,4")]
7245 (define_insn "*cmpsi_shiftsi"
7246 [(set (reg:CC CC_REGNUM)
7247 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
7248 (match_operator:SI 3 "shift_operator"
7249 [(match_operand:SI 1 "s_register_operand" "r,r")
7250 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
7253 [(set_attr "conds" "set")
7254 (set_attr "shift" "1")
7255 (set_attr "arch" "32,a")
7256 (set_attr "type" "alu_shift,alu_shift_reg")])
7258 (define_insn "*cmpsi_shiftsi_swp"
7259 [(set (reg:CC_SWP CC_REGNUM)
7260 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
7261 [(match_operand:SI 1 "s_register_operand" "r,r")
7262 (match_operand:SI 2 "shift_amount_operand" "M,rM")])
7263 (match_operand:SI 0 "s_register_operand" "r,r")))]
7266 [(set_attr "conds" "set")
7267 (set_attr "shift" "1")
7268 (set_attr "arch" "32,a")
7269 (set_attr "type" "alu_shift,alu_shift_reg")])
7271 (define_insn "*arm_cmpsi_negshiftsi_si"
7272 [(set (reg:CC_Z CC_REGNUM)
7274 (neg:SI (match_operator:SI 1 "shift_operator"
7275 [(match_operand:SI 2 "s_register_operand" "r")
7276 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7277 (match_operand:SI 0 "s_register_operand" "r")))]
7280 [(set_attr "conds" "set")
7281 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7282 (const_string "alu_shift")
7283 (const_string "alu_shift_reg")))]
7286 ;; DImode comparisons. The generic code generates branches that
7287 ;; if-conversion can not reduce to a conditional compare, so we do
7290 (define_insn "*arm_cmpdi_insn"
7291 [(set (reg:CC_NCV CC_REGNUM)
7292 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7293 (match_operand:DI 1 "arm_di_operand" "rDi")))
7294 (clobber (match_scratch:SI 2 "=r"))]
7295 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
7296 "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7297 [(set_attr "conds" "set")
7298 (set_attr "length" "8")]
7301 (define_insn "*arm_cmpdi_unsigned"
7302 [(set (reg:CC_CZ CC_REGNUM)
7303 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "r")
7304 (match_operand:DI 1 "arm_di_operand" "rDi")))]
7306 "cmp%?\\t%R0, %R1\;cmpeq\\t%Q0, %Q1"
7307 [(set_attr "conds" "set")
7308 (set_attr "length" "8")]
7311 (define_insn "*arm_cmpdi_zero"
7312 [(set (reg:CC_Z CC_REGNUM)
7313 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7315 (clobber (match_scratch:SI 1 "=r"))]
7317 "orr%.\\t%1, %Q0, %R0"
7318 [(set_attr "conds" "set")]
7321 (define_insn "*thumb_cmpdi_zero"
7322 [(set (reg:CC_Z CC_REGNUM)
7323 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
7325 (clobber (match_scratch:SI 1 "=l"))]
7327 "orr\\t%1, %Q0, %R0"
7328 [(set_attr "conds" "set")
7329 (set_attr "length" "2")]
7332 ;; Cirrus SF compare instruction
7333 (define_insn "*cirrus_cmpsf"
7334 [(set (reg:CCFP CC_REGNUM)
7335 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7336 (match_operand:SF 1 "cirrus_fp_register" "v")))]
7337 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7338 "cfcmps%?\\tr15, %V0, %V1"
7339 [(set_attr "type" "mav_farith")
7340 (set_attr "cirrus" "compare")]
7343 ;; Cirrus DF compare instruction
7344 (define_insn "*cirrus_cmpdf"
7345 [(set (reg:CCFP CC_REGNUM)
7346 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7347 (match_operand:DF 1 "cirrus_fp_register" "v")))]
7348 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7349 "cfcmpd%?\\tr15, %V0, %V1"
7350 [(set_attr "type" "mav_farith")
7351 (set_attr "cirrus" "compare")]
7354 (define_insn "*cirrus_cmpdi"
7355 [(set (reg:CC CC_REGNUM)
7356 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7357 (match_operand:DI 1 "cirrus_fp_register" "v")))]
7358 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7359 "cfcmp64%?\\tr15, %V0, %V1"
7360 [(set_attr "type" "mav_farith")
7361 (set_attr "cirrus" "compare")]
7364 ; This insn allows redundant compares to be removed by cse, nothing should
7365 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7366 ; is deleted later on. The match_dup will match the mode here, so that
7367 ; mode changes of the condition codes aren't lost by this even though we don't
7368 ; specify what they are.
7370 (define_insn "*deleted_compare"
7371 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
7373 "\\t%@ deleted compare"
7374 [(set_attr "conds" "set")
7375 (set_attr "length" "0")]
7379 ;; Conditional branch insns
7381 (define_expand "cbranch_cc"
7383 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7384 (match_operand 2 "" "")])
7385 (label_ref (match_operand 3 "" ""))
7388 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
7389 operands[1], operands[2]);
7390 operands[2] = const0_rtx;"
7394 ;; Patterns to match conditional branch insns.
7397 (define_insn "*arm_cond_branch"
7399 (if_then_else (match_operator 1 "arm_comparison_operator"
7400 [(match_operand 2 "cc_register" "") (const_int 0)])
7401 (label_ref (match_operand 0 "" ""))
7405 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7407 arm_ccfsm_state += 2;
7410 return \"b%d1\\t%l0\";
7412 [(set_attr "conds" "use")
7413 (set_attr "type" "branch")
7414 (set (attr "length")
7416 (and (match_test "TARGET_THUMB2")
7417 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7418 (le (minus (match_dup 0) (pc)) (const_int 256))))
7423 (define_insn "*arm_cond_branch_reversed"
7425 (if_then_else (match_operator 1 "arm_comparison_operator"
7426 [(match_operand 2 "cc_register" "") (const_int 0)])
7428 (label_ref (match_operand 0 "" ""))))]
7431 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7433 arm_ccfsm_state += 2;
7436 return \"b%D1\\t%l0\";
7438 [(set_attr "conds" "use")
7439 (set_attr "type" "branch")
7440 (set (attr "length")
7442 (and (match_test "TARGET_THUMB2")
7443 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7444 (le (minus (match_dup 0) (pc)) (const_int 256))))
7453 (define_expand "cstore_cc"
7454 [(set (match_operand:SI 0 "s_register_operand" "")
7455 (match_operator:SI 1 "" [(match_operand 2 "" "")
7456 (match_operand 3 "" "")]))]
7458 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7459 operands[2], operands[3]);
7460 operands[3] = const0_rtx;"
7463 (define_insn "*mov_scc"
7464 [(set (match_operand:SI 0 "s_register_operand" "=r")
7465 (match_operator:SI 1 "arm_comparison_operator"
7466 [(match_operand 2 "cc_register" "") (const_int 0)]))]
7468 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7469 [(set_attr "conds" "use")
7470 (set_attr "insn" "mov")
7471 (set_attr "length" "8")]
7474 (define_insn "*mov_negscc"
7475 [(set (match_operand:SI 0 "s_register_operand" "=r")
7476 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7477 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7479 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7480 [(set_attr "conds" "use")
7481 (set_attr "insn" "mov")
7482 (set_attr "length" "8")]
7485 (define_insn "*mov_notscc"
7486 [(set (match_operand:SI 0 "s_register_operand" "=r")
7487 (not:SI (match_operator:SI 1 "arm_comparison_operator"
7488 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7490 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7491 [(set_attr "conds" "use")
7492 (set_attr "insn" "mov")
7493 (set_attr "length" "8")]
7496 (define_expand "cstoresi4"
7497 [(set (match_operand:SI 0 "s_register_operand" "")
7498 (match_operator:SI 1 "arm_comparison_operator"
7499 [(match_operand:SI 2 "s_register_operand" "")
7500 (match_operand:SI 3 "reg_or_int_operand" "")]))]
7501 "TARGET_32BIT || TARGET_THUMB1"
7503 rtx op3, scratch, scratch2;
7507 if (!arm_add_operand (operands[3], SImode))
7508 operands[3] = force_reg (SImode, operands[3]);
7509 emit_insn (gen_cstore_cc (operands[0], operands[1],
7510 operands[2], operands[3]));
7514 if (operands[3] == const0_rtx)
7516 switch (GET_CODE (operands[1]))
7519 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
7523 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
7527 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7528 NULL_RTX, 0, OPTAB_WIDEN);
7529 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7530 NULL_RTX, 0, OPTAB_WIDEN);
7531 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7532 operands[0], 1, OPTAB_WIDEN);
7536 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7538 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7539 NULL_RTX, 1, OPTAB_WIDEN);
7543 scratch = expand_binop (SImode, ashr_optab, operands[2],
7544 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7545 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7546 NULL_RTX, 0, OPTAB_WIDEN);
7547 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7551 /* LT is handled by generic code. No need for unsigned with 0. */
7558 switch (GET_CODE (operands[1]))
7561 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7562 NULL_RTX, 0, OPTAB_WIDEN);
7563 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
7567 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7568 NULL_RTX, 0, OPTAB_WIDEN);
7569 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
7573 op3 = force_reg (SImode, operands[3]);
7575 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7576 NULL_RTX, 1, OPTAB_WIDEN);
7577 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7578 NULL_RTX, 0, OPTAB_WIDEN);
7579 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
7585 if (!thumb1_cmp_operand (op3, SImode))
7586 op3 = force_reg (SImode, op3);
7587 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7588 NULL_RTX, 0, OPTAB_WIDEN);
7589 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7590 NULL_RTX, 1, OPTAB_WIDEN);
7591 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
7596 op3 = force_reg (SImode, operands[3]);
7597 scratch = force_reg (SImode, const0_rtx);
7598 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
7604 if (!thumb1_cmp_operand (op3, SImode))
7605 op3 = force_reg (SImode, op3);
7606 scratch = force_reg (SImode, const0_rtx);
7607 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
7613 if (!thumb1_cmp_operand (op3, SImode))
7614 op3 = force_reg (SImode, op3);
7615 scratch = gen_reg_rtx (SImode);
7616 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
7620 op3 = force_reg (SImode, operands[3]);
7621 scratch = gen_reg_rtx (SImode);
7622 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
7625 /* No good sequences for GT, LT. */
7632 (define_expand "cstoresf4"
7633 [(set (match_operand:SI 0 "s_register_operand" "")
7634 (match_operator:SI 1 "arm_comparison_operator"
7635 [(match_operand:SF 2 "s_register_operand" "")
7636 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
7637 "TARGET_32BIT && TARGET_HARD_FLOAT"
7638 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7639 operands[2], operands[3])); DONE;"
7642 (define_expand "cstoredf4"
7643 [(set (match_operand:SI 0 "s_register_operand" "")
7644 (match_operator:SI 1 "arm_comparison_operator"
7645 [(match_operand:DF 2 "s_register_operand" "")
7646 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
7647 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
7648 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7649 operands[2], operands[3])); DONE;"
7652 (define_expand "cstoredi4"
7653 [(set (match_operand:SI 0 "s_register_operand" "")
7654 (match_operator:SI 1 "arm_comparison_operator"
7655 [(match_operand:DI 2 "cmpdi_operand" "")
7656 (match_operand:DI 3 "cmpdi_operand" "")]))]
7659 rtx swap = NULL_RTX;
7660 enum rtx_code code = GET_CODE (operands[1]);
7662 /* We should not have two constants. */
7663 gcc_assert (GET_MODE (operands[2]) == DImode
7664 || GET_MODE (operands[3]) == DImode);
7666 /* Flip unimplemented DImode comparisons to a form that
7667 arm_gen_compare_reg can handle. */
7671 swap = gen_rtx_LT (VOIDmode, operands[3], operands[2]); break;
7673 swap = gen_rtx_GE (VOIDmode, operands[3], operands[2]); break;
7675 swap = gen_rtx_LTU (VOIDmode, operands[3], operands[2]); break;
7677 swap = gen_rtx_GEU (VOIDmode, operands[3], operands[2]); break;
7682 emit_insn (gen_cstore_cc (operands[0], swap, operands[3],
7685 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
7691 (define_expand "cstoresi_eq0_thumb1"
7693 [(set (match_operand:SI 0 "s_register_operand" "")
7694 (eq:SI (match_operand:SI 1 "s_register_operand" "")
7696 (clobber (match_dup:SI 2))])]
7698 "operands[2] = gen_reg_rtx (SImode);"
7701 (define_expand "cstoresi_ne0_thumb1"
7703 [(set (match_operand:SI 0 "s_register_operand" "")
7704 (ne:SI (match_operand:SI 1 "s_register_operand" "")
7706 (clobber (match_dup:SI 2))])]
7708 "operands[2] = gen_reg_rtx (SImode);"
7711 (define_insn "*cstoresi_eq0_thumb1_insn"
7712 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
7713 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
7715 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
7718 neg\\t%0, %1\;adc\\t%0, %0, %1
7719 neg\\t%2, %1\;adc\\t%0, %1, %2"
7720 [(set_attr "length" "4")]
7723 (define_insn "*cstoresi_ne0_thumb1_insn"
7724 [(set (match_operand:SI 0 "s_register_operand" "=l")
7725 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
7727 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
7729 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
7730 [(set_attr "length" "4")]
7733 ;; Used as part of the expansion of thumb ltu and gtu sequences
7734 (define_insn "cstoresi_nltu_thumb1"
7735 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
7736 (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
7737 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
7739 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
7740 [(set_attr "length" "4")]
7743 (define_insn_and_split "cstoresi_ltu_thumb1"
7744 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
7745 (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
7746 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
7751 (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
7752 (set (match_dup 0) (neg:SI (match_dup 3)))]
7753 "operands[3] = gen_reg_rtx (SImode);"
7754 [(set_attr "length" "4")]
7757 ;; Used as part of the expansion of thumb les sequence.
7758 (define_insn "thumb1_addsi3_addgeu"
7759 [(set (match_operand:SI 0 "s_register_operand" "=l")
7760 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7761 (match_operand:SI 2 "s_register_operand" "l"))
7762 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
7763 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
7765 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
7766 [(set_attr "length" "4")]
7770 ;; Conditional move insns
7772 (define_expand "movsicc"
7773 [(set (match_operand:SI 0 "s_register_operand" "")
7774 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7775 (match_operand:SI 2 "arm_not_operand" "")
7776 (match_operand:SI 3 "arm_not_operand" "")))]
7780 enum rtx_code code = GET_CODE (operands[1]);
7783 if (code == UNEQ || code == LTGT)
7786 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7787 XEXP (operands[1], 1));
7788 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7792 (define_expand "movsfcc"
7793 [(set (match_operand:SF 0 "s_register_operand" "")
7794 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7795 (match_operand:SF 2 "s_register_operand" "")
7796 (match_operand:SF 3 "nonmemory_operand" "")))]
7797 "TARGET_32BIT && TARGET_HARD_FLOAT"
7800 enum rtx_code code = GET_CODE (operands[1]);
7803 if (code == UNEQ || code == LTGT)
7806 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
7807 Otherwise, ensure it is a valid FP add operand */
7808 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7809 || (!arm_float_add_operand (operands[3], SFmode)))
7810 operands[3] = force_reg (SFmode, operands[3]);
7812 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7813 XEXP (operands[1], 1));
7814 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7818 (define_expand "movdfcc"
7819 [(set (match_operand:DF 0 "s_register_operand" "")
7820 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7821 (match_operand:DF 2 "s_register_operand" "")
7822 (match_operand:DF 3 "arm_float_add_operand" "")))]
7823 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7826 enum rtx_code code = GET_CODE (operands[1]);
7829 if (code == UNEQ || code == LTGT)
7832 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7833 XEXP (operands[1], 1));
7834 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7838 (define_insn "*movsicc_insn"
7839 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7841 (match_operator 3 "arm_comparison_operator"
7842 [(match_operand 4 "cc_register" "") (const_int 0)])
7843 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7844 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7851 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7852 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7853 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7854 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7855 [(set_attr "length" "4,4,4,4,8,8,8,8")
7856 (set_attr "conds" "use")
7857 (set_attr "insn" "mov,mvn,mov,mvn,mov,mov,mvn,mvn")]
7860 (define_insn "*movsfcc_soft_insn"
7861 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7862 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7863 [(match_operand 4 "cc_register" "") (const_int 0)])
7864 (match_operand:SF 1 "s_register_operand" "0,r")
7865 (match_operand:SF 2 "s_register_operand" "r,0")))]
7866 "TARGET_ARM && TARGET_SOFT_FLOAT"
7870 [(set_attr "conds" "use")
7871 (set_attr "insn" "mov")]
7875 ;; Jump and linkage insns
7877 (define_expand "jump"
7879 (label_ref (match_operand 0 "" "")))]
7884 (define_insn "*arm_jump"
7886 (label_ref (match_operand 0 "" "")))]
7890 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7892 arm_ccfsm_state += 2;
7895 return \"b%?\\t%l0\";
7898 [(set_attr "predicable" "yes")
7899 (set (attr "length")
7901 (and (match_test "TARGET_THUMB2")
7902 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7903 (le (minus (match_dup 0) (pc)) (const_int 2048))))
7908 (define_insn "*thumb_jump"
7910 (label_ref (match_operand 0 "" "")))]
7913 if (get_attr_length (insn) == 2)
7915 return \"bl\\t%l0\\t%@ far jump\";
7917 [(set (attr "far_jump")
7919 (eq_attr "length" "4")
7920 (const_string "yes")
7921 (const_string "no")))
7922 (set (attr "length")
7924 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7925 (le (minus (match_dup 0) (pc)) (const_int 2048)))
7930 (define_expand "call"
7931 [(parallel [(call (match_operand 0 "memory_operand" "")
7932 (match_operand 1 "general_operand" ""))
7933 (use (match_operand 2 "" ""))
7934 (clobber (reg:SI LR_REGNUM))])]
7940 /* In an untyped call, we can get NULL for operand 2. */
7941 if (operands[2] == NULL_RTX)
7942 operands[2] = const0_rtx;
7944 /* Decide if we should generate indirect calls by loading the
7945 32-bit address of the callee into a register before performing the
7947 callee = XEXP (operands[0], 0);
7948 if (GET_CODE (callee) == SYMBOL_REF
7949 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7951 XEXP (operands[0], 0) = force_reg (Pmode, callee);
7953 pat = gen_call_internal (operands[0], operands[1], operands[2]);
7954 arm_emit_call_insn (pat, XEXP (operands[0], 0));
7959 (define_expand "call_internal"
7960 [(parallel [(call (match_operand 0 "memory_operand" "")
7961 (match_operand 1 "general_operand" ""))
7962 (use (match_operand 2 "" ""))
7963 (clobber (reg:SI LR_REGNUM))])])
7965 (define_insn "*call_reg_armv5"
7966 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7967 (match_operand 1 "" ""))
7968 (use (match_operand 2 "" ""))
7969 (clobber (reg:SI LR_REGNUM))]
7970 "TARGET_ARM && arm_arch5"
7972 [(set_attr "type" "call")]
7975 (define_insn "*call_reg_arm"
7976 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7977 (match_operand 1 "" ""))
7978 (use (match_operand 2 "" ""))
7979 (clobber (reg:SI LR_REGNUM))]
7980 "TARGET_ARM && !arm_arch5"
7982 return output_call (operands);
7984 ;; length is worst case, normally it is only two
7985 [(set_attr "length" "12")
7986 (set_attr "type" "call")]
7990 ;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
7991 ;; considered a function call by the branch predictor of some cores (PR40887).
7992 ;; Falls back to blx rN (*call_reg_armv5).
7994 (define_insn "*call_mem"
7995 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
7996 (match_operand 1 "" ""))
7997 (use (match_operand 2 "" ""))
7998 (clobber (reg:SI LR_REGNUM))]
7999 "TARGET_ARM && !arm_arch5"
8001 return output_call_mem (operands);
8003 [(set_attr "length" "12")
8004 (set_attr "type" "call")]
8007 (define_insn "*call_reg_thumb1_v5"
8008 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8009 (match_operand 1 "" ""))
8010 (use (match_operand 2 "" ""))
8011 (clobber (reg:SI LR_REGNUM))]
8012 "TARGET_THUMB1 && arm_arch5"
8014 [(set_attr "length" "2")
8015 (set_attr "type" "call")]
8018 (define_insn "*call_reg_thumb1"
8019 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8020 (match_operand 1 "" ""))
8021 (use (match_operand 2 "" ""))
8022 (clobber (reg:SI LR_REGNUM))]
8023 "TARGET_THUMB1 && !arm_arch5"
8026 if (!TARGET_CALLER_INTERWORKING)
8027 return thumb_call_via_reg (operands[0]);
8028 else if (operands[1] == const0_rtx)
8029 return \"bl\\t%__interwork_call_via_%0\";
8030 else if (frame_pointer_needed)
8031 return \"bl\\t%__interwork_r7_call_via_%0\";
8033 return \"bl\\t%__interwork_r11_call_via_%0\";
8035 [(set_attr "type" "call")]
8038 (define_expand "call_value"
8039 [(parallel [(set (match_operand 0 "" "")
8040 (call (match_operand 1 "memory_operand" "")
8041 (match_operand 2 "general_operand" "")))
8042 (use (match_operand 3 "" ""))
8043 (clobber (reg:SI LR_REGNUM))])]
8049 /* In an untyped call, we can get NULL for operand 2. */
8050 if (operands[3] == 0)
8051 operands[3] = const0_rtx;
8053 /* Decide if we should generate indirect calls by loading the
8054 32-bit address of the callee into a register before performing the
8056 callee = XEXP (operands[1], 0);
8057 if (GET_CODE (callee) == SYMBOL_REF
8058 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8060 XEXP (operands[1], 0) = force_reg (Pmode, callee);
8062 pat = gen_call_value_internal (operands[0], operands[1],
8063 operands[2], operands[3]);
8064 arm_emit_call_insn (pat, XEXP (operands[1], 0));
8069 (define_expand "call_value_internal"
8070 [(parallel [(set (match_operand 0 "" "")
8071 (call (match_operand 1 "memory_operand" "")
8072 (match_operand 2 "general_operand" "")))
8073 (use (match_operand 3 "" ""))
8074 (clobber (reg:SI LR_REGNUM))])])
8076 (define_insn "*call_value_reg_armv5"
8077 [(set (match_operand 0 "" "")
8078 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8079 (match_operand 2 "" "")))
8080 (use (match_operand 3 "" ""))
8081 (clobber (reg:SI LR_REGNUM))]
8082 "TARGET_ARM && arm_arch5"
8084 [(set_attr "type" "call")]
8087 (define_insn "*call_value_reg_arm"
8088 [(set (match_operand 0 "" "")
8089 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8090 (match_operand 2 "" "")))
8091 (use (match_operand 3 "" ""))
8092 (clobber (reg:SI LR_REGNUM))]
8093 "TARGET_ARM && !arm_arch5"
8095 return output_call (&operands[1]);
8097 [(set_attr "length" "12")
8098 (set_attr "type" "call")]
8101 ;; Note: see *call_mem
8103 (define_insn "*call_value_mem"
8104 [(set (match_operand 0 "" "")
8105 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
8106 (match_operand 2 "" "")))
8107 (use (match_operand 3 "" ""))
8108 (clobber (reg:SI LR_REGNUM))]
8109 "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
8111 return output_call_mem (&operands[1]);
8113 [(set_attr "length" "12")
8114 (set_attr "type" "call")]
8117 (define_insn "*call_value_reg_thumb1_v5"
8118 [(set (match_operand 0 "" "")
8119 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8120 (match_operand 2 "" "")))
8121 (use (match_operand 3 "" ""))
8122 (clobber (reg:SI LR_REGNUM))]
8123 "TARGET_THUMB1 && arm_arch5"
8125 [(set_attr "length" "2")
8126 (set_attr "type" "call")]
8129 (define_insn "*call_value_reg_thumb1"
8130 [(set (match_operand 0 "" "")
8131 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8132 (match_operand 2 "" "")))
8133 (use (match_operand 3 "" ""))
8134 (clobber (reg:SI LR_REGNUM))]
8135 "TARGET_THUMB1 && !arm_arch5"
8138 if (!TARGET_CALLER_INTERWORKING)
8139 return thumb_call_via_reg (operands[1]);
8140 else if (operands[2] == const0_rtx)
8141 return \"bl\\t%__interwork_call_via_%1\";
8142 else if (frame_pointer_needed)
8143 return \"bl\\t%__interwork_r7_call_via_%1\";
8145 return \"bl\\t%__interwork_r11_call_via_%1\";
8147 [(set_attr "type" "call")]
8150 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8151 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8153 (define_insn "*call_symbol"
8154 [(call (mem:SI (match_operand:SI 0 "" ""))
8155 (match_operand 1 "" ""))
8156 (use (match_operand 2 "" ""))
8157 (clobber (reg:SI LR_REGNUM))]
8159 && (GET_CODE (operands[0]) == SYMBOL_REF)
8160 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
8163 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
8165 [(set_attr "type" "call")]
8168 (define_insn "*call_value_symbol"
8169 [(set (match_operand 0 "" "")
8170 (call (mem:SI (match_operand:SI 1 "" ""))
8171 (match_operand:SI 2 "" "")))
8172 (use (match_operand 3 "" ""))
8173 (clobber (reg:SI LR_REGNUM))]
8175 && (GET_CODE (operands[1]) == SYMBOL_REF)
8176 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
8179 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
8181 [(set_attr "type" "call")]
8184 (define_insn "*call_insn"
8185 [(call (mem:SI (match_operand:SI 0 "" ""))
8186 (match_operand:SI 1 "" ""))
8187 (use (match_operand 2 "" ""))
8188 (clobber (reg:SI LR_REGNUM))]
8190 && GET_CODE (operands[0]) == SYMBOL_REF
8191 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
8193 [(set_attr "length" "4")
8194 (set_attr "type" "call")]
8197 (define_insn "*call_value_insn"
8198 [(set (match_operand 0 "" "")
8199 (call (mem:SI (match_operand 1 "" ""))
8200 (match_operand 2 "" "")))
8201 (use (match_operand 3 "" ""))
8202 (clobber (reg:SI LR_REGNUM))]
8204 && GET_CODE (operands[1]) == SYMBOL_REF
8205 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
8207 [(set_attr "length" "4")
8208 (set_attr "type" "call")]
8211 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
8212 (define_expand "sibcall"
8213 [(parallel [(call (match_operand 0 "memory_operand" "")
8214 (match_operand 1 "general_operand" ""))
8216 (use (match_operand 2 "" ""))])]
8220 if (operands[2] == NULL_RTX)
8221 operands[2] = const0_rtx;
8225 (define_expand "sibcall_value"
8226 [(parallel [(set (match_operand 0 "" "")
8227 (call (match_operand 1 "memory_operand" "")
8228 (match_operand 2 "general_operand" "")))
8230 (use (match_operand 3 "" ""))])]
8234 if (operands[3] == NULL_RTX)
8235 operands[3] = const0_rtx;
8239 (define_insn "*sibcall_insn"
8240 [(call (mem:SI (match_operand:SI 0 "" "X"))
8241 (match_operand 1 "" ""))
8243 (use (match_operand 2 "" ""))]
8244 "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF"
8246 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8248 [(set_attr "type" "call")]
8251 (define_insn "*sibcall_value_insn"
8252 [(set (match_operand 0 "" "")
8253 (call (mem:SI (match_operand:SI 1 "" "X"))
8254 (match_operand 2 "" "")))
8256 (use (match_operand 3 "" ""))]
8257 "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF"
8259 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8261 [(set_attr "type" "call")]
8264 (define_expand "return"
8266 "TARGET_32BIT && USE_RETURN_INSN (FALSE)"
8269 ;; Often the return insn will be the same as loading from memory, so set attr
8270 (define_insn "*arm_return"
8272 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
8275 if (arm_ccfsm_state == 2)
8277 arm_ccfsm_state += 2;
8280 return output_return_instruction (const_true_rtx, TRUE, FALSE);
8282 [(set_attr "type" "load1")
8283 (set_attr "length" "12")
8284 (set_attr "predicable" "yes")]
8287 (define_insn "*cond_return"
8289 (if_then_else (match_operator 0 "arm_comparison_operator"
8290 [(match_operand 1 "cc_register" "") (const_int 0)])
8293 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8296 if (arm_ccfsm_state == 2)
8298 arm_ccfsm_state += 2;
8301 return output_return_instruction (operands[0], TRUE, FALSE);
8303 [(set_attr "conds" "use")
8304 (set_attr "length" "12")
8305 (set_attr "type" "load1")]
8308 (define_insn "*cond_return_inverted"
8310 (if_then_else (match_operator 0 "arm_comparison_operator"
8311 [(match_operand 1 "cc_register" "") (const_int 0)])
8314 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8317 if (arm_ccfsm_state == 2)
8319 arm_ccfsm_state += 2;
8322 return output_return_instruction (operands[0], TRUE, TRUE);
8324 [(set_attr "conds" "use")
8325 (set_attr "length" "12")
8326 (set_attr "type" "load1")]
8329 ;; Generate a sequence of instructions to determine if the processor is
8330 ;; in 26-bit or 32-bit mode, and return the appropriate return address
8333 (define_expand "return_addr_mask"
8335 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8337 (set (match_operand:SI 0 "s_register_operand" "")
8338 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8340 (const_int 67108860)))] ; 0x03fffffc
8343 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
8346 (define_insn "*check_arch2"
8347 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8348 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8351 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8352 [(set_attr "length" "8")
8353 (set_attr "conds" "set")]
8356 ;; Call subroutine returning any type.
8358 (define_expand "untyped_call"
8359 [(parallel [(call (match_operand 0 "" "")
8361 (match_operand 1 "" "")
8362 (match_operand 2 "" "")])]
8367 rtx par = gen_rtx_PARALLEL (VOIDmode,
8368 rtvec_alloc (XVECLEN (operands[2], 0)));
8369 rtx addr = gen_reg_rtx (Pmode);
8373 emit_move_insn (addr, XEXP (operands[1], 0));
8374 mem = change_address (operands[1], BLKmode, addr);
8376 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8378 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
8380 /* Default code only uses r0 as a return value, but we could
8381 be using anything up to 4 registers. */
8382 if (REGNO (src) == R0_REGNUM)
8383 src = gen_rtx_REG (TImode, R0_REGNUM);
8385 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8387 size += GET_MODE_SIZE (GET_MODE (src));
8390 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8395 for (i = 0; i < XVECLEN (par, 0); i++)
8397 HOST_WIDE_INT offset = 0;
8398 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8401 emit_move_insn (addr, plus_constant (addr, size));
8403 mem = change_address (mem, GET_MODE (reg), NULL);
8404 if (REGNO (reg) == R0_REGNUM)
8406 /* On thumb we have to use a write-back instruction. */
8407 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8408 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8409 size = TARGET_ARM ? 16 : 0;
8413 emit_move_insn (mem, reg);
8414 size = GET_MODE_SIZE (GET_MODE (reg));
8418 /* The optimizer does not know that the call sets the function value
8419 registers we stored in the result block. We avoid problems by
8420 claiming that all hard registers are used and clobbered at this
8422 emit_insn (gen_blockage ());
8428 (define_expand "untyped_return"
8429 [(match_operand:BLK 0 "memory_operand" "")
8430 (match_operand 1 "" "")]
8435 rtx addr = gen_reg_rtx (Pmode);
8439 emit_move_insn (addr, XEXP (operands[0], 0));
8440 mem = change_address (operands[0], BLKmode, addr);
8442 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8444 HOST_WIDE_INT offset = 0;
8445 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8448 emit_move_insn (addr, plus_constant (addr, size));
8450 mem = change_address (mem, GET_MODE (reg), NULL);
8451 if (REGNO (reg) == R0_REGNUM)
8453 /* On thumb we have to use a write-back instruction. */
8454 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8455 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8456 size = TARGET_ARM ? 16 : 0;
8460 emit_move_insn (reg, mem);
8461 size = GET_MODE_SIZE (GET_MODE (reg));
8465 /* Emit USE insns before the return. */
8466 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8467 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
8469 /* Construct the return. */
8470 expand_naked_return ();
8476 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8477 ;; all of memory. This blocks insns from being moved across this point.
8479 (define_insn "blockage"
8480 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8483 [(set_attr "length" "0")
8484 (set_attr "type" "block")]
8487 (define_expand "casesi"
8488 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8489 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8490 (match_operand:SI 2 "const_int_operand" "") ; total range
8491 (match_operand:SI 3 "" "") ; table label
8492 (match_operand:SI 4 "" "")] ; Out of range label
8493 "TARGET_32BIT || optimize_size || flag_pic"
8496 enum insn_code code;
8497 if (operands[1] != const0_rtx)
8499 rtx reg = gen_reg_rtx (SImode);
8501 emit_insn (gen_addsi3 (reg, operands[0],
8502 gen_int_mode (-INTVAL (operands[1]),
8508 code = CODE_FOR_arm_casesi_internal;
8509 else if (TARGET_THUMB1)
8510 code = CODE_FOR_thumb1_casesi_internal_pic;
8512 code = CODE_FOR_thumb2_casesi_internal_pic;
8514 code = CODE_FOR_thumb2_casesi_internal;
8516 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8517 operands[2] = force_reg (SImode, operands[2]);
8519 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8520 operands[3], operands[4]));
8525 ;; The USE in this pattern is needed to tell flow analysis that this is
8526 ;; a CASESI insn. It has no other purpose.
8527 (define_insn "arm_casesi_internal"
8528 [(parallel [(set (pc)
8530 (leu (match_operand:SI 0 "s_register_operand" "r")
8531 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8532 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8533 (label_ref (match_operand 2 "" ""))))
8534 (label_ref (match_operand 3 "" ""))))
8535 (clobber (reg:CC CC_REGNUM))
8536 (use (label_ref (match_dup 2)))])]
8540 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8541 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8543 [(set_attr "conds" "clob")
8544 (set_attr "length" "12")]
8547 (define_expand "thumb1_casesi_internal_pic"
8548 [(match_operand:SI 0 "s_register_operand" "")
8549 (match_operand:SI 1 "thumb1_cmp_operand" "")
8550 (match_operand 2 "" "")
8551 (match_operand 3 "" "")]
8555 rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
8556 emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
8558 reg0 = gen_rtx_REG (SImode, 0);
8559 emit_move_insn (reg0, operands[0]);
8560 emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
8565 (define_insn "thumb1_casesi_dispatch"
8566 [(parallel [(set (pc) (unspec [(reg:SI 0)
8567 (label_ref (match_operand 0 "" ""))
8568 ;; (label_ref (match_operand 1 "" ""))
8570 UNSPEC_THUMB1_CASESI))
8571 (clobber (reg:SI IP_REGNUM))
8572 (clobber (reg:SI LR_REGNUM))])]
8574 "* return thumb1_output_casesi(operands);"
8575 [(set_attr "length" "4")]
8578 (define_expand "indirect_jump"
8580 (match_operand:SI 0 "s_register_operand" ""))]
8583 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8584 address and use bx. */
8588 tmp = gen_reg_rtx (SImode);
8589 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8595 ;; NB Never uses BX.
8596 (define_insn "*arm_indirect_jump"
8598 (match_operand:SI 0 "s_register_operand" "r"))]
8600 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8601 [(set_attr "predicable" "yes")]
8604 (define_insn "*load_indirect_jump"
8606 (match_operand:SI 0 "memory_operand" "m"))]
8608 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8609 [(set_attr "type" "load1")
8610 (set_attr "pool_range" "4096")
8611 (set_attr "neg_pool_range" "4084")
8612 (set_attr "predicable" "yes")]
8615 ;; NB Never uses BX.
8616 (define_insn "*thumb1_indirect_jump"
8618 (match_operand:SI 0 "register_operand" "l*r"))]
8621 [(set_attr "conds" "clob")
8622 (set_attr "length" "2")]
8632 if (TARGET_UNIFIED_ASM)
8635 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8636 return \"mov\\tr8, r8\";
8638 [(set (attr "length")
8639 (if_then_else (eq_attr "is_thumb" "yes")
8645 ;; Patterns to allow combination of arithmetic, cond code and shifts
8647 (define_insn "*arith_shiftsi"
8648 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8649 (match_operator:SI 1 "shiftable_operator"
8650 [(match_operator:SI 3 "shift_operator"
8651 [(match_operand:SI 4 "s_register_operand" "r,r,r,r")
8652 (match_operand:SI 5 "shift_amount_operand" "M,M,M,r")])
8653 (match_operand:SI 2 "s_register_operand" "rk,rk,r,rk")]))]
8655 "%i1%?\\t%0, %2, %4%S3"
8656 [(set_attr "predicable" "yes")
8657 (set_attr "shift" "4")
8658 (set_attr "arch" "a,t2,t2,a")
8659 ;; Thumb2 doesn't allow the stack pointer to be used for
8660 ;; operand1 for all operations other than add and sub. In this case
8661 ;; the minus operation is a candidate for an rsub and hence needs
8663 ;; We have to make sure to disable the fourth alternative if
8664 ;; the shift_operator is MULT, since otherwise the insn will
8665 ;; also match a multiply_accumulate pattern and validate_change
8666 ;; will allow a replacement of the constant with a register
8667 ;; despite the checks done in shift_operator.
8668 (set_attr_alternative "insn_enabled"
8669 [(const_string "yes")
8671 (match_operand:SI 1 "add_operator" "")
8672 (const_string "yes") (const_string "no"))
8673 (const_string "yes")
8675 (match_operand:SI 3 "mult_operator" "")
8676 (const_string "no") (const_string "yes"))])
8677 (set_attr "type" "alu_shift,alu_shift,alu_shift,alu_shift_reg")])
8680 [(set (match_operand:SI 0 "s_register_operand" "")
8681 (match_operator:SI 1 "shiftable_operator"
8682 [(match_operator:SI 2 "shiftable_operator"
8683 [(match_operator:SI 3 "shift_operator"
8684 [(match_operand:SI 4 "s_register_operand" "")
8685 (match_operand:SI 5 "reg_or_int_operand" "")])
8686 (match_operand:SI 6 "s_register_operand" "")])
8687 (match_operand:SI 7 "arm_rhs_operand" "")]))
8688 (clobber (match_operand:SI 8 "s_register_operand" ""))]
8691 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8694 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8697 (define_insn "*arith_shiftsi_compare0"
8698 [(set (reg:CC_NOOV CC_REGNUM)
8700 (match_operator:SI 1 "shiftable_operator"
8701 [(match_operator:SI 3 "shift_operator"
8702 [(match_operand:SI 4 "s_register_operand" "r,r")
8703 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8704 (match_operand:SI 2 "s_register_operand" "r,r")])
8706 (set (match_operand:SI 0 "s_register_operand" "=r,r")
8707 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8710 "%i1%.\\t%0, %2, %4%S3"
8711 [(set_attr "conds" "set")
8712 (set_attr "shift" "4")
8713 (set_attr "arch" "32,a")
8714 (set_attr "type" "alu_shift,alu_shift_reg")])
8716 (define_insn "*arith_shiftsi_compare0_scratch"
8717 [(set (reg:CC_NOOV CC_REGNUM)
8719 (match_operator:SI 1 "shiftable_operator"
8720 [(match_operator:SI 3 "shift_operator"
8721 [(match_operand:SI 4 "s_register_operand" "r,r")
8722 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8723 (match_operand:SI 2 "s_register_operand" "r,r")])
8725 (clobber (match_scratch:SI 0 "=r,r"))]
8727 "%i1%.\\t%0, %2, %4%S3"
8728 [(set_attr "conds" "set")
8729 (set_attr "shift" "4")
8730 (set_attr "arch" "32,a")
8731 (set_attr "type" "alu_shift,alu_shift_reg")])
8733 (define_insn "*sub_shiftsi"
8734 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8735 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
8736 (match_operator:SI 2 "shift_operator"
8737 [(match_operand:SI 3 "s_register_operand" "r,r")
8738 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8740 "sub%?\\t%0, %1, %3%S2"
8741 [(set_attr "predicable" "yes")
8742 (set_attr "shift" "3")
8743 (set_attr "arch" "32,a")
8744 (set_attr "type" "alu_shift,alu_shift_reg")])
8746 (define_insn "*sub_shiftsi_compare0"
8747 [(set (reg:CC_NOOV CC_REGNUM)
8749 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
8750 (match_operator:SI 2 "shift_operator"
8751 [(match_operand:SI 3 "s_register_operand" "r,r")
8752 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
8754 (set (match_operand:SI 0 "s_register_operand" "=r,r")
8755 (minus:SI (match_dup 1)
8756 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8758 "sub%.\\t%0, %1, %3%S2"
8759 [(set_attr "conds" "set")
8760 (set_attr "shift" "3")
8761 (set_attr "arch" "32,a")
8762 (set_attr "type" "alu_shift,alu_shift_reg")])
8764 (define_insn "*sub_shiftsi_compare0_scratch"
8765 [(set (reg:CC_NOOV CC_REGNUM)
8767 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
8768 (match_operator:SI 2 "shift_operator"
8769 [(match_operand:SI 3 "s_register_operand" "r,r")
8770 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
8772 (clobber (match_scratch:SI 0 "=r,r"))]
8774 "sub%.\\t%0, %1, %3%S2"
8775 [(set_attr "conds" "set")
8776 (set_attr "shift" "3")
8777 (set_attr "arch" "32,a")
8778 (set_attr "type" "alu_shift,alu_shift_reg")])
8781 (define_insn "*and_scc"
8782 [(set (match_operand:SI 0 "s_register_operand" "=r")
8783 (and:SI (match_operator:SI 1 "arm_comparison_operator"
8784 [(match_operand 3 "cc_register" "") (const_int 0)])
8785 (match_operand:SI 2 "s_register_operand" "r")))]
8787 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8788 [(set_attr "conds" "use")
8789 (set_attr "insn" "mov")
8790 (set_attr "length" "8")]
8793 (define_insn "*ior_scc"
8794 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8795 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8796 [(match_operand 3 "cc_register" "") (const_int 0)])
8797 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8801 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8802 [(set_attr "conds" "use")
8803 (set_attr "length" "4,8")]
8806 ; A series of splitters for the compare_scc pattern below. Note that
8807 ; order is important.
8809 [(set (match_operand:SI 0 "s_register_operand" "")
8810 (lt:SI (match_operand:SI 1 "s_register_operand" "")
8812 (clobber (reg:CC CC_REGNUM))]
8813 "TARGET_32BIT && reload_completed"
8814 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
8817 [(set (match_operand:SI 0 "s_register_operand" "")
8818 (ge:SI (match_operand:SI 1 "s_register_operand" "")
8820 (clobber (reg:CC CC_REGNUM))]
8821 "TARGET_32BIT && reload_completed"
8822 [(set (match_dup 0) (not:SI (match_dup 1)))
8823 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
8826 [(set (match_operand:SI 0 "s_register_operand" "")
8827 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8829 (clobber (reg:CC CC_REGNUM))]
8830 "TARGET_32BIT && reload_completed"
8832 [(set (reg:CC CC_REGNUM)
8833 (compare:CC (const_int 1) (match_dup 1)))
8835 (minus:SI (const_int 1) (match_dup 1)))])
8836 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
8837 (set (match_dup 0) (const_int 0)))])
8840 [(set (match_operand:SI 0 "s_register_operand" "")
8841 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8842 (match_operand:SI 2 "const_int_operand" "")))
8843 (clobber (reg:CC CC_REGNUM))]
8844 "TARGET_32BIT && reload_completed"
8846 [(set (reg:CC CC_REGNUM)
8847 (compare:CC (match_dup 1) (match_dup 2)))
8848 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
8849 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
8850 (set (match_dup 0) (const_int 1)))]
8852 operands[3] = GEN_INT (-INTVAL (operands[2]));
8856 [(set (match_operand:SI 0 "s_register_operand" "")
8857 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8858 (match_operand:SI 2 "arm_add_operand" "")))
8859 (clobber (reg:CC CC_REGNUM))]
8860 "TARGET_32BIT && reload_completed"
8862 [(set (reg:CC_NOOV CC_REGNUM)
8863 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
8865 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
8866 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
8867 (set (match_dup 0) (const_int 1)))])
8869 (define_insn_and_split "*compare_scc"
8870 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8871 (match_operator:SI 1 "arm_comparison_operator"
8872 [(match_operand:SI 2 "s_register_operand" "r,r")
8873 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8874 (clobber (reg:CC CC_REGNUM))]
8877 "&& reload_completed"
8878 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
8879 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
8880 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
8883 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8884 operands[2], operands[3]);
8885 enum rtx_code rc = GET_CODE (operands[1]);
8887 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
8889 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8890 if (mode == CCFPmode || mode == CCFPEmode)
8891 rc = reverse_condition_maybe_unordered (rc);
8893 rc = reverse_condition (rc);
8894 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8897 ;; Attempt to improve the sequence generated by the compare_scc splitters
8898 ;; not to use conditional execution.
8900 [(set (reg:CC CC_REGNUM)
8901 (compare:CC (match_operand:SI 1 "register_operand" "")
8902 (match_operand:SI 2 "arm_rhs_operand" "")))
8903 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8904 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8905 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8906 (set (match_dup 0) (const_int 1)))
8907 (match_scratch:SI 3 "r")]
8910 [(set (reg:CC CC_REGNUM)
8911 (compare:CC (match_dup 1) (match_dup 2)))
8912 (set (match_dup 3) (minus:SI (match_dup 1) (match_dup 2)))])
8914 [(set (reg:CC CC_REGNUM)
8915 (compare:CC (const_int 0) (match_dup 3)))
8916 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
8919 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
8920 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))
8921 (clobber (reg:CC CC_REGNUM))])])
8923 (define_insn "*cond_move"
8924 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8925 (if_then_else:SI (match_operator 3 "equality_operator"
8926 [(match_operator 4 "arm_comparison_operator"
8927 [(match_operand 5 "cc_register" "") (const_int 0)])
8929 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8930 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8933 if (GET_CODE (operands[3]) == NE)
8935 if (which_alternative != 1)
8936 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8937 if (which_alternative != 0)
8938 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8941 if (which_alternative != 0)
8942 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8943 if (which_alternative != 1)
8944 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8947 [(set_attr "conds" "use")
8948 (set_attr "insn" "mov")
8949 (set_attr "length" "4,4,8")]
8952 (define_insn "*cond_arith"
8953 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8954 (match_operator:SI 5 "shiftable_operator"
8955 [(match_operator:SI 4 "arm_comparison_operator"
8956 [(match_operand:SI 2 "s_register_operand" "r,r")
8957 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8958 (match_operand:SI 1 "s_register_operand" "0,?r")]))
8959 (clobber (reg:CC CC_REGNUM))]
8962 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8963 return \"%i5\\t%0, %1, %2, lsr #31\";
8965 output_asm_insn (\"cmp\\t%2, %3\", operands);
8966 if (GET_CODE (operands[5]) == AND)
8967 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8968 else if (GET_CODE (operands[5]) == MINUS)
8969 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8970 else if (which_alternative != 0)
8971 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8972 return \"%i5%d4\\t%0, %1, #1\";
8974 [(set_attr "conds" "clob")
8975 (set_attr "length" "12")]
8978 (define_insn "*cond_sub"
8979 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8980 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8981 (match_operator:SI 4 "arm_comparison_operator"
8982 [(match_operand:SI 2 "s_register_operand" "r,r")
8983 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8984 (clobber (reg:CC CC_REGNUM))]
8987 output_asm_insn (\"cmp\\t%2, %3\", operands);
8988 if (which_alternative != 0)
8989 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8990 return \"sub%d4\\t%0, %1, #1\";
8992 [(set_attr "conds" "clob")
8993 (set_attr "length" "8,12")]
8996 (define_insn "*cmp_ite0"
8997 [(set (match_operand 6 "dominant_cc_register" "")
9000 (match_operator 4 "arm_comparison_operator"
9001 [(match_operand:SI 0 "s_register_operand"
9002 "l,l,l,r,r,r,r,r,r")
9003 (match_operand:SI 1 "arm_add_operand"
9004 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
9005 (match_operator:SI 5 "arm_comparison_operator"
9006 [(match_operand:SI 2 "s_register_operand"
9007 "l,r,r,l,l,r,r,r,r")
9008 (match_operand:SI 3 "arm_add_operand"
9009 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
9015 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9017 {\"cmp%d5\\t%0, %1\",
9018 \"cmp%d4\\t%2, %3\"},
9019 {\"cmn%d5\\t%0, #%n1\",
9020 \"cmp%d4\\t%2, %3\"},
9021 {\"cmp%d5\\t%0, %1\",
9022 \"cmn%d4\\t%2, #%n3\"},
9023 {\"cmn%d5\\t%0, #%n1\",
9024 \"cmn%d4\\t%2, #%n3\"}
9026 static const char * const cmp2[NUM_OF_COND_CMP][2] =
9031 \"cmn\\t%0, #%n1\"},
9032 {\"cmn\\t%2, #%n3\",
9034 {\"cmn\\t%2, #%n3\",
9037 static const char * const ite[2] =
9042 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9043 CMP_CMP, CMN_CMP, CMP_CMP,
9044 CMN_CMP, CMP_CMN, CMN_CMN};
9046 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9048 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9049 if (TARGET_THUMB2) {
9050 output_asm_insn (ite[swap], operands);
9052 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9055 [(set_attr "conds" "set")
9056 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9057 (set_attr_alternative "length"
9063 (if_then_else (eq_attr "is_thumb" "no")
9066 (if_then_else (eq_attr "is_thumb" "no")
9069 (if_then_else (eq_attr "is_thumb" "no")
9072 (if_then_else (eq_attr "is_thumb" "no")
9077 (define_insn "*cmp_ite1"
9078 [(set (match_operand 6 "dominant_cc_register" "")
9081 (match_operator 4 "arm_comparison_operator"
9082 [(match_operand:SI 0 "s_register_operand"
9083 "l,l,l,r,r,r,r,r,r")
9084 (match_operand:SI 1 "arm_add_operand"
9085 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
9086 (match_operator:SI 5 "arm_comparison_operator"
9087 [(match_operand:SI 2 "s_register_operand"
9088 "l,r,r,l,l,r,r,r,r")
9089 (match_operand:SI 3 "arm_add_operand"
9090 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
9096 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9100 {\"cmn\\t%0, #%n1\",
9103 \"cmn\\t%2, #%n3\"},
9104 {\"cmn\\t%0, #%n1\",
9107 static const char * const cmp2[NUM_OF_COND_CMP][2] =
9109 {\"cmp%d4\\t%2, %3\",
9110 \"cmp%D5\\t%0, %1\"},
9111 {\"cmp%d4\\t%2, %3\",
9112 \"cmn%D5\\t%0, #%n1\"},
9113 {\"cmn%d4\\t%2, #%n3\",
9114 \"cmp%D5\\t%0, %1\"},
9115 {\"cmn%d4\\t%2, #%n3\",
9116 \"cmn%D5\\t%0, #%n1\"}
9118 static const char * const ite[2] =
9123 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9124 CMP_CMP, CMN_CMP, CMP_CMP,
9125 CMN_CMP, CMP_CMN, CMN_CMN};
9127 comparison_dominates_p (GET_CODE (operands[5]),
9128 reverse_condition (GET_CODE (operands[4])));
9130 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9131 if (TARGET_THUMB2) {
9132 output_asm_insn (ite[swap], operands);
9134 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9137 [(set_attr "conds" "set")
9138 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9139 (set_attr_alternative "length"
9145 (if_then_else (eq_attr "is_thumb" "no")
9148 (if_then_else (eq_attr "is_thumb" "no")
9151 (if_then_else (eq_attr "is_thumb" "no")
9154 (if_then_else (eq_attr "is_thumb" "no")
9159 (define_insn "*cmp_and"
9160 [(set (match_operand 6 "dominant_cc_register" "")
9163 (match_operator 4 "arm_comparison_operator"
9164 [(match_operand:SI 0 "s_register_operand"
9165 "l,l,l,r,r,r,r,r,r")
9166 (match_operand:SI 1 "arm_add_operand"
9167 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
9168 (match_operator:SI 5 "arm_comparison_operator"
9169 [(match_operand:SI 2 "s_register_operand"
9170 "l,r,r,l,l,r,r,r,r")
9171 (match_operand:SI 3 "arm_add_operand"
9172 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
9177 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9179 {\"cmp%d5\\t%0, %1\",
9180 \"cmp%d4\\t%2, %3\"},
9181 {\"cmn%d5\\t%0, #%n1\",
9182 \"cmp%d4\\t%2, %3\"},
9183 {\"cmp%d5\\t%0, %1\",
9184 \"cmn%d4\\t%2, #%n3\"},
9185 {\"cmn%d5\\t%0, #%n1\",
9186 \"cmn%d4\\t%2, #%n3\"}
9188 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9193 \"cmn\\t%0, #%n1\"},
9194 {\"cmn\\t%2, #%n3\",
9196 {\"cmn\\t%2, #%n3\",
9199 static const char *const ite[2] =
9204 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9205 CMP_CMP, CMN_CMP, CMP_CMP,
9206 CMN_CMP, CMP_CMN, CMN_CMN};
9208 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9210 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9211 if (TARGET_THUMB2) {
9212 output_asm_insn (ite[swap], operands);
9214 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9217 [(set_attr "conds" "set")
9218 (set_attr "predicable" "no")
9219 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9220 (set_attr_alternative "length"
9226 (if_then_else (eq_attr "is_thumb" "no")
9229 (if_then_else (eq_attr "is_thumb" "no")
9232 (if_then_else (eq_attr "is_thumb" "no")
9235 (if_then_else (eq_attr "is_thumb" "no")
9240 (define_insn "*cmp_ior"
9241 [(set (match_operand 6 "dominant_cc_register" "")
9244 (match_operator 4 "arm_comparison_operator"
9245 [(match_operand:SI 0 "s_register_operand"
9246 "l,l,l,r,r,r,r,r,r")
9247 (match_operand:SI 1 "arm_add_operand"
9248 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
9249 (match_operator:SI 5 "arm_comparison_operator"
9250 [(match_operand:SI 2 "s_register_operand"
9251 "l,r,r,l,l,r,r,r,r")
9252 (match_operand:SI 3 "arm_add_operand"
9253 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
9258 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9262 {\"cmn\\t%0, #%n1\",
9265 \"cmn\\t%2, #%n3\"},
9266 {\"cmn\\t%0, #%n1\",
9269 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9271 {\"cmp%D4\\t%2, %3\",
9272 \"cmp%D5\\t%0, %1\"},
9273 {\"cmp%D4\\t%2, %3\",
9274 \"cmn%D5\\t%0, #%n1\"},
9275 {\"cmn%D4\\t%2, #%n3\",
9276 \"cmp%D5\\t%0, %1\"},
9277 {\"cmn%D4\\t%2, #%n3\",
9278 \"cmn%D5\\t%0, #%n1\"}
9280 static const char *const ite[2] =
9285 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9286 CMP_CMP, CMN_CMP, CMP_CMP,
9287 CMN_CMP, CMP_CMN, CMN_CMN};
9289 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9291 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9292 if (TARGET_THUMB2) {
9293 output_asm_insn (ite[swap], operands);
9295 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9299 [(set_attr "conds" "set")
9300 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9301 (set_attr_alternative "length"
9307 (if_then_else (eq_attr "is_thumb" "no")
9310 (if_then_else (eq_attr "is_thumb" "no")
9313 (if_then_else (eq_attr "is_thumb" "no")
9316 (if_then_else (eq_attr "is_thumb" "no")
9321 (define_insn_and_split "*ior_scc_scc"
9322 [(set (match_operand:SI 0 "s_register_operand" "=r")
9323 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9324 [(match_operand:SI 1 "s_register_operand" "r")
9325 (match_operand:SI 2 "arm_add_operand" "rIL")])
9326 (match_operator:SI 6 "arm_comparison_operator"
9327 [(match_operand:SI 4 "s_register_operand" "r")
9328 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9329 (clobber (reg:CC CC_REGNUM))]
9331 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9334 "TARGET_32BIT && reload_completed"
9338 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9339 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9341 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9343 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9346 [(set_attr "conds" "clob")
9347 (set_attr "length" "16")])
9349 ; If the above pattern is followed by a CMP insn, then the compare is
9350 ; redundant, since we can rework the conditional instruction that follows.
9351 (define_insn_and_split "*ior_scc_scc_cmp"
9352 [(set (match_operand 0 "dominant_cc_register" "")
9353 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9354 [(match_operand:SI 1 "s_register_operand" "r")
9355 (match_operand:SI 2 "arm_add_operand" "rIL")])
9356 (match_operator:SI 6 "arm_comparison_operator"
9357 [(match_operand:SI 4 "s_register_operand" "r")
9358 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9360 (set (match_operand:SI 7 "s_register_operand" "=r")
9361 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9362 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9365 "TARGET_32BIT && reload_completed"
9369 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9370 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9372 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9374 [(set_attr "conds" "set")
9375 (set_attr "length" "16")])
9377 (define_insn_and_split "*and_scc_scc"
9378 [(set (match_operand:SI 0 "s_register_operand" "=r")
9379 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9380 [(match_operand:SI 1 "s_register_operand" "r")
9381 (match_operand:SI 2 "arm_add_operand" "rIL")])
9382 (match_operator:SI 6 "arm_comparison_operator"
9383 [(match_operand:SI 4 "s_register_operand" "r")
9384 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9385 (clobber (reg:CC CC_REGNUM))]
9387 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9390 "TARGET_32BIT && reload_completed
9391 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9396 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9397 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9399 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9401 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9404 [(set_attr "conds" "clob")
9405 (set_attr "length" "16")])
9407 ; If the above pattern is followed by a CMP insn, then the compare is
9408 ; redundant, since we can rework the conditional instruction that follows.
9409 (define_insn_and_split "*and_scc_scc_cmp"
9410 [(set (match_operand 0 "dominant_cc_register" "")
9411 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9412 [(match_operand:SI 1 "s_register_operand" "r")
9413 (match_operand:SI 2 "arm_add_operand" "rIL")])
9414 (match_operator:SI 6 "arm_comparison_operator"
9415 [(match_operand:SI 4 "s_register_operand" "r")
9416 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9418 (set (match_operand:SI 7 "s_register_operand" "=r")
9419 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9420 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9423 "TARGET_32BIT && reload_completed"
9427 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9428 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9430 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9432 [(set_attr "conds" "set")
9433 (set_attr "length" "16")])
9435 ;; If there is no dominance in the comparison, then we can still save an
9436 ;; instruction in the AND case, since we can know that the second compare
9437 ;; need only zero the value if false (if true, then the value is already
9439 (define_insn_and_split "*and_scc_scc_nodom"
9440 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9441 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9442 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9443 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9444 (match_operator:SI 6 "arm_comparison_operator"
9445 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9446 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9447 (clobber (reg:CC CC_REGNUM))]
9449 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9452 "TARGET_32BIT && reload_completed"
9453 [(parallel [(set (match_dup 0)
9454 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9455 (clobber (reg:CC CC_REGNUM))])
9456 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9458 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9461 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9462 operands[4], operands[5]),
9464 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9466 [(set_attr "conds" "clob")
9467 (set_attr "length" "20")])
9470 [(set (reg:CC_NOOV CC_REGNUM)
9471 (compare:CC_NOOV (ior:SI
9472 (and:SI (match_operand:SI 0 "s_register_operand" "")
9474 (match_operator:SI 1 "arm_comparison_operator"
9475 [(match_operand:SI 2 "s_register_operand" "")
9476 (match_operand:SI 3 "arm_add_operand" "")]))
9478 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9481 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9483 (set (reg:CC_NOOV CC_REGNUM)
9484 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9489 [(set (reg:CC_NOOV CC_REGNUM)
9490 (compare:CC_NOOV (ior:SI
9491 (match_operator:SI 1 "arm_comparison_operator"
9492 [(match_operand:SI 2 "s_register_operand" "")
9493 (match_operand:SI 3 "arm_add_operand" "")])
9494 (and:SI (match_operand:SI 0 "s_register_operand" "")
9497 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9500 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9502 (set (reg:CC_NOOV CC_REGNUM)
9503 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9506 ;; ??? The conditional patterns above need checking for Thumb-2 usefulness
9508 (define_insn "*negscc"
9509 [(set (match_operand:SI 0 "s_register_operand" "=r")
9510 (neg:SI (match_operator 3 "arm_comparison_operator"
9511 [(match_operand:SI 1 "s_register_operand" "r")
9512 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
9513 (clobber (reg:CC CC_REGNUM))]
9516 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9517 return \"mov\\t%0, %1, asr #31\";
9519 if (GET_CODE (operands[3]) == NE)
9520 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9522 output_asm_insn (\"cmp\\t%1, %2\", operands);
9523 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9524 return \"mvn%d3\\t%0, #0\";
9526 [(set_attr "conds" "clob")
9527 (set_attr "length" "12")]
9530 (define_insn "movcond"
9531 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9533 (match_operator 5 "arm_comparison_operator"
9534 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9535 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9536 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9537 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
9538 (clobber (reg:CC CC_REGNUM))]
9541 if (GET_CODE (operands[5]) == LT
9542 && (operands[4] == const0_rtx))
9544 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9546 if (operands[2] == const0_rtx)
9547 return \"and\\t%0, %1, %3, asr #31\";
9548 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9550 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9552 if (operands[1] == const0_rtx)
9553 return \"bic\\t%0, %2, %3, asr #31\";
9554 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9556 /* The only case that falls through to here is when both ops 1 & 2
9560 if (GET_CODE (operands[5]) == GE
9561 && (operands[4] == const0_rtx))
9563 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9565 if (operands[2] == const0_rtx)
9566 return \"bic\\t%0, %1, %3, asr #31\";
9567 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9569 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9571 if (operands[1] == const0_rtx)
9572 return \"and\\t%0, %2, %3, asr #31\";
9573 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9575 /* The only case that falls through to here is when both ops 1 & 2
9578 if (GET_CODE (operands[4]) == CONST_INT
9579 && !const_ok_for_arm (INTVAL (operands[4])))
9580 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9582 output_asm_insn (\"cmp\\t%3, %4\", operands);
9583 if (which_alternative != 0)
9584 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9585 if (which_alternative != 1)
9586 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9589 [(set_attr "conds" "clob")
9590 (set_attr "length" "8,8,12")]
9593 ;; ??? The patterns below need checking for Thumb-2 usefulness.
9595 (define_insn "*ifcompare_plus_move"
9596 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9597 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9598 [(match_operand:SI 4 "s_register_operand" "r,r")
9599 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9601 (match_operand:SI 2 "s_register_operand" "r,r")
9602 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
9603 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9604 (clobber (reg:CC CC_REGNUM))]
9607 [(set_attr "conds" "clob")
9608 (set_attr "length" "8,12")]
9611 (define_insn "*if_plus_move"
9612 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9614 (match_operator 4 "arm_comparison_operator"
9615 [(match_operand 5 "cc_register" "") (const_int 0)])
9617 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9618 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9619 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
9623 sub%d4\\t%0, %2, #%n3
9624 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
9625 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
9626 [(set_attr "conds" "use")
9627 (set_attr "length" "4,4,8,8")
9628 (set_attr "type" "*,*,*,*")]
9631 (define_insn "*ifcompare_move_plus"
9632 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9633 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9634 [(match_operand:SI 4 "s_register_operand" "r,r")
9635 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9636 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9638 (match_operand:SI 2 "s_register_operand" "r,r")
9639 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
9640 (clobber (reg:CC CC_REGNUM))]
9643 [(set_attr "conds" "clob")
9644 (set_attr "length" "8,12")]
9647 (define_insn "*if_move_plus"
9648 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9650 (match_operator 4 "arm_comparison_operator"
9651 [(match_operand 5 "cc_register" "") (const_int 0)])
9652 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
9654 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9655 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
9659 sub%D4\\t%0, %2, #%n3
9660 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
9661 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
9662 [(set_attr "conds" "use")
9663 (set_attr "length" "4,4,8,8")
9664 (set_attr "type" "*,*,*,*")]
9667 (define_insn "*ifcompare_arith_arith"
9668 [(set (match_operand:SI 0 "s_register_operand" "=r")
9669 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
9670 [(match_operand:SI 5 "s_register_operand" "r")
9671 (match_operand:SI 6 "arm_add_operand" "rIL")])
9672 (match_operator:SI 8 "shiftable_operator"
9673 [(match_operand:SI 1 "s_register_operand" "r")
9674 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9675 (match_operator:SI 7 "shiftable_operator"
9676 [(match_operand:SI 3 "s_register_operand" "r")
9677 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
9678 (clobber (reg:CC CC_REGNUM))]
9681 [(set_attr "conds" "clob")
9682 (set_attr "length" "12")]
9685 (define_insn "*if_arith_arith"
9686 [(set (match_operand:SI 0 "s_register_operand" "=r")
9687 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
9688 [(match_operand 8 "cc_register" "") (const_int 0)])
9689 (match_operator:SI 6 "shiftable_operator"
9690 [(match_operand:SI 1 "s_register_operand" "r")
9691 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9692 (match_operator:SI 7 "shiftable_operator"
9693 [(match_operand:SI 3 "s_register_operand" "r")
9694 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
9696 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
9697 [(set_attr "conds" "use")
9698 (set_attr "length" "8")]
9701 (define_insn "*ifcompare_arith_move"
9702 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9703 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9704 [(match_operand:SI 2 "s_register_operand" "r,r")
9705 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9706 (match_operator:SI 7 "shiftable_operator"
9707 [(match_operand:SI 4 "s_register_operand" "r,r")
9708 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
9709 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9710 (clobber (reg:CC CC_REGNUM))]
9713 /* If we have an operation where (op x 0) is the identity operation and
9714 the conditional operator is LT or GE and we are comparing against zero and
9715 everything is in registers then we can do this in two instructions. */
9716 if (operands[3] == const0_rtx
9717 && GET_CODE (operands[7]) != AND
9718 && GET_CODE (operands[5]) == REG
9719 && GET_CODE (operands[1]) == REG
9720 && REGNO (operands[1]) == REGNO (operands[4])
9721 && REGNO (operands[4]) != REGNO (operands[0]))
9723 if (GET_CODE (operands[6]) == LT)
9724 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9725 else if (GET_CODE (operands[6]) == GE)
9726 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9728 if (GET_CODE (operands[3]) == CONST_INT
9729 && !const_ok_for_arm (INTVAL (operands[3])))
9730 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9732 output_asm_insn (\"cmp\\t%2, %3\", operands);
9733 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9734 if (which_alternative != 0)
9735 return \"mov%D6\\t%0, %1\";
9738 [(set_attr "conds" "clob")
9739 (set_attr "length" "8,12")]
9742 (define_insn "*if_arith_move"
9743 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9744 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9745 [(match_operand 6 "cc_register" "") (const_int 0)])
9746 (match_operator:SI 5 "shiftable_operator"
9747 [(match_operand:SI 2 "s_register_operand" "r,r")
9748 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9749 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
9753 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
9754 [(set_attr "conds" "use")
9755 (set_attr "length" "4,8")
9756 (set_attr "type" "*,*")]
9759 (define_insn "*ifcompare_move_arith"
9760 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9761 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9762 [(match_operand:SI 4 "s_register_operand" "r,r")
9763 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9764 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9765 (match_operator:SI 7 "shiftable_operator"
9766 [(match_operand:SI 2 "s_register_operand" "r,r")
9767 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9768 (clobber (reg:CC CC_REGNUM))]
9771 /* If we have an operation where (op x 0) is the identity operation and
9772 the conditional operator is LT or GE and we are comparing against zero and
9773 everything is in registers then we can do this in two instructions */
9774 if (operands[5] == const0_rtx
9775 && GET_CODE (operands[7]) != AND
9776 && GET_CODE (operands[3]) == REG
9777 && GET_CODE (operands[1]) == REG
9778 && REGNO (operands[1]) == REGNO (operands[2])
9779 && REGNO (operands[2]) != REGNO (operands[0]))
9781 if (GET_CODE (operands[6]) == GE)
9782 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9783 else if (GET_CODE (operands[6]) == LT)
9784 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9787 if (GET_CODE (operands[5]) == CONST_INT
9788 && !const_ok_for_arm (INTVAL (operands[5])))
9789 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9791 output_asm_insn (\"cmp\\t%4, %5\", operands);
9793 if (which_alternative != 0)
9794 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
9795 return \"%I7%D6\\t%0, %2, %3\";
9797 [(set_attr "conds" "clob")
9798 (set_attr "length" "8,12")]
9801 (define_insn "*if_move_arith"
9802 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9804 (match_operator 4 "arm_comparison_operator"
9805 [(match_operand 6 "cc_register" "") (const_int 0)])
9806 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9807 (match_operator:SI 5 "shiftable_operator"
9808 [(match_operand:SI 2 "s_register_operand" "r,r")
9809 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
9813 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9814 [(set_attr "conds" "use")
9815 (set_attr "length" "4,8")
9816 (set_attr "type" "*,*")]
9819 (define_insn "*ifcompare_move_not"
9820 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9822 (match_operator 5 "arm_comparison_operator"
9823 [(match_operand:SI 3 "s_register_operand" "r,r")
9824 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9825 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9827 (match_operand:SI 2 "s_register_operand" "r,r"))))
9828 (clobber (reg:CC CC_REGNUM))]
9831 [(set_attr "conds" "clob")
9832 (set_attr "length" "8,12")]
9835 (define_insn "*if_move_not"
9836 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9838 (match_operator 4 "arm_comparison_operator"
9839 [(match_operand 3 "cc_register" "") (const_int 0)])
9840 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9841 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9845 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9846 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9847 [(set_attr "conds" "use")
9848 (set_attr "insn" "mvn")
9849 (set_attr "length" "4,8,8")]
9852 (define_insn "*ifcompare_not_move"
9853 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9855 (match_operator 5 "arm_comparison_operator"
9856 [(match_operand:SI 3 "s_register_operand" "r,r")
9857 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9859 (match_operand:SI 2 "s_register_operand" "r,r"))
9860 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9861 (clobber (reg:CC CC_REGNUM))]
9864 [(set_attr "conds" "clob")
9865 (set_attr "length" "8,12")]
9868 (define_insn "*if_not_move"
9869 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9871 (match_operator 4 "arm_comparison_operator"
9872 [(match_operand 3 "cc_register" "") (const_int 0)])
9873 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9874 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9878 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9879 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9880 [(set_attr "conds" "use")
9881 (set_attr "insn" "mvn")
9882 (set_attr "length" "4,8,8")]
9885 (define_insn "*ifcompare_shift_move"
9886 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9888 (match_operator 6 "arm_comparison_operator"
9889 [(match_operand:SI 4 "s_register_operand" "r,r")
9890 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9891 (match_operator:SI 7 "shift_operator"
9892 [(match_operand:SI 2 "s_register_operand" "r,r")
9893 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9894 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9895 (clobber (reg:CC CC_REGNUM))]
9898 [(set_attr "conds" "clob")
9899 (set_attr "length" "8,12")]
9902 (define_insn "*if_shift_move"
9903 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9905 (match_operator 5 "arm_comparison_operator"
9906 [(match_operand 6 "cc_register" "") (const_int 0)])
9907 (match_operator:SI 4 "shift_operator"
9908 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9909 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9910 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9914 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9915 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9916 [(set_attr "conds" "use")
9917 (set_attr "shift" "2")
9918 (set_attr "length" "4,8,8")
9919 (set_attr "insn" "mov")
9920 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9921 (const_string "alu_shift")
9922 (const_string "alu_shift_reg")))]
9925 (define_insn "*ifcompare_move_shift"
9926 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9928 (match_operator 6 "arm_comparison_operator"
9929 [(match_operand:SI 4 "s_register_operand" "r,r")
9930 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9931 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9932 (match_operator:SI 7 "shift_operator"
9933 [(match_operand:SI 2 "s_register_operand" "r,r")
9934 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9935 (clobber (reg:CC CC_REGNUM))]
9938 [(set_attr "conds" "clob")
9939 (set_attr "length" "8,12")]
9942 (define_insn "*if_move_shift"
9943 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9945 (match_operator 5 "arm_comparison_operator"
9946 [(match_operand 6 "cc_register" "") (const_int 0)])
9947 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9948 (match_operator:SI 4 "shift_operator"
9949 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9950 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9954 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9955 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9956 [(set_attr "conds" "use")
9957 (set_attr "shift" "2")
9958 (set_attr "length" "4,8,8")
9959 (set_attr "insn" "mov")
9960 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9961 (const_string "alu_shift")
9962 (const_string "alu_shift_reg")))]
9965 (define_insn "*ifcompare_shift_shift"
9966 [(set (match_operand:SI 0 "s_register_operand" "=r")
9968 (match_operator 7 "arm_comparison_operator"
9969 [(match_operand:SI 5 "s_register_operand" "r")
9970 (match_operand:SI 6 "arm_add_operand" "rIL")])
9971 (match_operator:SI 8 "shift_operator"
9972 [(match_operand:SI 1 "s_register_operand" "r")
9973 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9974 (match_operator:SI 9 "shift_operator"
9975 [(match_operand:SI 3 "s_register_operand" "r")
9976 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9977 (clobber (reg:CC CC_REGNUM))]
9980 [(set_attr "conds" "clob")
9981 (set_attr "length" "12")]
9984 (define_insn "*if_shift_shift"
9985 [(set (match_operand:SI 0 "s_register_operand" "=r")
9987 (match_operator 5 "arm_comparison_operator"
9988 [(match_operand 8 "cc_register" "") (const_int 0)])
9989 (match_operator:SI 6 "shift_operator"
9990 [(match_operand:SI 1 "s_register_operand" "r")
9991 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9992 (match_operator:SI 7 "shift_operator"
9993 [(match_operand:SI 3 "s_register_operand" "r")
9994 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9996 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9997 [(set_attr "conds" "use")
9998 (set_attr "shift" "1")
9999 (set_attr "length" "8")
10000 (set_attr "insn" "mov")
10001 (set (attr "type") (if_then_else
10002 (and (match_operand 2 "const_int_operand" "")
10003 (match_operand 4 "const_int_operand" ""))
10004 (const_string "alu_shift")
10005 (const_string "alu_shift_reg")))]
10008 (define_insn "*ifcompare_not_arith"
10009 [(set (match_operand:SI 0 "s_register_operand" "=r")
10011 (match_operator 6 "arm_comparison_operator"
10012 [(match_operand:SI 4 "s_register_operand" "r")
10013 (match_operand:SI 5 "arm_add_operand" "rIL")])
10014 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10015 (match_operator:SI 7 "shiftable_operator"
10016 [(match_operand:SI 2 "s_register_operand" "r")
10017 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
10018 (clobber (reg:CC CC_REGNUM))]
10021 [(set_attr "conds" "clob")
10022 (set_attr "length" "12")]
10025 (define_insn "*if_not_arith"
10026 [(set (match_operand:SI 0 "s_register_operand" "=r")
10028 (match_operator 5 "arm_comparison_operator"
10029 [(match_operand 4 "cc_register" "") (const_int 0)])
10030 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10031 (match_operator:SI 6 "shiftable_operator"
10032 [(match_operand:SI 2 "s_register_operand" "r")
10033 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
10035 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
10036 [(set_attr "conds" "use")
10037 (set_attr "insn" "mvn")
10038 (set_attr "length" "8")]
10041 (define_insn "*ifcompare_arith_not"
10042 [(set (match_operand:SI 0 "s_register_operand" "=r")
10044 (match_operator 6 "arm_comparison_operator"
10045 [(match_operand:SI 4 "s_register_operand" "r")
10046 (match_operand:SI 5 "arm_add_operand" "rIL")])
10047 (match_operator:SI 7 "shiftable_operator"
10048 [(match_operand:SI 2 "s_register_operand" "r")
10049 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10050 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
10051 (clobber (reg:CC CC_REGNUM))]
10054 [(set_attr "conds" "clob")
10055 (set_attr "length" "12")]
10058 (define_insn "*if_arith_not"
10059 [(set (match_operand:SI 0 "s_register_operand" "=r")
10061 (match_operator 5 "arm_comparison_operator"
10062 [(match_operand 4 "cc_register" "") (const_int 0)])
10063 (match_operator:SI 6 "shiftable_operator"
10064 [(match_operand:SI 2 "s_register_operand" "r")
10065 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10066 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
10068 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
10069 [(set_attr "conds" "use")
10070 (set_attr "insn" "mvn")
10071 (set_attr "length" "8")]
10074 (define_insn "*ifcompare_neg_move"
10075 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10077 (match_operator 5 "arm_comparison_operator"
10078 [(match_operand:SI 3 "s_register_operand" "r,r")
10079 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10080 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10081 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10082 (clobber (reg:CC CC_REGNUM))]
10085 [(set_attr "conds" "clob")
10086 (set_attr "length" "8,12")]
10089 (define_insn "*if_neg_move"
10090 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10092 (match_operator 4 "arm_comparison_operator"
10093 [(match_operand 3 "cc_register" "") (const_int 0)])
10094 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10095 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10098 rsb%d4\\t%0, %2, #0
10099 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
10100 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
10101 [(set_attr "conds" "use")
10102 (set_attr "length" "4,8,8")]
10105 (define_insn "*ifcompare_move_neg"
10106 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10108 (match_operator 5 "arm_comparison_operator"
10109 [(match_operand:SI 3 "s_register_operand" "r,r")
10110 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10111 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10112 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
10113 (clobber (reg:CC CC_REGNUM))]
10116 [(set_attr "conds" "clob")
10117 (set_attr "length" "8,12")]
10120 (define_insn "*if_move_neg"
10121 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10123 (match_operator 4 "arm_comparison_operator"
10124 [(match_operand 3 "cc_register" "") (const_int 0)])
10125 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10126 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
10129 rsb%D4\\t%0, %2, #0
10130 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
10131 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
10132 [(set_attr "conds" "use")
10133 (set_attr "length" "4,8,8")]
10136 (define_insn "*arith_adjacentmem"
10137 [(set (match_operand:SI 0 "s_register_operand" "=r")
10138 (match_operator:SI 1 "shiftable_operator"
10139 [(match_operand:SI 2 "memory_operand" "m")
10140 (match_operand:SI 3 "memory_operand" "m")]))
10141 (clobber (match_scratch:SI 4 "=r"))]
10142 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
10148 HOST_WIDE_INT val1 = 0, val2 = 0;
10150 if (REGNO (operands[0]) > REGNO (operands[4]))
10152 ldm[1] = operands[4];
10153 ldm[2] = operands[0];
10157 ldm[1] = operands[0];
10158 ldm[2] = operands[4];
10161 base_reg = XEXP (operands[2], 0);
10163 if (!REG_P (base_reg))
10165 val1 = INTVAL (XEXP (base_reg, 1));
10166 base_reg = XEXP (base_reg, 0);
10169 if (!REG_P (XEXP (operands[3], 0)))
10170 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
10172 arith[0] = operands[0];
10173 arith[3] = operands[1];
10187 if (val1 !=0 && val2 != 0)
10191 if (val1 == 4 || val2 == 4)
10192 /* Other val must be 8, since we know they are adjacent and neither
10194 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
10195 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
10197 ldm[0] = ops[0] = operands[4];
10199 ops[2] = GEN_INT (val1);
10200 output_add_immediate (ops);
10202 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10204 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10208 /* Offset is out of range for a single add, so use two ldr. */
10211 ops[2] = GEN_INT (val1);
10212 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10214 ops[2] = GEN_INT (val2);
10215 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10218 else if (val1 != 0)
10221 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10223 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10228 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10230 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10232 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10235 [(set_attr "length" "12")
10236 (set_attr "predicable" "yes")
10237 (set_attr "type" "load1")]
10240 ; This pattern is never tried by combine, so do it as a peephole
10243 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10244 (match_operand:SI 1 "arm_general_register_operand" ""))
10245 (set (reg:CC CC_REGNUM)
10246 (compare:CC (match_dup 1) (const_int 0)))]
10248 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10249 (set (match_dup 0) (match_dup 1))])]
10254 [(set (match_operand:SI 0 "s_register_operand" "")
10255 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10257 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
10258 [(match_operand:SI 3 "s_register_operand" "")
10259 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10260 (clobber (match_operand:SI 5 "s_register_operand" ""))]
10262 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10263 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10268 ;; This split can be used because CC_Z mode implies that the following
10269 ;; branch will be an equality, or an unsigned inequality, so the sign
10270 ;; extension is not needed.
10273 [(set (reg:CC_Z CC_REGNUM)
10275 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
10277 (match_operand 1 "const_int_operand" "")))
10278 (clobber (match_scratch:SI 2 ""))]
10280 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10281 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
10282 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
10283 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
10285 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
10288 ;; ??? Check the patterns above for Thumb-2 usefulness
10290 (define_expand "prologue"
10291 [(clobber (const_int 0))]
10294 arm_expand_prologue ();
10296 thumb1_expand_prologue ();
10301 (define_expand "epilogue"
10302 [(clobber (const_int 0))]
10305 if (crtl->calls_eh_return)
10306 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
10308 thumb1_expand_epilogue ();
10309 else if (USE_RETURN_INSN (FALSE))
10311 emit_jump_insn (gen_return ());
10314 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10315 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10320 (define_insn "prologue_thumb1_interwork"
10321 [(unspec_volatile [(const_int 0)] VUNSPEC_THUMB1_INTERWORK)]
10323 "* return thumb1_output_interwork ();"
10324 [(set_attr "length" "8")]
10327 ;; Note - although unspec_volatile's USE all hard registers,
10328 ;; USEs are ignored after relaod has completed. Thus we need
10329 ;; to add an unspec of the link register to ensure that flow
10330 ;; does not think that it is unused by the sibcall branch that
10331 ;; will replace the standard function epilogue.
10332 (define_insn "sibcall_epilogue"
10333 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10334 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10337 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
10338 return output_return_instruction (const_true_rtx, FALSE, FALSE);
10339 return arm_output_epilogue (next_nonnote_insn (insn));
10341 ;; Length is absolute worst case
10342 [(set_attr "length" "44")
10343 (set_attr "type" "block")
10344 ;; We don't clobber the conditions, but the potential length of this
10345 ;; operation is sufficient to make conditionalizing the sequence
10346 ;; unlikely to be profitable.
10347 (set_attr "conds" "clob")]
10350 (define_insn "*epilogue_insns"
10351 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
10355 return arm_output_epilogue (NULL);
10356 else /* TARGET_THUMB1 */
10357 return thumb_unexpanded_epilogue ();
10359 ; Length is absolute worst case
10360 [(set_attr "length" "44")
10361 (set_attr "type" "block")
10362 ;; We don't clobber the conditions, but the potential length of this
10363 ;; operation is sufficient to make conditionalizing the sequence
10364 ;; unlikely to be profitable.
10365 (set_attr "conds" "clob")]
10368 (define_expand "eh_epilogue"
10369 [(use (match_operand:SI 0 "register_operand" ""))
10370 (use (match_operand:SI 1 "register_operand" ""))
10371 (use (match_operand:SI 2 "register_operand" ""))]
10375 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10376 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10378 rtx ra = gen_rtx_REG (Pmode, 2);
10380 emit_move_insn (ra, operands[2]);
10383 /* This is a hack -- we may have crystalized the function type too
10385 cfun->machine->func_type = 0;
10389 ;; This split is only used during output to reduce the number of patterns
10390 ;; that need assembler instructions adding to them. We allowed the setting
10391 ;; of the conditions to be implicit during rtl generation so that
10392 ;; the conditional compare patterns would work. However this conflicts to
10393 ;; some extent with the conditional data operations, so we have to split them
10396 ;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10397 ;; conditional execution sufficient?
10400 [(set (match_operand:SI 0 "s_register_operand" "")
10401 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10402 [(match_operand 2 "" "") (match_operand 3 "" "")])
10404 (match_operand 4 "" "")))
10405 (clobber (reg:CC CC_REGNUM))]
10406 "TARGET_ARM && reload_completed"
10407 [(set (match_dup 5) (match_dup 6))
10408 (cond_exec (match_dup 7)
10409 (set (match_dup 0) (match_dup 4)))]
10412 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10413 operands[2], operands[3]);
10414 enum rtx_code rc = GET_CODE (operands[1]);
10416 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10417 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10418 if (mode == CCFPmode || mode == CCFPEmode)
10419 rc = reverse_condition_maybe_unordered (rc);
10421 rc = reverse_condition (rc);
10423 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10428 [(set (match_operand:SI 0 "s_register_operand" "")
10429 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10430 [(match_operand 2 "" "") (match_operand 3 "" "")])
10431 (match_operand 4 "" "")
10433 (clobber (reg:CC CC_REGNUM))]
10434 "TARGET_ARM && reload_completed"
10435 [(set (match_dup 5) (match_dup 6))
10436 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10437 (set (match_dup 0) (match_dup 4)))]
10440 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10441 operands[2], operands[3]);
10443 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10444 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10449 [(set (match_operand:SI 0 "s_register_operand" "")
10450 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10451 [(match_operand 2 "" "") (match_operand 3 "" "")])
10452 (match_operand 4 "" "")
10453 (match_operand 5 "" "")))
10454 (clobber (reg:CC CC_REGNUM))]
10455 "TARGET_ARM && reload_completed"
10456 [(set (match_dup 6) (match_dup 7))
10457 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10458 (set (match_dup 0) (match_dup 4)))
10459 (cond_exec (match_dup 8)
10460 (set (match_dup 0) (match_dup 5)))]
10463 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10464 operands[2], operands[3]);
10465 enum rtx_code rc = GET_CODE (operands[1]);
10467 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10468 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10469 if (mode == CCFPmode || mode == CCFPEmode)
10470 rc = reverse_condition_maybe_unordered (rc);
10472 rc = reverse_condition (rc);
10474 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10479 [(set (match_operand:SI 0 "s_register_operand" "")
10480 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10481 [(match_operand:SI 2 "s_register_operand" "")
10482 (match_operand:SI 3 "arm_add_operand" "")])
10483 (match_operand:SI 4 "arm_rhs_operand" "")
10485 (match_operand:SI 5 "s_register_operand" ""))))
10486 (clobber (reg:CC CC_REGNUM))]
10487 "TARGET_ARM && reload_completed"
10488 [(set (match_dup 6) (match_dup 7))
10489 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10490 (set (match_dup 0) (match_dup 4)))
10491 (cond_exec (match_dup 8)
10492 (set (match_dup 0) (not:SI (match_dup 5))))]
10495 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10496 operands[2], operands[3]);
10497 enum rtx_code rc = GET_CODE (operands[1]);
10499 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10500 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10501 if (mode == CCFPmode || mode == CCFPEmode)
10502 rc = reverse_condition_maybe_unordered (rc);
10504 rc = reverse_condition (rc);
10506 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10510 (define_insn "*cond_move_not"
10511 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10512 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10513 [(match_operand 3 "cc_register" "") (const_int 0)])
10514 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10516 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10520 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10521 [(set_attr "conds" "use")
10522 (set_attr "insn" "mvn")
10523 (set_attr "length" "4,8")]
10526 ;; The next two patterns occur when an AND operation is followed by a
10527 ;; scc insn sequence
10529 (define_insn "*sign_extract_onebit"
10530 [(set (match_operand:SI 0 "s_register_operand" "=r")
10531 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10533 (match_operand:SI 2 "const_int_operand" "n")))
10534 (clobber (reg:CC CC_REGNUM))]
10537 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10538 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10539 return \"mvnne\\t%0, #0\";
10541 [(set_attr "conds" "clob")
10542 (set_attr "length" "8")]
10545 (define_insn "*not_signextract_onebit"
10546 [(set (match_operand:SI 0 "s_register_operand" "=r")
10548 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10550 (match_operand:SI 2 "const_int_operand" "n"))))
10551 (clobber (reg:CC CC_REGNUM))]
10554 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10555 output_asm_insn (\"tst\\t%1, %2\", operands);
10556 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10557 return \"movne\\t%0, #0\";
10559 [(set_attr "conds" "clob")
10560 (set_attr "length" "12")]
10562 ;; ??? The above patterns need auditing for Thumb-2
10564 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
10565 ;; expressions. For simplicity, the first register is also in the unspec
10567 ;; To avoid the usage of GNU extension, the length attribute is computed
10568 ;; in a C function arm_attr_length_push_multi.
10569 (define_insn "*push_multi"
10570 [(match_parallel 2 "multi_register_push"
10571 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
10572 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
10573 UNSPEC_PUSH_MULT))])]
10577 int num_saves = XVECLEN (operands[2], 0);
10579 /* For the StrongARM at least it is faster to
10580 use STR to store only a single register.
10581 In Thumb mode always use push, and the assembler will pick
10582 something appropriate. */
10583 if (num_saves == 1 && TARGET_ARM)
10584 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
10591 strcpy (pattern, \"stm%(fd%)\\t%m0!, {%1\");
10592 else if (TARGET_THUMB2)
10593 strcpy (pattern, \"push%?\\t{%1\");
10595 strcpy (pattern, \"push\\t{%1\");
10597 for (i = 1; i < num_saves; i++)
10599 strcat (pattern, \", %|\");
10601 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10604 strcat (pattern, \"}\");
10605 output_asm_insn (pattern, operands);
10610 [(set_attr "type" "store4")
10611 (set (attr "length")
10612 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
10615 (define_insn "stack_tie"
10616 [(set (mem:BLK (scratch))
10617 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10618 (match_operand:SI 1 "s_register_operand" "rk")]
10622 [(set_attr "length" "0")]
10625 ;; Similarly for the floating point registers
10626 (define_insn "*push_fp_multi"
10627 [(match_parallel 2 "multi_register_push"
10628 [(set (match_operand:BLK 0 "memory_operand" "=m")
10629 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "")]
10630 UNSPEC_PUSH_MULT))])]
10631 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
10636 sprintf (pattern, \"sfm%%(fd%%)\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10637 output_asm_insn (pattern, operands);
10640 [(set_attr "type" "f_fpa_store")]
10643 ;; Special patterns for dealing with the constant pool
10645 (define_insn "align_4"
10646 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10649 assemble_align (32);
10654 (define_insn "align_8"
10655 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10658 assemble_align (64);
10663 (define_insn "consttable_end"
10664 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10667 making_const_table = FALSE;
10672 (define_insn "consttable_1"
10673 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10676 making_const_table = TRUE;
10677 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10678 assemble_zeros (3);
10681 [(set_attr "length" "4")]
10684 (define_insn "consttable_2"
10685 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10688 making_const_table = TRUE;
10689 gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
10690 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10691 assemble_zeros (2);
10694 [(set_attr "length" "4")]
10697 (define_insn "consttable_4"
10698 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10702 rtx x = operands[0];
10703 making_const_table = TRUE;
10704 switch (GET_MODE_CLASS (GET_MODE (x)))
10707 if (GET_MODE (x) == HFmode)
10708 arm_emit_fp16_const (x);
10712 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
10713 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
10717 /* XXX: Sometimes gcc does something really dumb and ends up with
10718 a HIGH in a constant pool entry, usually because it's trying to
10719 load into a VFP register. We know this will always be used in
10720 combination with a LO_SUM which ignores the high bits, so just
10721 strip off the HIGH. */
10722 if (GET_CODE (x) == HIGH)
10724 assemble_integer (x, 4, BITS_PER_WORD, 1);
10725 mark_symbol_refs_as_used (x);
10730 [(set_attr "length" "4")]
10733 (define_insn "consttable_8"
10734 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10738 making_const_table = TRUE;
10739 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10744 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10745 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10749 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10754 [(set_attr "length" "8")]
10757 (define_insn "consttable_16"
10758 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10762 making_const_table = TRUE;
10763 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10768 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10769 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10773 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10778 [(set_attr "length" "16")]
10781 ;; Miscellaneous Thumb patterns
10783 (define_expand "tablejump"
10784 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10785 (use (label_ref (match_operand 1 "" "")))])]
10790 /* Hopefully, CSE will eliminate this copy. */
10791 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10792 rtx reg2 = gen_reg_rtx (SImode);
10794 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10795 operands[0] = reg2;
10800 ;; NB never uses BX.
10801 (define_insn "*thumb1_tablejump"
10802 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10803 (use (label_ref (match_operand 1 "" "")))]
10806 [(set_attr "length" "2")]
10809 ;; V5 Instructions,
10811 (define_insn "clzsi2"
10812 [(set (match_operand:SI 0 "s_register_operand" "=r")
10813 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10814 "TARGET_32BIT && arm_arch5"
10816 [(set_attr "predicable" "yes")
10817 (set_attr "insn" "clz")])
10819 (define_insn "rbitsi2"
10820 [(set (match_operand:SI 0 "s_register_operand" "=r")
10821 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
10822 "TARGET_32BIT && arm_arch_thumb2"
10824 [(set_attr "predicable" "yes")
10825 (set_attr "insn" "clz")])
10827 (define_expand "ctzsi2"
10828 [(set (match_operand:SI 0 "s_register_operand" "")
10829 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10830 "TARGET_32BIT && arm_arch_thumb2"
10833 rtx tmp = gen_reg_rtx (SImode);
10834 emit_insn (gen_rbitsi2 (tmp, operands[1]));
10835 emit_insn (gen_clzsi2 (operands[0], tmp));
10841 ;; V5E instructions.
10843 (define_insn "prefetch"
10844 [(prefetch (match_operand:SI 0 "address_operand" "p")
10845 (match_operand:SI 1 "" "")
10846 (match_operand:SI 2 "" ""))]
10847 "TARGET_32BIT && arm_arch5e"
10850 ;; General predication pattern
10853 [(match_operator 0 "arm_comparison_operator"
10854 [(match_operand 1 "cc_register" "")
10860 (define_insn "prologue_use"
10861 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10863 "%@ %0 needed for prologue"
10864 [(set_attr "length" "0")]
10868 ;; Patterns for exception handling
10870 (define_expand "eh_return"
10871 [(use (match_operand 0 "general_operand" ""))]
10876 emit_insn (gen_arm_eh_return (operands[0]));
10878 emit_insn (gen_thumb_eh_return (operands[0]));
10883 ;; We can't expand this before we know where the link register is stored.
10884 (define_insn_and_split "arm_eh_return"
10885 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10887 (clobber (match_scratch:SI 1 "=&r"))]
10890 "&& reload_completed"
10894 arm_set_return_address (operands[0], operands[1]);
10899 (define_insn_and_split "thumb_eh_return"
10900 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10902 (clobber (match_scratch:SI 1 "=&l"))]
10905 "&& reload_completed"
10909 thumb_set_return_address (operands[0], operands[1]);
10917 (define_insn "load_tp_hard"
10918 [(set (match_operand:SI 0 "register_operand" "=r")
10919 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10921 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10922 [(set_attr "predicable" "yes")]
10925 ;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10926 (define_insn "load_tp_soft"
10927 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10928 (clobber (reg:SI LR_REGNUM))
10929 (clobber (reg:SI IP_REGNUM))
10930 (clobber (reg:CC CC_REGNUM))]
10932 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10933 [(set_attr "conds" "clob")]
10936 ;; tls descriptor call
10937 (define_insn "tlscall"
10938 [(set (reg:SI R0_REGNUM)
10939 (unspec:SI [(reg:SI R0_REGNUM)
10940 (match_operand:SI 0 "" "X")
10941 (match_operand 1 "" "")] UNSPEC_TLS))
10942 (clobber (reg:SI R1_REGNUM))
10943 (clobber (reg:SI LR_REGNUM))
10944 (clobber (reg:SI CC_REGNUM))]
10947 targetm.asm_out.internal_label (asm_out_file, "LPIC",
10948 INTVAL (operands[1]));
10949 return "bl\\t%c0(tlscall)";
10951 [(set_attr "conds" "clob")
10952 (set_attr "length" "4")]
10957 ;; We only care about the lower 16 bits of the constant
10958 ;; being inserted into the upper 16 bits of the register.
10959 (define_insn "*arm_movtas_ze"
10960 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
10963 (match_operand:SI 1 "const_int_operand" ""))]
10966 [(set_attr "predicable" "yes")
10967 (set_attr "length" "4")]
10970 (define_insn "*arm_rev"
10971 [(set (match_operand:SI 0 "s_register_operand" "=r")
10972 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
10973 "TARGET_32BIT && arm_arch6"
10975 [(set_attr "predicable" "yes")
10976 (set_attr "length" "4")]
10979 (define_insn "*thumb1_rev"
10980 [(set (match_operand:SI 0 "s_register_operand" "=l")
10981 (bswap:SI (match_operand:SI 1 "s_register_operand" "l")))]
10982 "TARGET_THUMB1 && arm_arch6"
10984 [(set_attr "length" "2")]
10987 (define_expand "arm_legacy_rev"
10988 [(set (match_operand:SI 2 "s_register_operand" "")
10989 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
10993 (lshiftrt:SI (match_dup 2)
10995 (set (match_operand:SI 3 "s_register_operand" "")
10996 (rotatert:SI (match_dup 1)
10999 (and:SI (match_dup 2)
11000 (const_int -65281)))
11001 (set (match_operand:SI 0 "s_register_operand" "")
11002 (xor:SI (match_dup 3)
11008 ;; Reuse temporaries to keep register pressure down.
11009 (define_expand "thumb_legacy_rev"
11010 [(set (match_operand:SI 2 "s_register_operand" "")
11011 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
11013 (set (match_operand:SI 3 "s_register_operand" "")
11014 (lshiftrt:SI (match_dup 1)
11017 (ior:SI (match_dup 3)
11019 (set (match_operand:SI 4 "s_register_operand" "")
11021 (set (match_operand:SI 5 "s_register_operand" "")
11022 (rotatert:SI (match_dup 1)
11025 (ashift:SI (match_dup 5)
11028 (lshiftrt:SI (match_dup 5)
11031 (ior:SI (match_dup 5)
11034 (rotatert:SI (match_dup 5)
11036 (set (match_operand:SI 0 "s_register_operand" "")
11037 (ior:SI (match_dup 5)
11043 (define_expand "bswapsi2"
11044 [(set (match_operand:SI 0 "s_register_operand" "=r")
11045 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
11046 "TARGET_EITHER && (arm_arch6 || !optimize_size)"
11050 rtx op2 = gen_reg_rtx (SImode);
11051 rtx op3 = gen_reg_rtx (SImode);
11055 rtx op4 = gen_reg_rtx (SImode);
11056 rtx op5 = gen_reg_rtx (SImode);
11058 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11059 op2, op3, op4, op5));
11063 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11072 ;; Load the load/store multiple patterns
11073 (include "ldmstm.md")
11074 ;; Load the FPA co-processor patterns
11076 ;; Load the Maverick co-processor patterns
11077 (include "cirrus.md")
11078 ;; Vector bits common to IWMMXT and Neon
11079 (include "vec-common.md")
11080 ;; Load the Intel Wireless Multimedia Extension patterns
11081 (include "iwmmxt.md")
11082 ;; Load the VFP co-processor patterns
11084 ;; Thumb-2 patterns
11085 (include "thumb2.md")
11087 (include "neon.md")
11088 ;; Synchronization Primitives
11089 (include "sync.md")
11090 ;; Fixed-point patterns
11091 (include "arm-fixed.md")