]> git.ipfire.org Git - thirdparty/gcc.git/blame_incremental - gcc/config/arm/arm.md
2012-05-22 Dimitrios Apostolou <jimis@gmx.net>
[thirdparty/gcc.git] / gcc / config / arm / arm.md
... / ...
CommitLineData
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, 2011, 2012
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).
8
9;; This file is part of GCC.
10
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.
15
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.
20
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/>.
24
25;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
27\f
28;;---------------------------------------------------------------------------
29;; Constants
30
31;; Register numbers
32(define_constants
33 [(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
43 ]
44)
45;; 3rd operand to select_dominance_cc_mode
46(define_constants
47 [(DOM_CC_X_AND_Y 0)
48 (DOM_CC_NX_OR_Y 1)
49 (DOM_CC_X_OR_Y 2)
50 ]
51)
52;; conditional compare combination
53(define_constants
54 [(CMP_CMP 0)
55 (CMN_CMP 1)
56 (CMP_CMN 2)
57 (CMN_CMN 3)
58 (NUM_OF_COND_CMP 4)
59 ]
60)
61
62;; UNSPEC Usage:
63;; Note: sin and cos are no-longer used.
64;; Unspec enumerators for Neon are defined in neon.md.
65
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 ...)
76 ; expressions.
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
89 ; register to "use".
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.
115 UNSPEC_UNALIGNED_LOAD ; Used to represent ldr/ldrh instructions that access
116 ; unaligned locations, on architectures which support
117 ; that.
118 UNSPEC_UNALIGNED_STORE ; Same for str/strh.
119 UNSPEC_PIC_UNIFIED ; Create a common pic addressing form.
120 UNSPEC_LL ; Represent an unpaired load-register-exclusive.
121])
122
123;; UNSPEC_VOLATILE Usage:
124
125(define_c_enum "unspecv" [
126 VUNSPEC_BLOCKAGE ; `blockage' insn to prevent scheduling across an
127 ; insn in the code.
128 VUNSPEC_EPILOGUE ; `epilogue' insn, used to represent any part of the
129 ; instruction epilogue sequence that isn't expanded
130 ; into normal RTL. Used for both normal and sibcall
131 ; epilogues.
132 VUNSPEC_THUMB1_INTERWORK ; `prologue_thumb1_interwork' insn, used to swap
133 ; modes from arm to thumb.
134 VUNSPEC_ALIGN ; `align' insn. Used at the head of a minipool table
135 ; for inlined constants.
136 VUNSPEC_POOL_END ; `end-of-table'. Used to mark the end of a minipool
137 ; table.
138 VUNSPEC_POOL_1 ; `pool-entry(1)'. An entry in the constant pool for
139 ; an 8-bit object.
140 VUNSPEC_POOL_2 ; `pool-entry(2)'. An entry in the constant pool for
141 ; a 16-bit object.
142 VUNSPEC_POOL_4 ; `pool-entry(4)'. An entry in the constant pool for
143 ; a 32-bit object.
144 VUNSPEC_POOL_8 ; `pool-entry(8)'. An entry in the constant pool for
145 ; a 64-bit object.
146 VUNSPEC_POOL_16 ; `pool-entry(16)'. An entry in the constant pool for
147 ; a 128-bit object.
148 VUNSPEC_TMRC ; Used by the iWMMXt TMRC instruction.
149 VUNSPEC_TMCR ; Used by the iWMMXt TMCR instruction.
150 VUNSPEC_ALIGN8 ; 8-byte alignment version of VUNSPEC_ALIGN
151 VUNSPEC_WCMP_EQ ; Used by the iWMMXt WCMPEQ instructions
152 VUNSPEC_WCMP_GTU ; Used by the iWMMXt WCMPGTU instructions
153 VUNSPEC_WCMP_GT ; Used by the iwMMXT WCMPGT instructions
154 VUNSPEC_EH_RETURN ; Use to override the return address for exception
155 ; handling.
156 VUNSPEC_ATOMIC_CAS ; Represent an atomic compare swap.
157 VUNSPEC_ATOMIC_XCHG ; Represent an atomic exchange.
158 VUNSPEC_ATOMIC_OP ; Represent an atomic operation.
159 VUNSPEC_LL ; Represent a load-register-exclusive.
160 VUNSPEC_SC ; Represent a store-register-exclusive.
161])
162\f
163;;---------------------------------------------------------------------------
164;; Attributes
165
166;; Processor type. This is created automatically from arm-cores.def.
167(include "arm-tune.md")
168
169; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
170; generating ARM code. This is used to control the length of some insn
171; patterns that share the same RTL in both ARM and Thumb code.
172(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
173
174; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
175(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
176
177; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
178(define_attr "is_thumb1" "no,yes" (const (symbol_ref "thumb1_code")))
179
180;; Operand number of an input operand that is shifted. Zero if the
181;; given instruction does not shift one of its input operands.
182(define_attr "shift" "" (const_int 0))
183
184; Floating Point Unit. If we only have floating point emulation, then there
185; is no point in scheduling the floating point insns. (Well, for best
186; performance we should try and group them together).
187(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
188 (const (symbol_ref "arm_fpu_attr")))
189
190; LENGTH of an instruction (in bytes)
191(define_attr "length" ""
192 (const_int 4))
193
194; The architecture which supports the instruction (or alternative).
195; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
196; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
197; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
198; arm_arch6. This attribute is used to compute attribute "enabled",
199; use type "any" to enable an alternative in all cases.
200(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,onlya8,neon_onlya8,nota8,neon_nota8"
201 (const_string "any"))
202
203(define_attr "arch_enabled" "no,yes"
204 (cond [(eq_attr "arch" "any")
205 (const_string "yes")
206
207 (and (eq_attr "arch" "a")
208 (match_test "TARGET_ARM"))
209 (const_string "yes")
210
211 (and (eq_attr "arch" "t")
212 (match_test "TARGET_THUMB"))
213 (const_string "yes")
214
215 (and (eq_attr "arch" "t1")
216 (match_test "TARGET_THUMB1"))
217 (const_string "yes")
218
219 (and (eq_attr "arch" "t2")
220 (match_test "TARGET_THUMB2"))
221 (const_string "yes")
222
223 (and (eq_attr "arch" "32")
224 (match_test "TARGET_32BIT"))
225 (const_string "yes")
226
227 (and (eq_attr "arch" "v6")
228 (match_test "TARGET_32BIT && arm_arch6"))
229 (const_string "yes")
230
231 (and (eq_attr "arch" "nov6")
232 (match_test "TARGET_32BIT && !arm_arch6"))
233 (const_string "yes")
234
235 (and (eq_attr "arch" "onlya8")
236 (eq_attr "tune" "cortexa8"))
237 (const_string "yes")
238
239 (and (eq_attr "arch" "neon_onlya8")
240 (eq_attr "tune" "cortexa8")
241 (match_test "TARGET_NEON"))
242 (const_string "yes")
243
244 (and (eq_attr "arch" "nota8")
245 (not (eq_attr "tune" "cortexa8")))
246 (const_string "yes")
247
248 (and (eq_attr "arch" "neon_nota8")
249 (not (eq_attr "tune" "cortexa8"))
250 (match_test "TARGET_NEON"))
251 (const_string "yes")]
252 (const_string "no")))
253
254; Allows an insn to disable certain alternatives for reasons other than
255; arch support.
256(define_attr "insn_enabled" "no,yes"
257 (const_string "yes"))
258
259; Enable all alternatives that are both arch_enabled and insn_enabled.
260 (define_attr "enabled" "no,yes"
261 (if_then_else (eq_attr "insn_enabled" "yes")
262 (if_then_else (eq_attr "arch_enabled" "yes")
263 (const_string "yes")
264 (const_string "no"))
265 (const_string "no")))
266
267; POOL_RANGE is how far away from a constant pool entry that this insn
268; can be placed. If the distance is zero, then this insn will never
269; reference the pool.
270; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
271; before its address. It is set to <max_range> - (8 + <data_size>).
272(define_attr "arm_pool_range" "" (const_int 0))
273(define_attr "thumb2_pool_range" "" (const_int 0))
274(define_attr "arm_neg_pool_range" "" (const_int 0))
275(define_attr "thumb2_neg_pool_range" "" (const_int 0))
276
277(define_attr "pool_range" ""
278 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
279 (attr "arm_pool_range")))
280(define_attr "neg_pool_range" ""
281 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
282 (attr "arm_neg_pool_range")))
283
284; An assembler sequence may clobber the condition codes without us knowing.
285; If such an insn references the pool, then we have no way of knowing how,
286; so use the most conservative value for pool_range.
287(define_asm_attributes
288 [(set_attr "conds" "clob")
289 (set_attr "length" "4")
290 (set_attr "pool_range" "250")])
291
292;; The instruction used to implement a particular pattern. This
293;; information is used by pipeline descriptions to provide accurate
294;; scheduling information.
295
296(define_attr "insn"
297 "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,sat,other"
298 (const_string "other"))
299
300; TYPE attribute is used to detect floating point instructions which, if
301; running on a co-processor can run in parallel with other, basic instructions
302; If write-buffer scheduling is enabled then it can also be used in the
303; scheduling of writes.
304
305; Classification of each insn
306; Note: vfp.md has different meanings for some of these, and some further
307; types as well. See that file for details.
308; alu any alu instruction that doesn't hit memory or fp
309; regs or have a shifted source operand
310; alu_shift any data instruction that doesn't hit memory or fp
311; regs, but has a source operand shifted by a constant
312; alu_shift_reg any data instruction that doesn't hit memory or fp
313; regs, but has a source operand shifted by a register value
314; mult a multiply instruction
315; block blockage insn, this blocks all functional units
316; float a floating point arithmetic operation (subject to expansion)
317; fdivd DFmode floating point division
318; fdivs SFmode floating point division
319; fmul Floating point multiply
320; ffmul Fast floating point multiply
321; farith Floating point arithmetic (4 cycle)
322; ffarith Fast floating point arithmetic (2 cycle)
323; float_em a floating point arithmetic operation that is normally emulated
324; even on a machine with an fpa.
325; f_fpa_load a floating point load from memory. Only for the FPA.
326; f_fpa_store a floating point store to memory. Only for the FPA.
327; f_load[sd] A single/double load from memory. Used for VFP unit.
328; f_store[sd] A single/double store to memory. Used for VFP unit.
329; f_flag a transfer of co-processor flags to the CPSR
330; f_mem_r a transfer of a floating point register to a real reg via mem
331; r_mem_f the reverse of f_mem_r
332; f_2_r fast transfer float to arm (no memory needed)
333; r_2_f fast transfer arm to float
334; f_cvt convert floating<->integral
335; branch a branch
336; call a subroutine call
337; load_byte load byte(s) from memory to arm registers
338; load1 load 1 word from memory to arm registers
339; load2 load 2 words from memory to arm registers
340; load3 load 3 words from memory to arm registers
341; load4 load 4 words from memory to arm registers
342; store store 1 word to memory from arm registers
343; store2 store 2 words
344; store3 store 3 words
345; store4 store 4 (or more) words
346; Additions for Cirrus Maverick co-processor:
347; mav_farith Floating point arithmetic (4 cycle)
348; mav_dmult Double multiplies (7 cycle)
349;
350
351(define_attr "type"
352 "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"
353 (if_then_else
354 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
355 (const_string "mult")
356 (const_string "alu")))
357
358; Is this an (integer side) multiply with a 64-bit result?
359(define_attr "mul64" "no,yes"
360 (if_then_else
361 (eq_attr "insn" "smlalxy,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
362 (const_string "yes")
363 (const_string "no")))
364
365; Load scheduling, set from the arm_ld_sched variable
366; initialized by arm_option_override()
367(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
368
369;; Classification of NEON instructions for scheduling purposes.
370;; Do not set this attribute and the "type" attribute together in
371;; any one instruction pattern.
372(define_attr "neon_type"
373 "neon_int_1,\
374 neon_int_2,\
375 neon_int_3,\
376 neon_int_4,\
377 neon_int_5,\
378 neon_vqneg_vqabs,\
379 neon_vmov,\
380 neon_vaba,\
381 neon_vsma,\
382 neon_vaba_qqq,\
383 neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
384 neon_mul_qqq_8_16_32_ddd_32,\
385 neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
386 neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
387 neon_mla_qqq_8_16,\
388 neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
389 neon_mla_qqq_32_qqd_32_scalar,\
390 neon_mul_ddd_16_scalar_32_16_long_scalar,\
391 neon_mul_qqd_32_scalar,\
392 neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
393 neon_shift_1,\
394 neon_shift_2,\
395 neon_shift_3,\
396 neon_vshl_ddd,\
397 neon_vqshl_vrshl_vqrshl_qqq,\
398 neon_vsra_vrsra,\
399 neon_fp_vadd_ddd_vabs_dd,\
400 neon_fp_vadd_qqq_vabs_qq,\
401 neon_fp_vsum,\
402 neon_fp_vmul_ddd,\
403 neon_fp_vmul_qqd,\
404 neon_fp_vmla_ddd,\
405 neon_fp_vmla_qqq,\
406 neon_fp_vmla_ddd_scalar,\
407 neon_fp_vmla_qqq_scalar,\
408 neon_fp_vrecps_vrsqrts_ddd,\
409 neon_fp_vrecps_vrsqrts_qqq,\
410 neon_bp_simple,\
411 neon_bp_2cycle,\
412 neon_bp_3cycle,\
413 neon_ldr,\
414 neon_str,\
415 neon_vld1_1_2_regs,\
416 neon_vld1_3_4_regs,\
417 neon_vld2_2_regs_vld1_vld2_all_lanes,\
418 neon_vld2_4_regs,\
419 neon_vld3_vld4,\
420 neon_vst1_1_2_regs_vst2_2_regs,\
421 neon_vst1_3_4_regs,\
422 neon_vst2_4_regs_vst3_vst4,\
423 neon_vst3_vst4,\
424 neon_vld1_vld2_lane,\
425 neon_vld3_vld4_lane,\
426 neon_vst1_vst2_lane,\
427 neon_vst3_vst4_lane,\
428 neon_vld3_vld4_all_lanes,\
429 neon_mcr,\
430 neon_mcr_2_mcrr,\
431 neon_mrc,\
432 neon_mrrc,\
433 neon_ldm_2,\
434 neon_stm_2,\
435 none"
436 (const_string "none"))
437
438; condition codes: this one is used by final_prescan_insn to speed up
439; conditionalizing instructions. It saves having to scan the rtl to see if
440; it uses or alters the condition codes.
441;
442; USE means that the condition codes are used by the insn in the process of
443; outputting code, this means (at present) that we can't use the insn in
444; inlined branches
445;
446; SET means that the purpose of the insn is to set the condition codes in a
447; well defined manner.
448;
449; CLOB means that the condition codes are altered in an undefined manner, if
450; they are altered at all
451;
452; UNCONDITIONAL means the instruction can not be conditionally executed and
453; that the instruction does not use or alter the condition codes.
454;
455; NOCOND means that the instruction does not use or alter the condition
456; codes but can be converted into a conditionally exectuted instruction.
457
458(define_attr "conds" "use,set,clob,unconditional,nocond"
459 (if_then_else
460 (ior (eq_attr "is_thumb1" "yes")
461 (eq_attr "type" "call"))
462 (const_string "clob")
463 (if_then_else (eq_attr "neon_type" "none")
464 (const_string "nocond")
465 (const_string "unconditional"))))
466
467; Predicable means that the insn can be conditionally executed based on
468; an automatically added predicate (additional patterns are generated by
469; gen...). We default to 'no' because no Thumb patterns match this rule
470; and not all ARM patterns do.
471(define_attr "predicable" "no,yes" (const_string "no"))
472
473; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
474; have one. Later ones, such as StrongARM, have write-back caches, so don't
475; suffer blockages enough to warrant modelling this (and it can adversely
476; affect the schedule).
477(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
478
479; WRITE_CONFLICT implies that a read following an unrelated write is likely
480; to stall the processor. Used with model_wbuf above.
481(define_attr "write_conflict" "no,yes"
482 (if_then_else (eq_attr "type"
483 "block,float_em,f_fpa_load,f_fpa_store,f_mem_r,r_mem_f,call,load1")
484 (const_string "yes")
485 (const_string "no")))
486
487; Classify the insns into those that take one cycle and those that take more
488; than one on the main cpu execution unit.
489(define_attr "core_cycles" "single,multi"
490 (if_then_else (eq_attr "type"
491 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
492 (const_string "single")
493 (const_string "multi")))
494
495;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
496;; distant label. Only applicable to Thumb code.
497(define_attr "far_jump" "yes,no" (const_string "no"))
498
499
500;; The number of machine instructions this pattern expands to.
501;; Used for Thumb-2 conditional execution.
502(define_attr "ce_count" "" (const_int 1))
503
504;;---------------------------------------------------------------------------
505;; Mode iterators
506
507(include "iterators.md")
508
509;;---------------------------------------------------------------------------
510;; Predicates
511
512(include "predicates.md")
513(include "constraints.md")
514
515;;---------------------------------------------------------------------------
516;; Pipeline descriptions
517
518(define_attr "tune_cortexr4" "yes,no"
519 (const (if_then_else
520 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
521 (const_string "yes")
522 (const_string "no"))))
523
524;; True if the generic scheduling description should be used.
525
526(define_attr "generic_sched" "yes,no"
527 (const (if_then_else
528 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa5,cortexa8,cortexa9,cortexa15,cortexm4")
529 (eq_attr "tune_cortexr4" "yes"))
530 (const_string "no")
531 (const_string "yes"))))
532
533(define_attr "generic_vfp" "yes,no"
534 (const (if_then_else
535 (and (eq_attr "fpu" "vfp")
536 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa8,cortexa9,cortexm4")
537 (eq_attr "tune_cortexr4" "no"))
538 (const_string "yes")
539 (const_string "no"))))
540
541(include "arm-generic.md")
542(include "arm926ejs.md")
543(include "arm1020e.md")
544(include "arm1026ejs.md")
545(include "arm1136jfs.md")
546(include "fa526.md")
547(include "fa606te.md")
548(include "fa626te.md")
549(include "fmp626.md")
550(include "fa726te.md")
551(include "cortex-a5.md")
552(include "cortex-a8.md")
553(include "cortex-a9.md")
554(include "cortex-a15.md")
555(include "cortex-r4.md")
556(include "cortex-r4f.md")
557(include "cortex-m4.md")
558(include "cortex-m4-fpu.md")
559(include "vfp11.md")
560
561\f
562;;---------------------------------------------------------------------------
563;; Insn patterns
564;;
565;; Addition insns.
566
567;; Note: For DImode insns, there is normally no reason why operands should
568;; not be in the same register, what we don't want is for something being
569;; written to partially overlap something that is an input.
570;; Cirrus 64bit additions should not be split because we have a native
571;; 64bit addition instructions.
572
573(define_expand "adddi3"
574 [(parallel
575 [(set (match_operand:DI 0 "s_register_operand" "")
576 (plus:DI (match_operand:DI 1 "s_register_operand" "")
577 (match_operand:DI 2 "s_register_operand" "")))
578 (clobber (reg:CC CC_REGNUM))])]
579 "TARGET_EITHER"
580 "
581 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
582 {
583 if (!cirrus_fp_register (operands[0], DImode))
584 operands[0] = force_reg (DImode, operands[0]);
585 if (!cirrus_fp_register (operands[1], DImode))
586 operands[1] = force_reg (DImode, operands[1]);
587 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
588 DONE;
589 }
590
591 if (TARGET_THUMB1)
592 {
593 if (GET_CODE (operands[1]) != REG)
594 operands[1] = force_reg (DImode, operands[1]);
595 if (GET_CODE (operands[2]) != REG)
596 operands[2] = force_reg (DImode, operands[2]);
597 }
598 "
599)
600
601(define_insn "*thumb1_adddi3"
602 [(set (match_operand:DI 0 "register_operand" "=l")
603 (plus:DI (match_operand:DI 1 "register_operand" "%0")
604 (match_operand:DI 2 "register_operand" "l")))
605 (clobber (reg:CC CC_REGNUM))
606 ]
607 "TARGET_THUMB1"
608 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
609 [(set_attr "length" "4")]
610)
611
612(define_insn_and_split "*arm_adddi3"
613 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
614 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
615 (match_operand:DI 2 "s_register_operand" "r, 0")))
616 (clobber (reg:CC CC_REGNUM))]
617 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK) && !TARGET_NEON"
618 "#"
619 "TARGET_32BIT && reload_completed
620 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
621 [(parallel [(set (reg:CC_C CC_REGNUM)
622 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
623 (match_dup 1)))
624 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
625 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
626 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
627 "
628 {
629 operands[3] = gen_highpart (SImode, operands[0]);
630 operands[0] = gen_lowpart (SImode, operands[0]);
631 operands[4] = gen_highpart (SImode, operands[1]);
632 operands[1] = gen_lowpart (SImode, operands[1]);
633 operands[5] = gen_highpart (SImode, operands[2]);
634 operands[2] = gen_lowpart (SImode, operands[2]);
635 }"
636 [(set_attr "conds" "clob")
637 (set_attr "length" "8")]
638)
639
640(define_insn_and_split "*adddi_sesidi_di"
641 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
642 (plus:DI (sign_extend:DI
643 (match_operand:SI 2 "s_register_operand" "r,r"))
644 (match_operand:DI 1 "s_register_operand" "0,r")))
645 (clobber (reg:CC CC_REGNUM))]
646 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
647 "#"
648 "TARGET_32BIT && reload_completed"
649 [(parallel [(set (reg:CC_C CC_REGNUM)
650 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
651 (match_dup 1)))
652 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
653 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
654 (const_int 31))
655 (match_dup 4))
656 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
657 "
658 {
659 operands[3] = gen_highpart (SImode, operands[0]);
660 operands[0] = gen_lowpart (SImode, operands[0]);
661 operands[4] = gen_highpart (SImode, operands[1]);
662 operands[1] = gen_lowpart (SImode, operands[1]);
663 operands[2] = gen_lowpart (SImode, operands[2]);
664 }"
665 [(set_attr "conds" "clob")
666 (set_attr "length" "8")]
667)
668
669(define_insn_and_split "*adddi_zesidi_di"
670 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
671 (plus:DI (zero_extend:DI
672 (match_operand:SI 2 "s_register_operand" "r,r"))
673 (match_operand:DI 1 "s_register_operand" "0,r")))
674 (clobber (reg:CC CC_REGNUM))]
675 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
676 "#"
677 "TARGET_32BIT && reload_completed"
678 [(parallel [(set (reg:CC_C CC_REGNUM)
679 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
680 (match_dup 1)))
681 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
682 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
683 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
684 "
685 {
686 operands[3] = gen_highpart (SImode, operands[0]);
687 operands[0] = gen_lowpart (SImode, operands[0]);
688 operands[4] = gen_highpart (SImode, operands[1]);
689 operands[1] = gen_lowpart (SImode, operands[1]);
690 operands[2] = gen_lowpart (SImode, operands[2]);
691 }"
692 [(set_attr "conds" "clob")
693 (set_attr "length" "8")]
694)
695
696(define_expand "addsi3"
697 [(set (match_operand:SI 0 "s_register_operand" "")
698 (plus:SI (match_operand:SI 1 "s_register_operand" "")
699 (match_operand:SI 2 "reg_or_int_operand" "")))]
700 "TARGET_EITHER"
701 "
702 if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
703 {
704 arm_split_constant (PLUS, SImode, NULL_RTX,
705 INTVAL (operands[2]), operands[0], operands[1],
706 optimize && can_create_pseudo_p ());
707 DONE;
708 }
709 "
710)
711
712; If there is a scratch available, this will be faster than synthesizing the
713; addition.
714(define_peephole2
715 [(match_scratch:SI 3 "r")
716 (set (match_operand:SI 0 "arm_general_register_operand" "")
717 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
718 (match_operand:SI 2 "const_int_operand" "")))]
719 "TARGET_32BIT &&
720 !(const_ok_for_arm (INTVAL (operands[2]))
721 || const_ok_for_arm (-INTVAL (operands[2])))
722 && const_ok_for_arm (~INTVAL (operands[2]))"
723 [(set (match_dup 3) (match_dup 2))
724 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
725 ""
726)
727
728;; The r/r/k alternative is required when reloading the address
729;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
730;; put the duplicated register first, and not try the commutative version.
731(define_insn_and_split "*arm_addsi3"
732 [(set (match_operand:SI 0 "s_register_operand" "=r, k,r,r, k, r, k,r, k, r")
733 (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,k,r,rk,k, rk,k,rk,k, rk")
734 (match_operand:SI 2 "reg_or_int_operand" "rI,rI,k,Pj,Pj,L, L,PJ,PJ,?n")))]
735 "TARGET_32BIT"
736 "@
737 add%?\\t%0, %1, %2
738 add%?\\t%0, %1, %2
739 add%?\\t%0, %2, %1
740 addw%?\\t%0, %1, %2
741 addw%?\\t%0, %1, %2
742 sub%?\\t%0, %1, #%n2
743 sub%?\\t%0, %1, #%n2
744 subw%?\\t%0, %1, #%n2
745 subw%?\\t%0, %1, #%n2
746 #"
747 "TARGET_32BIT
748 && GET_CODE (operands[2]) == CONST_INT
749 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
750 && (reload_completed || !arm_eliminable_register (operands[1]))"
751 [(clobber (const_int 0))]
752 "
753 arm_split_constant (PLUS, SImode, curr_insn,
754 INTVAL (operands[2]), operands[0],
755 operands[1], 0);
756 DONE;
757 "
758 [(set_attr "length" "4,4,4,4,4,4,4,4,4,16")
759 (set_attr "predicable" "yes")
760 (set_attr "arch" "*,*,*,t2,t2,*,*,t2,t2,*")]
761)
762
763(define_insn_and_split "*thumb1_addsi3"
764 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,k,l,l,l")
765 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,k,k,0,l,k")
766 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,M,O,Pa,Pb,Pc")))]
767 "TARGET_THUMB1"
768 "*
769 static const char * const asms[] =
770 {
771 \"add\\t%0, %0, %2\",
772 \"sub\\t%0, %0, #%n2\",
773 \"add\\t%0, %1, %2\",
774 \"add\\t%0, %0, %2\",
775 \"add\\t%0, %0, %2\",
776 \"add\\t%0, %1, %2\",
777 \"add\\t%0, %1, %2\",
778 \"#\",
779 \"#\",
780 \"#\"
781 };
782 if ((which_alternative == 2 || which_alternative == 6)
783 && GET_CODE (operands[2]) == CONST_INT
784 && INTVAL (operands[2]) < 0)
785 return \"sub\\t%0, %1, #%n2\";
786 return asms[which_alternative];
787 "
788 "&& reload_completed && CONST_INT_P (operands[2])
789 && ((operands[1] != stack_pointer_rtx
790 && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255))
791 || (operands[1] == stack_pointer_rtx
792 && INTVAL (operands[2]) > 1020))"
793 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
794 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
795 {
796 HOST_WIDE_INT offset = INTVAL (operands[2]);
797 if (operands[1] == stack_pointer_rtx)
798 offset -= 1020;
799 else
800 {
801 if (offset > 255)
802 offset = 255;
803 else if (offset < -255)
804 offset = -255;
805 }
806 operands[3] = GEN_INT (offset);
807 operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
808 }
809 [(set_attr "length" "2,2,2,2,2,2,2,4,4,4")]
810)
811
812;; Reloading and elimination of the frame pointer can
813;; sometimes cause this optimization to be missed.
814(define_peephole2
815 [(set (match_operand:SI 0 "arm_general_register_operand" "")
816 (match_operand:SI 1 "const_int_operand" ""))
817 (set (match_dup 0)
818 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
819 "TARGET_THUMB1
820 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
821 && (INTVAL (operands[1]) & 3) == 0"
822 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
823 ""
824)
825
826(define_insn "addsi3_compare0"
827 [(set (reg:CC_NOOV CC_REGNUM)
828 (compare:CC_NOOV
829 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
830 (match_operand:SI 2 "arm_add_operand" "rI,L"))
831 (const_int 0)))
832 (set (match_operand:SI 0 "s_register_operand" "=r,r")
833 (plus:SI (match_dup 1) (match_dup 2)))]
834 "TARGET_ARM"
835 "@
836 add%.\\t%0, %1, %2
837 sub%.\\t%0, %1, #%n2"
838 [(set_attr "conds" "set")]
839)
840
841(define_insn "*addsi3_compare0_scratch"
842 [(set (reg:CC_NOOV CC_REGNUM)
843 (compare:CC_NOOV
844 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
845 (match_operand:SI 1 "arm_add_operand" "rI,L"))
846 (const_int 0)))]
847 "TARGET_ARM"
848 "@
849 cmn%?\\t%0, %1
850 cmp%?\\t%0, #%n1"
851 [(set_attr "conds" "set")
852 (set_attr "predicable" "yes")]
853)
854
855(define_insn "*compare_negsi_si"
856 [(set (reg:CC_Z CC_REGNUM)
857 (compare:CC_Z
858 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
859 (match_operand:SI 1 "s_register_operand" "r")))]
860 "TARGET_32BIT"
861 "cmn%?\\t%1, %0"
862 [(set_attr "conds" "set")
863 (set_attr "predicable" "yes")]
864)
865
866;; This is the canonicalization of addsi3_compare0_for_combiner when the
867;; addend is a constant.
868(define_insn "*cmpsi2_addneg"
869 [(set (reg:CC CC_REGNUM)
870 (compare:CC
871 (match_operand:SI 1 "s_register_operand" "r,r")
872 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
873 (set (match_operand:SI 0 "s_register_operand" "=r,r")
874 (plus:SI (match_dup 1)
875 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
876 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
877 "@
878 add%.\\t%0, %1, %3
879 sub%.\\t%0, %1, #%n3"
880 [(set_attr "conds" "set")]
881)
882
883;; Convert the sequence
884;; sub rd, rn, #1
885;; cmn rd, #1 (equivalent to cmp rd, #-1)
886;; bne dest
887;; into
888;; subs rd, rn, #1
889;; bcs dest ((unsigned)rn >= 1)
890;; similarly for the beq variant using bcc.
891;; This is a common looping idiom (while (n--))
892(define_peephole2
893 [(set (match_operand:SI 0 "arm_general_register_operand" "")
894 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
895 (const_int -1)))
896 (set (match_operand 2 "cc_register" "")
897 (compare (match_dup 0) (const_int -1)))
898 (set (pc)
899 (if_then_else (match_operator 3 "equality_operator"
900 [(match_dup 2) (const_int 0)])
901 (match_operand 4 "" "")
902 (match_operand 5 "" "")))]
903 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
904 [(parallel[
905 (set (match_dup 2)
906 (compare:CC
907 (match_dup 1) (const_int 1)))
908 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
909 (set (pc)
910 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
911 (match_dup 4)
912 (match_dup 5)))]
913 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
914 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
915 ? GEU : LTU),
916 VOIDmode,
917 operands[2], const0_rtx);"
918)
919
920;; The next four insns work because they compare the result with one of
921;; the operands, and we know that the use of the condition code is
922;; either GEU or LTU, so we can use the carry flag from the addition
923;; instead of doing the compare a second time.
924(define_insn "*addsi3_compare_op1"
925 [(set (reg:CC_C CC_REGNUM)
926 (compare:CC_C
927 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
928 (match_operand:SI 2 "arm_add_operand" "rI,L"))
929 (match_dup 1)))
930 (set (match_operand:SI 0 "s_register_operand" "=r,r")
931 (plus:SI (match_dup 1) (match_dup 2)))]
932 "TARGET_32BIT"
933 "@
934 add%.\\t%0, %1, %2
935 sub%.\\t%0, %1, #%n2"
936 [(set_attr "conds" "set")]
937)
938
939(define_insn "*addsi3_compare_op2"
940 [(set (reg:CC_C CC_REGNUM)
941 (compare:CC_C
942 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
943 (match_operand:SI 2 "arm_add_operand" "rI,L"))
944 (match_dup 2)))
945 (set (match_operand:SI 0 "s_register_operand" "=r,r")
946 (plus:SI (match_dup 1) (match_dup 2)))]
947 "TARGET_32BIT"
948 "@
949 add%.\\t%0, %1, %2
950 sub%.\\t%0, %1, #%n2"
951 [(set_attr "conds" "set")]
952)
953
954(define_insn "*compare_addsi2_op0"
955 [(set (reg:CC_C CC_REGNUM)
956 (compare:CC_C
957 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
958 (match_operand:SI 1 "arm_add_operand" "rI,L"))
959 (match_dup 0)))]
960 "TARGET_32BIT"
961 "@
962 cmn%?\\t%0, %1
963 cmp%?\\t%0, #%n1"
964 [(set_attr "conds" "set")
965 (set_attr "predicable" "yes")]
966)
967
968(define_insn "*compare_addsi2_op1"
969 [(set (reg:CC_C CC_REGNUM)
970 (compare:CC_C
971 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
972 (match_operand:SI 1 "arm_add_operand" "rI,L"))
973 (match_dup 1)))]
974 "TARGET_32BIT"
975 "@
976 cmn%?\\t%0, %1
977 cmp%?\\t%0, #%n1"
978 [(set_attr "conds" "set")
979 (set_attr "predicable" "yes")]
980)
981
982(define_insn "*addsi3_carryin_<optab>"
983 [(set (match_operand:SI 0 "s_register_operand" "=r")
984 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
985 (match_operand:SI 2 "arm_rhs_operand" "rI"))
986 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
987 "TARGET_32BIT"
988 "adc%?\\t%0, %1, %2"
989 [(set_attr "conds" "use")]
990)
991
992(define_insn "*addsi3_carryin_alt2_<optab>"
993 [(set (match_operand:SI 0 "s_register_operand" "=r")
994 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
995 (match_operand:SI 1 "s_register_operand" "%r"))
996 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
997 "TARGET_32BIT"
998 "adc%?\\t%0, %1, %2"
999 [(set_attr "conds" "use")]
1000)
1001
1002(define_insn "*addsi3_carryin_shift_<optab>"
1003 [(set (match_operand:SI 0 "s_register_operand" "=r")
1004 (plus:SI (plus:SI
1005 (match_operator:SI 2 "shift_operator"
1006 [(match_operand:SI 3 "s_register_operand" "r")
1007 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1008 (match_operand:SI 1 "s_register_operand" "r"))
1009 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
1010 "TARGET_32BIT"
1011 "adc%?\\t%0, %1, %3%S2"
1012 [(set_attr "conds" "use")
1013 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
1014 (const_string "alu_shift")
1015 (const_string "alu_shift_reg")))]
1016)
1017
1018(define_insn "*addsi3_carryin_clobercc_<optab>"
1019 [(set (match_operand:SI 0 "s_register_operand" "=r")
1020 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
1021 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1022 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
1023 (clobber (reg:CC CC_REGNUM))]
1024 "TARGET_32BIT"
1025 "adc%.\\t%0, %1, %2"
1026 [(set_attr "conds" "set")]
1027)
1028
1029(define_expand "incscc"
1030 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1031 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
1032 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
1033 (match_operand:SI 1 "s_register_operand" "0,?r")))]
1034 "TARGET_32BIT"
1035 ""
1036)
1037
1038(define_insn "*arm_incscc"
1039 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1040 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
1041 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
1042 (match_operand:SI 1 "s_register_operand" "0,?r")))]
1043 "TARGET_ARM"
1044 "@
1045 add%d2\\t%0, %1, #1
1046 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
1047 [(set_attr "conds" "use")
1048 (set_attr "length" "4,8")]
1049)
1050
1051; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
1052(define_split
1053 [(set (match_operand:SI 0 "s_register_operand" "")
1054 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1055 (match_operand:SI 2 "s_register_operand" ""))
1056 (const_int -1)))
1057 (clobber (match_operand:SI 3 "s_register_operand" ""))]
1058 "TARGET_32BIT"
1059 [(set (match_dup 3) (match_dup 1))
1060 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1061 "
1062 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1063")
1064
1065(define_expand "addsf3"
1066 [(set (match_operand:SF 0 "s_register_operand" "")
1067 (plus:SF (match_operand:SF 1 "s_register_operand" "")
1068 (match_operand:SF 2 "arm_float_add_operand" "")))]
1069 "TARGET_32BIT && TARGET_HARD_FLOAT"
1070 "
1071 if (TARGET_MAVERICK
1072 && !cirrus_fp_register (operands[2], SFmode))
1073 operands[2] = force_reg (SFmode, operands[2]);
1074")
1075
1076(define_expand "adddf3"
1077 [(set (match_operand:DF 0 "s_register_operand" "")
1078 (plus:DF (match_operand:DF 1 "s_register_operand" "")
1079 (match_operand:DF 2 "arm_float_add_operand" "")))]
1080 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1081 "
1082 if (TARGET_MAVERICK
1083 && !cirrus_fp_register (operands[2], DFmode))
1084 operands[2] = force_reg (DFmode, operands[2]);
1085")
1086
1087(define_expand "subdi3"
1088 [(parallel
1089 [(set (match_operand:DI 0 "s_register_operand" "")
1090 (minus:DI (match_operand:DI 1 "s_register_operand" "")
1091 (match_operand:DI 2 "s_register_operand" "")))
1092 (clobber (reg:CC CC_REGNUM))])]
1093 "TARGET_EITHER"
1094 "
1095 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
1096 && TARGET_32BIT
1097 && cirrus_fp_register (operands[0], DImode)
1098 && cirrus_fp_register (operands[1], DImode))
1099 {
1100 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
1101 DONE;
1102 }
1103
1104 if (TARGET_THUMB1)
1105 {
1106 if (GET_CODE (operands[1]) != REG)
1107 operands[1] = force_reg (DImode, operands[1]);
1108 if (GET_CODE (operands[2]) != REG)
1109 operands[2] = force_reg (DImode, operands[2]);
1110 }
1111 "
1112)
1113
1114(define_insn "*arm_subdi3"
1115 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
1116 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1117 (match_operand:DI 2 "s_register_operand" "r,0,0")))
1118 (clobber (reg:CC CC_REGNUM))]
1119 "TARGET_32BIT && !TARGET_NEON"
1120 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
1121 [(set_attr "conds" "clob")
1122 (set_attr "length" "8")]
1123)
1124
1125(define_insn "*thumb_subdi3"
1126 [(set (match_operand:DI 0 "register_operand" "=l")
1127 (minus:DI (match_operand:DI 1 "register_operand" "0")
1128 (match_operand:DI 2 "register_operand" "l")))
1129 (clobber (reg:CC CC_REGNUM))]
1130 "TARGET_THUMB1"
1131 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
1132 [(set_attr "length" "4")]
1133)
1134
1135(define_insn "*subdi_di_zesidi"
1136 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1137 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
1138 (zero_extend:DI
1139 (match_operand:SI 2 "s_register_operand" "r,r"))))
1140 (clobber (reg:CC CC_REGNUM))]
1141 "TARGET_32BIT"
1142 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1143 [(set_attr "conds" "clob")
1144 (set_attr "length" "8")]
1145)
1146
1147(define_insn "*subdi_di_sesidi"
1148 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1149 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
1150 (sign_extend:DI
1151 (match_operand:SI 2 "s_register_operand" "r,r"))))
1152 (clobber (reg:CC CC_REGNUM))]
1153 "TARGET_32BIT"
1154 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
1155 [(set_attr "conds" "clob")
1156 (set_attr "length" "8")]
1157)
1158
1159(define_insn "*subdi_zesidi_di"
1160 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1161 (minus:DI (zero_extend:DI
1162 (match_operand:SI 2 "s_register_operand" "r,r"))
1163 (match_operand:DI 1 "s_register_operand" "0,r")))
1164 (clobber (reg:CC CC_REGNUM))]
1165 "TARGET_ARM"
1166 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1167 [(set_attr "conds" "clob")
1168 (set_attr "length" "8")]
1169)
1170
1171(define_insn "*subdi_sesidi_di"
1172 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1173 (minus:DI (sign_extend:DI
1174 (match_operand:SI 2 "s_register_operand" "r,r"))
1175 (match_operand:DI 1 "s_register_operand" "0,r")))
1176 (clobber (reg:CC CC_REGNUM))]
1177 "TARGET_ARM"
1178 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1179 [(set_attr "conds" "clob")
1180 (set_attr "length" "8")]
1181)
1182
1183(define_insn "*subdi_zesidi_zesidi"
1184 [(set (match_operand:DI 0 "s_register_operand" "=r")
1185 (minus:DI (zero_extend:DI
1186 (match_operand:SI 1 "s_register_operand" "r"))
1187 (zero_extend:DI
1188 (match_operand:SI 2 "s_register_operand" "r"))))
1189 (clobber (reg:CC CC_REGNUM))]
1190 "TARGET_32BIT"
1191 "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1192 [(set_attr "conds" "clob")
1193 (set_attr "length" "8")]
1194)
1195
1196(define_expand "subsi3"
1197 [(set (match_operand:SI 0 "s_register_operand" "")
1198 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1199 (match_operand:SI 2 "s_register_operand" "")))]
1200 "TARGET_EITHER"
1201 "
1202 if (GET_CODE (operands[1]) == CONST_INT)
1203 {
1204 if (TARGET_32BIT)
1205 {
1206 arm_split_constant (MINUS, SImode, NULL_RTX,
1207 INTVAL (operands[1]), operands[0],
1208 operands[2], optimize && can_create_pseudo_p ());
1209 DONE;
1210 }
1211 else /* TARGET_THUMB1 */
1212 operands[1] = force_reg (SImode, operands[1]);
1213 }
1214 "
1215)
1216
1217(define_insn "thumb1_subsi3_insn"
1218 [(set (match_operand:SI 0 "register_operand" "=l")
1219 (minus:SI (match_operand:SI 1 "register_operand" "l")
1220 (match_operand:SI 2 "reg_or_int_operand" "lPd")))]
1221 "TARGET_THUMB1"
1222 "sub\\t%0, %1, %2"
1223 [(set_attr "length" "2")
1224 (set_attr "conds" "set")])
1225
1226; ??? Check Thumb-2 split length
1227(define_insn_and_split "*arm_subsi3_insn"
1228 [(set (match_operand:SI 0 "s_register_operand" "=r,r,rk,r")
1229 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,k,?n")
1230 (match_operand:SI 2 "reg_or_int_operand" "r,rI,r, r")))]
1231 "TARGET_32BIT"
1232 "@
1233 rsb%?\\t%0, %2, %1
1234 sub%?\\t%0, %1, %2
1235 sub%?\\t%0, %1, %2
1236 #"
1237 "&& (GET_CODE (operands[1]) == CONST_INT
1238 && !const_ok_for_arm (INTVAL (operands[1])))"
1239 [(clobber (const_int 0))]
1240 "
1241 arm_split_constant (MINUS, SImode, curr_insn,
1242 INTVAL (operands[1]), operands[0], operands[2], 0);
1243 DONE;
1244 "
1245 [(set_attr "length" "4,4,4,16")
1246 (set_attr "predicable" "yes")]
1247)
1248
1249(define_peephole2
1250 [(match_scratch:SI 3 "r")
1251 (set (match_operand:SI 0 "arm_general_register_operand" "")
1252 (minus:SI (match_operand:SI 1 "const_int_operand" "")
1253 (match_operand:SI 2 "arm_general_register_operand" "")))]
1254 "TARGET_32BIT
1255 && !const_ok_for_arm (INTVAL (operands[1]))
1256 && const_ok_for_arm (~INTVAL (operands[1]))"
1257 [(set (match_dup 3) (match_dup 1))
1258 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1259 ""
1260)
1261
1262(define_insn "*subsi3_compare0"
1263 [(set (reg:CC_NOOV CC_REGNUM)
1264 (compare:CC_NOOV
1265 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1266 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1267 (const_int 0)))
1268 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1269 (minus:SI (match_dup 1) (match_dup 2)))]
1270 "TARGET_32BIT"
1271 "@
1272 sub%.\\t%0, %1, %2
1273 rsb%.\\t%0, %2, %1"
1274 [(set_attr "conds" "set")]
1275)
1276
1277(define_insn "*subsi3_compare"
1278 [(set (reg:CC CC_REGNUM)
1279 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,I")
1280 (match_operand:SI 2 "arm_rhs_operand" "rI,r")))
1281 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1282 (minus:SI (match_dup 1) (match_dup 2)))]
1283 "TARGET_32BIT"
1284 "@
1285 sub%.\\t%0, %1, %2
1286 rsb%.\\t%0, %2, %1"
1287 [(set_attr "conds" "set")]
1288)
1289
1290(define_expand "decscc"
1291 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1292 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1293 (match_operator:SI 2 "arm_comparison_operator"
1294 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1295 "TARGET_32BIT"
1296 ""
1297)
1298
1299(define_insn "*arm_decscc"
1300 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1301 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1302 (match_operator:SI 2 "arm_comparison_operator"
1303 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1304 "TARGET_ARM"
1305 "@
1306 sub%d2\\t%0, %1, #1
1307 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1308 [(set_attr "conds" "use")
1309 (set_attr "length" "*,8")]
1310)
1311
1312(define_expand "subsf3"
1313 [(set (match_operand:SF 0 "s_register_operand" "")
1314 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1315 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1316 "TARGET_32BIT && TARGET_HARD_FLOAT"
1317 "
1318 if (TARGET_MAVERICK)
1319 {
1320 if (!cirrus_fp_register (operands[1], SFmode))
1321 operands[1] = force_reg (SFmode, operands[1]);
1322 if (!cirrus_fp_register (operands[2], SFmode))
1323 operands[2] = force_reg (SFmode, operands[2]);
1324 }
1325")
1326
1327(define_expand "subdf3"
1328 [(set (match_operand:DF 0 "s_register_operand" "")
1329 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1330 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1331 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1332 "
1333 if (TARGET_MAVERICK)
1334 {
1335 if (!cirrus_fp_register (operands[1], DFmode))
1336 operands[1] = force_reg (DFmode, operands[1]);
1337 if (!cirrus_fp_register (operands[2], DFmode))
1338 operands[2] = force_reg (DFmode, operands[2]);
1339 }
1340")
1341
1342\f
1343;; Multiplication insns
1344
1345(define_expand "mulsi3"
1346 [(set (match_operand:SI 0 "s_register_operand" "")
1347 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1348 (match_operand:SI 1 "s_register_operand" "")))]
1349 "TARGET_EITHER"
1350 ""
1351)
1352
1353;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1354(define_insn "*arm_mulsi3"
1355 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1356 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1357 (match_operand:SI 1 "s_register_operand" "%0,r")))]
1358 "TARGET_32BIT && !arm_arch6"
1359 "mul%?\\t%0, %2, %1"
1360 [(set_attr "insn" "mul")
1361 (set_attr "predicable" "yes")]
1362)
1363
1364(define_insn "*arm_mulsi3_v6"
1365 [(set (match_operand:SI 0 "s_register_operand" "=r")
1366 (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1367 (match_operand:SI 2 "s_register_operand" "r")))]
1368 "TARGET_32BIT && arm_arch6"
1369 "mul%?\\t%0, %1, %2"
1370 [(set_attr "insn" "mul")
1371 (set_attr "predicable" "yes")]
1372)
1373
1374; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1375; 1 and 2; are the same, because reload will make operand 0 match
1376; operand 1 without realizing that this conflicts with operand 2. We fix
1377; this by adding another alternative to match this case, and then `reload'
1378; it ourselves. This alternative must come first.
1379(define_insn "*thumb_mulsi3"
1380 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1381 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1382 (match_operand:SI 2 "register_operand" "l,l,l")))]
1383 "TARGET_THUMB1 && !arm_arch6"
1384 "*
1385 if (which_alternative < 2)
1386 return \"mov\\t%0, %1\;mul\\t%0, %2\";
1387 else
1388 return \"mul\\t%0, %2\";
1389 "
1390 [(set_attr "length" "4,4,2")
1391 (set_attr "insn" "mul")]
1392)
1393
1394(define_insn "*thumb_mulsi3_v6"
1395 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
1396 (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1397 (match_operand:SI 2 "register_operand" "l,0,0")))]
1398 "TARGET_THUMB1 && arm_arch6"
1399 "@
1400 mul\\t%0, %2
1401 mul\\t%0, %1
1402 mul\\t%0, %1"
1403 [(set_attr "length" "2")
1404 (set_attr "insn" "mul")]
1405)
1406
1407(define_insn "*mulsi3_compare0"
1408 [(set (reg:CC_NOOV CC_REGNUM)
1409 (compare:CC_NOOV (mult:SI
1410 (match_operand:SI 2 "s_register_operand" "r,r")
1411 (match_operand:SI 1 "s_register_operand" "%0,r"))
1412 (const_int 0)))
1413 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1414 (mult:SI (match_dup 2) (match_dup 1)))]
1415 "TARGET_ARM && !arm_arch6"
1416 "mul%.\\t%0, %2, %1"
1417 [(set_attr "conds" "set")
1418 (set_attr "insn" "muls")]
1419)
1420
1421(define_insn "*mulsi3_compare0_v6"
1422 [(set (reg:CC_NOOV CC_REGNUM)
1423 (compare:CC_NOOV (mult:SI
1424 (match_operand:SI 2 "s_register_operand" "r")
1425 (match_operand:SI 1 "s_register_operand" "r"))
1426 (const_int 0)))
1427 (set (match_operand:SI 0 "s_register_operand" "=r")
1428 (mult:SI (match_dup 2) (match_dup 1)))]
1429 "TARGET_ARM && arm_arch6 && optimize_size"
1430 "mul%.\\t%0, %2, %1"
1431 [(set_attr "conds" "set")
1432 (set_attr "insn" "muls")]
1433)
1434
1435(define_insn "*mulsi_compare0_scratch"
1436 [(set (reg:CC_NOOV CC_REGNUM)
1437 (compare:CC_NOOV (mult:SI
1438 (match_operand:SI 2 "s_register_operand" "r,r")
1439 (match_operand:SI 1 "s_register_operand" "%0,r"))
1440 (const_int 0)))
1441 (clobber (match_scratch:SI 0 "=&r,&r"))]
1442 "TARGET_ARM && !arm_arch6"
1443 "mul%.\\t%0, %2, %1"
1444 [(set_attr "conds" "set")
1445 (set_attr "insn" "muls")]
1446)
1447
1448(define_insn "*mulsi_compare0_scratch_v6"
1449 [(set (reg:CC_NOOV CC_REGNUM)
1450 (compare:CC_NOOV (mult:SI
1451 (match_operand:SI 2 "s_register_operand" "r")
1452 (match_operand:SI 1 "s_register_operand" "r"))
1453 (const_int 0)))
1454 (clobber (match_scratch:SI 0 "=r"))]
1455 "TARGET_ARM && arm_arch6 && optimize_size"
1456 "mul%.\\t%0, %2, %1"
1457 [(set_attr "conds" "set")
1458 (set_attr "insn" "muls")]
1459)
1460
1461;; Unnamed templates to match MLA instruction.
1462
1463(define_insn "*mulsi3addsi"
1464 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1465 (plus:SI
1466 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1467 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1468 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
1469 "TARGET_32BIT && !arm_arch6"
1470 "mla%?\\t%0, %2, %1, %3"
1471 [(set_attr "insn" "mla")
1472 (set_attr "predicable" "yes")]
1473)
1474
1475(define_insn "*mulsi3addsi_v6"
1476 [(set (match_operand:SI 0 "s_register_operand" "=r")
1477 (plus:SI
1478 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1479 (match_operand:SI 1 "s_register_operand" "r"))
1480 (match_operand:SI 3 "s_register_operand" "r")))]
1481 "TARGET_32BIT && arm_arch6"
1482 "mla%?\\t%0, %2, %1, %3"
1483 [(set_attr "insn" "mla")
1484 (set_attr "predicable" "yes")]
1485)
1486
1487(define_insn "*mulsi3addsi_compare0"
1488 [(set (reg:CC_NOOV CC_REGNUM)
1489 (compare:CC_NOOV
1490 (plus:SI (mult:SI
1491 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1492 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1493 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
1494 (const_int 0)))
1495 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1496 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1497 (match_dup 3)))]
1498 "TARGET_ARM && arm_arch6"
1499 "mla%.\\t%0, %2, %1, %3"
1500 [(set_attr "conds" "set")
1501 (set_attr "insn" "mlas")]
1502)
1503
1504(define_insn "*mulsi3addsi_compare0_v6"
1505 [(set (reg:CC_NOOV CC_REGNUM)
1506 (compare:CC_NOOV
1507 (plus:SI (mult:SI
1508 (match_operand:SI 2 "s_register_operand" "r")
1509 (match_operand:SI 1 "s_register_operand" "r"))
1510 (match_operand:SI 3 "s_register_operand" "r"))
1511 (const_int 0)))
1512 (set (match_operand:SI 0 "s_register_operand" "=r")
1513 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1514 (match_dup 3)))]
1515 "TARGET_ARM && arm_arch6 && optimize_size"
1516 "mla%.\\t%0, %2, %1, %3"
1517 [(set_attr "conds" "set")
1518 (set_attr "insn" "mlas")]
1519)
1520
1521(define_insn "*mulsi3addsi_compare0_scratch"
1522 [(set (reg:CC_NOOV CC_REGNUM)
1523 (compare:CC_NOOV
1524 (plus:SI (mult:SI
1525 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1526 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1527 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1528 (const_int 0)))
1529 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1530 "TARGET_ARM && !arm_arch6"
1531 "mla%.\\t%0, %2, %1, %3"
1532 [(set_attr "conds" "set")
1533 (set_attr "insn" "mlas")]
1534)
1535
1536(define_insn "*mulsi3addsi_compare0_scratch_v6"
1537 [(set (reg:CC_NOOV CC_REGNUM)
1538 (compare:CC_NOOV
1539 (plus:SI (mult:SI
1540 (match_operand:SI 2 "s_register_operand" "r")
1541 (match_operand:SI 1 "s_register_operand" "r"))
1542 (match_operand:SI 3 "s_register_operand" "r"))
1543 (const_int 0)))
1544 (clobber (match_scratch:SI 0 "=r"))]
1545 "TARGET_ARM && arm_arch6 && optimize_size"
1546 "mla%.\\t%0, %2, %1, %3"
1547 [(set_attr "conds" "set")
1548 (set_attr "insn" "mlas")]
1549)
1550
1551(define_insn "*mulsi3subsi"
1552 [(set (match_operand:SI 0 "s_register_operand" "=r")
1553 (minus:SI
1554 (match_operand:SI 3 "s_register_operand" "r")
1555 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1556 (match_operand:SI 1 "s_register_operand" "r"))))]
1557 "TARGET_32BIT && arm_arch_thumb2"
1558 "mls%?\\t%0, %2, %1, %3"
1559 [(set_attr "insn" "mla")
1560 (set_attr "predicable" "yes")]
1561)
1562
1563(define_expand "maddsidi4"
1564 [(set (match_operand:DI 0 "s_register_operand" "")
1565 (plus:DI
1566 (mult:DI
1567 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1568 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1569 (match_operand:DI 3 "s_register_operand" "")))]
1570 "TARGET_32BIT && arm_arch3m"
1571 "")
1572
1573(define_insn "*mulsidi3adddi"
1574 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1575 (plus:DI
1576 (mult:DI
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_arch3m && !arm_arch6"
1581 "smlal%?\\t%Q0, %R0, %3, %2"
1582 [(set_attr "insn" "smlal")
1583 (set_attr "predicable" "yes")]
1584)
1585
1586(define_insn "*mulsidi3adddi_v6"
1587 [(set (match_operand:DI 0 "s_register_operand" "=r")
1588 (plus:DI
1589 (mult:DI
1590 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1591 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1592 (match_operand:DI 1 "s_register_operand" "0")))]
1593 "TARGET_32BIT && arm_arch6"
1594 "smlal%?\\t%Q0, %R0, %3, %2"
1595 [(set_attr "insn" "smlal")
1596 (set_attr "predicable" "yes")]
1597)
1598
1599;; 32x32->64 widening multiply.
1600;; As with mulsi3, the only difference between the v3-5 and v6+
1601;; versions of these patterns is the requirement that the output not
1602;; overlap the inputs, but that still means we have to have a named
1603;; expander and two different starred insns.
1604
1605(define_expand "mulsidi3"
1606 [(set (match_operand:DI 0 "s_register_operand" "")
1607 (mult:DI
1608 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1609 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1610 "TARGET_32BIT && arm_arch3m"
1611 ""
1612)
1613
1614(define_insn "*mulsidi3_nov6"
1615 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1616 (mult:DI
1617 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1618 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1619 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1620 "smull%?\\t%Q0, %R0, %1, %2"
1621 [(set_attr "insn" "smull")
1622 (set_attr "predicable" "yes")]
1623)
1624
1625(define_insn "*mulsidi3_v6"
1626 [(set (match_operand:DI 0 "s_register_operand" "=r")
1627 (mult:DI
1628 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1629 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1630 "TARGET_32BIT && arm_arch6"
1631 "smull%?\\t%Q0, %R0, %1, %2"
1632 [(set_attr "insn" "smull")
1633 (set_attr "predicable" "yes")]
1634)
1635
1636(define_expand "umulsidi3"
1637 [(set (match_operand:DI 0 "s_register_operand" "")
1638 (mult:DI
1639 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1640 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1641 "TARGET_32BIT && arm_arch3m"
1642 ""
1643)
1644
1645(define_insn "*umulsidi3_nov6"
1646 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1647 (mult:DI
1648 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1649 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1650 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1651 "umull%?\\t%Q0, %R0, %1, %2"
1652 [(set_attr "insn" "umull")
1653 (set_attr "predicable" "yes")]
1654)
1655
1656(define_insn "*umulsidi3_v6"
1657 [(set (match_operand:DI 0 "s_register_operand" "=r")
1658 (mult:DI
1659 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1660 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1661 "TARGET_32BIT && arm_arch6"
1662 "umull%?\\t%Q0, %R0, %1, %2"
1663 [(set_attr "insn" "umull")
1664 (set_attr "predicable" "yes")]
1665)
1666
1667(define_expand "umaddsidi4"
1668 [(set (match_operand:DI 0 "s_register_operand" "")
1669 (plus:DI
1670 (mult:DI
1671 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1672 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1673 (match_operand:DI 3 "s_register_operand" "")))]
1674 "TARGET_32BIT && arm_arch3m"
1675 "")
1676
1677(define_insn "*umulsidi3adddi"
1678 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1679 (plus:DI
1680 (mult:DI
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_arch3m && !arm_arch6"
1685 "umlal%?\\t%Q0, %R0, %3, %2"
1686 [(set_attr "insn" "umlal")
1687 (set_attr "predicable" "yes")]
1688)
1689
1690(define_insn "*umulsidi3adddi_v6"
1691 [(set (match_operand:DI 0 "s_register_operand" "=r")
1692 (plus:DI
1693 (mult:DI
1694 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1695 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1696 (match_operand:DI 1 "s_register_operand" "0")))]
1697 "TARGET_32BIT && arm_arch6"
1698 "umlal%?\\t%Q0, %R0, %3, %2"
1699 [(set_attr "insn" "umlal")
1700 (set_attr "predicable" "yes")]
1701)
1702
1703(define_expand "smulsi3_highpart"
1704 [(parallel
1705 [(set (match_operand:SI 0 "s_register_operand" "")
1706 (truncate:SI
1707 (lshiftrt:DI
1708 (mult:DI
1709 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1710 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1711 (const_int 32))))
1712 (clobber (match_scratch:SI 3 ""))])]
1713 "TARGET_32BIT && arm_arch3m"
1714 ""
1715)
1716
1717(define_insn "*smulsi3_highpart_nov6"
1718 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1719 (truncate:SI
1720 (lshiftrt:DI
1721 (mult:DI
1722 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
1723 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1724 (const_int 32))))
1725 (clobber (match_scratch:SI 3 "=&r,&r"))]
1726 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1727 "smull%?\\t%3, %0, %2, %1"
1728 [(set_attr "insn" "smull")
1729 (set_attr "predicable" "yes")]
1730)
1731
1732(define_insn "*smulsi3_highpart_v6"
1733 [(set (match_operand:SI 0 "s_register_operand" "=r")
1734 (truncate:SI
1735 (lshiftrt:DI
1736 (mult:DI
1737 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1738 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1739 (const_int 32))))
1740 (clobber (match_scratch:SI 3 "=r"))]
1741 "TARGET_32BIT && arm_arch6"
1742 "smull%?\\t%3, %0, %2, %1"
1743 [(set_attr "insn" "smull")
1744 (set_attr "predicable" "yes")]
1745)
1746
1747(define_expand "umulsi3_highpart"
1748 [(parallel
1749 [(set (match_operand:SI 0 "s_register_operand" "")
1750 (truncate:SI
1751 (lshiftrt:DI
1752 (mult:DI
1753 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1754 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1755 (const_int 32))))
1756 (clobber (match_scratch:SI 3 ""))])]
1757 "TARGET_32BIT && arm_arch3m"
1758 ""
1759)
1760
1761(define_insn "*umulsi3_highpart_nov6"
1762 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1763 (truncate:SI
1764 (lshiftrt:DI
1765 (mult:DI
1766 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
1767 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1768 (const_int 32))))
1769 (clobber (match_scratch:SI 3 "=&r,&r"))]
1770 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1771 "umull%?\\t%3, %0, %2, %1"
1772 [(set_attr "insn" "umull")
1773 (set_attr "predicable" "yes")]
1774)
1775
1776(define_insn "*umulsi3_highpart_v6"
1777 [(set (match_operand:SI 0 "s_register_operand" "=r")
1778 (truncate:SI
1779 (lshiftrt:DI
1780 (mult:DI
1781 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1782 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1783 (const_int 32))))
1784 (clobber (match_scratch:SI 3 "=r"))]
1785 "TARGET_32BIT && arm_arch6"
1786 "umull%?\\t%3, %0, %2, %1"
1787 [(set_attr "insn" "umull")
1788 (set_attr "predicable" "yes")]
1789)
1790
1791(define_insn "mulhisi3"
1792 [(set (match_operand:SI 0 "s_register_operand" "=r")
1793 (mult:SI (sign_extend:SI
1794 (match_operand:HI 1 "s_register_operand" "%r"))
1795 (sign_extend:SI
1796 (match_operand:HI 2 "s_register_operand" "r"))))]
1797 "TARGET_DSP_MULTIPLY"
1798 "smulbb%?\\t%0, %1, %2"
1799 [(set_attr "insn" "smulxy")
1800 (set_attr "predicable" "yes")]
1801)
1802
1803(define_insn "*mulhisi3tb"
1804 [(set (match_operand:SI 0 "s_register_operand" "=r")
1805 (mult:SI (ashiftrt:SI
1806 (match_operand:SI 1 "s_register_operand" "r")
1807 (const_int 16))
1808 (sign_extend:SI
1809 (match_operand:HI 2 "s_register_operand" "r"))))]
1810 "TARGET_DSP_MULTIPLY"
1811 "smultb%?\\t%0, %1, %2"
1812 [(set_attr "insn" "smulxy")
1813 (set_attr "predicable" "yes")]
1814)
1815
1816(define_insn "*mulhisi3bt"
1817 [(set (match_operand:SI 0 "s_register_operand" "=r")
1818 (mult:SI (sign_extend:SI
1819 (match_operand:HI 1 "s_register_operand" "r"))
1820 (ashiftrt:SI
1821 (match_operand:SI 2 "s_register_operand" "r")
1822 (const_int 16))))]
1823 "TARGET_DSP_MULTIPLY"
1824 "smulbt%?\\t%0, %1, %2"
1825 [(set_attr "insn" "smulxy")
1826 (set_attr "predicable" "yes")]
1827)
1828
1829(define_insn "*mulhisi3tt"
1830 [(set (match_operand:SI 0 "s_register_operand" "=r")
1831 (mult:SI (ashiftrt:SI
1832 (match_operand:SI 1 "s_register_operand" "r")
1833 (const_int 16))
1834 (ashiftrt:SI
1835 (match_operand:SI 2 "s_register_operand" "r")
1836 (const_int 16))))]
1837 "TARGET_DSP_MULTIPLY"
1838 "smultt%?\\t%0, %1, %2"
1839 [(set_attr "insn" "smulxy")
1840 (set_attr "predicable" "yes")]
1841)
1842
1843(define_insn "maddhisi4"
1844 [(set (match_operand:SI 0 "s_register_operand" "=r")
1845 (plus:SI (mult:SI (sign_extend:SI
1846 (match_operand:HI 1 "s_register_operand" "r"))
1847 (sign_extend:SI
1848 (match_operand:HI 2 "s_register_operand" "r")))
1849 (match_operand:SI 3 "s_register_operand" "r")))]
1850 "TARGET_DSP_MULTIPLY"
1851 "smlabb%?\\t%0, %1, %2, %3"
1852 [(set_attr "insn" "smlaxy")
1853 (set_attr "predicable" "yes")]
1854)
1855
1856;; Note: there is no maddhisi4ibt because this one is canonical form
1857(define_insn "*maddhisi4tb"
1858 [(set (match_operand:SI 0 "s_register_operand" "=r")
1859 (plus:SI (mult:SI (ashiftrt:SI
1860 (match_operand:SI 1 "s_register_operand" "r")
1861 (const_int 16))
1862 (sign_extend:SI
1863 (match_operand:HI 2 "s_register_operand" "r")))
1864 (match_operand:SI 3 "s_register_operand" "r")))]
1865 "TARGET_DSP_MULTIPLY"
1866 "smlatb%?\\t%0, %1, %2, %3"
1867 [(set_attr "insn" "smlaxy")
1868 (set_attr "predicable" "yes")]
1869)
1870
1871(define_insn "*maddhisi4tt"
1872 [(set (match_operand:SI 0 "s_register_operand" "=r")
1873 (plus:SI (mult:SI (ashiftrt:SI
1874 (match_operand:SI 1 "s_register_operand" "r")
1875 (const_int 16))
1876 (ashiftrt:SI
1877 (match_operand:SI 2 "s_register_operand" "r")
1878 (const_int 16)))
1879 (match_operand:SI 3 "s_register_operand" "r")))]
1880 "TARGET_DSP_MULTIPLY"
1881 "smlatt%?\\t%0, %1, %2, %3"
1882 [(set_attr "insn" "smlaxy")
1883 (set_attr "predicable" "yes")]
1884)
1885
1886(define_insn "maddhidi4"
1887 [(set (match_operand:DI 0 "s_register_operand" "=r")
1888 (plus:DI
1889 (mult:DI (sign_extend:DI
1890 (match_operand:HI 1 "s_register_operand" "r"))
1891 (sign_extend:DI
1892 (match_operand:HI 2 "s_register_operand" "r")))
1893 (match_operand:DI 3 "s_register_operand" "0")))]
1894 "TARGET_DSP_MULTIPLY"
1895 "smlalbb%?\\t%Q0, %R0, %1, %2"
1896 [(set_attr "insn" "smlalxy")
1897 (set_attr "predicable" "yes")])
1898
1899;; Note: there is no maddhidi4ibt because this one is canonical form
1900(define_insn "*maddhidi4tb"
1901 [(set (match_operand:DI 0 "s_register_operand" "=r")
1902 (plus:DI
1903 (mult:DI (sign_extend:DI
1904 (ashiftrt:SI
1905 (match_operand:SI 1 "s_register_operand" "r")
1906 (const_int 16)))
1907 (sign_extend:DI
1908 (match_operand:HI 2 "s_register_operand" "r")))
1909 (match_operand:DI 3 "s_register_operand" "0")))]
1910 "TARGET_DSP_MULTIPLY"
1911 "smlaltb%?\\t%Q0, %R0, %1, %2"
1912 [(set_attr "insn" "smlalxy")
1913 (set_attr "predicable" "yes")])
1914
1915(define_insn "*maddhidi4tt"
1916 [(set (match_operand:DI 0 "s_register_operand" "=r")
1917 (plus:DI
1918 (mult:DI (sign_extend:DI
1919 (ashiftrt:SI
1920 (match_operand:SI 1 "s_register_operand" "r")
1921 (const_int 16)))
1922 (sign_extend:DI
1923 (ashiftrt:SI
1924 (match_operand:SI 2 "s_register_operand" "r")
1925 (const_int 16))))
1926 (match_operand:DI 3 "s_register_operand" "0")))]
1927 "TARGET_DSP_MULTIPLY"
1928 "smlaltt%?\\t%Q0, %R0, %1, %2"
1929 [(set_attr "insn" "smlalxy")
1930 (set_attr "predicable" "yes")])
1931
1932(define_expand "mulsf3"
1933 [(set (match_operand:SF 0 "s_register_operand" "")
1934 (mult:SF (match_operand:SF 1 "s_register_operand" "")
1935 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1936 "TARGET_32BIT && TARGET_HARD_FLOAT"
1937 "
1938 if (TARGET_MAVERICK
1939 && !cirrus_fp_register (operands[2], SFmode))
1940 operands[2] = force_reg (SFmode, operands[2]);
1941")
1942
1943(define_expand "muldf3"
1944 [(set (match_operand:DF 0 "s_register_operand" "")
1945 (mult:DF (match_operand:DF 1 "s_register_operand" "")
1946 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1947 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1948 "
1949 if (TARGET_MAVERICK
1950 && !cirrus_fp_register (operands[2], DFmode))
1951 operands[2] = force_reg (DFmode, operands[2]);
1952")
1953\f
1954;; Division insns
1955
1956(define_expand "divsf3"
1957 [(set (match_operand:SF 0 "s_register_operand" "")
1958 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1959 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1960 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1961 "")
1962
1963(define_expand "divdf3"
1964 [(set (match_operand:DF 0 "s_register_operand" "")
1965 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1966 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1967 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
1968 "")
1969\f
1970;; Modulo insns
1971
1972(define_expand "modsf3"
1973 [(set (match_operand:SF 0 "s_register_operand" "")
1974 (mod:SF (match_operand:SF 1 "s_register_operand" "")
1975 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1976 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
1977 "")
1978
1979(define_expand "moddf3"
1980 [(set (match_operand:DF 0 "s_register_operand" "")
1981 (mod:DF (match_operand:DF 1 "s_register_operand" "")
1982 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1983 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
1984 "")
1985\f
1986;; Boolean and,ior,xor insns
1987
1988;; Split up double word logical operations
1989
1990;; Split up simple DImode logical operations. Simply perform the logical
1991;; operation on the upper and lower halves of the registers.
1992(define_split
1993 [(set (match_operand:DI 0 "s_register_operand" "")
1994 (match_operator:DI 6 "logical_binary_operator"
1995 [(match_operand:DI 1 "s_register_operand" "")
1996 (match_operand:DI 2 "s_register_operand" "")]))]
1997 "TARGET_32BIT && reload_completed
1998 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
1999 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2000 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2001 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
2002 "
2003 {
2004 operands[3] = gen_highpart (SImode, operands[0]);
2005 operands[0] = gen_lowpart (SImode, operands[0]);
2006 operands[4] = gen_highpart (SImode, operands[1]);
2007 operands[1] = gen_lowpart (SImode, operands[1]);
2008 operands[5] = gen_highpart (SImode, operands[2]);
2009 operands[2] = gen_lowpart (SImode, operands[2]);
2010 }"
2011)
2012
2013(define_split
2014 [(set (match_operand:DI 0 "s_register_operand" "")
2015 (match_operator:DI 6 "logical_binary_operator"
2016 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2017 (match_operand:DI 1 "s_register_operand" "")]))]
2018 "TARGET_32BIT && reload_completed"
2019 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2020 (set (match_dup 3) (match_op_dup:SI 6
2021 [(ashiftrt:SI (match_dup 2) (const_int 31))
2022 (match_dup 4)]))]
2023 "
2024 {
2025 operands[3] = gen_highpart (SImode, operands[0]);
2026 operands[0] = gen_lowpart (SImode, operands[0]);
2027 operands[4] = gen_highpart (SImode, operands[1]);
2028 operands[1] = gen_lowpart (SImode, operands[1]);
2029 operands[5] = gen_highpart (SImode, operands[2]);
2030 operands[2] = gen_lowpart (SImode, operands[2]);
2031 }"
2032)
2033
2034;; The zero extend of operand 2 means we can just copy the high part of
2035;; operand1 into operand0.
2036(define_split
2037 [(set (match_operand:DI 0 "s_register_operand" "")
2038 (ior:DI
2039 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2040 (match_operand:DI 1 "s_register_operand" "")))]
2041 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
2042 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
2043 (set (match_dup 3) (match_dup 4))]
2044 "
2045 {
2046 operands[4] = gen_highpart (SImode, operands[1]);
2047 operands[3] = gen_highpart (SImode, operands[0]);
2048 operands[0] = gen_lowpart (SImode, operands[0]);
2049 operands[1] = gen_lowpart (SImode, operands[1]);
2050 }"
2051)
2052
2053;; The zero extend of operand 2 means we can just copy the high part of
2054;; operand1 into operand0.
2055(define_split
2056 [(set (match_operand:DI 0 "s_register_operand" "")
2057 (xor:DI
2058 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2059 (match_operand:DI 1 "s_register_operand" "")))]
2060 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
2061 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
2062 (set (match_dup 3) (match_dup 4))]
2063 "
2064 {
2065 operands[4] = gen_highpart (SImode, operands[1]);
2066 operands[3] = gen_highpart (SImode, operands[0]);
2067 operands[0] = gen_lowpart (SImode, operands[0]);
2068 operands[1] = gen_lowpart (SImode, operands[1]);
2069 }"
2070)
2071
2072(define_expand "anddi3"
2073 [(set (match_operand:DI 0 "s_register_operand" "")
2074 (and:DI (match_operand:DI 1 "s_register_operand" "")
2075 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
2076 "TARGET_32BIT"
2077 ""
2078)
2079
2080(define_insn "*anddi3_insn"
2081 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2082 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2083 (match_operand:DI 2 "s_register_operand" "r,r")))]
2084 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
2085 "#"
2086 [(set_attr "length" "8")]
2087)
2088
2089(define_insn_and_split "*anddi_zesidi_di"
2090 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2091 (and:DI (zero_extend:DI
2092 (match_operand:SI 2 "s_register_operand" "r,r"))
2093 (match_operand:DI 1 "s_register_operand" "0,r")))]
2094 "TARGET_32BIT"
2095 "#"
2096 "TARGET_32BIT && reload_completed"
2097 ; The zero extend of operand 2 clears the high word of the output
2098 ; operand.
2099 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2100 (set (match_dup 3) (const_int 0))]
2101 "
2102 {
2103 operands[3] = gen_highpart (SImode, operands[0]);
2104 operands[0] = gen_lowpart (SImode, operands[0]);
2105 operands[1] = gen_lowpart (SImode, operands[1]);
2106 }"
2107 [(set_attr "length" "8")]
2108)
2109
2110(define_insn "*anddi_sesdi_di"
2111 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2112 (and:DI (sign_extend:DI
2113 (match_operand:SI 2 "s_register_operand" "r,r"))
2114 (match_operand:DI 1 "s_register_operand" "0,r")))]
2115 "TARGET_32BIT"
2116 "#"
2117 [(set_attr "length" "8")]
2118)
2119
2120(define_expand "andsi3"
2121 [(set (match_operand:SI 0 "s_register_operand" "")
2122 (and:SI (match_operand:SI 1 "s_register_operand" "")
2123 (match_operand:SI 2 "reg_or_int_operand" "")))]
2124 "TARGET_EITHER"
2125 "
2126 if (TARGET_32BIT)
2127 {
2128 if (GET_CODE (operands[2]) == CONST_INT)
2129 {
2130 if (INTVAL (operands[2]) == 255 && arm_arch6)
2131 {
2132 operands[1] = convert_to_mode (QImode, operands[1], 1);
2133 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2134 operands[1]));
2135 }
2136 else
2137 arm_split_constant (AND, SImode, NULL_RTX,
2138 INTVAL (operands[2]), operands[0],
2139 operands[1],
2140 optimize && can_create_pseudo_p ());
2141
2142 DONE;
2143 }
2144 }
2145 else /* TARGET_THUMB1 */
2146 {
2147 if (GET_CODE (operands[2]) != CONST_INT)
2148 {
2149 rtx tmp = force_reg (SImode, operands[2]);
2150 if (rtx_equal_p (operands[0], operands[1]))
2151 operands[2] = tmp;
2152 else
2153 {
2154 operands[2] = operands[1];
2155 operands[1] = tmp;
2156 }
2157 }
2158 else
2159 {
2160 int i;
2161
2162 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
2163 {
2164 operands[2] = force_reg (SImode,
2165 GEN_INT (~INTVAL (operands[2])));
2166
2167 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
2168
2169 DONE;
2170 }
2171
2172 for (i = 9; i <= 31; i++)
2173 {
2174 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2175 {
2176 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2177 const0_rtx));
2178 DONE;
2179 }
2180 else if ((((HOST_WIDE_INT) 1) << i) - 1
2181 == ~INTVAL (operands[2]))
2182 {
2183 rtx shift = GEN_INT (i);
2184 rtx reg = gen_reg_rtx (SImode);
2185
2186 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2187 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2188
2189 DONE;
2190 }
2191 }
2192
2193 operands[2] = force_reg (SImode, operands[2]);
2194 }
2195 }
2196 "
2197)
2198
2199; ??? Check split length for Thumb-2
2200(define_insn_and_split "*arm_andsi3_insn"
2201 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2202 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2203 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
2204 "TARGET_32BIT"
2205 "@
2206 and%?\\t%0, %1, %2
2207 bic%?\\t%0, %1, #%B2
2208 #"
2209 "TARGET_32BIT
2210 && GET_CODE (operands[2]) == CONST_INT
2211 && !(const_ok_for_arm (INTVAL (operands[2]))
2212 || const_ok_for_arm (~INTVAL (operands[2])))"
2213 [(clobber (const_int 0))]
2214 "
2215 arm_split_constant (AND, SImode, curr_insn,
2216 INTVAL (operands[2]), operands[0], operands[1], 0);
2217 DONE;
2218 "
2219 [(set_attr "length" "4,4,16")
2220 (set_attr "predicable" "yes")]
2221)
2222
2223(define_insn "*thumb1_andsi3_insn"
2224 [(set (match_operand:SI 0 "register_operand" "=l")
2225 (and:SI (match_operand:SI 1 "register_operand" "%0")
2226 (match_operand:SI 2 "register_operand" "l")))]
2227 "TARGET_THUMB1"
2228 "and\\t%0, %2"
2229 [(set_attr "length" "2")
2230 (set_attr "conds" "set")])
2231
2232(define_insn "*andsi3_compare0"
2233 [(set (reg:CC_NOOV CC_REGNUM)
2234 (compare:CC_NOOV
2235 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
2236 (match_operand:SI 2 "arm_not_operand" "rI,K"))
2237 (const_int 0)))
2238 (set (match_operand:SI 0 "s_register_operand" "=r,r")
2239 (and:SI (match_dup 1) (match_dup 2)))]
2240 "TARGET_32BIT"
2241 "@
2242 and%.\\t%0, %1, %2
2243 bic%.\\t%0, %1, #%B2"
2244 [(set_attr "conds" "set")]
2245)
2246
2247(define_insn "*andsi3_compare0_scratch"
2248 [(set (reg:CC_NOOV CC_REGNUM)
2249 (compare:CC_NOOV
2250 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
2251 (match_operand:SI 1 "arm_not_operand" "rI,K"))
2252 (const_int 0)))
2253 (clobber (match_scratch:SI 2 "=X,r"))]
2254 "TARGET_32BIT"
2255 "@
2256 tst%?\\t%0, %1
2257 bic%.\\t%2, %0, #%B1"
2258 [(set_attr "conds" "set")]
2259)
2260
2261(define_insn "*zeroextractsi_compare0_scratch"
2262 [(set (reg:CC_NOOV CC_REGNUM)
2263 (compare:CC_NOOV (zero_extract:SI
2264 (match_operand:SI 0 "s_register_operand" "r")
2265 (match_operand 1 "const_int_operand" "n")
2266 (match_operand 2 "const_int_operand" "n"))
2267 (const_int 0)))]
2268 "TARGET_32BIT
2269 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2270 && INTVAL (operands[1]) > 0
2271 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2272 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
2273 "*
2274 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2275 << INTVAL (operands[2]));
2276 output_asm_insn (\"tst%?\\t%0, %1\", operands);
2277 return \"\";
2278 "
2279 [(set_attr "conds" "set")
2280 (set_attr "predicable" "yes")]
2281)
2282
2283(define_insn_and_split "*ne_zeroextractsi"
2284 [(set (match_operand:SI 0 "s_register_operand" "=r")
2285 (ne:SI (zero_extract:SI
2286 (match_operand:SI 1 "s_register_operand" "r")
2287 (match_operand:SI 2 "const_int_operand" "n")
2288 (match_operand:SI 3 "const_int_operand" "n"))
2289 (const_int 0)))
2290 (clobber (reg:CC CC_REGNUM))]
2291 "TARGET_32BIT
2292 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2293 && INTVAL (operands[2]) > 0
2294 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2295 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2296 "#"
2297 "TARGET_32BIT
2298 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2299 && INTVAL (operands[2]) > 0
2300 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2301 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2302 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2303 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2304 (const_int 0)))
2305 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2306 (set (match_dup 0)
2307 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2308 (match_dup 0) (const_int 1)))]
2309 "
2310 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2311 << INTVAL (operands[3]));
2312 "
2313 [(set_attr "conds" "clob")
2314 (set (attr "length")
2315 (if_then_else (eq_attr "is_thumb" "yes")
2316 (const_int 12)
2317 (const_int 8)))]
2318)
2319
2320(define_insn_and_split "*ne_zeroextractsi_shifted"
2321 [(set (match_operand:SI 0 "s_register_operand" "=r")
2322 (ne:SI (zero_extract:SI
2323 (match_operand:SI 1 "s_register_operand" "r")
2324 (match_operand:SI 2 "const_int_operand" "n")
2325 (const_int 0))
2326 (const_int 0)))
2327 (clobber (reg:CC CC_REGNUM))]
2328 "TARGET_ARM"
2329 "#"
2330 "TARGET_ARM"
2331 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2332 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2333 (const_int 0)))
2334 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2335 (set (match_dup 0)
2336 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2337 (match_dup 0) (const_int 1)))]
2338 "
2339 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2340 "
2341 [(set_attr "conds" "clob")
2342 (set_attr "length" "8")]
2343)
2344
2345(define_insn_and_split "*ite_ne_zeroextractsi"
2346 [(set (match_operand:SI 0 "s_register_operand" "=r")
2347 (if_then_else:SI (ne (zero_extract:SI
2348 (match_operand:SI 1 "s_register_operand" "r")
2349 (match_operand:SI 2 "const_int_operand" "n")
2350 (match_operand:SI 3 "const_int_operand" "n"))
2351 (const_int 0))
2352 (match_operand:SI 4 "arm_not_operand" "rIK")
2353 (const_int 0)))
2354 (clobber (reg:CC CC_REGNUM))]
2355 "TARGET_ARM
2356 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2357 && INTVAL (operands[2]) > 0
2358 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2359 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2360 && !reg_overlap_mentioned_p (operands[0], operands[4])"
2361 "#"
2362 "TARGET_ARM
2363 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2364 && INTVAL (operands[2]) > 0
2365 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2366 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2367 && !reg_overlap_mentioned_p (operands[0], operands[4])"
2368 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2369 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2370 (const_int 0)))
2371 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2372 (set (match_dup 0)
2373 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2374 (match_dup 0) (match_dup 4)))]
2375 "
2376 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2377 << INTVAL (operands[3]));
2378 "
2379 [(set_attr "conds" "clob")
2380 (set_attr "length" "8")]
2381)
2382
2383(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2384 [(set (match_operand:SI 0 "s_register_operand" "=r")
2385 (if_then_else:SI (ne (zero_extract:SI
2386 (match_operand:SI 1 "s_register_operand" "r")
2387 (match_operand:SI 2 "const_int_operand" "n")
2388 (const_int 0))
2389 (const_int 0))
2390 (match_operand:SI 3 "arm_not_operand" "rIK")
2391 (const_int 0)))
2392 (clobber (reg:CC CC_REGNUM))]
2393 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2394 "#"
2395 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2396 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2397 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2398 (const_int 0)))
2399 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2400 (set (match_dup 0)
2401 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2402 (match_dup 0) (match_dup 3)))]
2403 "
2404 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2405 "
2406 [(set_attr "conds" "clob")
2407 (set_attr "length" "8")]
2408)
2409
2410(define_split
2411 [(set (match_operand:SI 0 "s_register_operand" "")
2412 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2413 (match_operand:SI 2 "const_int_operand" "")
2414 (match_operand:SI 3 "const_int_operand" "")))
2415 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2416 "TARGET_THUMB1"
2417 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2418 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2419 "{
2420 HOST_WIDE_INT temp = INTVAL (operands[2]);
2421
2422 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2423 operands[3] = GEN_INT (32 - temp);
2424 }"
2425)
2426
2427;; ??? Use Thumb-2 has bitfield insert/extract instructions.
2428(define_split
2429 [(set (match_operand:SI 0 "s_register_operand" "")
2430 (match_operator:SI 1 "shiftable_operator"
2431 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2432 (match_operand:SI 3 "const_int_operand" "")
2433 (match_operand:SI 4 "const_int_operand" ""))
2434 (match_operand:SI 5 "s_register_operand" "")]))
2435 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2436 "TARGET_ARM"
2437 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2438 (set (match_dup 0)
2439 (match_op_dup 1
2440 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2441 (match_dup 5)]))]
2442 "{
2443 HOST_WIDE_INT temp = INTVAL (operands[3]);
2444
2445 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2446 operands[4] = GEN_INT (32 - temp);
2447 }"
2448)
2449
2450(define_split
2451 [(set (match_operand:SI 0 "s_register_operand" "")
2452 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2453 (match_operand:SI 2 "const_int_operand" "")
2454 (match_operand:SI 3 "const_int_operand" "")))]
2455 "TARGET_THUMB1"
2456 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2457 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2458 "{
2459 HOST_WIDE_INT temp = INTVAL (operands[2]);
2460
2461 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2462 operands[3] = GEN_INT (32 - temp);
2463 }"
2464)
2465
2466(define_split
2467 [(set (match_operand:SI 0 "s_register_operand" "")
2468 (match_operator:SI 1 "shiftable_operator"
2469 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2470 (match_operand:SI 3 "const_int_operand" "")
2471 (match_operand:SI 4 "const_int_operand" ""))
2472 (match_operand:SI 5 "s_register_operand" "")]))
2473 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2474 "TARGET_ARM"
2475 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2476 (set (match_dup 0)
2477 (match_op_dup 1
2478 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2479 (match_dup 5)]))]
2480 "{
2481 HOST_WIDE_INT temp = INTVAL (operands[3]);
2482
2483 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2484 operands[4] = GEN_INT (32 - temp);
2485 }"
2486)
2487
2488;;; ??? This pattern is bogus. If operand3 has bits outside the range
2489;;; represented by the bitfield, then this will produce incorrect results.
2490;;; Somewhere, the value needs to be truncated. On targets like the m68k,
2491;;; which have a real bit-field insert instruction, the truncation happens
2492;;; in the bit-field insert instruction itself. Since arm does not have a
2493;;; bit-field insert instruction, we would have to emit code here to truncate
2494;;; the value before we insert. This loses some of the advantage of having
2495;;; this insv pattern, so this pattern needs to be reevalutated.
2496
2497(define_expand "insv"
2498 [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2499 (match_operand 1 "general_operand" "")
2500 (match_operand 2 "general_operand" ""))
2501 (match_operand 3 "reg_or_int_operand" ""))]
2502 "TARGET_ARM || arm_arch_thumb2"
2503 "
2504 {
2505 int start_bit = INTVAL (operands[2]);
2506 int width = INTVAL (operands[1]);
2507 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2508 rtx target, subtarget;
2509
2510 if (arm_arch_thumb2)
2511 {
2512 if (unaligned_access && MEM_P (operands[0])
2513 && s_register_operand (operands[3], GET_MODE (operands[3]))
2514 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
2515 {
2516 rtx base_addr;
2517
2518 if (BYTES_BIG_ENDIAN)
2519 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2520 - start_bit;
2521
2522 if (width == 32)
2523 {
2524 base_addr = adjust_address (operands[0], SImode,
2525 start_bit / BITS_PER_UNIT);
2526 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
2527 }
2528 else
2529 {
2530 rtx tmp = gen_reg_rtx (HImode);
2531
2532 base_addr = adjust_address (operands[0], HImode,
2533 start_bit / BITS_PER_UNIT);
2534 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2535 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2536 }
2537 DONE;
2538 }
2539 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
2540 {
2541 bool use_bfi = TRUE;
2542
2543 if (GET_CODE (operands[3]) == CONST_INT)
2544 {
2545 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2546
2547 if (val == 0)
2548 {
2549 emit_insn (gen_insv_zero (operands[0], operands[1],
2550 operands[2]));
2551 DONE;
2552 }
2553
2554 /* See if the set can be done with a single orr instruction. */
2555 if (val == mask && const_ok_for_arm (val << start_bit))
2556 use_bfi = FALSE;
2557 }
2558
2559 if (use_bfi)
2560 {
2561 if (GET_CODE (operands[3]) != REG)
2562 operands[3] = force_reg (SImode, operands[3]);
2563
2564 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2565 operands[3]));
2566 DONE;
2567 }
2568 }
2569 else
2570 FAIL;
2571 }
2572
2573 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2574 FAIL;
2575
2576 target = copy_rtx (operands[0]);
2577 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2578 subreg as the final target. */
2579 if (GET_CODE (target) == SUBREG)
2580 {
2581 subtarget = gen_reg_rtx (SImode);
2582 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2583 < GET_MODE_SIZE (SImode))
2584 target = SUBREG_REG (target);
2585 }
2586 else
2587 subtarget = target;
2588
2589 if (GET_CODE (operands[3]) == CONST_INT)
2590 {
2591 /* Since we are inserting a known constant, we may be able to
2592 reduce the number of bits that we have to clear so that
2593 the mask becomes simple. */
2594 /* ??? This code does not check to see if the new mask is actually
2595 simpler. It may not be. */
2596 rtx op1 = gen_reg_rtx (SImode);
2597 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2598 start of this pattern. */
2599 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2600 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2601
2602 emit_insn (gen_andsi3 (op1, operands[0],
2603 gen_int_mode (~mask2, SImode)));
2604 emit_insn (gen_iorsi3 (subtarget, op1,
2605 gen_int_mode (op3_value << start_bit, SImode)));
2606 }
2607 else if (start_bit == 0
2608 && !(const_ok_for_arm (mask)
2609 || const_ok_for_arm (~mask)))
2610 {
2611 /* A Trick, since we are setting the bottom bits in the word,
2612 we can shift operand[3] up, operand[0] down, OR them together
2613 and rotate the result back again. This takes 3 insns, and
2614 the third might be mergeable into another op. */
2615 /* The shift up copes with the possibility that operand[3] is
2616 wider than the bitfield. */
2617 rtx op0 = gen_reg_rtx (SImode);
2618 rtx op1 = gen_reg_rtx (SImode);
2619
2620 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2621 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2622 emit_insn (gen_iorsi3 (op1, op1, op0));
2623 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2624 }
2625 else if ((width + start_bit == 32)
2626 && !(const_ok_for_arm (mask)
2627 || const_ok_for_arm (~mask)))
2628 {
2629 /* Similar trick, but slightly less efficient. */
2630
2631 rtx op0 = gen_reg_rtx (SImode);
2632 rtx op1 = gen_reg_rtx (SImode);
2633
2634 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2635 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2636 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2637 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2638 }
2639 else
2640 {
2641 rtx op0 = gen_int_mode (mask, SImode);
2642 rtx op1 = gen_reg_rtx (SImode);
2643 rtx op2 = gen_reg_rtx (SImode);
2644
2645 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2646 {
2647 rtx tmp = gen_reg_rtx (SImode);
2648
2649 emit_insn (gen_movsi (tmp, op0));
2650 op0 = tmp;
2651 }
2652
2653 /* Mask out any bits in operand[3] that are not needed. */
2654 emit_insn (gen_andsi3 (op1, operands[3], op0));
2655
2656 if (GET_CODE (op0) == CONST_INT
2657 && (const_ok_for_arm (mask << start_bit)
2658 || const_ok_for_arm (~(mask << start_bit))))
2659 {
2660 op0 = gen_int_mode (~(mask << start_bit), SImode);
2661 emit_insn (gen_andsi3 (op2, operands[0], op0));
2662 }
2663 else
2664 {
2665 if (GET_CODE (op0) == CONST_INT)
2666 {
2667 rtx tmp = gen_reg_rtx (SImode);
2668
2669 emit_insn (gen_movsi (tmp, op0));
2670 op0 = tmp;
2671 }
2672
2673 if (start_bit != 0)
2674 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
2675
2676 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2677 }
2678
2679 if (start_bit != 0)
2680 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
2681
2682 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2683 }
2684
2685 if (subtarget != target)
2686 {
2687 /* If TARGET is still a SUBREG, then it must be wider than a word,
2688 so we must be careful only to set the subword we were asked to. */
2689 if (GET_CODE (target) == SUBREG)
2690 emit_move_insn (target, subtarget);
2691 else
2692 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2693 }
2694
2695 DONE;
2696 }"
2697)
2698
2699(define_insn "insv_zero"
2700 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2701 (match_operand:SI 1 "const_int_operand" "M")
2702 (match_operand:SI 2 "const_int_operand" "M"))
2703 (const_int 0))]
2704 "arm_arch_thumb2"
2705 "bfc%?\t%0, %2, %1"
2706 [(set_attr "length" "4")
2707 (set_attr "predicable" "yes")]
2708)
2709
2710(define_insn "insv_t2"
2711 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2712 (match_operand:SI 1 "const_int_operand" "M")
2713 (match_operand:SI 2 "const_int_operand" "M"))
2714 (match_operand:SI 3 "s_register_operand" "r"))]
2715 "arm_arch_thumb2"
2716 "bfi%?\t%0, %3, %2, %1"
2717 [(set_attr "length" "4")
2718 (set_attr "predicable" "yes")]
2719)
2720
2721; constants for op 2 will never be given to these patterns.
2722(define_insn_and_split "*anddi_notdi_di"
2723 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2724 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2725 (match_operand:DI 2 "s_register_operand" "r,0")))]
2726 "TARGET_32BIT"
2727 "#"
2728 "TARGET_32BIT && reload_completed
2729 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2730 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2731 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2732 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2733 "
2734 {
2735 operands[3] = gen_highpart (SImode, operands[0]);
2736 operands[0] = gen_lowpart (SImode, operands[0]);
2737 operands[4] = gen_highpart (SImode, operands[1]);
2738 operands[1] = gen_lowpart (SImode, operands[1]);
2739 operands[5] = gen_highpart (SImode, operands[2]);
2740 operands[2] = gen_lowpart (SImode, operands[2]);
2741 }"
2742 [(set_attr "length" "8")
2743 (set_attr "predicable" "yes")]
2744)
2745
2746(define_insn_and_split "*anddi_notzesidi_di"
2747 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2748 (and:DI (not:DI (zero_extend:DI
2749 (match_operand:SI 2 "s_register_operand" "r,r")))
2750 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2751 "TARGET_32BIT"
2752 "@
2753 bic%?\\t%Q0, %Q1, %2
2754 #"
2755 ; (not (zero_extend ...)) allows us to just copy the high word from
2756 ; operand1 to operand0.
2757 "TARGET_32BIT
2758 && reload_completed
2759 && operands[0] != operands[1]"
2760 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2761 (set (match_dup 3) (match_dup 4))]
2762 "
2763 {
2764 operands[3] = gen_highpart (SImode, operands[0]);
2765 operands[0] = gen_lowpart (SImode, operands[0]);
2766 operands[4] = gen_highpart (SImode, operands[1]);
2767 operands[1] = gen_lowpart (SImode, operands[1]);
2768 }"
2769 [(set_attr "length" "4,8")
2770 (set_attr "predicable" "yes")]
2771)
2772
2773(define_insn_and_split "*anddi_notsesidi_di"
2774 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2775 (and:DI (not:DI (sign_extend:DI
2776 (match_operand:SI 2 "s_register_operand" "r,r")))
2777 (match_operand:DI 1 "s_register_operand" "0,r")))]
2778 "TARGET_32BIT"
2779 "#"
2780 "TARGET_32BIT && reload_completed"
2781 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2782 (set (match_dup 3) (and:SI (not:SI
2783 (ashiftrt:SI (match_dup 2) (const_int 31)))
2784 (match_dup 4)))]
2785 "
2786 {
2787 operands[3] = gen_highpart (SImode, operands[0]);
2788 operands[0] = gen_lowpart (SImode, operands[0]);
2789 operands[4] = gen_highpart (SImode, operands[1]);
2790 operands[1] = gen_lowpart (SImode, operands[1]);
2791 }"
2792 [(set_attr "length" "8")
2793 (set_attr "predicable" "yes")]
2794)
2795
2796(define_insn "andsi_notsi_si"
2797 [(set (match_operand:SI 0 "s_register_operand" "=r")
2798 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2799 (match_operand:SI 1 "s_register_operand" "r")))]
2800 "TARGET_32BIT"
2801 "bic%?\\t%0, %1, %2"
2802 [(set_attr "predicable" "yes")]
2803)
2804
2805(define_insn "thumb1_bicsi3"
2806 [(set (match_operand:SI 0 "register_operand" "=l")
2807 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2808 (match_operand:SI 2 "register_operand" "0")))]
2809 "TARGET_THUMB1"
2810 "bic\\t%0, %1"
2811 [(set_attr "length" "2")
2812 (set_attr "conds" "set")])
2813
2814(define_insn "andsi_not_shiftsi_si"
2815 [(set (match_operand:SI 0 "s_register_operand" "=r")
2816 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2817 [(match_operand:SI 2 "s_register_operand" "r")
2818 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2819 (match_operand:SI 1 "s_register_operand" "r")))]
2820 "TARGET_ARM"
2821 "bic%?\\t%0, %1, %2%S4"
2822 [(set_attr "predicable" "yes")
2823 (set_attr "shift" "2")
2824 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2825 (const_string "alu_shift")
2826 (const_string "alu_shift_reg")))]
2827)
2828
2829(define_insn "*andsi_notsi_si_compare0"
2830 [(set (reg:CC_NOOV CC_REGNUM)
2831 (compare:CC_NOOV
2832 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2833 (match_operand:SI 1 "s_register_operand" "r"))
2834 (const_int 0)))
2835 (set (match_operand:SI 0 "s_register_operand" "=r")
2836 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2837 "TARGET_32BIT"
2838 "bic%.\\t%0, %1, %2"
2839 [(set_attr "conds" "set")]
2840)
2841
2842(define_insn "*andsi_notsi_si_compare0_scratch"
2843 [(set (reg:CC_NOOV CC_REGNUM)
2844 (compare:CC_NOOV
2845 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2846 (match_operand:SI 1 "s_register_operand" "r"))
2847 (const_int 0)))
2848 (clobber (match_scratch:SI 0 "=r"))]
2849 "TARGET_32BIT"
2850 "bic%.\\t%0, %1, %2"
2851 [(set_attr "conds" "set")]
2852)
2853
2854(define_expand "iordi3"
2855 [(set (match_operand:DI 0 "s_register_operand" "")
2856 (ior:DI (match_operand:DI 1 "s_register_operand" "")
2857 (match_operand:DI 2 "neon_logic_op2" "")))]
2858 "TARGET_32BIT"
2859 ""
2860)
2861
2862(define_insn "*iordi3_insn"
2863 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2864 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2865 (match_operand:DI 2 "s_register_operand" "r,r")))]
2866 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
2867 "#"
2868 [(set_attr "length" "8")
2869 (set_attr "predicable" "yes")]
2870)
2871
2872(define_insn "*iordi_zesidi_di"
2873 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2874 (ior:DI (zero_extend:DI
2875 (match_operand:SI 2 "s_register_operand" "r,r"))
2876 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2877 "TARGET_32BIT"
2878 "@
2879 orr%?\\t%Q0, %Q1, %2
2880 #"
2881 [(set_attr "length" "4,8")
2882 (set_attr "predicable" "yes")]
2883)
2884
2885(define_insn "*iordi_sesidi_di"
2886 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2887 (ior:DI (sign_extend:DI
2888 (match_operand:SI 2 "s_register_operand" "r,r"))
2889 (match_operand:DI 1 "s_register_operand" "0,r")))]
2890 "TARGET_32BIT"
2891 "#"
2892 [(set_attr "length" "8")
2893 (set_attr "predicable" "yes")]
2894)
2895
2896(define_expand "iorsi3"
2897 [(set (match_operand:SI 0 "s_register_operand" "")
2898 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2899 (match_operand:SI 2 "reg_or_int_operand" "")))]
2900 "TARGET_EITHER"
2901 "
2902 if (GET_CODE (operands[2]) == CONST_INT)
2903 {
2904 if (TARGET_32BIT)
2905 {
2906 arm_split_constant (IOR, SImode, NULL_RTX,
2907 INTVAL (operands[2]), operands[0], operands[1],
2908 optimize && can_create_pseudo_p ());
2909 DONE;
2910 }
2911 else /* TARGET_THUMB1 */
2912 {
2913 rtx tmp = force_reg (SImode, operands[2]);
2914 if (rtx_equal_p (operands[0], operands[1]))
2915 operands[2] = tmp;
2916 else
2917 {
2918 operands[2] = operands[1];
2919 operands[1] = tmp;
2920 }
2921 }
2922 }
2923 "
2924)
2925
2926(define_insn_and_split "*iorsi3_insn"
2927 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2928 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
2929 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
2930 "TARGET_32BIT"
2931 "@
2932 orr%?\\t%0, %1, %2
2933 orn%?\\t%0, %1, #%B2
2934 #"
2935 "TARGET_32BIT
2936 && GET_CODE (operands[2]) == CONST_INT
2937 && !(const_ok_for_arm (INTVAL (operands[2]))
2938 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
2939 [(clobber (const_int 0))]
2940{
2941 arm_split_constant (IOR, SImode, curr_insn,
2942 INTVAL (operands[2]), operands[0], operands[1], 0);
2943 DONE;
2944}
2945 [(set_attr "length" "4,4,16")
2946 (set_attr "arch" "32,t2,32")
2947 (set_attr "predicable" "yes")])
2948
2949(define_insn "*thumb1_iorsi3_insn"
2950 [(set (match_operand:SI 0 "register_operand" "=l")
2951 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2952 (match_operand:SI 2 "register_operand" "l")))]
2953 "TARGET_THUMB1"
2954 "orr\\t%0, %2"
2955 [(set_attr "length" "2")
2956 (set_attr "conds" "set")])
2957
2958(define_peephole2
2959 [(match_scratch:SI 3 "r")
2960 (set (match_operand:SI 0 "arm_general_register_operand" "")
2961 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2962 (match_operand:SI 2 "const_int_operand" "")))]
2963 "TARGET_ARM
2964 && !const_ok_for_arm (INTVAL (operands[2]))
2965 && const_ok_for_arm (~INTVAL (operands[2]))"
2966 [(set (match_dup 3) (match_dup 2))
2967 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2968 ""
2969)
2970
2971(define_insn "*iorsi3_compare0"
2972 [(set (reg:CC_NOOV CC_REGNUM)
2973 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2974 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2975 (const_int 0)))
2976 (set (match_operand:SI 0 "s_register_operand" "=r")
2977 (ior:SI (match_dup 1) (match_dup 2)))]
2978 "TARGET_32BIT"
2979 "orr%.\\t%0, %1, %2"
2980 [(set_attr "conds" "set")]
2981)
2982
2983(define_insn "*iorsi3_compare0_scratch"
2984 [(set (reg:CC_NOOV CC_REGNUM)
2985 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2986 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2987 (const_int 0)))
2988 (clobber (match_scratch:SI 0 "=r"))]
2989 "TARGET_32BIT"
2990 "orr%.\\t%0, %1, %2"
2991 [(set_attr "conds" "set")]
2992)
2993
2994(define_expand "xordi3"
2995 [(set (match_operand:DI 0 "s_register_operand" "")
2996 (xor:DI (match_operand:DI 1 "s_register_operand" "")
2997 (match_operand:DI 2 "s_register_operand" "")))]
2998 "TARGET_32BIT"
2999 ""
3000)
3001
3002(define_insn "*xordi3_insn"
3003 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3004 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
3005 (match_operand:DI 2 "s_register_operand" "r,r")))]
3006 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
3007 "#"
3008 [(set_attr "length" "8")
3009 (set_attr "predicable" "yes")]
3010)
3011
3012(define_insn "*xordi_zesidi_di"
3013 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3014 (xor:DI (zero_extend:DI
3015 (match_operand:SI 2 "s_register_operand" "r,r"))
3016 (match_operand:DI 1 "s_register_operand" "0,?r")))]
3017 "TARGET_32BIT"
3018 "@
3019 eor%?\\t%Q0, %Q1, %2
3020 #"
3021 [(set_attr "length" "4,8")
3022 (set_attr "predicable" "yes")]
3023)
3024
3025(define_insn "*xordi_sesidi_di"
3026 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3027 (xor:DI (sign_extend:DI
3028 (match_operand:SI 2 "s_register_operand" "r,r"))
3029 (match_operand:DI 1 "s_register_operand" "0,r")))]
3030 "TARGET_32BIT"
3031 "#"
3032 [(set_attr "length" "8")
3033 (set_attr "predicable" "yes")]
3034)
3035
3036(define_expand "xorsi3"
3037 [(set (match_operand:SI 0 "s_register_operand" "")
3038 (xor:SI (match_operand:SI 1 "s_register_operand" "")
3039 (match_operand:SI 2 "reg_or_int_operand" "")))]
3040 "TARGET_EITHER"
3041 "if (GET_CODE (operands[2]) == CONST_INT)
3042 {
3043 if (TARGET_32BIT)
3044 {
3045 arm_split_constant (XOR, SImode, NULL_RTX,
3046 INTVAL (operands[2]), operands[0], operands[1],
3047 optimize && can_create_pseudo_p ());
3048 DONE;
3049 }
3050 else /* TARGET_THUMB1 */
3051 {
3052 rtx tmp = force_reg (SImode, operands[2]);
3053 if (rtx_equal_p (operands[0], operands[1]))
3054 operands[2] = tmp;
3055 else
3056 {
3057 operands[2] = operands[1];
3058 operands[1] = tmp;
3059 }
3060 }
3061 }"
3062)
3063
3064(define_insn_and_split "*arm_xorsi3"
3065 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3066 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3067 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
3068 "TARGET_32BIT"
3069 "@
3070 eor%?\\t%0, %1, %2
3071 #"
3072 "TARGET_32BIT
3073 && GET_CODE (operands[2]) == CONST_INT
3074 && !const_ok_for_arm (INTVAL (operands[2]))"
3075 [(clobber (const_int 0))]
3076{
3077 arm_split_constant (XOR, SImode, curr_insn,
3078 INTVAL (operands[2]), operands[0], operands[1], 0);
3079 DONE;
3080}
3081 [(set_attr "length" "4,16")
3082 (set_attr "predicable" "yes")]
3083)
3084
3085(define_insn "*thumb1_xorsi3_insn"
3086 [(set (match_operand:SI 0 "register_operand" "=l")
3087 (xor:SI (match_operand:SI 1 "register_operand" "%0")
3088 (match_operand:SI 2 "register_operand" "l")))]
3089 "TARGET_THUMB1"
3090 "eor\\t%0, %2"
3091 [(set_attr "length" "2")
3092 (set_attr "conds" "set")])
3093
3094(define_insn "*xorsi3_compare0"
3095 [(set (reg:CC_NOOV CC_REGNUM)
3096 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
3097 (match_operand:SI 2 "arm_rhs_operand" "rI"))
3098 (const_int 0)))
3099 (set (match_operand:SI 0 "s_register_operand" "=r")
3100 (xor:SI (match_dup 1) (match_dup 2)))]
3101 "TARGET_32BIT"
3102 "eor%.\\t%0, %1, %2"
3103 [(set_attr "conds" "set")]
3104)
3105
3106(define_insn "*xorsi3_compare0_scratch"
3107 [(set (reg:CC_NOOV CC_REGNUM)
3108 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
3109 (match_operand:SI 1 "arm_rhs_operand" "rI"))
3110 (const_int 0)))]
3111 "TARGET_32BIT"
3112 "teq%?\\t%0, %1"
3113 [(set_attr "conds" "set")]
3114)
3115
3116; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3117; (NOT D) we can sometimes merge the final NOT into one of the following
3118; insns.
3119
3120(define_split
3121 [(set (match_operand:SI 0 "s_register_operand" "")
3122 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3123 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3124 (match_operand:SI 3 "arm_rhs_operand" "")))
3125 (clobber (match_operand:SI 4 "s_register_operand" ""))]
3126 "TARGET_32BIT"
3127 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3128 (not:SI (match_dup 3))))
3129 (set (match_dup 0) (not:SI (match_dup 4)))]
3130 ""
3131)
3132
3133(define_insn "*andsi_iorsi3_notsi"
3134 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
3135 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
3136 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3137 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
3138 "TARGET_32BIT"
3139 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3140 [(set_attr "length" "8")
3141 (set_attr "ce_count" "2")
3142 (set_attr "predicable" "yes")]
3143)
3144
3145; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3146; insns are available?
3147(define_split
3148 [(set (match_operand:SI 0 "s_register_operand" "")
3149 (match_operator:SI 1 "logical_binary_operator"
3150 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3151 (match_operand:SI 3 "const_int_operand" "")
3152 (match_operand:SI 4 "const_int_operand" ""))
3153 (match_operator:SI 9 "logical_binary_operator"
3154 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3155 (match_operand:SI 6 "const_int_operand" ""))
3156 (match_operand:SI 7 "s_register_operand" "")])]))
3157 (clobber (match_operand:SI 8 "s_register_operand" ""))]
3158 "TARGET_32BIT
3159 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3160 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3161 [(set (match_dup 8)
3162 (match_op_dup 1
3163 [(ashift:SI (match_dup 2) (match_dup 4))
3164 (match_dup 5)]))
3165 (set (match_dup 0)
3166 (match_op_dup 1
3167 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3168 (match_dup 7)]))]
3169 "
3170 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3171")
3172
3173(define_split
3174 [(set (match_operand:SI 0 "s_register_operand" "")
3175 (match_operator:SI 1 "logical_binary_operator"
3176 [(match_operator:SI 9 "logical_binary_operator"
3177 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3178 (match_operand:SI 6 "const_int_operand" ""))
3179 (match_operand:SI 7 "s_register_operand" "")])
3180 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3181 (match_operand:SI 3 "const_int_operand" "")
3182 (match_operand:SI 4 "const_int_operand" ""))]))
3183 (clobber (match_operand:SI 8 "s_register_operand" ""))]
3184 "TARGET_32BIT
3185 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3186 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3187 [(set (match_dup 8)
3188 (match_op_dup 1
3189 [(ashift:SI (match_dup 2) (match_dup 4))
3190 (match_dup 5)]))
3191 (set (match_dup 0)
3192 (match_op_dup 1
3193 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3194 (match_dup 7)]))]
3195 "
3196 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3197")
3198
3199(define_split
3200 [(set (match_operand:SI 0 "s_register_operand" "")
3201 (match_operator:SI 1 "logical_binary_operator"
3202 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3203 (match_operand:SI 3 "const_int_operand" "")
3204 (match_operand:SI 4 "const_int_operand" ""))
3205 (match_operator:SI 9 "logical_binary_operator"
3206 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3207 (match_operand:SI 6 "const_int_operand" ""))
3208 (match_operand:SI 7 "s_register_operand" "")])]))
3209 (clobber (match_operand:SI 8 "s_register_operand" ""))]
3210 "TARGET_32BIT
3211 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3212 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3213 [(set (match_dup 8)
3214 (match_op_dup 1
3215 [(ashift:SI (match_dup 2) (match_dup 4))
3216 (match_dup 5)]))
3217 (set (match_dup 0)
3218 (match_op_dup 1
3219 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3220 (match_dup 7)]))]
3221 "
3222 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3223")
3224
3225(define_split
3226 [(set (match_operand:SI 0 "s_register_operand" "")
3227 (match_operator:SI 1 "logical_binary_operator"
3228 [(match_operator:SI 9 "logical_binary_operator"
3229 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3230 (match_operand:SI 6 "const_int_operand" ""))
3231 (match_operand:SI 7 "s_register_operand" "")])
3232 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3233 (match_operand:SI 3 "const_int_operand" "")
3234 (match_operand:SI 4 "const_int_operand" ""))]))
3235 (clobber (match_operand:SI 8 "s_register_operand" ""))]
3236 "TARGET_32BIT
3237 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3238 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3239 [(set (match_dup 8)
3240 (match_op_dup 1
3241 [(ashift:SI (match_dup 2) (match_dup 4))
3242 (match_dup 5)]))
3243 (set (match_dup 0)
3244 (match_op_dup 1
3245 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3246 (match_dup 7)]))]
3247 "
3248 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3249")
3250\f
3251
3252;; Minimum and maximum insns
3253
3254(define_expand "smaxsi3"
3255 [(parallel [
3256 (set (match_operand:SI 0 "s_register_operand" "")
3257 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3258 (match_operand:SI 2 "arm_rhs_operand" "")))
3259 (clobber (reg:CC CC_REGNUM))])]
3260 "TARGET_32BIT"
3261 "
3262 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
3263 {
3264 /* No need for a clobber of the condition code register here. */
3265 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3266 gen_rtx_SMAX (SImode, operands[1],
3267 operands[2])));
3268 DONE;
3269 }
3270")
3271
3272(define_insn "*smax_0"
3273 [(set (match_operand:SI 0 "s_register_operand" "=r")
3274 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3275 (const_int 0)))]
3276 "TARGET_32BIT"
3277 "bic%?\\t%0, %1, %1, asr #31"
3278 [(set_attr "predicable" "yes")]
3279)
3280
3281(define_insn "*smax_m1"
3282 [(set (match_operand:SI 0 "s_register_operand" "=r")
3283 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3284 (const_int -1)))]
3285 "TARGET_32BIT"
3286 "orr%?\\t%0, %1, %1, asr #31"
3287 [(set_attr "predicable" "yes")]
3288)
3289
3290(define_insn "*arm_smax_insn"
3291 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3292 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3293 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
3294 (clobber (reg:CC CC_REGNUM))]
3295 "TARGET_ARM"
3296 "@
3297 cmp\\t%1, %2\;movlt\\t%0, %2
3298 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3299 [(set_attr "conds" "clob")
3300 (set_attr "length" "8,12")]
3301)
3302
3303(define_expand "sminsi3"
3304 [(parallel [
3305 (set (match_operand:SI 0 "s_register_operand" "")
3306 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3307 (match_operand:SI 2 "arm_rhs_operand" "")))
3308 (clobber (reg:CC CC_REGNUM))])]
3309 "TARGET_32BIT"
3310 "
3311 if (operands[2] == const0_rtx)
3312 {
3313 /* No need for a clobber of the condition code register here. */
3314 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3315 gen_rtx_SMIN (SImode, operands[1],
3316 operands[2])));
3317 DONE;
3318 }
3319")
3320
3321(define_insn "*smin_0"
3322 [(set (match_operand:SI 0 "s_register_operand" "=r")
3323 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3324 (const_int 0)))]
3325 "TARGET_32BIT"
3326 "and%?\\t%0, %1, %1, asr #31"
3327 [(set_attr "predicable" "yes")]
3328)
3329
3330(define_insn "*arm_smin_insn"
3331 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3332 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3333 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
3334 (clobber (reg:CC CC_REGNUM))]
3335 "TARGET_ARM"
3336 "@
3337 cmp\\t%1, %2\;movge\\t%0, %2
3338 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3339 [(set_attr "conds" "clob")
3340 (set_attr "length" "8,12")]
3341)
3342
3343(define_expand "umaxsi3"
3344 [(parallel [
3345 (set (match_operand:SI 0 "s_register_operand" "")
3346 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3347 (match_operand:SI 2 "arm_rhs_operand" "")))
3348 (clobber (reg:CC CC_REGNUM))])]
3349 "TARGET_32BIT"
3350 ""
3351)
3352
3353(define_insn "*arm_umaxsi3"
3354 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3355 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3356 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3357 (clobber (reg:CC CC_REGNUM))]
3358 "TARGET_ARM"
3359 "@
3360 cmp\\t%1, %2\;movcc\\t%0, %2
3361 cmp\\t%1, %2\;movcs\\t%0, %1
3362 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3363 [(set_attr "conds" "clob")
3364 (set_attr "length" "8,8,12")]
3365)
3366
3367(define_expand "uminsi3"
3368 [(parallel [
3369 (set (match_operand:SI 0 "s_register_operand" "")
3370 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3371 (match_operand:SI 2 "arm_rhs_operand" "")))
3372 (clobber (reg:CC CC_REGNUM))])]
3373 "TARGET_32BIT"
3374 ""
3375)
3376
3377(define_insn "*arm_uminsi3"
3378 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3379 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3380 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3381 (clobber (reg:CC CC_REGNUM))]
3382 "TARGET_ARM"
3383 "@
3384 cmp\\t%1, %2\;movcs\\t%0, %2
3385 cmp\\t%1, %2\;movcc\\t%0, %1
3386 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3387 [(set_attr "conds" "clob")
3388 (set_attr "length" "8,8,12")]
3389)
3390
3391(define_insn "*store_minmaxsi"
3392 [(set (match_operand:SI 0 "memory_operand" "=m")
3393 (match_operator:SI 3 "minmax_operator"
3394 [(match_operand:SI 1 "s_register_operand" "r")
3395 (match_operand:SI 2 "s_register_operand" "r")]))
3396 (clobber (reg:CC CC_REGNUM))]
3397 "TARGET_32BIT"
3398 "*
3399 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3400 operands[1], operands[2]);
3401 output_asm_insn (\"cmp\\t%1, %2\", operands);
3402 if (TARGET_THUMB2)
3403 output_asm_insn (\"ite\t%d3\", operands);
3404 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3405 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3406 return \"\";
3407 "
3408 [(set_attr "conds" "clob")
3409 (set (attr "length")
3410 (if_then_else (eq_attr "is_thumb" "yes")
3411 (const_int 14)
3412 (const_int 12)))
3413 (set_attr "type" "store1")]
3414)
3415
3416; Reject the frame pointer in operand[1], since reloading this after
3417; it has been eliminated can cause carnage.
3418(define_insn "*minmax_arithsi"
3419 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3420 (match_operator:SI 4 "shiftable_operator"
3421 [(match_operator:SI 5 "minmax_operator"
3422 [(match_operand:SI 2 "s_register_operand" "r,r")
3423 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3424 (match_operand:SI 1 "s_register_operand" "0,?r")]))
3425 (clobber (reg:CC CC_REGNUM))]
3426 "TARGET_32BIT && !arm_eliminable_register (operands[1])"
3427 "*
3428 {
3429 enum rtx_code code = GET_CODE (operands[4]);
3430 bool need_else;
3431
3432 if (which_alternative != 0 || operands[3] != const0_rtx
3433 || (code != PLUS && code != IOR && code != XOR))
3434 need_else = true;
3435 else
3436 need_else = false;
3437
3438 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3439 operands[2], operands[3]);
3440 output_asm_insn (\"cmp\\t%2, %3\", operands);
3441 if (TARGET_THUMB2)
3442 {
3443 if (need_else)
3444 output_asm_insn (\"ite\\t%d5\", operands);
3445 else
3446 output_asm_insn (\"it\\t%d5\", operands);
3447 }
3448 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
3449 if (need_else)
3450 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3451 return \"\";
3452 }"
3453 [(set_attr "conds" "clob")
3454 (set (attr "length")
3455 (if_then_else (eq_attr "is_thumb" "yes")
3456 (const_int 14)
3457 (const_int 12)))]
3458)
3459
3460(define_code_iterator SAT [smin smax])
3461(define_code_iterator SATrev [smin smax])
3462(define_code_attr SATlo [(smin "1") (smax "2")])
3463(define_code_attr SAThi [(smin "2") (smax "1")])
3464
3465(define_insn "*satsi_<SAT:code>"
3466 [(set (match_operand:SI 0 "s_register_operand" "=r")
3467 (SAT:SI (SATrev:SI (match_operand:SI 3 "s_register_operand" "r")
3468 (match_operand:SI 1 "const_int_operand" "i"))
3469 (match_operand:SI 2 "const_int_operand" "i")))]
3470 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3471 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3472{
3473 int mask;
3474 bool signed_sat;
3475 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3476 &mask, &signed_sat))
3477 gcc_unreachable ();
3478
3479 operands[1] = GEN_INT (mask);
3480 if (signed_sat)
3481 return "ssat%?\t%0, %1, %3";
3482 else
3483 return "usat%?\t%0, %1, %3";
3484}
3485 [(set_attr "predicable" "yes")
3486 (set_attr "insn" "sat")])
3487
3488(define_insn "*satsi_<SAT:code>_shift"
3489 [(set (match_operand:SI 0 "s_register_operand" "=r")
3490 (SAT:SI (SATrev:SI (match_operator:SI 3 "sat_shift_operator"
3491 [(match_operand:SI 4 "s_register_operand" "r")
3492 (match_operand:SI 5 "const_int_operand" "i")])
3493 (match_operand:SI 1 "const_int_operand" "i"))
3494 (match_operand:SI 2 "const_int_operand" "i")))]
3495 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3496 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3497{
3498 int mask;
3499 bool signed_sat;
3500 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3501 &mask, &signed_sat))
3502 gcc_unreachable ();
3503
3504 operands[1] = GEN_INT (mask);
3505 if (signed_sat)
3506 return "ssat%?\t%0, %1, %4%S3";
3507 else
3508 return "usat%?\t%0, %1, %4%S3";
3509}
3510 [(set_attr "predicable" "yes")
3511 (set_attr "insn" "sat")
3512 (set_attr "shift" "3")
3513 (set_attr "type" "alu_shift")])
3514\f
3515;; Shift and rotation insns
3516
3517(define_expand "ashldi3"
3518 [(set (match_operand:DI 0 "s_register_operand" "")
3519 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
3520 (match_operand:SI 2 "reg_or_int_operand" "")))]
3521 "TARGET_32BIT"
3522 "
3523 if (!CONST_INT_P (operands[2])
3524 && (TARGET_REALLY_IWMMXT || (TARGET_HARD_FLOAT && TARGET_MAVERICK)))
3525 ; /* No special preparation statements; expand pattern as above. */
3526 else
3527 {
3528 rtx scratch1, scratch2;
3529
3530 if (CONST_INT_P (operands[2])
3531 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3532 {
3533 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3534 DONE;
3535 }
3536
3537 /* Ideally we should use iwmmxt here if we could know that operands[1]
3538 ends up already living in an iwmmxt register. Otherwise it's
3539 cheaper to have the alternate code being generated than moving
3540 values to iwmmxt regs and back. */
3541
3542 /* If we're optimizing for size, we prefer the libgcc calls. */
3543 if (optimize_function_for_size_p (cfun))
3544 FAIL;
3545
3546 /* Expand operation using core-registers.
3547 'FAIL' would achieve the same thing, but this is a bit smarter. */
3548 scratch1 = gen_reg_rtx (SImode);
3549 scratch2 = gen_reg_rtx (SImode);
3550 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
3551 operands[2], scratch1, scratch2);
3552 DONE;
3553 }
3554 "
3555)
3556
3557(define_insn "arm_ashldi3_1bit"
3558 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
3559 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
3560 (const_int 1)))
3561 (clobber (reg:CC CC_REGNUM))]
3562 "TARGET_32BIT"
3563 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3564 [(set_attr "conds" "clob")
3565 (set_attr "length" "8")]
3566)
3567
3568(define_expand "ashlsi3"
3569 [(set (match_operand:SI 0 "s_register_operand" "")
3570 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3571 (match_operand:SI 2 "arm_rhs_operand" "")))]
3572 "TARGET_EITHER"
3573 "
3574 if (GET_CODE (operands[2]) == CONST_INT
3575 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3576 {
3577 emit_insn (gen_movsi (operands[0], const0_rtx));
3578 DONE;
3579 }
3580 "
3581)
3582
3583(define_insn "*thumb1_ashlsi3"
3584 [(set (match_operand:SI 0 "register_operand" "=l,l")
3585 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3586 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3587 "TARGET_THUMB1"
3588 "lsl\\t%0, %1, %2"
3589 [(set_attr "length" "2")
3590 (set_attr "conds" "set")])
3591
3592(define_expand "ashrdi3"
3593 [(set (match_operand:DI 0 "s_register_operand" "")
3594 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3595 (match_operand:SI 2 "reg_or_int_operand" "")))]
3596 "TARGET_32BIT"
3597 "
3598 if (!CONST_INT_P (operands[2])
3599 && (TARGET_REALLY_IWMMXT || (TARGET_HARD_FLOAT && TARGET_MAVERICK)))
3600 ; /* No special preparation statements; expand pattern as above. */
3601 else
3602 {
3603 rtx scratch1, scratch2;
3604
3605 if (CONST_INT_P (operands[2])
3606 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3607 {
3608 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3609 DONE;
3610 }
3611
3612 /* Ideally we should use iwmmxt here if we could know that operands[1]
3613 ends up already living in an iwmmxt register. Otherwise it's
3614 cheaper to have the alternate code being generated than moving
3615 values to iwmmxt regs and back. */
3616
3617 /* If we're optimizing for size, we prefer the libgcc calls. */
3618 if (optimize_function_for_size_p (cfun))
3619 FAIL;
3620
3621 /* Expand operation using core-registers.
3622 'FAIL' would achieve the same thing, but this is a bit smarter. */
3623 scratch1 = gen_reg_rtx (SImode);
3624 scratch2 = gen_reg_rtx (SImode);
3625 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
3626 operands[2], scratch1, scratch2);
3627 DONE;
3628 }
3629 "
3630)
3631
3632(define_insn "arm_ashrdi3_1bit"
3633 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
3634 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
3635 (const_int 1)))
3636 (clobber (reg:CC CC_REGNUM))]
3637 "TARGET_32BIT"
3638 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3639 [(set_attr "conds" "clob")
3640 (set_attr "insn" "mov")
3641 (set_attr "length" "8")]
3642)
3643
3644(define_expand "ashrsi3"
3645 [(set (match_operand:SI 0 "s_register_operand" "")
3646 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3647 (match_operand:SI 2 "arm_rhs_operand" "")))]
3648 "TARGET_EITHER"
3649 "
3650 if (GET_CODE (operands[2]) == CONST_INT
3651 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3652 operands[2] = GEN_INT (31);
3653 "
3654)
3655
3656(define_insn "*thumb1_ashrsi3"
3657 [(set (match_operand:SI 0 "register_operand" "=l,l")
3658 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3659 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3660 "TARGET_THUMB1"
3661 "asr\\t%0, %1, %2"
3662 [(set_attr "length" "2")
3663 (set_attr "conds" "set")])
3664
3665(define_expand "lshrdi3"
3666 [(set (match_operand:DI 0 "s_register_operand" "")
3667 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3668 (match_operand:SI 2 "reg_or_int_operand" "")))]
3669 "TARGET_32BIT"
3670 "
3671 if (!CONST_INT_P (operands[2])
3672 && (TARGET_REALLY_IWMMXT || (TARGET_HARD_FLOAT && TARGET_MAVERICK)))
3673 ; /* No special preparation statements; expand pattern as above. */
3674 else
3675 {
3676 rtx scratch1, scratch2;
3677
3678 if (CONST_INT_P (operands[2])
3679 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3680 {
3681 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3682 DONE;
3683 }
3684
3685 /* Ideally we should use iwmmxt here if we could know that operands[1]
3686 ends up already living in an iwmmxt register. Otherwise it's
3687 cheaper to have the alternate code being generated than moving
3688 values to iwmmxt regs and back. */
3689
3690 /* If we're optimizing for size, we prefer the libgcc calls. */
3691 if (optimize_function_for_size_p (cfun))
3692 FAIL;
3693
3694 /* Expand operation using core-registers.
3695 'FAIL' would achieve the same thing, but this is a bit smarter. */
3696 scratch1 = gen_reg_rtx (SImode);
3697 scratch2 = gen_reg_rtx (SImode);
3698 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
3699 operands[2], scratch1, scratch2);
3700 DONE;
3701 }
3702 "
3703)
3704
3705(define_insn "arm_lshrdi3_1bit"
3706 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
3707 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
3708 (const_int 1)))
3709 (clobber (reg:CC CC_REGNUM))]
3710 "TARGET_32BIT"
3711 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3712 [(set_attr "conds" "clob")
3713 (set_attr "insn" "mov")
3714 (set_attr "length" "8")]
3715)
3716
3717(define_expand "lshrsi3"
3718 [(set (match_operand:SI 0 "s_register_operand" "")
3719 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3720 (match_operand:SI 2 "arm_rhs_operand" "")))]
3721 "TARGET_EITHER"
3722 "
3723 if (GET_CODE (operands[2]) == CONST_INT
3724 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3725 {
3726 emit_insn (gen_movsi (operands[0], const0_rtx));
3727 DONE;
3728 }
3729 "
3730)
3731
3732(define_insn "*thumb1_lshrsi3"
3733 [(set (match_operand:SI 0 "register_operand" "=l,l")
3734 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3735 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3736 "TARGET_THUMB1"
3737 "lsr\\t%0, %1, %2"
3738 [(set_attr "length" "2")
3739 (set_attr "conds" "set")])
3740
3741(define_expand "rotlsi3"
3742 [(set (match_operand:SI 0 "s_register_operand" "")
3743 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3744 (match_operand:SI 2 "reg_or_int_operand" "")))]
3745 "TARGET_32BIT"
3746 "
3747 if (GET_CODE (operands[2]) == CONST_INT)
3748 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3749 else
3750 {
3751 rtx reg = gen_reg_rtx (SImode);
3752 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3753 operands[2] = reg;
3754 }
3755 "
3756)
3757
3758(define_expand "rotrsi3"
3759 [(set (match_operand:SI 0 "s_register_operand" "")
3760 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3761 (match_operand:SI 2 "arm_rhs_operand" "")))]
3762 "TARGET_EITHER"
3763 "
3764 if (TARGET_32BIT)
3765 {
3766 if (GET_CODE (operands[2]) == CONST_INT
3767 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3768 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3769 }
3770 else /* TARGET_THUMB1 */
3771 {
3772 if (GET_CODE (operands [2]) == CONST_INT)
3773 operands [2] = force_reg (SImode, operands[2]);
3774 }
3775 "
3776)
3777
3778(define_insn "*thumb1_rotrsi3"
3779 [(set (match_operand:SI 0 "register_operand" "=l")
3780 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3781 (match_operand:SI 2 "register_operand" "l")))]
3782 "TARGET_THUMB1"
3783 "ror\\t%0, %0, %2"
3784 [(set_attr "length" "2")]
3785)
3786
3787(define_insn "*arm_shiftsi3"
3788 [(set (match_operand:SI 0 "s_register_operand" "=r")
3789 (match_operator:SI 3 "shift_operator"
3790 [(match_operand:SI 1 "s_register_operand" "r")
3791 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
3792 "TARGET_32BIT"
3793 "* return arm_output_shift(operands, 0);"
3794 [(set_attr "predicable" "yes")
3795 (set_attr "shift" "1")
3796 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3797 (const_string "alu_shift")
3798 (const_string "alu_shift_reg")))]
3799)
3800
3801(define_insn "*shiftsi3_compare0"
3802 [(set (reg:CC_NOOV CC_REGNUM)
3803 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3804 [(match_operand:SI 1 "s_register_operand" "r")
3805 (match_operand:SI 2 "arm_rhs_operand" "rM")])
3806 (const_int 0)))
3807 (set (match_operand:SI 0 "s_register_operand" "=r")
3808 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
3809 "TARGET_32BIT"
3810 "* return arm_output_shift(operands, 1);"
3811 [(set_attr "conds" "set")
3812 (set_attr "shift" "1")
3813 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3814 (const_string "alu_shift")
3815 (const_string "alu_shift_reg")))]
3816)
3817
3818(define_insn "*shiftsi3_compare0_scratch"
3819 [(set (reg:CC_NOOV CC_REGNUM)
3820 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3821 [(match_operand:SI 1 "s_register_operand" "r")
3822 (match_operand:SI 2 "arm_rhs_operand" "rM")])
3823 (const_int 0)))
3824 (clobber (match_scratch:SI 0 "=r"))]
3825 "TARGET_32BIT"
3826 "* return arm_output_shift(operands, 1);"
3827 [(set_attr "conds" "set")
3828 (set_attr "shift" "1")]
3829)
3830
3831(define_insn "*not_shiftsi"
3832 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3833 (not:SI (match_operator:SI 3 "shift_operator"
3834 [(match_operand:SI 1 "s_register_operand" "r,r")
3835 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3836 "TARGET_32BIT"
3837 "mvn%?\\t%0, %1%S3"
3838 [(set_attr "predicable" "yes")
3839 (set_attr "shift" "1")
3840 (set_attr "insn" "mvn")
3841 (set_attr "arch" "32,a")
3842 (set_attr "type" "alu_shift,alu_shift_reg")])
3843
3844(define_insn "*not_shiftsi_compare0"
3845 [(set (reg:CC_NOOV CC_REGNUM)
3846 (compare:CC_NOOV
3847 (not:SI (match_operator:SI 3 "shift_operator"
3848 [(match_operand:SI 1 "s_register_operand" "r,r")
3849 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3850 (const_int 0)))
3851 (set (match_operand:SI 0 "s_register_operand" "=r,r")
3852 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
3853 "TARGET_32BIT"
3854 "mvn%.\\t%0, %1%S3"
3855 [(set_attr "conds" "set")
3856 (set_attr "shift" "1")
3857 (set_attr "insn" "mvn")
3858 (set_attr "arch" "32,a")
3859 (set_attr "type" "alu_shift,alu_shift_reg")])
3860
3861(define_insn "*not_shiftsi_compare0_scratch"
3862 [(set (reg:CC_NOOV CC_REGNUM)
3863 (compare:CC_NOOV
3864 (not:SI (match_operator:SI 3 "shift_operator"
3865 [(match_operand:SI 1 "s_register_operand" "r,r")
3866 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3867 (const_int 0)))
3868 (clobber (match_scratch:SI 0 "=r,r"))]
3869 "TARGET_32BIT"
3870 "mvn%.\\t%0, %1%S3"
3871 [(set_attr "conds" "set")
3872 (set_attr "shift" "1")
3873 (set_attr "insn" "mvn")
3874 (set_attr "arch" "32,a")
3875 (set_attr "type" "alu_shift,alu_shift_reg")])
3876
3877;; We don't really have extzv, but defining this using shifts helps
3878;; to reduce register pressure later on.
3879
3880(define_expand "extzv"
3881 [(set (match_operand 0 "s_register_operand" "")
3882 (zero_extract (match_operand 1 "nonimmediate_operand" "")
3883 (match_operand 2 "const_int_operand" "")
3884 (match_operand 3 "const_int_operand" "")))]
3885 "TARGET_THUMB1 || arm_arch_thumb2"
3886 "
3887 {
3888 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3889 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3890
3891 if (arm_arch_thumb2)
3892 {
3893 HOST_WIDE_INT width = INTVAL (operands[2]);
3894 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
3895
3896 if (unaligned_access && MEM_P (operands[1])
3897 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
3898 {
3899 rtx base_addr;
3900
3901 if (BYTES_BIG_ENDIAN)
3902 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
3903 - bitpos;
3904
3905 if (width == 32)
3906 {
3907 base_addr = adjust_address (operands[1], SImode,
3908 bitpos / BITS_PER_UNIT);
3909 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
3910 }
3911 else
3912 {
3913 rtx dest = operands[0];
3914 rtx tmp = gen_reg_rtx (SImode);
3915
3916 /* We may get a paradoxical subreg here. Strip it off. */
3917 if (GET_CODE (dest) == SUBREG
3918 && GET_MODE (dest) == SImode
3919 && GET_MODE (SUBREG_REG (dest)) == HImode)
3920 dest = SUBREG_REG (dest);
3921
3922 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
3923 FAIL;
3924
3925 base_addr = adjust_address (operands[1], HImode,
3926 bitpos / BITS_PER_UNIT);
3927 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
3928 emit_move_insn (gen_lowpart (SImode, dest), tmp);
3929 }
3930 DONE;
3931 }
3932 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
3933 {
3934 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3935 operands[3]));
3936 DONE;
3937 }
3938 else
3939 FAIL;
3940 }
3941
3942 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
3943 FAIL;
3944
3945 operands[3] = GEN_INT (rshift);
3946
3947 if (lshift == 0)
3948 {
3949 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3950 DONE;
3951 }
3952
3953 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
3954 operands[3], gen_reg_rtx (SImode)));
3955 DONE;
3956 }"
3957)
3958
3959;; Helper for extzv, for the Thumb-1 register-shifts case.
3960
3961(define_expand "extzv_t1"
3962 [(set (match_operand:SI 4 "s_register_operand" "")
3963 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
3964 (match_operand:SI 2 "const_int_operand" "")))
3965 (set (match_operand:SI 0 "s_register_operand" "")
3966 (lshiftrt:SI (match_dup 4)
3967 (match_operand:SI 3 "const_int_operand" "")))]
3968 "TARGET_THUMB1"
3969 "")
3970
3971(define_expand "extv"
3972 [(set (match_operand 0 "s_register_operand" "")
3973 (sign_extract (match_operand 1 "nonimmediate_operand" "")
3974 (match_operand 2 "const_int_operand" "")
3975 (match_operand 3 "const_int_operand" "")))]
3976 "arm_arch_thumb2"
3977{
3978 HOST_WIDE_INT width = INTVAL (operands[2]);
3979 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
3980
3981 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
3982 && (bitpos % BITS_PER_UNIT) == 0)
3983 {
3984 rtx base_addr;
3985
3986 if (BYTES_BIG_ENDIAN)
3987 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
3988
3989 if (width == 32)
3990 {
3991 base_addr = adjust_address (operands[1], SImode,
3992 bitpos / BITS_PER_UNIT);
3993 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
3994 }
3995 else
3996 {
3997 rtx dest = operands[0];
3998 rtx tmp = gen_reg_rtx (SImode);
3999
4000 /* We may get a paradoxical subreg here. Strip it off. */
4001 if (GET_CODE (dest) == SUBREG
4002 && GET_MODE (dest) == SImode
4003 && GET_MODE (SUBREG_REG (dest)) == HImode)
4004 dest = SUBREG_REG (dest);
4005
4006 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4007 FAIL;
4008
4009 base_addr = adjust_address (operands[1], HImode,
4010 bitpos / BITS_PER_UNIT);
4011 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
4012 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4013 }
4014
4015 DONE;
4016 }
4017 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4018 FAIL;
4019 else if (GET_MODE (operands[0]) == SImode
4020 && GET_MODE (operands[1]) == SImode)
4021 {
4022 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
4023 operands[3]));
4024 DONE;
4025 }
4026
4027 FAIL;
4028})
4029
4030; Helper to expand register forms of extv with the proper modes.
4031
4032(define_expand "extv_regsi"
4033 [(set (match_operand:SI 0 "s_register_operand" "")
4034 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
4035 (match_operand 2 "const_int_operand" "")
4036 (match_operand 3 "const_int_operand" "")))]
4037 ""
4038{
4039})
4040
4041; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
4042
4043(define_insn "unaligned_loadsi"
4044 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4045 (unspec:SI [(match_operand:SI 1 "memory_operand" "Uw,m")]
4046 UNSPEC_UNALIGNED_LOAD))]
4047 "unaligned_access && TARGET_32BIT"
4048 "ldr%?\t%0, %1\t@ unaligned"
4049 [(set_attr "arch" "t2,any")
4050 (set_attr "length" "2,4")
4051 (set_attr "predicable" "yes")
4052 (set_attr "type" "load1")])
4053
4054(define_insn "unaligned_loadhis"
4055 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4056 (sign_extend:SI
4057 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4058 UNSPEC_UNALIGNED_LOAD)))]
4059 "unaligned_access && TARGET_32BIT"
4060 "ldr%(sh%)\t%0, %1\t@ unaligned"
4061 [(set_attr "arch" "t2,any")
4062 (set_attr "length" "2,4")
4063 (set_attr "predicable" "yes")
4064 (set_attr "type" "load_byte")])
4065
4066(define_insn "unaligned_loadhiu"
4067 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4068 (zero_extend:SI
4069 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4070 UNSPEC_UNALIGNED_LOAD)))]
4071 "unaligned_access && TARGET_32BIT"
4072 "ldr%(h%)\t%0, %1\t@ unaligned"
4073 [(set_attr "arch" "t2,any")
4074 (set_attr "length" "2,4")
4075 (set_attr "predicable" "yes")
4076 (set_attr "type" "load_byte")])
4077
4078(define_insn "unaligned_storesi"
4079 [(set (match_operand:SI 0 "memory_operand" "=Uw,m")
4080 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,r")]
4081 UNSPEC_UNALIGNED_STORE))]
4082 "unaligned_access && TARGET_32BIT"
4083 "str%?\t%1, %0\t@ unaligned"
4084 [(set_attr "arch" "t2,any")
4085 (set_attr "length" "2,4")
4086 (set_attr "predicable" "yes")
4087 (set_attr "type" "store1")])
4088
4089(define_insn "unaligned_storehi"
4090 [(set (match_operand:HI 0 "memory_operand" "=Uw,m")
4091 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
4092 UNSPEC_UNALIGNED_STORE))]
4093 "unaligned_access && TARGET_32BIT"
4094 "str%(h%)\t%1, %0\t@ unaligned"
4095 [(set_attr "arch" "t2,any")
4096 (set_attr "length" "2,4")
4097 (set_attr "predicable" "yes")
4098 (set_attr "type" "store1")])
4099
4100(define_insn "*extv_reg"
4101 [(set (match_operand:SI 0 "s_register_operand" "=r")
4102 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
4103 (match_operand:SI 2 "const_int_operand" "M")
4104 (match_operand:SI 3 "const_int_operand" "M")))]
4105 "arm_arch_thumb2"
4106 "sbfx%?\t%0, %1, %3, %2"
4107 [(set_attr "length" "4")
4108 (set_attr "predicable" "yes")]
4109)
4110
4111(define_insn "extzv_t2"
4112 [(set (match_operand:SI 0 "s_register_operand" "=r")
4113 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
4114 (match_operand:SI 2 "const_int_operand" "M")
4115 (match_operand:SI 3 "const_int_operand" "M")))]
4116 "arm_arch_thumb2"
4117 "ubfx%?\t%0, %1, %3, %2"
4118 [(set_attr "length" "4")
4119 (set_attr "predicable" "yes")]
4120)
4121
4122
4123;; Division instructions
4124(define_insn "divsi3"
4125 [(set (match_operand:SI 0 "s_register_operand" "=r")
4126 (div:SI (match_operand:SI 1 "s_register_operand" "r")
4127 (match_operand:SI 2 "s_register_operand" "r")))]
4128 "TARGET_IDIV"
4129 "sdiv%?\t%0, %1, %2"
4130 [(set_attr "predicable" "yes")
4131 (set_attr "insn" "sdiv")]
4132)
4133
4134(define_insn "udivsi3"
4135 [(set (match_operand:SI 0 "s_register_operand" "=r")
4136 (udiv:SI (match_operand:SI 1 "s_register_operand" "r")
4137 (match_operand:SI 2 "s_register_operand" "r")))]
4138 "TARGET_IDIV"
4139 "udiv%?\t%0, %1, %2"
4140 [(set_attr "predicable" "yes")
4141 (set_attr "insn" "udiv")]
4142)
4143
4144\f
4145;; Unary arithmetic insns
4146
4147(define_expand "negdi2"
4148 [(parallel
4149 [(set (match_operand:DI 0 "s_register_operand" "")
4150 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
4151 (clobber (reg:CC CC_REGNUM))])]
4152 "TARGET_EITHER"
4153 {
4154 if (TARGET_NEON)
4155 {
4156 emit_insn (gen_negdi2_neon (operands[0], operands[1]));
4157 DONE;
4158 }
4159 }
4160)
4161
4162;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
4163;; The first alternative allows the common case of a *full* overlap.
4164(define_insn "*arm_negdi2"
4165 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4166 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
4167 (clobber (reg:CC CC_REGNUM))]
4168 "TARGET_ARM"
4169 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
4170 [(set_attr "conds" "clob")
4171 (set_attr "length" "8")]
4172)
4173
4174(define_insn "*thumb1_negdi2"
4175 [(set (match_operand:DI 0 "register_operand" "=&l")
4176 (neg:DI (match_operand:DI 1 "register_operand" "l")))
4177 (clobber (reg:CC CC_REGNUM))]
4178 "TARGET_THUMB1"
4179 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
4180 [(set_attr "length" "6")]
4181)
4182
4183(define_expand "negsi2"
4184 [(set (match_operand:SI 0 "s_register_operand" "")
4185 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
4186 "TARGET_EITHER"
4187 ""
4188)
4189
4190(define_insn "*arm_negsi2"
4191 [(set (match_operand:SI 0 "s_register_operand" "=r")
4192 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
4193 "TARGET_32BIT"
4194 "rsb%?\\t%0, %1, #0"
4195 [(set_attr "predicable" "yes")]
4196)
4197
4198(define_insn "*thumb1_negsi2"
4199 [(set (match_operand:SI 0 "register_operand" "=l")
4200 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
4201 "TARGET_THUMB1"
4202 "neg\\t%0, %1"
4203 [(set_attr "length" "2")]
4204)
4205
4206(define_expand "negsf2"
4207 [(set (match_operand:SF 0 "s_register_operand" "")
4208 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
4209 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
4210 ""
4211)
4212
4213(define_expand "negdf2"
4214 [(set (match_operand:DF 0 "s_register_operand" "")
4215 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
4216 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
4217 "")
4218
4219;; abssi2 doesn't really clobber the condition codes if a different register
4220;; is being set. To keep things simple, assume during rtl manipulations that
4221;; it does, but tell the final scan operator the truth. Similarly for
4222;; (neg (abs...))
4223
4224(define_expand "abssi2"
4225 [(parallel
4226 [(set (match_operand:SI 0 "s_register_operand" "")
4227 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
4228 (clobber (match_dup 2))])]
4229 "TARGET_EITHER"
4230 "
4231 if (TARGET_THUMB1)
4232 operands[2] = gen_rtx_SCRATCH (SImode);
4233 else
4234 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4235")
4236
4237(define_insn "*arm_abssi2"
4238 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4239 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
4240 (clobber (reg:CC CC_REGNUM))]
4241 "TARGET_ARM"
4242 "@
4243 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
4244 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
4245 [(set_attr "conds" "clob,*")
4246 (set_attr "shift" "1")
4247 ;; predicable can't be set based on the variant, so left as no
4248 (set_attr "length" "8")]
4249)
4250
4251(define_insn_and_split "*thumb1_abssi2"
4252 [(set (match_operand:SI 0 "s_register_operand" "=l")
4253 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
4254 (clobber (match_scratch:SI 2 "=&l"))]
4255 "TARGET_THUMB1"
4256 "#"
4257 "TARGET_THUMB1 && reload_completed"
4258 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
4259 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
4260 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
4261 ""
4262 [(set_attr "length" "6")]
4263)
4264
4265(define_insn "*arm_neg_abssi2"
4266 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4267 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
4268 (clobber (reg:CC CC_REGNUM))]
4269 "TARGET_ARM"
4270 "@
4271 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
4272 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
4273 [(set_attr "conds" "clob,*")
4274 (set_attr "shift" "1")
4275 ;; predicable can't be set based on the variant, so left as no
4276 (set_attr "length" "8")]
4277)
4278
4279(define_insn_and_split "*thumb1_neg_abssi2"
4280 [(set (match_operand:SI 0 "s_register_operand" "=l")
4281 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
4282 (clobber (match_scratch:SI 2 "=&l"))]
4283 "TARGET_THUMB1"
4284 "#"
4285 "TARGET_THUMB1 && reload_completed"
4286 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
4287 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
4288 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
4289 ""
4290 [(set_attr "length" "6")]
4291)
4292
4293(define_expand "abssf2"
4294 [(set (match_operand:SF 0 "s_register_operand" "")
4295 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
4296 "TARGET_32BIT && TARGET_HARD_FLOAT"
4297 "")
4298
4299(define_expand "absdf2"
4300 [(set (match_operand:DF 0 "s_register_operand" "")
4301 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
4302 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4303 "")
4304
4305(define_expand "sqrtsf2"
4306 [(set (match_operand:SF 0 "s_register_operand" "")
4307 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
4308 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
4309 "")
4310
4311(define_expand "sqrtdf2"
4312 [(set (match_operand:DF 0 "s_register_operand" "")
4313 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
4314 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
4315 "")
4316
4317(define_insn_and_split "one_cmpldi2"
4318 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,?w")
4319 (not:DI (match_operand:DI 1 "s_register_operand" " w, 0, r, w")))]
4320 "TARGET_32BIT"
4321 "@
4322 vmvn\t%P0, %P1
4323 #
4324 #
4325 vmvn\t%P0, %P1"
4326 "TARGET_32BIT && reload_completed
4327 && arm_general_register_operand (operands[0], DImode)"
4328 [(set (match_dup 0) (not:SI (match_dup 1)))
4329 (set (match_dup 2) (not:SI (match_dup 3)))]
4330 "
4331 {
4332 operands[2] = gen_highpart (SImode, operands[0]);
4333 operands[0] = gen_lowpart (SImode, operands[0]);
4334 operands[3] = gen_highpart (SImode, operands[1]);
4335 operands[1] = gen_lowpart (SImode, operands[1]);
4336 }"
4337 [(set_attr "length" "*,8,8,*")
4338 (set_attr "predicable" "no,yes,yes,no")
4339 (set_attr "neon_type" "neon_int_1,*,*,neon_int_1")
4340 (set_attr "arch" "neon_nota8,*,*,neon_onlya8")]
4341)
4342
4343(define_expand "one_cmplsi2"
4344 [(set (match_operand:SI 0 "s_register_operand" "")
4345 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
4346 "TARGET_EITHER"
4347 ""
4348)
4349
4350(define_insn "*arm_one_cmplsi2"
4351 [(set (match_operand:SI 0 "s_register_operand" "=r")
4352 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
4353 "TARGET_32BIT"
4354 "mvn%?\\t%0, %1"
4355 [(set_attr "predicable" "yes")
4356 (set_attr "insn" "mvn")]
4357)
4358
4359(define_insn "*thumb1_one_cmplsi2"
4360 [(set (match_operand:SI 0 "register_operand" "=l")
4361 (not:SI (match_operand:SI 1 "register_operand" "l")))]
4362 "TARGET_THUMB1"
4363 "mvn\\t%0, %1"
4364 [(set_attr "length" "2")
4365 (set_attr "insn" "mvn")]
4366)
4367
4368(define_insn "*notsi_compare0"
4369 [(set (reg:CC_NOOV CC_REGNUM)
4370 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4371 (const_int 0)))
4372 (set (match_operand:SI 0 "s_register_operand" "=r")
4373 (not:SI (match_dup 1)))]
4374 "TARGET_32BIT"
4375 "mvn%.\\t%0, %1"
4376 [(set_attr "conds" "set")
4377 (set_attr "insn" "mvn")]
4378)
4379
4380(define_insn "*notsi_compare0_scratch"
4381 [(set (reg:CC_NOOV CC_REGNUM)
4382 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4383 (const_int 0)))
4384 (clobber (match_scratch:SI 0 "=r"))]
4385 "TARGET_32BIT"
4386 "mvn%.\\t%0, %1"
4387 [(set_attr "conds" "set")
4388 (set_attr "insn" "mvn")]
4389)
4390\f
4391;; Fixed <--> Floating conversion insns
4392
4393(define_expand "floatsihf2"
4394 [(set (match_operand:HF 0 "general_operand" "")
4395 (float:HF (match_operand:SI 1 "general_operand" "")))]
4396 "TARGET_EITHER"
4397 "
4398 {
4399 rtx op1 = gen_reg_rtx (SFmode);
4400 expand_float (op1, operands[1], 0);
4401 op1 = convert_to_mode (HFmode, op1, 0);
4402 emit_move_insn (operands[0], op1);
4403 DONE;
4404 }"
4405)
4406
4407(define_expand "floatdihf2"
4408 [(set (match_operand:HF 0 "general_operand" "")
4409 (float:HF (match_operand:DI 1 "general_operand" "")))]
4410 "TARGET_EITHER"
4411 "
4412 {
4413 rtx op1 = gen_reg_rtx (SFmode);
4414 expand_float (op1, operands[1], 0);
4415 op1 = convert_to_mode (HFmode, op1, 0);
4416 emit_move_insn (operands[0], op1);
4417 DONE;
4418 }"
4419)
4420
4421(define_expand "floatsisf2"
4422 [(set (match_operand:SF 0 "s_register_operand" "")
4423 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
4424 "TARGET_32BIT && TARGET_HARD_FLOAT"
4425 "
4426 if (TARGET_MAVERICK)
4427 {
4428 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
4429 DONE;
4430 }
4431")
4432
4433(define_expand "floatsidf2"
4434 [(set (match_operand:DF 0 "s_register_operand" "")
4435 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
4436 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4437 "
4438 if (TARGET_MAVERICK)
4439 {
4440 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
4441 DONE;
4442 }
4443")
4444
4445(define_expand "fix_trunchfsi2"
4446 [(set (match_operand:SI 0 "general_operand" "")
4447 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4448 "TARGET_EITHER"
4449 "
4450 {
4451 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4452 expand_fix (operands[0], op1, 0);
4453 DONE;
4454 }"
4455)
4456
4457(define_expand "fix_trunchfdi2"
4458 [(set (match_operand:DI 0 "general_operand" "")
4459 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4460 "TARGET_EITHER"
4461 "
4462 {
4463 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4464 expand_fix (operands[0], op1, 0);
4465 DONE;
4466 }"
4467)
4468
4469(define_expand "fix_truncsfsi2"
4470 [(set (match_operand:SI 0 "s_register_operand" "")
4471 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
4472 "TARGET_32BIT && TARGET_HARD_FLOAT"
4473 "
4474 if (TARGET_MAVERICK)
4475 {
4476 if (!cirrus_fp_register (operands[0], SImode))
4477 operands[0] = force_reg (SImode, operands[0]);
4478 if (!cirrus_fp_register (operands[1], SFmode))
4479 operands[1] = force_reg (SFmode, operands[0]);
4480 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
4481 DONE;
4482 }
4483")
4484
4485(define_expand "fix_truncdfsi2"
4486 [(set (match_operand:SI 0 "s_register_operand" "")
4487 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
4488 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4489 "
4490 if (TARGET_MAVERICK)
4491 {
4492 if (!cirrus_fp_register (operands[1], DFmode))
4493 operands[1] = force_reg (DFmode, operands[0]);
4494 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
4495 DONE;
4496 }
4497")
4498
4499;; Truncation insns
4500
4501(define_expand "truncdfsf2"
4502 [(set (match_operand:SF 0 "s_register_operand" "")
4503 (float_truncate:SF
4504 (match_operand:DF 1 "s_register_operand" "")))]
4505 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4506 ""
4507)
4508
4509/* DFmode -> HFmode conversions have to go through SFmode. */
4510(define_expand "truncdfhf2"
4511 [(set (match_operand:HF 0 "general_operand" "")
4512 (float_truncate:HF
4513 (match_operand:DF 1 "general_operand" "")))]
4514 "TARGET_EITHER"
4515 "
4516 {
4517 rtx op1;
4518 op1 = convert_to_mode (SFmode, operands[1], 0);
4519 op1 = convert_to_mode (HFmode, op1, 0);
4520 emit_move_insn (operands[0], op1);
4521 DONE;
4522 }"
4523)
4524\f
4525;; Zero and sign extension instructions.
4526
4527(define_insn "zero_extend<mode>di2"
4528 [(set (match_operand:DI 0 "s_register_operand" "=r")
4529 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
4530 "<qhs_zextenddi_cstr>")))]
4531 "TARGET_32BIT <qhs_zextenddi_cond>"
4532 "#"
4533 [(set_attr "length" "8")
4534 (set_attr "ce_count" "2")
4535 (set_attr "predicable" "yes")]
4536)
4537
4538(define_insn "extend<mode>di2"
4539 [(set (match_operand:DI 0 "s_register_operand" "=r")
4540 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4541 "<qhs_extenddi_cstr>")))]
4542 "TARGET_32BIT <qhs_sextenddi_cond>"
4543 "#"
4544 [(set_attr "length" "8")
4545 (set_attr "ce_count" "2")
4546 (set_attr "shift" "1")
4547 (set_attr "predicable" "yes")]
4548)
4549
4550;; Splits for all extensions to DImode
4551(define_split
4552 [(set (match_operand:DI 0 "s_register_operand" "")
4553 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
4554 "TARGET_32BIT"
4555 [(set (match_dup 0) (match_dup 1))]
4556{
4557 rtx lo_part = gen_lowpart (SImode, operands[0]);
4558 enum machine_mode src_mode = GET_MODE (operands[1]);
4559
4560 if (REG_P (operands[0])
4561 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4562 emit_clobber (operands[0]);
4563 if (!REG_P (lo_part) || src_mode != SImode
4564 || !rtx_equal_p (lo_part, operands[1]))
4565 {
4566 if (src_mode == SImode)
4567 emit_move_insn (lo_part, operands[1]);
4568 else
4569 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4570 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4571 operands[1] = lo_part;
4572 }
4573 operands[0] = gen_highpart (SImode, operands[0]);
4574 operands[1] = const0_rtx;
4575})
4576
4577(define_split
4578 [(set (match_operand:DI 0 "s_register_operand" "")
4579 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
4580 "TARGET_32BIT"
4581 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4582{
4583 rtx lo_part = gen_lowpart (SImode, operands[0]);
4584 enum machine_mode src_mode = GET_MODE (operands[1]);
4585
4586 if (REG_P (operands[0])
4587 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4588 emit_clobber (operands[0]);
4589
4590 if (!REG_P (lo_part) || src_mode != SImode
4591 || !rtx_equal_p (lo_part, operands[1]))
4592 {
4593 if (src_mode == SImode)
4594 emit_move_insn (lo_part, operands[1]);
4595 else
4596 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4597 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4598 operands[1] = lo_part;
4599 }
4600 operands[0] = gen_highpart (SImode, operands[0]);
4601})
4602
4603(define_expand "zero_extendhisi2"
4604 [(set (match_operand:SI 0 "s_register_operand" "")
4605 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
4606 "TARGET_EITHER"
4607{
4608 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
4609 {
4610 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4611 DONE;
4612 }
4613 if (!arm_arch6 && !MEM_P (operands[1]))
4614 {
4615 rtx t = gen_lowpart (SImode, operands[1]);
4616 rtx tmp = gen_reg_rtx (SImode);
4617 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4618 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4619 DONE;
4620 }
4621})
4622
4623(define_split
4624 [(set (match_operand:SI 0 "s_register_operand" "")
4625 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
4626 "!TARGET_THUMB2 && !arm_arch6"
4627 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4628 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4629{
4630 operands[2] = gen_lowpart (SImode, operands[1]);
4631})
4632
4633(define_insn "*thumb1_zero_extendhisi2"
4634 [(set (match_operand:SI 0 "register_operand" "=l,l")
4635 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
4636 "TARGET_THUMB1"
4637{
4638 rtx mem;
4639
4640 if (which_alternative == 0 && arm_arch6)
4641 return "uxth\t%0, %1";
4642 if (which_alternative == 0)
4643 return "#";
4644
4645 mem = XEXP (operands[1], 0);
4646
4647 if (GET_CODE (mem) == CONST)
4648 mem = XEXP (mem, 0);
4649
4650 if (GET_CODE (mem) == PLUS)
4651 {
4652 rtx a = XEXP (mem, 0);
4653
4654 /* This can happen due to bugs in reload. */
4655 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4656 {
4657 rtx ops[2];
4658 ops[0] = operands[0];
4659 ops[1] = a;
4660
4661 output_asm_insn ("mov\t%0, %1", ops);
4662
4663 XEXP (mem, 0) = operands[0];
4664 }
4665 }
4666
4667 return "ldrh\t%0, %1";
4668}
4669 [(set_attr_alternative "length"
4670 [(if_then_else (eq_attr "is_arch6" "yes")
4671 (const_int 2) (const_int 4))
4672 (const_int 4)])
4673 (set_attr "type" "alu_shift,load_byte")]
4674)
4675
4676(define_insn "*arm_zero_extendhisi2"
4677 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4678 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4679 "TARGET_ARM && arm_arch4 && !arm_arch6"
4680 "@
4681 #
4682 ldr%(h%)\\t%0, %1"
4683 [(set_attr "type" "alu_shift,load_byte")
4684 (set_attr "predicable" "yes")]
4685)
4686
4687(define_insn "*arm_zero_extendhisi2_v6"
4688 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4689 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4690 "TARGET_ARM && arm_arch6"
4691 "@
4692 uxth%?\\t%0, %1
4693 ldr%(h%)\\t%0, %1"
4694 [(set_attr "type" "alu_shift,load_byte")
4695 (set_attr "predicable" "yes")]
4696)
4697
4698(define_insn "*arm_zero_extendhisi2addsi"
4699 [(set (match_operand:SI 0 "s_register_operand" "=r")
4700 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4701 (match_operand:SI 2 "s_register_operand" "r")))]
4702 "TARGET_INT_SIMD"
4703 "uxtah%?\\t%0, %2, %1"
4704 [(set_attr "type" "alu_shift")
4705 (set_attr "predicable" "yes")]
4706)
4707
4708(define_expand "zero_extendqisi2"
4709 [(set (match_operand:SI 0 "s_register_operand" "")
4710 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4711 "TARGET_EITHER"
4712{
4713 if (TARGET_ARM && !arm_arch6 && GET_CODE (operands[1]) != MEM)
4714 {
4715 emit_insn (gen_andsi3 (operands[0],
4716 gen_lowpart (SImode, operands[1]),
4717 GEN_INT (255)));
4718 DONE;
4719 }
4720 if (!arm_arch6 && !MEM_P (operands[1]))
4721 {
4722 rtx t = gen_lowpart (SImode, operands[1]);
4723 rtx tmp = gen_reg_rtx (SImode);
4724 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4725 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
4726 DONE;
4727 }
4728})
4729
4730(define_split
4731 [(set (match_operand:SI 0 "s_register_operand" "")
4732 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
4733 "!arm_arch6"
4734 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4735 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
4736{
4737 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4738 if (TARGET_ARM)
4739 {
4740 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
4741 DONE;
4742 }
4743})
4744
4745(define_insn "*thumb1_zero_extendqisi2"
4746 [(set (match_operand:SI 0 "register_operand" "=l,l")
4747 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
4748 "TARGET_THUMB1 && !arm_arch6"
4749 "@
4750 #
4751 ldrb\\t%0, %1"
4752 [(set_attr "length" "4,2")
4753 (set_attr "type" "alu_shift,load_byte")
4754 (set_attr "pool_range" "*,32")]
4755)
4756
4757(define_insn "*thumb1_zero_extendqisi2_v6"
4758 [(set (match_operand:SI 0 "register_operand" "=l,l")
4759 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
4760 "TARGET_THUMB1 && arm_arch6"
4761 "@
4762 uxtb\\t%0, %1
4763 ldrb\\t%0, %1"
4764 [(set_attr "length" "2")
4765 (set_attr "type" "alu_shift,load_byte")]
4766)
4767
4768(define_insn "*arm_zero_extendqisi2"
4769 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4770 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4771 "TARGET_ARM && !arm_arch6"
4772 "@
4773 #
4774 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4775 [(set_attr "length" "8,4")
4776 (set_attr "type" "alu_shift,load_byte")
4777 (set_attr "predicable" "yes")]
4778)
4779
4780(define_insn "*arm_zero_extendqisi2_v6"
4781 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4782 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4783 "TARGET_ARM && arm_arch6"
4784 "@
4785 uxtb%(%)\\t%0, %1
4786 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4787 [(set_attr "type" "alu_shift,load_byte")
4788 (set_attr "predicable" "yes")]
4789)
4790
4791(define_insn "*arm_zero_extendqisi2addsi"
4792 [(set (match_operand:SI 0 "s_register_operand" "=r")
4793 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4794 (match_operand:SI 2 "s_register_operand" "r")))]
4795 "TARGET_INT_SIMD"
4796 "uxtab%?\\t%0, %2, %1"
4797 [(set_attr "predicable" "yes")
4798 (set_attr "insn" "xtab")
4799 (set_attr "type" "alu_shift")]
4800)
4801
4802(define_split
4803 [(set (match_operand:SI 0 "s_register_operand" "")
4804 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4805 (clobber (match_operand:SI 2 "s_register_operand" ""))]
4806 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
4807 [(set (match_dup 2) (match_dup 1))
4808 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4809 ""
4810)
4811
4812(define_split
4813 [(set (match_operand:SI 0 "s_register_operand" "")
4814 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4815 (clobber (match_operand:SI 2 "s_register_operand" ""))]
4816 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
4817 [(set (match_dup 2) (match_dup 1))
4818 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4819 ""
4820)
4821
4822
4823(define_split
4824 [(set (match_operand:SI 0 "s_register_operand" "")
4825 (ior_xor:SI (and:SI (ashift:SI
4826 (match_operand:SI 1 "s_register_operand" "")
4827 (match_operand:SI 2 "const_int_operand" ""))
4828 (match_operand:SI 3 "const_int_operand" ""))
4829 (zero_extend:SI
4830 (match_operator 5 "subreg_lowpart_operator"
4831 [(match_operand:SI 4 "s_register_operand" "")]))))]
4832 "TARGET_32BIT
4833 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
4834 == (GET_MODE_MASK (GET_MODE (operands[5]))
4835 & (GET_MODE_MASK (GET_MODE (operands[5]))
4836 << (INTVAL (operands[2])))))"
4837 [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
4838 (match_dup 4)))
4839 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4840 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4841)
4842
4843(define_insn "*compareqi_eq0"
4844 [(set (reg:CC_Z CC_REGNUM)
4845 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
4846 (const_int 0)))]
4847 "TARGET_32BIT"
4848 "tst%?\\t%0, #255"
4849 [(set_attr "conds" "set")
4850 (set_attr "predicable" "yes")]
4851)
4852
4853(define_expand "extendhisi2"
4854 [(set (match_operand:SI 0 "s_register_operand" "")
4855 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
4856 "TARGET_EITHER"
4857{
4858 if (TARGET_THUMB1)
4859 {
4860 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4861 DONE;
4862 }
4863 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
4864 {
4865 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4866 DONE;
4867 }
4868
4869 if (!arm_arch6 && !MEM_P (operands[1]))
4870 {
4871 rtx t = gen_lowpart (SImode, operands[1]);
4872 rtx tmp = gen_reg_rtx (SImode);
4873 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4874 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
4875 DONE;
4876 }
4877})
4878
4879(define_split
4880 [(parallel
4881 [(set (match_operand:SI 0 "register_operand" "")
4882 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
4883 (clobber (match_scratch:SI 2 ""))])]
4884 "!arm_arch6"
4885 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4886 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4887{
4888 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4889})
4890
4891;; We used to have an early-clobber on the scratch register here.
4892;; However, there's a bug somewhere in reload which means that this
4893;; can be partially ignored during spill allocation if the memory
4894;; address also needs reloading; this causes us to die later on when
4895;; we try to verify the operands. Fortunately, we don't really need
4896;; the early-clobber: we can always use operand 0 if operand 2
4897;; overlaps the address.
4898(define_insn "thumb1_extendhisi2"
4899 [(set (match_operand:SI 0 "register_operand" "=l,l")
4900 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4901 (clobber (match_scratch:SI 2 "=X,l"))]
4902 "TARGET_THUMB1"
4903 "*
4904 {
4905 rtx ops[4];
4906 rtx mem;
4907
4908 if (which_alternative == 0 && !arm_arch6)
4909 return \"#\";
4910 if (which_alternative == 0)
4911 return \"sxth\\t%0, %1\";
4912
4913 mem = XEXP (operands[1], 0);
4914
4915 /* This code used to try to use 'V', and fix the address only if it was
4916 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4917 range of QImode offsets, and offsettable_address_p does a QImode
4918 address check. */
4919
4920 if (GET_CODE (mem) == CONST)
4921 mem = XEXP (mem, 0);
4922
4923 if (GET_CODE (mem) == LABEL_REF)
4924 return \"ldr\\t%0, %1\";
4925
4926 if (GET_CODE (mem) == PLUS)
4927 {
4928 rtx a = XEXP (mem, 0);
4929 rtx b = XEXP (mem, 1);
4930
4931 if (GET_CODE (a) == LABEL_REF
4932 && GET_CODE (b) == CONST_INT)
4933 return \"ldr\\t%0, %1\";
4934
4935 if (GET_CODE (b) == REG)
4936 return \"ldrsh\\t%0, %1\";
4937
4938 ops[1] = a;
4939 ops[2] = b;
4940 }
4941 else
4942 {
4943 ops[1] = mem;
4944 ops[2] = const0_rtx;
4945 }
4946
4947 gcc_assert (GET_CODE (ops[1]) == REG);
4948
4949 ops[0] = operands[0];
4950 if (reg_mentioned_p (operands[2], ops[1]))
4951 ops[3] = ops[0];
4952 else
4953 ops[3] = operands[2];
4954 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4955 return \"\";
4956 }"
4957 [(set_attr_alternative "length"
4958 [(if_then_else (eq_attr "is_arch6" "yes")
4959 (const_int 2) (const_int 4))
4960 (const_int 4)])
4961 (set_attr "type" "alu_shift,load_byte")
4962 (set_attr "pool_range" "*,1020")]
4963)
4964
4965;; This pattern will only be used when ldsh is not available
4966(define_expand "extendhisi2_mem"
4967 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4968 (set (match_dup 3)
4969 (zero_extend:SI (match_dup 7)))
4970 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4971 (set (match_operand:SI 0 "" "")
4972 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
4973 "TARGET_ARM"
4974 "
4975 {
4976 rtx mem1, mem2;
4977 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4978
4979 mem1 = change_address (operands[1], QImode, addr);
4980 mem2 = change_address (operands[1], QImode,
4981 plus_constant (Pmode, addr, 1));
4982 operands[0] = gen_lowpart (SImode, operands[0]);
4983 operands[1] = mem1;
4984 operands[2] = gen_reg_rtx (SImode);
4985 operands[3] = gen_reg_rtx (SImode);
4986 operands[6] = gen_reg_rtx (SImode);
4987 operands[7] = mem2;
4988
4989 if (BYTES_BIG_ENDIAN)
4990 {
4991 operands[4] = operands[2];
4992 operands[5] = operands[3];
4993 }
4994 else
4995 {
4996 operands[4] = operands[3];
4997 operands[5] = operands[2];
4998 }
4999 }"
5000)
5001
5002(define_split
5003 [(set (match_operand:SI 0 "register_operand" "")
5004 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
5005 "!arm_arch6"
5006 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5007 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5008{
5009 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5010})
5011
5012(define_insn "*arm_extendhisi2"
5013 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5014 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
5015 "TARGET_ARM && arm_arch4 && !arm_arch6"
5016 "@
5017 #
5018 ldr%(sh%)\\t%0, %1"
5019 [(set_attr "length" "8,4")
5020 (set_attr "type" "alu_shift,load_byte")
5021 (set_attr "predicable" "yes")
5022 (set_attr "pool_range" "*,256")
5023 (set_attr "neg_pool_range" "*,244")]
5024)
5025
5026;; ??? Check Thumb-2 pool range
5027(define_insn "*arm_extendhisi2_v6"
5028 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5029 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
5030 "TARGET_32BIT && arm_arch6"
5031 "@
5032 sxth%?\\t%0, %1
5033 ldr%(sh%)\\t%0, %1"
5034 [(set_attr "type" "alu_shift,load_byte")
5035 (set_attr "predicable" "yes")
5036 (set_attr "pool_range" "*,256")
5037 (set_attr "neg_pool_range" "*,244")]
5038)
5039
5040(define_insn "*arm_extendhisi2addsi"
5041 [(set (match_operand:SI 0 "s_register_operand" "=r")
5042 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5043 (match_operand:SI 2 "s_register_operand" "r")))]
5044 "TARGET_INT_SIMD"
5045 "sxtah%?\\t%0, %2, %1"
5046)
5047
5048(define_expand "extendqihi2"
5049 [(set (match_dup 2)
5050 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
5051 (const_int 24)))
5052 (set (match_operand:HI 0 "s_register_operand" "")
5053 (ashiftrt:SI (match_dup 2)
5054 (const_int 24)))]
5055 "TARGET_ARM"
5056 "
5057 {
5058 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
5059 {
5060 emit_insn (gen_rtx_SET (VOIDmode,
5061 operands[0],
5062 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
5063 DONE;
5064 }
5065 if (!s_register_operand (operands[1], QImode))
5066 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5067 operands[0] = gen_lowpart (SImode, operands[0]);
5068 operands[1] = gen_lowpart (SImode, operands[1]);
5069 operands[2] = gen_reg_rtx (SImode);
5070 }"
5071)
5072
5073(define_insn "*arm_extendqihi_insn"
5074 [(set (match_operand:HI 0 "s_register_operand" "=r")
5075 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
5076 "TARGET_ARM && arm_arch4"
5077 "ldr%(sb%)\\t%0, %1"
5078 [(set_attr "type" "load_byte")
5079 (set_attr "predicable" "yes")
5080 (set_attr "pool_range" "256")
5081 (set_attr "neg_pool_range" "244")]
5082)
5083
5084(define_expand "extendqisi2"
5085 [(set (match_operand:SI 0 "s_register_operand" "")
5086 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
5087 "TARGET_EITHER"
5088{
5089 if (!arm_arch4 && MEM_P (operands[1]))
5090 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5091
5092 if (!arm_arch6 && !MEM_P (operands[1]))
5093 {
5094 rtx t = gen_lowpart (SImode, operands[1]);
5095 rtx tmp = gen_reg_rtx (SImode);
5096 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5097 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
5098 DONE;
5099 }
5100})
5101
5102(define_split
5103 [(set (match_operand:SI 0 "register_operand" "")
5104 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5105 "!arm_arch6"
5106 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5107 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5108{
5109 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5110})
5111
5112(define_insn "*arm_extendqisi"
5113 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5114 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
5115 "TARGET_ARM && arm_arch4 && !arm_arch6"
5116 "@
5117 #
5118 ldr%(sb%)\\t%0, %1"
5119 [(set_attr "length" "8,4")
5120 (set_attr "type" "alu_shift,load_byte")
5121 (set_attr "predicable" "yes")
5122 (set_attr "pool_range" "*,256")
5123 (set_attr "neg_pool_range" "*,244")]
5124)
5125
5126(define_insn "*arm_extendqisi_v6"
5127 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5128 (sign_extend:SI
5129 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
5130 "TARGET_ARM && arm_arch6"
5131 "@
5132 sxtb%?\\t%0, %1
5133 ldr%(sb%)\\t%0, %1"
5134 [(set_attr "type" "alu_shift,load_byte")
5135 (set_attr "predicable" "yes")
5136 (set_attr "pool_range" "*,256")
5137 (set_attr "neg_pool_range" "*,244")]
5138)
5139
5140(define_insn "*arm_extendqisi2addsi"
5141 [(set (match_operand:SI 0 "s_register_operand" "=r")
5142 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5143 (match_operand:SI 2 "s_register_operand" "r")))]
5144 "TARGET_INT_SIMD"
5145 "sxtab%?\\t%0, %2, %1"
5146 [(set_attr "type" "alu_shift")
5147 (set_attr "insn" "xtab")
5148 (set_attr "predicable" "yes")]
5149)
5150
5151(define_split
5152 [(set (match_operand:SI 0 "register_operand" "")
5153 (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))]
5154 "TARGET_THUMB1 && reload_completed"
5155 [(set (match_dup 0) (match_dup 2))
5156 (set (match_dup 0) (sign_extend:SI (match_dup 3)))]
5157{
5158 rtx addr = XEXP (operands[1], 0);
5159
5160 if (GET_CODE (addr) == CONST)
5161 addr = XEXP (addr, 0);
5162
5163 if (GET_CODE (addr) == PLUS
5164 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
5165 /* No split necessary. */
5166 FAIL;
5167
5168 if (GET_CODE (addr) == PLUS
5169 && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1)))
5170 FAIL;
5171
5172 if (reg_overlap_mentioned_p (operands[0], addr))
5173 {
5174 rtx t = gen_lowpart (QImode, operands[0]);
5175 emit_move_insn (t, operands[1]);
5176 emit_insn (gen_thumb1_extendqisi2 (operands[0], t));
5177 DONE;
5178 }
5179
5180 if (REG_P (addr))
5181 {
5182 addr = gen_rtx_PLUS (Pmode, addr, operands[0]);
5183 operands[2] = const0_rtx;
5184 }
5185 else if (GET_CODE (addr) != PLUS)
5186 FAIL;
5187 else if (REG_P (XEXP (addr, 0)))
5188 {
5189 operands[2] = XEXP (addr, 1);
5190 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]);
5191 }
5192 else
5193 {
5194 operands[2] = XEXP (addr, 0);
5195 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]);
5196 }
5197
5198 operands[3] = change_address (operands[1], QImode, addr);
5199})
5200
5201(define_peephole2
5202 [(set (match_operand:SI 0 "register_operand" "")
5203 (plus:SI (match_dup 0) (match_operand 1 "const_int_operand")))
5204 (set (match_operand:SI 2 "register_operand" "") (const_int 0))
5205 (set (match_operand:SI 3 "register_operand" "")
5206 (sign_extend:SI (match_operand:QI 4 "memory_operand" "")))]
5207 "TARGET_THUMB1
5208 && GET_CODE (XEXP (operands[4], 0)) == PLUS
5209 && rtx_equal_p (operands[0], XEXP (XEXP (operands[4], 0), 0))
5210 && rtx_equal_p (operands[2], XEXP (XEXP (operands[4], 0), 1))
5211 && (peep2_reg_dead_p (3, operands[0])
5212 || rtx_equal_p (operands[0], operands[3]))
5213 && (peep2_reg_dead_p (3, operands[2])
5214 || rtx_equal_p (operands[2], operands[3]))"
5215 [(set (match_dup 2) (match_dup 1))
5216 (set (match_dup 3) (sign_extend:SI (match_dup 4)))]
5217{
5218 rtx addr = gen_rtx_PLUS (Pmode, operands[0], operands[2]);
5219 operands[4] = change_address (operands[4], QImode, addr);
5220})
5221
5222(define_insn "thumb1_extendqisi2"
5223 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
5224 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
5225 "TARGET_THUMB1"
5226{
5227 rtx addr;
5228
5229 if (which_alternative == 0 && arm_arch6)
5230 return "sxtb\\t%0, %1";
5231 if (which_alternative == 0)
5232 return "#";
5233
5234 addr = XEXP (operands[1], 0);
5235 if (GET_CODE (addr) == PLUS
5236 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
5237 return "ldrsb\\t%0, %1";
5238
5239 return "#";
5240}
5241 [(set_attr_alternative "length"
5242 [(if_then_else (eq_attr "is_arch6" "yes")
5243 (const_int 2) (const_int 4))
5244 (const_int 2)
5245 (if_then_else (eq_attr "is_arch6" "yes")
5246 (const_int 4) (const_int 6))])
5247 (set_attr "type" "alu_shift,load_byte,load_byte")]
5248)
5249
5250(define_expand "extendsfdf2"
5251 [(set (match_operand:DF 0 "s_register_operand" "")
5252 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
5253 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
5254 ""
5255)
5256
5257/* HFmode -> DFmode conversions have to go through SFmode. */
5258(define_expand "extendhfdf2"
5259 [(set (match_operand:DF 0 "general_operand" "")
5260 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
5261 "TARGET_EITHER"
5262 "
5263 {
5264 rtx op1;
5265 op1 = convert_to_mode (SFmode, operands[1], 0);
5266 op1 = convert_to_mode (DFmode, op1, 0);
5267 emit_insn (gen_movdf (operands[0], op1));
5268 DONE;
5269 }"
5270)
5271\f
5272;; Move insns (including loads and stores)
5273
5274;; XXX Just some ideas about movti.
5275;; I don't think these are a good idea on the arm, there just aren't enough
5276;; registers
5277;;(define_expand "loadti"
5278;; [(set (match_operand:TI 0 "s_register_operand" "")
5279;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
5280;; "" "")
5281
5282;;(define_expand "storeti"
5283;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
5284;; (match_operand:TI 1 "s_register_operand" ""))]
5285;; "" "")
5286
5287;;(define_expand "movti"
5288;; [(set (match_operand:TI 0 "general_operand" "")
5289;; (match_operand:TI 1 "general_operand" ""))]
5290;; ""
5291;; "
5292;;{
5293;; rtx insn;
5294;;
5295;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
5296;; operands[1] = copy_to_reg (operands[1]);
5297;; if (GET_CODE (operands[0]) == MEM)
5298;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
5299;; else if (GET_CODE (operands[1]) == MEM)
5300;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5301;; else
5302;; FAIL;
5303;;
5304;; emit_insn (insn);
5305;; DONE;
5306;;}")
5307
5308;; Recognize garbage generated above.
5309
5310;;(define_insn ""
5311;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5312;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5313;; ""
5314;; "*
5315;; {
5316;; register mem = (which_alternative < 3);
5317;; register const char *template;
5318;;
5319;; operands[mem] = XEXP (operands[mem], 0);
5320;; switch (which_alternative)
5321;; {
5322;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5323;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5324;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5325;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5326;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5327;; case 5: template = \"stmia\\t%0, %M1\"; break;
5328;; }
5329;; output_asm_insn (template, operands);
5330;; return \"\";
5331;; }")
5332
5333(define_expand "movdi"
5334 [(set (match_operand:DI 0 "general_operand" "")
5335 (match_operand:DI 1 "general_operand" ""))]
5336 "TARGET_EITHER"
5337 "
5338 if (can_create_pseudo_p ())
5339 {
5340 if (GET_CODE (operands[0]) != REG)
5341 operands[1] = force_reg (DImode, operands[1]);
5342 }
5343 "
5344)
5345
5346(define_insn "*arm_movdi"
5347 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
5348 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
5349 "TARGET_32BIT
5350 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
5351 && !TARGET_IWMMXT
5352 && ( register_operand (operands[0], DImode)
5353 || register_operand (operands[1], DImode))"
5354 "*
5355 switch (which_alternative)
5356 {
5357 case 0:
5358 case 1:
5359 case 2:
5360 return \"#\";
5361 default:
5362 return output_move_double (operands, true, NULL);
5363 }
5364 "
5365 [(set_attr "length" "8,12,16,8,8")
5366 (set_attr "type" "*,*,*,load2,store2")
5367 (set_attr "arm_pool_range" "*,*,*,1020,*")
5368 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
5369 (set_attr "thumb2_pool_range" "*,*,*,4096,*")
5370 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
5371)
5372
5373(define_split
5374 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5375 (match_operand:ANY64 1 "const_double_operand" ""))]
5376 "TARGET_32BIT
5377 && reload_completed
5378 && (arm_const_double_inline_cost (operands[1])
5379 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
5380 [(const_int 0)]
5381 "
5382 arm_split_constant (SET, SImode, curr_insn,
5383 INTVAL (gen_lowpart (SImode, operands[1])),
5384 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5385 arm_split_constant (SET, SImode, curr_insn,
5386 INTVAL (gen_highpart_mode (SImode,
5387 GET_MODE (operands[0]),
5388 operands[1])),
5389 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5390 DONE;
5391 "
5392)
5393
5394; If optimizing for size, or if we have load delay slots, then
5395; we want to split the constant into two separate operations.
5396; In both cases this may split a trivial part into a single data op
5397; leaving a single complex constant to load. We can also get longer
5398; offsets in a LDR which means we get better chances of sharing the pool
5399; entries. Finally, we can normally do a better job of scheduling
5400; LDR instructions than we can with LDM.
5401; This pattern will only match if the one above did not.
5402(define_split
5403 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5404 (match_operand:ANY64 1 "const_double_operand" ""))]
5405 "TARGET_ARM && reload_completed
5406 && arm_const_double_by_parts (operands[1])"
5407 [(set (match_dup 0) (match_dup 1))
5408 (set (match_dup 2) (match_dup 3))]
5409 "
5410 operands[2] = gen_highpart (SImode, operands[0]);
5411 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5412 operands[1]);
5413 operands[0] = gen_lowpart (SImode, operands[0]);
5414 operands[1] = gen_lowpart (SImode, operands[1]);
5415 "
5416)
5417
5418(define_split
5419 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5420 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5421 "TARGET_EITHER && reload_completed"
5422 [(set (match_dup 0) (match_dup 1))
5423 (set (match_dup 2) (match_dup 3))]
5424 "
5425 operands[2] = gen_highpart (SImode, operands[0]);
5426 operands[3] = gen_highpart (SImode, operands[1]);
5427 operands[0] = gen_lowpart (SImode, operands[0]);
5428 operands[1] = gen_lowpart (SImode, operands[1]);
5429
5430 /* Handle a partial overlap. */
5431 if (rtx_equal_p (operands[0], operands[3]))
5432 {
5433 rtx tmp0 = operands[0];
5434 rtx tmp1 = operands[1];
5435
5436 operands[0] = operands[2];
5437 operands[1] = operands[3];
5438 operands[2] = tmp0;
5439 operands[3] = tmp1;
5440 }
5441 "
5442)
5443
5444;; We can't actually do base+index doubleword loads if the index and
5445;; destination overlap. Split here so that we at least have chance to
5446;; schedule.
5447(define_split
5448 [(set (match_operand:DI 0 "s_register_operand" "")
5449 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5450 (match_operand:SI 2 "s_register_operand" ""))))]
5451 "TARGET_LDRD
5452 && reg_overlap_mentioned_p (operands[0], operands[1])
5453 && reg_overlap_mentioned_p (operands[0], operands[2])"
5454 [(set (match_dup 4)
5455 (plus:SI (match_dup 1)
5456 (match_dup 2)))
5457 (set (match_dup 0)
5458 (mem:DI (match_dup 4)))]
5459 "
5460 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5461 "
5462)
5463
5464;;; ??? This should have alternatives for constants.
5465;;; ??? This was originally identical to the movdf_insn pattern.
5466;;; ??? The 'i' constraint looks funny, but it should always be replaced by
5467;;; thumb_reorg with a memory reference.
5468(define_insn "*thumb1_movdi_insn"
5469 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
5470 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
5471 "TARGET_THUMB1
5472 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
5473 && ( register_operand (operands[0], DImode)
5474 || register_operand (operands[1], DImode))"
5475 "*
5476 {
5477 switch (which_alternative)
5478 {
5479 default:
5480 case 0:
5481 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5482 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5483 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5484 case 1:
5485 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
5486 case 2:
5487 operands[1] = GEN_INT (- INTVAL (operands[1]));
5488 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
5489 case 3:
5490 return \"ldmia\\t%1, {%0, %H0}\";
5491 case 4:
5492 return \"stmia\\t%0, {%1, %H1}\";
5493 case 5:
5494 return thumb_load_double_from_address (operands);
5495 case 6:
5496 operands[2] = gen_rtx_MEM (SImode,
5497 plus_constant (Pmode, XEXP (operands[0], 0), 4));
5498 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5499 return \"\";
5500 case 7:
5501 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5502 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5503 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5504 }
5505 }"
5506 [(set_attr "length" "4,4,6,2,2,6,4,4")
5507 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
5508 (set_attr "insn" "*,mov,*,*,*,*,*,mov")
5509 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
5510)
5511
5512(define_expand "movsi"
5513 [(set (match_operand:SI 0 "general_operand" "")
5514 (match_operand:SI 1 "general_operand" ""))]
5515 "TARGET_EITHER"
5516 "
5517 {
5518 rtx base, offset, tmp;
5519
5520 if (TARGET_32BIT)
5521 {
5522 /* Everything except mem = const or mem = mem can be done easily. */
5523 if (GET_CODE (operands[0]) == MEM)
5524 operands[1] = force_reg (SImode, operands[1]);
5525 if (arm_general_register_operand (operands[0], SImode)
5526 && GET_CODE (operands[1]) == CONST_INT
5527 && !(const_ok_for_arm (INTVAL (operands[1]))
5528 || const_ok_for_arm (~INTVAL (operands[1]))))
5529 {
5530 arm_split_constant (SET, SImode, NULL_RTX,
5531 INTVAL (operands[1]), operands[0], NULL_RTX,
5532 optimize && can_create_pseudo_p ());
5533 DONE;
5534 }
5535
5536 if (TARGET_USE_MOVT && !target_word_relocations
5537 && GET_CODE (operands[1]) == SYMBOL_REF
5538 && !flag_pic && !arm_tls_referenced_p (operands[1]))
5539 {
5540 arm_emit_movpair (operands[0], operands[1]);
5541 DONE;
5542 }
5543 }
5544 else /* TARGET_THUMB1... */
5545 {
5546 if (can_create_pseudo_p ())
5547 {
5548 if (GET_CODE (operands[0]) != REG)
5549 operands[1] = force_reg (SImode, operands[1]);
5550 }
5551 }
5552
5553 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5554 {
5555 split_const (operands[1], &base, &offset);
5556 if (GET_CODE (base) == SYMBOL_REF
5557 && !offset_within_block_p (base, INTVAL (offset)))
5558 {
5559 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5560 emit_move_insn (tmp, base);
5561 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5562 DONE;
5563 }
5564 }
5565
5566 /* Recognize the case where operand[1] is a reference to thread-local
5567 data and load its address to a register. */
5568 if (arm_tls_referenced_p (operands[1]))
5569 {
5570 rtx tmp = operands[1];
5571 rtx addend = NULL;
5572
5573 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5574 {
5575 addend = XEXP (XEXP (tmp, 0), 1);
5576 tmp = XEXP (XEXP (tmp, 0), 0);
5577 }
5578
5579 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5580 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5581
5582 tmp = legitimize_tls_address (tmp,
5583 !can_create_pseudo_p () ? operands[0] : 0);
5584 if (addend)
5585 {
5586 tmp = gen_rtx_PLUS (SImode, tmp, addend);
5587 tmp = force_operand (tmp, operands[0]);
5588 }
5589 operands[1] = tmp;
5590 }
5591 else if (flag_pic
5592 && (CONSTANT_P (operands[1])
5593 || symbol_mentioned_p (operands[1])
5594 || label_mentioned_p (operands[1])))
5595 operands[1] = legitimize_pic_address (operands[1], SImode,
5596 (!can_create_pseudo_p ()
5597 ? operands[0]
5598 : 0));
5599 }
5600 "
5601)
5602
5603;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5604;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5605;; so this does not matter.
5606(define_insn "*arm_movt"
5607 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5608 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5609 (match_operand:SI 2 "general_operand" "i")))]
5610 "arm_arch_thumb2"
5611 "movt%?\t%0, #:upper16:%c2"
5612 [(set_attr "predicable" "yes")
5613 (set_attr "length" "4")]
5614)
5615
5616(define_insn "*arm_movsi_insn"
5617 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
5618 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
5619 "TARGET_ARM && ! TARGET_IWMMXT
5620 && !(TARGET_HARD_FLOAT && TARGET_VFP)
5621 && ( register_operand (operands[0], SImode)
5622 || register_operand (operands[1], SImode))"
5623 "@
5624 mov%?\\t%0, %1
5625 mov%?\\t%0, %1
5626 mvn%?\\t%0, #%B1
5627 movw%?\\t%0, %1
5628 ldr%?\\t%0, %1
5629 str%?\\t%1, %0"
5630 [(set_attr "type" "*,*,*,*,load1,store1")
5631 (set_attr "insn" "mov,mov,mvn,mov,*,*")
5632 (set_attr "predicable" "yes")
5633 (set_attr "pool_range" "*,*,*,*,4096,*")
5634 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
5635)
5636
5637(define_split
5638 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5639 (match_operand:SI 1 "const_int_operand" ""))]
5640 "TARGET_32BIT
5641 && (!(const_ok_for_arm (INTVAL (operands[1]))
5642 || const_ok_for_arm (~INTVAL (operands[1]))))"
5643 [(clobber (const_int 0))]
5644 "
5645 arm_split_constant (SET, SImode, NULL_RTX,
5646 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
5647 DONE;
5648 "
5649)
5650
5651(define_insn "*thumb1_movsi_insn"
5652 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*l*h*k")
5653 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*l*h*k"))]
5654 "TARGET_THUMB1
5655 && ( register_operand (operands[0], SImode)
5656 || register_operand (operands[1], SImode))"
5657 "@
5658 mov %0, %1
5659 mov %0, %1
5660 #
5661 #
5662 ldmia\\t%1, {%0}
5663 stmia\\t%0, {%1}
5664 ldr\\t%0, %1
5665 str\\t%1, %0
5666 mov\\t%0, %1"
5667 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
5668 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
5669 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")
5670 (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")])
5671
5672(define_split
5673 [(set (match_operand:SI 0 "register_operand" "")
5674 (match_operand:SI 1 "const_int_operand" ""))]
5675 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
5676 [(set (match_dup 2) (match_dup 1))
5677 (set (match_dup 0) (neg:SI (match_dup 2)))]
5678 "
5679 {
5680 operands[1] = GEN_INT (- INTVAL (operands[1]));
5681 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5682 }"
5683)
5684
5685(define_split
5686 [(set (match_operand:SI 0 "register_operand" "")
5687 (match_operand:SI 1 "const_int_operand" ""))]
5688 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
5689 [(set (match_dup 2) (match_dup 1))
5690 (set (match_dup 0) (ashift:SI (match_dup 2) (match_dup 3)))]
5691 "
5692 {
5693 unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
5694 unsigned HOST_WIDE_INT mask = 0xff;
5695 int i;
5696
5697 for (i = 0; i < 25; i++)
5698 if ((val & (mask << i)) == val)
5699 break;
5700
5701 /* Don't split if the shift is zero. */
5702 if (i == 0)
5703 FAIL;
5704
5705 operands[1] = GEN_INT (val >> i);
5706 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5707 operands[3] = GEN_INT (i);
5708 }"
5709)
5710
5711;; For thumb1 split imm move [256-510] into mov [1-255] and add #255
5712(define_split
5713 [(set (match_operand:SI 0 "register_operand" "")
5714 (match_operand:SI 1 "const_int_operand" ""))]
5715 "TARGET_THUMB1 && satisfies_constraint_Pe (operands[1])"
5716 [(set (match_dup 2) (match_dup 1))
5717 (set (match_dup 0) (plus:SI (match_dup 2) (match_dup 3)))]
5718 "
5719 {
5720 operands[1] = GEN_INT (INTVAL (operands[1]) - 255);
5721 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5722 operands[3] = GEN_INT (255);
5723 }"
5724)
5725
5726;; When generating pic, we need to load the symbol offset into a register.
5727;; So that the optimizer does not confuse this with a normal symbol load
5728;; we use an unspec. The offset will be loaded from a constant pool entry,
5729;; since that is the only type of relocation we can use.
5730
5731;; Wrap calculation of the whole PIC address in a single pattern for the
5732;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5733;; a PIC address involves two loads from memory, so we want to CSE it
5734;; as often as possible.
5735;; This pattern will be split into one of the pic_load_addr_* patterns
5736;; and a move after GCSE optimizations.
5737;;
5738;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5739(define_expand "calculate_pic_address"
5740 [(set (match_operand:SI 0 "register_operand" "")
5741 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5742 (unspec:SI [(match_operand:SI 2 "" "")]
5743 UNSPEC_PIC_SYM))))]
5744 "flag_pic"
5745)
5746
5747;; Split calculate_pic_address into pic_load_addr_* and a move.
5748(define_split
5749 [(set (match_operand:SI 0 "register_operand" "")
5750 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5751 (unspec:SI [(match_operand:SI 2 "" "")]
5752 UNSPEC_PIC_SYM))))]
5753 "flag_pic"
5754 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5755 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5756 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5757)
5758
5759;; operand1 is the memory address to go into
5760;; pic_load_addr_32bit.
5761;; operand2 is the PIC label to be emitted
5762;; from pic_add_dot_plus_eight.
5763;; We do this to allow hoisting of the entire insn.
5764(define_insn_and_split "pic_load_addr_unified"
5765 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
5766 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
5767 (match_operand:SI 2 "" "")]
5768 UNSPEC_PIC_UNIFIED))]
5769 "flag_pic"
5770 "#"
5771 "&& reload_completed"
5772 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
5773 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
5774 (match_dup 2)] UNSPEC_PIC_BASE))]
5775 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
5776 [(set_attr "type" "load1,load1,load1")
5777 (set_attr "pool_range" "4096,4096,1024")
5778 (set_attr "neg_pool_range" "4084,0,0")
5779 (set_attr "arch" "a,t2,t1")
5780 (set_attr "length" "8,6,4")]
5781)
5782
5783;; The rather odd constraints on the following are to force reload to leave
5784;; the insn alone, and to force the minipool generation pass to then move
5785;; the GOT symbol to memory.
5786
5787(define_insn "pic_load_addr_32bit"
5788 [(set (match_operand:SI 0 "s_register_operand" "=r")
5789 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5790 "TARGET_32BIT && flag_pic"
5791 "ldr%?\\t%0, %1"
5792 [(set_attr "type" "load1")
5793 (set_attr "pool_range" "4096")
5794 (set (attr "neg_pool_range")
5795 (if_then_else (eq_attr "is_thumb" "no")
5796 (const_int 4084)
5797 (const_int 0)))]
5798)
5799
5800(define_insn "pic_load_addr_thumb1"
5801 [(set (match_operand:SI 0 "s_register_operand" "=l")
5802 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5803 "TARGET_THUMB1 && flag_pic"
5804 "ldr\\t%0, %1"
5805 [(set_attr "type" "load1")
5806 (set (attr "pool_range") (const_int 1024))]
5807)
5808
5809(define_insn "pic_add_dot_plus_four"
5810 [(set (match_operand:SI 0 "register_operand" "=r")
5811 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5812 (const_int 4)
5813 (match_operand 2 "" "")]
5814 UNSPEC_PIC_BASE))]
5815 "TARGET_THUMB"
5816 "*
5817 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5818 INTVAL (operands[2]));
5819 return \"add\\t%0, %|pc\";
5820 "
5821 [(set_attr "length" "2")]
5822)
5823
5824(define_insn "pic_add_dot_plus_eight"
5825 [(set (match_operand:SI 0 "register_operand" "=r")
5826 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5827 (const_int 8)
5828 (match_operand 2 "" "")]
5829 UNSPEC_PIC_BASE))]
5830 "TARGET_ARM"
5831 "*
5832 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5833 INTVAL (operands[2]));
5834 return \"add%?\\t%0, %|pc, %1\";
5835 "
5836 [(set_attr "predicable" "yes")]
5837)
5838
5839(define_insn "tls_load_dot_plus_eight"
5840 [(set (match_operand:SI 0 "register_operand" "=r")
5841 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5842 (const_int 8)
5843 (match_operand 2 "" "")]
5844 UNSPEC_PIC_BASE)))]
5845 "TARGET_ARM"
5846 "*
5847 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5848 INTVAL (operands[2]));
5849 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5850 "
5851 [(set_attr "predicable" "yes")]
5852)
5853
5854;; PIC references to local variables can generate pic_add_dot_plus_eight
5855;; followed by a load. These sequences can be crunched down to
5856;; tls_load_dot_plus_eight by a peephole.
5857
5858(define_peephole2
5859 [(set (match_operand:SI 0 "register_operand" "")
5860 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5861 (const_int 8)
5862 (match_operand 1 "" "")]
5863 UNSPEC_PIC_BASE))
5864 (set (match_operand:SI 2 "arm_general_register_operand" "")
5865 (mem:SI (match_dup 0)))]
5866 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
5867 [(set (match_dup 2)
5868 (mem:SI (unspec:SI [(match_dup 3)
5869 (const_int 8)
5870 (match_dup 1)]
5871 UNSPEC_PIC_BASE)))]
5872 ""
5873)
5874
5875(define_insn "pic_offset_arm"
5876 [(set (match_operand:SI 0 "register_operand" "=r")
5877 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5878 (unspec:SI [(match_operand:SI 2 "" "X")]
5879 UNSPEC_PIC_OFFSET))))]
5880 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5881 "ldr%?\\t%0, [%1,%2]"
5882 [(set_attr "type" "load1")]
5883)
5884
5885(define_expand "builtin_setjmp_receiver"
5886 [(label_ref (match_operand 0 "" ""))]
5887 "flag_pic"
5888 "
5889{
5890 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5891 register. */
5892 if (arm_pic_register != INVALID_REGNUM)
5893 arm_load_pic_register (1UL << 3);
5894 DONE;
5895}")
5896
5897;; If copying one reg to another we can set the condition codes according to
5898;; its value. Such a move is common after a return from subroutine and the
5899;; result is being tested against zero.
5900
5901(define_insn "*movsi_compare0"
5902 [(set (reg:CC CC_REGNUM)
5903 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5904 (const_int 0)))
5905 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5906 (match_dup 1))]
5907 "TARGET_32BIT"
5908 "@
5909 cmp%?\\t%0, #0
5910 sub%.\\t%0, %1, #0"
5911 [(set_attr "conds" "set")]
5912)
5913
5914;; Subroutine to store a half word from a register into memory.
5915;; Operand 0 is the source register (HImode)
5916;; Operand 1 is the destination address in a register (SImode)
5917
5918;; In both this routine and the next, we must be careful not to spill
5919;; a memory address of reg+large_const into a separate PLUS insn, since this
5920;; can generate unrecognizable rtl.
5921
5922(define_expand "storehi"
5923 [;; store the low byte
5924 (set (match_operand 1 "" "") (match_dup 3))
5925 ;; extract the high byte
5926 (set (match_dup 2)
5927 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
5928 ;; store the high byte
5929 (set (match_dup 4) (match_dup 5))]
5930 "TARGET_ARM"
5931 "
5932 {
5933 rtx op1 = operands[1];
5934 rtx addr = XEXP (op1, 0);
5935 enum rtx_code code = GET_CODE (addr);
5936
5937 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5938 || code == MINUS)
5939 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
5940
5941 operands[4] = adjust_address (op1, QImode, 1);
5942 operands[1] = adjust_address (operands[1], QImode, 0);
5943 operands[3] = gen_lowpart (QImode, operands[0]);
5944 operands[0] = gen_lowpart (SImode, operands[0]);
5945 operands[2] = gen_reg_rtx (SImode);
5946 operands[5] = gen_lowpart (QImode, operands[2]);
5947 }"
5948)
5949
5950(define_expand "storehi_bigend"
5951 [(set (match_dup 4) (match_dup 3))
5952 (set (match_dup 2)
5953 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
5954 (set (match_operand 1 "" "") (match_dup 5))]
5955 "TARGET_ARM"
5956 "
5957 {
5958 rtx op1 = operands[1];
5959 rtx addr = XEXP (op1, 0);
5960 enum rtx_code code = GET_CODE (addr);
5961
5962 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5963 || code == MINUS)
5964 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
5965
5966 operands[4] = adjust_address (op1, QImode, 1);
5967 operands[1] = adjust_address (operands[1], QImode, 0);
5968 operands[3] = gen_lowpart (QImode, operands[0]);
5969 operands[0] = gen_lowpart (SImode, operands[0]);
5970 operands[2] = gen_reg_rtx (SImode);
5971 operands[5] = gen_lowpart (QImode, operands[2]);
5972 }"
5973)
5974
5975;; Subroutine to store a half word integer constant into memory.
5976(define_expand "storeinthi"
5977 [(set (match_operand 0 "" "")
5978 (match_operand 1 "" ""))
5979 (set (match_dup 3) (match_dup 2))]
5980 "TARGET_ARM"
5981 "
5982 {
5983 HOST_WIDE_INT value = INTVAL (operands[1]);
5984 rtx addr = XEXP (operands[0], 0);
5985 rtx op0 = operands[0];
5986 enum rtx_code code = GET_CODE (addr);
5987
5988 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5989 || code == MINUS)
5990 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
5991
5992 operands[1] = gen_reg_rtx (SImode);
5993 if (BYTES_BIG_ENDIAN)
5994 {
5995 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5996 if ((value & 255) == ((value >> 8) & 255))
5997 operands[2] = operands[1];
5998 else
5999 {
6000 operands[2] = gen_reg_rtx (SImode);
6001 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
6002 }
6003 }
6004 else
6005 {
6006 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
6007 if ((value & 255) == ((value >> 8) & 255))
6008 operands[2] = operands[1];
6009 else
6010 {
6011 operands[2] = gen_reg_rtx (SImode);
6012 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
6013 }
6014 }
6015
6016 operands[3] = adjust_address (op0, QImode, 1);
6017 operands[0] = adjust_address (operands[0], QImode, 0);
6018 operands[2] = gen_lowpart (QImode, operands[2]);
6019 operands[1] = gen_lowpart (QImode, operands[1]);
6020 }"
6021)
6022
6023(define_expand "storehi_single_op"
6024 [(set (match_operand:HI 0 "memory_operand" "")
6025 (match_operand:HI 1 "general_operand" ""))]
6026 "TARGET_32BIT && arm_arch4"
6027 "
6028 if (!s_register_operand (operands[1], HImode))
6029 operands[1] = copy_to_mode_reg (HImode, operands[1]);
6030 "
6031)
6032
6033(define_expand "movhi"
6034 [(set (match_operand:HI 0 "general_operand" "")
6035 (match_operand:HI 1 "general_operand" ""))]
6036 "TARGET_EITHER"
6037 "
6038 if (TARGET_ARM)
6039 {
6040 if (can_create_pseudo_p ())
6041 {
6042 if (GET_CODE (operands[0]) == MEM)
6043 {
6044 if (arm_arch4)
6045 {
6046 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
6047 DONE;
6048 }
6049 if (GET_CODE (operands[1]) == CONST_INT)
6050 emit_insn (gen_storeinthi (operands[0], operands[1]));
6051 else
6052 {
6053 if (GET_CODE (operands[1]) == MEM)
6054 operands[1] = force_reg (HImode, operands[1]);
6055 if (BYTES_BIG_ENDIAN)
6056 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
6057 else
6058 emit_insn (gen_storehi (operands[1], operands[0]));
6059 }
6060 DONE;
6061 }
6062 /* Sign extend a constant, and keep it in an SImode reg. */
6063 else if (GET_CODE (operands[1]) == CONST_INT)
6064 {
6065 rtx reg = gen_reg_rtx (SImode);
6066 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6067
6068 /* If the constant is already valid, leave it alone. */
6069 if (!const_ok_for_arm (val))
6070 {
6071 /* If setting all the top bits will make the constant
6072 loadable in a single instruction, then set them.
6073 Otherwise, sign extend the number. */
6074
6075 if (const_ok_for_arm (~(val | ~0xffff)))
6076 val |= ~0xffff;
6077 else if (val & 0x8000)
6078 val |= ~0xffff;
6079 }
6080
6081 emit_insn (gen_movsi (reg, GEN_INT (val)));
6082 operands[1] = gen_lowpart (HImode, reg);
6083 }
6084 else if (arm_arch4 && optimize && can_create_pseudo_p ()
6085 && GET_CODE (operands[1]) == MEM)
6086 {
6087 rtx reg = gen_reg_rtx (SImode);
6088
6089 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6090 operands[1] = gen_lowpart (HImode, reg);
6091 }
6092 else if (!arm_arch4)
6093 {
6094 if (GET_CODE (operands[1]) == MEM)
6095 {
6096 rtx base;
6097 rtx offset = const0_rtx;
6098 rtx reg = gen_reg_rtx (SImode);
6099
6100 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
6101 || (GET_CODE (base) == PLUS
6102 && (GET_CODE (offset = XEXP (base, 1))
6103 == CONST_INT)
6104 && ((INTVAL(offset) & 1) != 1)
6105 && GET_CODE (base = XEXP (base, 0)) == REG))
6106 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
6107 {
6108 rtx new_rtx;
6109
6110 new_rtx = widen_memory_access (operands[1], SImode,
6111 ((INTVAL (offset) & ~3)
6112 - INTVAL (offset)));
6113 emit_insn (gen_movsi (reg, new_rtx));
6114 if (((INTVAL (offset) & 2) != 0)
6115 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
6116 {
6117 rtx reg2 = gen_reg_rtx (SImode);
6118
6119 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
6120 reg = reg2;
6121 }
6122 }
6123 else
6124 emit_insn (gen_movhi_bytes (reg, operands[1]));
6125
6126 operands[1] = gen_lowpart (HImode, reg);
6127 }
6128 }
6129 }
6130 /* Handle loading a large integer during reload. */
6131 else if (GET_CODE (operands[1]) == CONST_INT
6132 && !const_ok_for_arm (INTVAL (operands[1]))
6133 && !const_ok_for_arm (~INTVAL (operands[1])))
6134 {
6135 /* Writing a constant to memory needs a scratch, which should
6136 be handled with SECONDARY_RELOADs. */
6137 gcc_assert (GET_CODE (operands[0]) == REG);
6138
6139 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6140 emit_insn (gen_movsi (operands[0], operands[1]));
6141 DONE;
6142 }
6143 }
6144 else if (TARGET_THUMB2)
6145 {
6146 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
6147 if (can_create_pseudo_p ())
6148 {
6149 if (GET_CODE (operands[0]) != REG)
6150 operands[1] = force_reg (HImode, operands[1]);
6151 /* Zero extend a constant, and keep it in an SImode reg. */
6152 else if (GET_CODE (operands[1]) == CONST_INT)
6153 {
6154 rtx reg = gen_reg_rtx (SImode);
6155 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6156
6157 emit_insn (gen_movsi (reg, GEN_INT (val)));
6158 operands[1] = gen_lowpart (HImode, reg);
6159 }
6160 }
6161 }
6162 else /* TARGET_THUMB1 */
6163 {
6164 if (can_create_pseudo_p ())
6165 {
6166 if (GET_CODE (operands[1]) == CONST_INT)
6167 {
6168 rtx reg = gen_reg_rtx (SImode);
6169
6170 emit_insn (gen_movsi (reg, operands[1]));
6171 operands[1] = gen_lowpart (HImode, reg);
6172 }
6173
6174 /* ??? We shouldn't really get invalid addresses here, but this can
6175 happen if we are passed a SP (never OK for HImode/QImode) or
6176 virtual register (also rejected as illegitimate for HImode/QImode)
6177 relative address. */
6178 /* ??? This should perhaps be fixed elsewhere, for instance, in
6179 fixup_stack_1, by checking for other kinds of invalid addresses,
6180 e.g. a bare reference to a virtual register. This may confuse the
6181 alpha though, which must handle this case differently. */
6182 if (GET_CODE (operands[0]) == MEM
6183 && !memory_address_p (GET_MODE (operands[0]),
6184 XEXP (operands[0], 0)))
6185 operands[0]
6186 = replace_equiv_address (operands[0],
6187 copy_to_reg (XEXP (operands[0], 0)));
6188
6189 if (GET_CODE (operands[1]) == MEM
6190 && !memory_address_p (GET_MODE (operands[1]),
6191 XEXP (operands[1], 0)))
6192 operands[1]
6193 = replace_equiv_address (operands[1],
6194 copy_to_reg (XEXP (operands[1], 0)));
6195
6196 if (GET_CODE (operands[1]) == MEM && optimize > 0)
6197 {
6198 rtx reg = gen_reg_rtx (SImode);
6199
6200 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6201 operands[1] = gen_lowpart (HImode, reg);
6202 }
6203
6204 if (GET_CODE (operands[0]) == MEM)
6205 operands[1] = force_reg (HImode, operands[1]);
6206 }
6207 else if (GET_CODE (operands[1]) == CONST_INT
6208 && !satisfies_constraint_I (operands[1]))
6209 {
6210 /* Handle loading a large integer during reload. */
6211
6212 /* Writing a constant to memory needs a scratch, which should
6213 be handled with SECONDARY_RELOADs. */
6214 gcc_assert (GET_CODE (operands[0]) == REG);
6215
6216 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6217 emit_insn (gen_movsi (operands[0], operands[1]));
6218 DONE;
6219 }
6220 }
6221 "
6222)
6223
6224(define_insn "*thumb1_movhi_insn"
6225 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
6226 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
6227 "TARGET_THUMB1
6228 && ( register_operand (operands[0], HImode)
6229 || register_operand (operands[1], HImode))"
6230 "*
6231 switch (which_alternative)
6232 {
6233 case 0: return \"add %0, %1, #0\";
6234 case 2: return \"strh %1, %0\";
6235 case 3: return \"mov %0, %1\";
6236 case 4: return \"mov %0, %1\";
6237 case 5: return \"mov %0, %1\";
6238 default: gcc_unreachable ();
6239 case 1:
6240 /* The stack pointer can end up being taken as an index register.
6241 Catch this case here and deal with it. */
6242 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
6243 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
6244 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
6245 {
6246 rtx ops[2];
6247 ops[0] = operands[0];
6248 ops[1] = XEXP (XEXP (operands[1], 0), 0);
6249
6250 output_asm_insn (\"mov %0, %1\", ops);
6251
6252 XEXP (XEXP (operands[1], 0), 0) = operands[0];
6253
6254 }
6255 return \"ldrh %0, %1\";
6256 }"
6257 [(set_attr "length" "2,4,2,2,2,2")
6258 (set_attr "type" "*,load1,store1,*,*,*")
6259 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
6260
6261
6262(define_expand "movhi_bytes"
6263 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
6264 (set (match_dup 3)
6265 (zero_extend:SI (match_dup 6)))
6266 (set (match_operand:SI 0 "" "")
6267 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
6268 "TARGET_ARM"
6269 "
6270 {
6271 rtx mem1, mem2;
6272 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6273
6274 mem1 = change_address (operands[1], QImode, addr);
6275 mem2 = change_address (operands[1], QImode,
6276 plus_constant (Pmode, addr, 1));
6277 operands[0] = gen_lowpart (SImode, operands[0]);
6278 operands[1] = mem1;
6279 operands[2] = gen_reg_rtx (SImode);
6280 operands[3] = gen_reg_rtx (SImode);
6281 operands[6] = mem2;
6282
6283 if (BYTES_BIG_ENDIAN)
6284 {
6285 operands[4] = operands[2];
6286 operands[5] = operands[3];
6287 }
6288 else
6289 {
6290 operands[4] = operands[3];
6291 operands[5] = operands[2];
6292 }
6293 }"
6294)
6295
6296(define_expand "movhi_bigend"
6297 [(set (match_dup 2)
6298 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
6299 (const_int 16)))
6300 (set (match_dup 3)
6301 (ashiftrt:SI (match_dup 2) (const_int 16)))
6302 (set (match_operand:HI 0 "s_register_operand" "")
6303 (match_dup 4))]
6304 "TARGET_ARM"
6305 "
6306 operands[2] = gen_reg_rtx (SImode);
6307 operands[3] = gen_reg_rtx (SImode);
6308 operands[4] = gen_lowpart (HImode, operands[3]);
6309 "
6310)
6311
6312;; Pattern to recognize insn generated default case above
6313(define_insn "*movhi_insn_arch4"
6314 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
6315 (match_operand:HI 1 "general_operand" "rI,K,r,mi"))]
6316 "TARGET_ARM
6317 && arm_arch4
6318 && (register_operand (operands[0], HImode)
6319 || register_operand (operands[1], HImode))"
6320 "@
6321 mov%?\\t%0, %1\\t%@ movhi
6322 mvn%?\\t%0, #%B1\\t%@ movhi
6323 str%(h%)\\t%1, %0\\t%@ movhi
6324 ldr%(h%)\\t%0, %1\\t%@ movhi"
6325 [(set_attr "type" "*,*,store1,load1")
6326 (set_attr "predicable" "yes")
6327 (set_attr "insn" "mov,mvn,*,*")
6328 (set_attr "pool_range" "*,*,*,256")
6329 (set_attr "neg_pool_range" "*,*,*,244")]
6330)
6331
6332(define_insn "*movhi_bytes"
6333 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
6334 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
6335 "TARGET_ARM"
6336 "@
6337 mov%?\\t%0, %1\\t%@ movhi
6338 mvn%?\\t%0, #%B1\\t%@ movhi"
6339 [(set_attr "predicable" "yes")
6340 (set_attr "insn" "mov,mvn")]
6341)
6342
6343(define_expand "thumb_movhi_clobber"
6344 [(set (match_operand:HI 0 "memory_operand" "")
6345 (match_operand:HI 1 "register_operand" ""))
6346 (clobber (match_operand:DI 2 "register_operand" ""))]
6347 "TARGET_THUMB1"
6348 "
6349 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
6350 && REGNO (operands[1]) <= LAST_LO_REGNUM)
6351 {
6352 emit_insn (gen_movhi (operands[0], operands[1]));
6353 DONE;
6354 }
6355 /* XXX Fixme, need to handle other cases here as well. */
6356 gcc_unreachable ();
6357 "
6358)
6359
6360;; We use a DImode scratch because we may occasionally need an additional
6361;; temporary if the address isn't offsettable -- push_reload doesn't seem
6362;; to take any notice of the "o" constraints on reload_memory_operand operand.
6363(define_expand "reload_outhi"
6364 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
6365 (match_operand:HI 1 "s_register_operand" "r")
6366 (match_operand:DI 2 "s_register_operand" "=&l")])]
6367 "TARGET_EITHER"
6368 "if (TARGET_ARM)
6369 arm_reload_out_hi (operands);
6370 else
6371 thumb_reload_out_hi (operands);
6372 DONE;
6373 "
6374)
6375
6376(define_expand "reload_inhi"
6377 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
6378 (match_operand:HI 1 "arm_reload_memory_operand" "o")
6379 (match_operand:DI 2 "s_register_operand" "=&r")])]
6380 "TARGET_EITHER"
6381 "
6382 if (TARGET_ARM)
6383 arm_reload_in_hi (operands);
6384 else
6385 thumb_reload_out_hi (operands);
6386 DONE;
6387")
6388
6389(define_expand "movqi"
6390 [(set (match_operand:QI 0 "general_operand" "")
6391 (match_operand:QI 1 "general_operand" ""))]
6392 "TARGET_EITHER"
6393 "
6394 /* Everything except mem = const or mem = mem can be done easily */
6395
6396 if (can_create_pseudo_p ())
6397 {
6398 if (GET_CODE (operands[1]) == CONST_INT)
6399 {
6400 rtx reg = gen_reg_rtx (SImode);
6401
6402 /* For thumb we want an unsigned immediate, then we are more likely
6403 to be able to use a movs insn. */
6404 if (TARGET_THUMB)
6405 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6406
6407 emit_insn (gen_movsi (reg, operands[1]));
6408 operands[1] = gen_lowpart (QImode, reg);
6409 }
6410
6411 if (TARGET_THUMB)
6412 {
6413 /* ??? We shouldn't really get invalid addresses here, but this can
6414 happen if we are passed a SP (never OK for HImode/QImode) or
6415 virtual register (also rejected as illegitimate for HImode/QImode)
6416 relative address. */
6417 /* ??? This should perhaps be fixed elsewhere, for instance, in
6418 fixup_stack_1, by checking for other kinds of invalid addresses,
6419 e.g. a bare reference to a virtual register. This may confuse the
6420 alpha though, which must handle this case differently. */
6421 if (GET_CODE (operands[0]) == MEM
6422 && !memory_address_p (GET_MODE (operands[0]),
6423 XEXP (operands[0], 0)))
6424 operands[0]
6425 = replace_equiv_address (operands[0],
6426 copy_to_reg (XEXP (operands[0], 0)));
6427 if (GET_CODE (operands[1]) == MEM
6428 && !memory_address_p (GET_MODE (operands[1]),
6429 XEXP (operands[1], 0)))
6430 operands[1]
6431 = replace_equiv_address (operands[1],
6432 copy_to_reg (XEXP (operands[1], 0)));
6433 }
6434
6435 if (GET_CODE (operands[1]) == MEM && optimize > 0)
6436 {
6437 rtx reg = gen_reg_rtx (SImode);
6438
6439 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6440 operands[1] = gen_lowpart (QImode, reg);
6441 }
6442
6443 if (GET_CODE (operands[0]) == MEM)
6444 operands[1] = force_reg (QImode, operands[1]);
6445 }
6446 else if (TARGET_THUMB
6447 && GET_CODE (operands[1]) == CONST_INT
6448 && !satisfies_constraint_I (operands[1]))
6449 {
6450 /* Handle loading a large integer during reload. */
6451
6452 /* Writing a constant to memory needs a scratch, which should
6453 be handled with SECONDARY_RELOADs. */
6454 gcc_assert (GET_CODE (operands[0]) == REG);
6455
6456 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6457 emit_insn (gen_movsi (operands[0], operands[1]));
6458 DONE;
6459 }
6460 "
6461)
6462
6463
6464(define_insn "*arm_movqi_insn"
6465 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,l,Uu,r,m")
6466 (match_operand:QI 1 "general_operand" "rI,K,Uu,l,m,r"))]
6467 "TARGET_32BIT
6468 && ( register_operand (operands[0], QImode)
6469 || register_operand (operands[1], QImode))"
6470 "@
6471 mov%?\\t%0, %1
6472 mvn%?\\t%0, #%B1
6473 ldr%(b%)\\t%0, %1
6474 str%(b%)\\t%1, %0
6475 ldr%(b%)\\t%0, %1
6476 str%(b%)\\t%1, %0"
6477 [(set_attr "type" "*,*,load1,store1,load1,store1")
6478 (set_attr "insn" "mov,mvn,*,*,*,*")
6479 (set_attr "predicable" "yes")
6480 (set_attr "arch" "any,any,t2,t2,any,any")
6481 (set_attr "length" "4,4,2,2,4,4")]
6482)
6483
6484(define_insn "*thumb1_movqi_insn"
6485 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
6486 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
6487 "TARGET_THUMB1
6488 && ( register_operand (operands[0], QImode)
6489 || register_operand (operands[1], QImode))"
6490 "@
6491 add\\t%0, %1, #0
6492 ldrb\\t%0, %1
6493 strb\\t%1, %0
6494 mov\\t%0, %1
6495 mov\\t%0, %1
6496 mov\\t%0, %1"
6497 [(set_attr "length" "2")
6498 (set_attr "type" "*,load1,store1,*,*,*")
6499 (set_attr "insn" "*,*,*,mov,mov,mov")
6500 (set_attr "pool_range" "*,32,*,*,*,*")
6501 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
6502
6503;; HFmode moves
6504(define_expand "movhf"
6505 [(set (match_operand:HF 0 "general_operand" "")
6506 (match_operand:HF 1 "general_operand" ""))]
6507 "TARGET_EITHER"
6508 "
6509 if (TARGET_32BIT)
6510 {
6511 if (GET_CODE (operands[0]) == MEM)
6512 operands[1] = force_reg (HFmode, operands[1]);
6513 }
6514 else /* TARGET_THUMB1 */
6515 {
6516 if (can_create_pseudo_p ())
6517 {
6518 if (GET_CODE (operands[0]) != REG)
6519 operands[1] = force_reg (HFmode, operands[1]);
6520 }
6521 }
6522 "
6523)
6524
6525(define_insn "*arm32_movhf"
6526 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6527 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
6528 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
6529 && ( s_register_operand (operands[0], HFmode)
6530 || s_register_operand (operands[1], HFmode))"
6531 "*
6532 switch (which_alternative)
6533 {
6534 case 0: /* ARM register from memory */
6535 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
6536 case 1: /* memory from ARM register */
6537 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
6538 case 2: /* ARM register from ARM register */
6539 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6540 case 3: /* ARM register from constant */
6541 {
6542 REAL_VALUE_TYPE r;
6543 long bits;
6544 rtx ops[4];
6545
6546 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
6547 bits = real_to_target (NULL, &r, HFmode);
6548 ops[0] = operands[0];
6549 ops[1] = GEN_INT (bits);
6550 ops[2] = GEN_INT (bits & 0xff00);
6551 ops[3] = GEN_INT (bits & 0x00ff);
6552
6553 if (arm_arch_thumb2)
6554 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6555 else
6556 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6557 return \"\";
6558 }
6559 default:
6560 gcc_unreachable ();
6561 }
6562 "
6563 [(set_attr "conds" "unconditional")
6564 (set_attr "type" "load1,store1,*,*")
6565 (set_attr "insn" "*,*,mov,mov")
6566 (set_attr "length" "4,4,4,8")
6567 (set_attr "predicable" "yes")]
6568)
6569
6570(define_insn "*thumb1_movhf"
6571 [(set (match_operand:HF 0 "nonimmediate_operand" "=l,l,m,*r,*h")
6572 (match_operand:HF 1 "general_operand" "l,mF,l,*h,*r"))]
6573 "TARGET_THUMB1
6574 && ( s_register_operand (operands[0], HFmode)
6575 || s_register_operand (operands[1], HFmode))"
6576 "*
6577 switch (which_alternative)
6578 {
6579 case 1:
6580 {
6581 rtx addr;
6582 gcc_assert (GET_CODE(operands[1]) == MEM);
6583 addr = XEXP (operands[1], 0);
6584 if (GET_CODE (addr) == LABEL_REF
6585 || (GET_CODE (addr) == CONST
6586 && GET_CODE (XEXP (addr, 0)) == PLUS
6587 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
6588 && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT))
6589 {
6590 /* Constant pool entry. */
6591 return \"ldr\\t%0, %1\";
6592 }
6593 return \"ldrh\\t%0, %1\";
6594 }
6595 case 2: return \"strh\\t%1, %0\";
6596 default: return \"mov\\t%0, %1\";
6597 }
6598 "
6599 [(set_attr "length" "2")
6600 (set_attr "type" "*,load1,store1,*,*")
6601 (set_attr "insn" "mov,*,*,mov,mov")
6602 (set_attr "pool_range" "*,1020,*,*,*")
6603 (set_attr "conds" "clob,nocond,nocond,nocond,nocond")])
6604
6605(define_expand "movsf"
6606 [(set (match_operand:SF 0 "general_operand" "")
6607 (match_operand:SF 1 "general_operand" ""))]
6608 "TARGET_EITHER"
6609 "
6610 if (TARGET_32BIT)
6611 {
6612 if (GET_CODE (operands[0]) == MEM)
6613 operands[1] = force_reg (SFmode, operands[1]);
6614 }
6615 else /* TARGET_THUMB1 */
6616 {
6617 if (can_create_pseudo_p ())
6618 {
6619 if (GET_CODE (operands[0]) != REG)
6620 operands[1] = force_reg (SFmode, operands[1]);
6621 }
6622 }
6623 "
6624)
6625
6626;; Transform a floating-point move of a constant into a core register into
6627;; an SImode operation.
6628(define_split
6629 [(set (match_operand:SF 0 "arm_general_register_operand" "")
6630 (match_operand:SF 1 "immediate_operand" ""))]
6631 "TARGET_EITHER
6632 && reload_completed
6633 && GET_CODE (operands[1]) == CONST_DOUBLE"
6634 [(set (match_dup 2) (match_dup 3))]
6635 "
6636 operands[2] = gen_lowpart (SImode, operands[0]);
6637 operands[3] = gen_lowpart (SImode, operands[1]);
6638 if (operands[2] == 0 || operands[3] == 0)
6639 FAIL;
6640 "
6641)
6642
6643(define_insn "*arm_movsf_soft_insn"
6644 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6645 (match_operand:SF 1 "general_operand" "r,mE,r"))]
6646 "TARGET_32BIT
6647 && TARGET_SOFT_FLOAT
6648 && (GET_CODE (operands[0]) != MEM
6649 || register_operand (operands[1], SFmode))"
6650 "@
6651 mov%?\\t%0, %1
6652 ldr%?\\t%0, %1\\t%@ float
6653 str%?\\t%1, %0\\t%@ float"
6654 [(set_attr "predicable" "yes")
6655 (set_attr "type" "*,load1,store1")
6656 (set_attr "insn" "mov,*,*")
6657 (set_attr "pool_range" "*,4096,*")
6658 (set_attr "arm_neg_pool_range" "*,4084,*")
6659 (set_attr "thumb2_neg_pool_range" "*,0,*")]
6660)
6661
6662;;; ??? This should have alternatives for constants.
6663(define_insn "*thumb1_movsf_insn"
6664 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
6665 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
6666 "TARGET_THUMB1
6667 && ( register_operand (operands[0], SFmode)
6668 || register_operand (operands[1], SFmode))"
6669 "@
6670 add\\t%0, %1, #0
6671 ldmia\\t%1, {%0}
6672 stmia\\t%0, {%1}
6673 ldr\\t%0, %1
6674 str\\t%1, %0
6675 mov\\t%0, %1
6676 mov\\t%0, %1"
6677 [(set_attr "length" "2")
6678 (set_attr "type" "*,load1,store1,load1,store1,*,*")
6679 (set_attr "pool_range" "*,*,*,1020,*,*,*")
6680 (set_attr "insn" "*,*,*,*,*,mov,mov")
6681 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,nocond,nocond")]
6682)
6683
6684(define_expand "movdf"
6685 [(set (match_operand:DF 0 "general_operand" "")
6686 (match_operand:DF 1 "general_operand" ""))]
6687 "TARGET_EITHER"
6688 "
6689 if (TARGET_32BIT)
6690 {
6691 if (GET_CODE (operands[0]) == MEM)
6692 operands[1] = force_reg (DFmode, operands[1]);
6693 }
6694 else /* TARGET_THUMB */
6695 {
6696 if (can_create_pseudo_p ())
6697 {
6698 if (GET_CODE (operands[0]) != REG)
6699 operands[1] = force_reg (DFmode, operands[1]);
6700 }
6701 }
6702 "
6703)
6704
6705;; Reloading a df mode value stored in integer regs to memory can require a
6706;; scratch reg.
6707(define_expand "reload_outdf"
6708 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
6709 (match_operand:DF 1 "s_register_operand" "r")
6710 (match_operand:SI 2 "s_register_operand" "=&r")]
6711 "TARGET_THUMB2"
6712 "
6713 {
6714 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
6715
6716 if (code == REG)
6717 operands[2] = XEXP (operands[0], 0);
6718 else if (code == POST_INC || code == PRE_DEC)
6719 {
6720 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6721 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6722 emit_insn (gen_movdi (operands[0], operands[1]));
6723 DONE;
6724 }
6725 else if (code == PRE_INC)
6726 {
6727 rtx reg = XEXP (XEXP (operands[0], 0), 0);
6728
6729 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6730 operands[2] = reg;
6731 }
6732 else if (code == POST_DEC)
6733 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6734 else
6735 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6736 XEXP (XEXP (operands[0], 0), 1)));
6737
6738 emit_insn (gen_rtx_SET (VOIDmode,
6739 replace_equiv_address (operands[0], operands[2]),
6740 operands[1]));
6741
6742 if (code == POST_DEC)
6743 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6744
6745 DONE;
6746 }"
6747)
6748
6749(define_insn "*movdf_soft_insn"
6750 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6751 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
6752 "TARGET_32BIT && TARGET_SOFT_FLOAT
6753 && ( register_operand (operands[0], DFmode)
6754 || register_operand (operands[1], DFmode))"
6755 "*
6756 switch (which_alternative)
6757 {
6758 case 0:
6759 case 1:
6760 case 2:
6761 return \"#\";
6762 default:
6763 return output_move_double (operands, true, NULL);
6764 }
6765 "
6766 [(set_attr "length" "8,12,16,8,8")
6767 (set_attr "type" "*,*,*,load2,store2")
6768 (set_attr "pool_range" "*,*,*,1020,*")
6769 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
6770 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
6771)
6772
6773;;; ??? This should have alternatives for constants.
6774;;; ??? This was originally identical to the movdi_insn pattern.
6775;;; ??? The 'F' constraint looks funny, but it should always be replaced by
6776;;; thumb_reorg with a memory reference.
6777(define_insn "*thumb_movdf_insn"
6778 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
6779 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
6780 "TARGET_THUMB1
6781 && ( register_operand (operands[0], DFmode)
6782 || register_operand (operands[1], DFmode))"
6783 "*
6784 switch (which_alternative)
6785 {
6786 default:
6787 case 0:
6788 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6789 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6790 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6791 case 1:
6792 return \"ldmia\\t%1, {%0, %H0}\";
6793 case 2:
6794 return \"stmia\\t%0, {%1, %H1}\";
6795 case 3:
6796 return thumb_load_double_from_address (operands);
6797 case 4:
6798 operands[2] = gen_rtx_MEM (SImode,
6799 plus_constant (Pmode,
6800 XEXP (operands[0], 0), 4));
6801 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6802 return \"\";
6803 case 5:
6804 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6805 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6806 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6807 }
6808 "
6809 [(set_attr "length" "4,2,2,6,4,4")
6810 (set_attr "type" "*,load2,store2,load2,store2,*")
6811 (set_attr "insn" "*,*,*,*,*,mov")
6812 (set_attr "pool_range" "*,*,*,1020,*,*")]
6813)
6814
6815(define_expand "movxf"
6816 [(set (match_operand:XF 0 "general_operand" "")
6817 (match_operand:XF 1 "general_operand" ""))]
6818 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
6819 "
6820 if (GET_CODE (operands[0]) == MEM)
6821 operands[1] = force_reg (XFmode, operands[1]);
6822 "
6823)
6824
6825\f
6826
6827;; load- and store-multiple insns
6828;; The arm can load/store any set of registers, provided that they are in
6829;; ascending order, but these expanders assume a contiguous set.
6830
6831(define_expand "load_multiple"
6832 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6833 (match_operand:SI 1 "" ""))
6834 (use (match_operand:SI 2 "" ""))])]
6835 "TARGET_32BIT"
6836{
6837 HOST_WIDE_INT offset = 0;
6838
6839 /* Support only fixed point registers. */
6840 if (GET_CODE (operands[2]) != CONST_INT
6841 || INTVAL (operands[2]) > 14
6842 || INTVAL (operands[2]) < 2
6843 || GET_CODE (operands[1]) != MEM
6844 || GET_CODE (operands[0]) != REG
6845 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6846 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
6847 FAIL;
6848
6849 operands[3]
6850 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6851 INTVAL (operands[2]),
6852 force_reg (SImode, XEXP (operands[1], 0)),
6853 FALSE, operands[1], &offset);
6854})
6855
6856(define_expand "store_multiple"
6857 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6858 (match_operand:SI 1 "" ""))
6859 (use (match_operand:SI 2 "" ""))])]
6860 "TARGET_32BIT"
6861{
6862 HOST_WIDE_INT offset = 0;
6863
6864 /* Support only fixed point registers. */
6865 if (GET_CODE (operands[2]) != CONST_INT
6866 || INTVAL (operands[2]) > 14
6867 || INTVAL (operands[2]) < 2
6868 || GET_CODE (operands[1]) != REG
6869 || GET_CODE (operands[0]) != MEM
6870 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6871 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
6872 FAIL;
6873
6874 operands[3]
6875 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6876 INTVAL (operands[2]),
6877 force_reg (SImode, XEXP (operands[0], 0)),
6878 FALSE, operands[0], &offset);
6879})
6880
6881
6882;; Move a block of memory if it is word aligned and MORE than 2 words long.
6883;; We could let this apply for blocks of less than this, but it clobbers so
6884;; many registers that there is then probably a better way.
6885
6886(define_expand "movmemqi"
6887 [(match_operand:BLK 0 "general_operand" "")
6888 (match_operand:BLK 1 "general_operand" "")
6889 (match_operand:SI 2 "const_int_operand" "")
6890 (match_operand:SI 3 "const_int_operand" "")]
6891 "TARGET_EITHER"
6892 "
6893 if (TARGET_32BIT)
6894 {
6895 if (arm_gen_movmemqi (operands))
6896 DONE;
6897 FAIL;
6898 }
6899 else /* TARGET_THUMB1 */
6900 {
6901 if ( INTVAL (operands[3]) != 4
6902 || INTVAL (operands[2]) > 48)
6903 FAIL;
6904
6905 thumb_expand_movmemqi (operands);
6906 DONE;
6907 }
6908 "
6909)
6910
6911;; Thumb block-move insns
6912
6913(define_insn "movmem12b"
6914 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6915 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6916 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6917 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6918 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6919 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6920 (set (match_operand:SI 0 "register_operand" "=l")
6921 (plus:SI (match_dup 2) (const_int 12)))
6922 (set (match_operand:SI 1 "register_operand" "=l")
6923 (plus:SI (match_dup 3) (const_int 12)))
6924 (clobber (match_scratch:SI 4 "=&l"))
6925 (clobber (match_scratch:SI 5 "=&l"))
6926 (clobber (match_scratch:SI 6 "=&l"))]
6927 "TARGET_THUMB1"
6928 "* return thumb_output_move_mem_multiple (3, operands);"
6929 [(set_attr "length" "4")
6930 ; This isn't entirely accurate... It loads as well, but in terms of
6931 ; scheduling the following insn it is better to consider it as a store
6932 (set_attr "type" "store3")]
6933)
6934
6935(define_insn "movmem8b"
6936 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6937 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6938 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6939 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6940 (set (match_operand:SI 0 "register_operand" "=l")
6941 (plus:SI (match_dup 2) (const_int 8)))
6942 (set (match_operand:SI 1 "register_operand" "=l")
6943 (plus:SI (match_dup 3) (const_int 8)))
6944 (clobber (match_scratch:SI 4 "=&l"))
6945 (clobber (match_scratch:SI 5 "=&l"))]
6946 "TARGET_THUMB1"
6947 "* return thumb_output_move_mem_multiple (2, operands);"
6948 [(set_attr "length" "4")
6949 ; This isn't entirely accurate... It loads as well, but in terms of
6950 ; scheduling the following insn it is better to consider it as a store
6951 (set_attr "type" "store2")]
6952)
6953
6954\f
6955
6956;; Compare & branch insns
6957;; The range calculations are based as follows:
6958;; For forward branches, the address calculation returns the address of
6959;; the next instruction. This is 2 beyond the branch instruction.
6960;; For backward branches, the address calculation returns the address of
6961;; the first instruction in this pattern (cmp). This is 2 before the branch
6962;; instruction for the shortest sequence, and 4 before the branch instruction
6963;; if we have to jump around an unconditional branch.
6964;; To the basic branch range the PC offset must be added (this is +4).
6965;; So for forward branches we have
6966;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6967;; And for backward branches we have
6968;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6969;;
6970;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6971;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
6972
6973(define_expand "cbranchsi4"
6974 [(set (pc) (if_then_else
6975 (match_operator 0 "expandable_comparison_operator"
6976 [(match_operand:SI 1 "s_register_operand" "")
6977 (match_operand:SI 2 "nonmemory_operand" "")])
6978 (label_ref (match_operand 3 "" ""))
6979 (pc)))]
6980 "TARGET_THUMB1 || TARGET_32BIT"
6981 "
6982 if (!TARGET_THUMB1)
6983 {
6984 if (!arm_add_operand (operands[2], SImode))
6985 operands[2] = force_reg (SImode, operands[2]);
6986 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6987 operands[3]));
6988 DONE;
6989 }
6990 if (thumb1_cmpneg_operand (operands[2], SImode))
6991 {
6992 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6993 operands[3], operands[0]));
6994 DONE;
6995 }
6996 if (!thumb1_cmp_operand (operands[2], SImode))
6997 operands[2] = force_reg (SImode, operands[2]);
6998 ")
6999
7000;; A pattern to recognize a special situation and optimize for it.
7001;; On the thumb, zero-extension from memory is preferrable to sign-extension
7002;; due to the available addressing modes. Hence, convert a signed comparison
7003;; with zero into an unsigned comparison with 127 if possible.
7004(define_expand "cbranchqi4"
7005 [(set (pc) (if_then_else
7006 (match_operator 0 "lt_ge_comparison_operator"
7007 [(match_operand:QI 1 "memory_operand" "")
7008 (match_operand:QI 2 "const0_operand" "")])
7009 (label_ref (match_operand 3 "" ""))
7010 (pc)))]
7011 "TARGET_THUMB1"
7012{
7013 rtx xops[4];
7014 xops[1] = gen_reg_rtx (SImode);
7015 emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
7016 xops[2] = GEN_INT (127);
7017 xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
7018 VOIDmode, xops[1], xops[2]);
7019 xops[3] = operands[3];
7020 emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
7021 DONE;
7022})
7023
7024(define_expand "cbranchsf4"
7025 [(set (pc) (if_then_else
7026 (match_operator 0 "expandable_comparison_operator"
7027 [(match_operand:SF 1 "s_register_operand" "")
7028 (match_operand:SF 2 "arm_float_compare_operand" "")])
7029 (label_ref (match_operand 3 "" ""))
7030 (pc)))]
7031 "TARGET_32BIT && TARGET_HARD_FLOAT"
7032 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7033 operands[3])); DONE;"
7034)
7035
7036(define_expand "cbranchdf4"
7037 [(set (pc) (if_then_else
7038 (match_operator 0 "expandable_comparison_operator"
7039 [(match_operand:DF 1 "s_register_operand" "")
7040 (match_operand:DF 2 "arm_float_compare_operand" "")])
7041 (label_ref (match_operand 3 "" ""))
7042 (pc)))]
7043 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
7044 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7045 operands[3])); DONE;"
7046)
7047
7048(define_expand "cbranchdi4"
7049 [(set (pc) (if_then_else
7050 (match_operator 0 "expandable_comparison_operator"
7051 [(match_operand:DI 1 "cmpdi_operand" "")
7052 (match_operand:DI 2 "cmpdi_operand" "")])
7053 (label_ref (match_operand 3 "" ""))
7054 (pc)))]
7055 "TARGET_32BIT"
7056 "{
7057 rtx swap = NULL_RTX;
7058 enum rtx_code code = GET_CODE (operands[0]);
7059
7060 /* We should not have two constants. */
7061 gcc_assert (GET_MODE (operands[1]) == DImode
7062 || GET_MODE (operands[2]) == DImode);
7063
7064 /* Flip unimplemented DImode comparisons to a form that
7065 arm_gen_compare_reg can handle. */
7066 switch (code)
7067 {
7068 case GT:
7069 swap = gen_rtx_LT (VOIDmode, operands[2], operands[1]); break;
7070 case LE:
7071 swap = gen_rtx_GE (VOIDmode, operands[2], operands[1]); break;
7072 case GTU:
7073 swap = gen_rtx_LTU (VOIDmode, operands[2], operands[1]); break;
7074 case LEU:
7075 swap = gen_rtx_GEU (VOIDmode, operands[2], operands[1]); break;
7076 default:
7077 break;
7078 }
7079 if (swap)
7080 emit_jump_insn (gen_cbranch_cc (swap, operands[2], operands[1],
7081 operands[3]));
7082 else
7083 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7084 operands[3]));
7085 DONE;
7086 }"
7087)
7088
7089(define_insn "cbranchsi4_insn"
7090 [(set (pc) (if_then_else
7091 (match_operator 0 "arm_comparison_operator"
7092 [(match_operand:SI 1 "s_register_operand" "l,l*h")
7093 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
7094 (label_ref (match_operand 3 "" ""))
7095 (pc)))]
7096 "TARGET_THUMB1"
7097{
7098 rtx t = cfun->machine->thumb1_cc_insn;
7099 if (t != NULL_RTX)
7100 {
7101 if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
7102 || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2]))
7103 t = NULL_RTX;
7104 if (cfun->machine->thumb1_cc_mode == CC_NOOVmode)
7105 {
7106 if (!noov_comparison_operator (operands[0], VOIDmode))
7107 t = NULL_RTX;
7108 }
7109 else if (cfun->machine->thumb1_cc_mode != CCmode)
7110 t = NULL_RTX;
7111 }
7112 if (t == NULL_RTX)
7113 {
7114 output_asm_insn ("cmp\t%1, %2", operands);
7115 cfun->machine->thumb1_cc_insn = insn;
7116 cfun->machine->thumb1_cc_op0 = operands[1];
7117 cfun->machine->thumb1_cc_op1 = operands[2];
7118 cfun->machine->thumb1_cc_mode = CCmode;
7119 }
7120 else
7121 /* Ensure we emit the right type of condition code on the jump. */
7122 XEXP (operands[0], 0) = gen_rtx_REG (cfun->machine->thumb1_cc_mode,
7123 CC_REGNUM);
7124
7125 switch (get_attr_length (insn))
7126 {
7127 case 4: return \"b%d0\\t%l3\";
7128 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7129 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7130 }
7131}
7132 [(set (attr "far_jump")
7133 (if_then_else
7134 (eq_attr "length" "8")
7135 (const_string "yes")
7136 (const_string "no")))
7137 (set (attr "length")
7138 (if_then_else
7139 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7140 (le (minus (match_dup 3) (pc)) (const_int 256)))
7141 (const_int 4)
7142 (if_then_else
7143 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7144 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7145 (const_int 6)
7146 (const_int 8))))]
7147)
7148
7149(define_insn "cbranchsi4_scratch"
7150 [(set (pc) (if_then_else
7151 (match_operator 4 "arm_comparison_operator"
7152 [(match_operand:SI 1 "s_register_operand" "l,0")
7153 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
7154 (label_ref (match_operand 3 "" ""))
7155 (pc)))
7156 (clobber (match_scratch:SI 0 "=l,l"))]
7157 "TARGET_THUMB1"
7158 "*
7159 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
7160
7161 switch (get_attr_length (insn))
7162 {
7163 case 4: return \"b%d4\\t%l3\";
7164 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7165 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7166 }
7167 "
7168 [(set (attr "far_jump")
7169 (if_then_else
7170 (eq_attr "length" "8")
7171 (const_string "yes")
7172 (const_string "no")))
7173 (set (attr "length")
7174 (if_then_else
7175 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7176 (le (minus (match_dup 3) (pc)) (const_int 256)))
7177 (const_int 4)
7178 (if_then_else
7179 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7180 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7181 (const_int 6)
7182 (const_int 8))))]
7183)
7184
7185;; Two peepholes to generate subtract of 0 instead of a move if the
7186;; condition codes will be useful.
7187(define_peephole2
7188 [(set (match_operand:SI 0 "low_register_operand" "")
7189 (match_operand:SI 1 "low_register_operand" ""))
7190 (set (pc)
7191 (if_then_else (match_operator 2 "arm_comparison_operator"
7192 [(match_dup 1) (const_int 0)])
7193 (label_ref (match_operand 3 "" ""))
7194 (pc)))]
7195 "TARGET_THUMB1"
7196 [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
7197 (set (pc)
7198 (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
7199 (label_ref (match_dup 3))
7200 (pc)))]
7201 "")
7202
7203;; Sigh! This variant shouldn't be needed, but combine often fails to
7204;; merge cases like this because the op1 is a hard register in
7205;; arm_class_likely_spilled_p.
7206(define_peephole2
7207 [(set (match_operand:SI 0 "low_register_operand" "")
7208 (match_operand:SI 1 "low_register_operand" ""))
7209 (set (pc)
7210 (if_then_else (match_operator 2 "arm_comparison_operator"
7211 [(match_dup 0) (const_int 0)])
7212 (label_ref (match_operand 3 "" ""))
7213 (pc)))]
7214 "TARGET_THUMB1"
7215 [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
7216 (set (pc)
7217 (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
7218 (label_ref (match_dup 3))
7219 (pc)))]
7220 "")
7221
7222(define_insn "*negated_cbranchsi4"
7223 [(set (pc)
7224 (if_then_else
7225 (match_operator 0 "equality_operator"
7226 [(match_operand:SI 1 "s_register_operand" "l")
7227 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
7228 (label_ref (match_operand 3 "" ""))
7229 (pc)))]
7230 "TARGET_THUMB1"
7231 "*
7232 output_asm_insn (\"cmn\\t%1, %2\", operands);
7233 switch (get_attr_length (insn))
7234 {
7235 case 4: return \"b%d0\\t%l3\";
7236 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7237 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7238 }
7239 "
7240 [(set (attr "far_jump")
7241 (if_then_else
7242 (eq_attr "length" "8")
7243 (const_string "yes")
7244 (const_string "no")))
7245 (set (attr "length")
7246 (if_then_else
7247 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7248 (le (minus (match_dup 3) (pc)) (const_int 256)))
7249 (const_int 4)
7250 (if_then_else
7251 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7252 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7253 (const_int 6)
7254 (const_int 8))))]
7255)
7256
7257(define_insn "*tbit_cbranch"
7258 [(set (pc)
7259 (if_then_else
7260 (match_operator 0 "equality_operator"
7261 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
7262 (const_int 1)
7263 (match_operand:SI 2 "const_int_operand" "i"))
7264 (const_int 0)])
7265 (label_ref (match_operand 3 "" ""))
7266 (pc)))
7267 (clobber (match_scratch:SI 4 "=l"))]
7268 "TARGET_THUMB1"
7269 "*
7270 {
7271 rtx op[3];
7272 op[0] = operands[4];
7273 op[1] = operands[1];
7274 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
7275
7276 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
7277 switch (get_attr_length (insn))
7278 {
7279 case 4: return \"b%d0\\t%l3\";
7280 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7281 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7282 }
7283 }"
7284 [(set (attr "far_jump")
7285 (if_then_else
7286 (eq_attr "length" "8")
7287 (const_string "yes")
7288 (const_string "no")))
7289 (set (attr "length")
7290 (if_then_else
7291 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7292 (le (minus (match_dup 3) (pc)) (const_int 256)))
7293 (const_int 4)
7294 (if_then_else
7295 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7296 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7297 (const_int 6)
7298 (const_int 8))))]
7299)
7300
7301(define_insn "*tlobits_cbranch"
7302 [(set (pc)
7303 (if_then_else
7304 (match_operator 0 "equality_operator"
7305 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
7306 (match_operand:SI 2 "const_int_operand" "i")
7307 (const_int 0))
7308 (const_int 0)])
7309 (label_ref (match_operand 3 "" ""))
7310 (pc)))
7311 (clobber (match_scratch:SI 4 "=l"))]
7312 "TARGET_THUMB1"
7313 "*
7314 {
7315 rtx op[3];
7316 op[0] = operands[4];
7317 op[1] = operands[1];
7318 op[2] = GEN_INT (32 - INTVAL (operands[2]));
7319
7320 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
7321 switch (get_attr_length (insn))
7322 {
7323 case 4: return \"b%d0\\t%l3\";
7324 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7325 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7326 }
7327 }"
7328 [(set (attr "far_jump")
7329 (if_then_else
7330 (eq_attr "length" "8")
7331 (const_string "yes")
7332 (const_string "no")))
7333 (set (attr "length")
7334 (if_then_else
7335 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7336 (le (minus (match_dup 3) (pc)) (const_int 256)))
7337 (const_int 4)
7338 (if_then_else
7339 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7340 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7341 (const_int 6)
7342 (const_int 8))))]
7343)
7344
7345(define_insn "*tstsi3_cbranch"
7346 [(set (pc)
7347 (if_then_else
7348 (match_operator 3 "equality_operator"
7349 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
7350 (match_operand:SI 1 "s_register_operand" "l"))
7351 (const_int 0)])
7352 (label_ref (match_operand 2 "" ""))
7353 (pc)))]
7354 "TARGET_THUMB1"
7355 "*
7356 {
7357 output_asm_insn (\"tst\\t%0, %1\", operands);
7358 switch (get_attr_length (insn))
7359 {
7360 case 4: return \"b%d3\\t%l2\";
7361 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
7362 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
7363 }
7364 }"
7365 [(set (attr "far_jump")
7366 (if_then_else
7367 (eq_attr "length" "8")
7368 (const_string "yes")
7369 (const_string "no")))
7370 (set (attr "length")
7371 (if_then_else
7372 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
7373 (le (minus (match_dup 2) (pc)) (const_int 256)))
7374 (const_int 4)
7375 (if_then_else
7376 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
7377 (le (minus (match_dup 2) (pc)) (const_int 2048)))
7378 (const_int 6)
7379 (const_int 8))))]
7380)
7381
7382(define_insn "*cbranchne_decr1"
7383 [(set (pc)
7384 (if_then_else (match_operator 3 "equality_operator"
7385 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
7386 (const_int 0)])
7387 (label_ref (match_operand 4 "" ""))
7388 (pc)))
7389 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
7390 (plus:SI (match_dup 2) (const_int -1)))
7391 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
7392 "TARGET_THUMB1"
7393 "*
7394 {
7395 rtx cond[2];
7396 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
7397 ? GEU : LTU),
7398 VOIDmode, operands[2], const1_rtx);
7399 cond[1] = operands[4];
7400
7401 if (which_alternative == 0)
7402 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
7403 else if (which_alternative == 1)
7404 {
7405 /* We must provide an alternative for a hi reg because reload
7406 cannot handle output reloads on a jump instruction, but we
7407 can't subtract into that. Fortunately a mov from lo to hi
7408 does not clobber the condition codes. */
7409 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7410 output_asm_insn (\"mov\\t%0, %1\", operands);
7411 }
7412 else
7413 {
7414 /* Similarly, but the target is memory. */
7415 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7416 output_asm_insn (\"str\\t%1, %0\", operands);
7417 }
7418
7419 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7420 {
7421 case 4:
7422 output_asm_insn (\"b%d0\\t%l1\", cond);
7423 return \"\";
7424 case 6:
7425 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
7426 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
7427 default:
7428 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
7429 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7430 }
7431 }
7432 "
7433 [(set (attr "far_jump")
7434 (if_then_else
7435 (ior (and (eq (symbol_ref ("which_alternative"))
7436 (const_int 0))
7437 (eq_attr "length" "8"))
7438 (eq_attr "length" "10"))
7439 (const_string "yes")
7440 (const_string "no")))
7441 (set_attr_alternative "length"
7442 [
7443 ;; Alternative 0
7444 (if_then_else
7445 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7446 (le (minus (match_dup 4) (pc)) (const_int 256)))
7447 (const_int 4)
7448 (if_then_else
7449 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7450 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7451 (const_int 6)
7452 (const_int 8)))
7453 ;; Alternative 1
7454 (if_then_else
7455 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7456 (le (minus (match_dup 4) (pc)) (const_int 256)))
7457 (const_int 6)
7458 (if_then_else
7459 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7460 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7461 (const_int 8)
7462 (const_int 10)))
7463 ;; Alternative 2
7464 (if_then_else
7465 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7466 (le (minus (match_dup 4) (pc)) (const_int 256)))
7467 (const_int 6)
7468 (if_then_else
7469 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7470 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7471 (const_int 8)
7472 (const_int 10)))
7473 ;; Alternative 3
7474 (if_then_else
7475 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7476 (le (minus (match_dup 4) (pc)) (const_int 256)))
7477 (const_int 6)
7478 (if_then_else
7479 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7480 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7481 (const_int 8)
7482 (const_int 10)))])]
7483)
7484
7485(define_insn "*addsi3_cbranch"
7486 [(set (pc)
7487 (if_then_else
7488 (match_operator 4 "arm_comparison_operator"
7489 [(plus:SI
7490 (match_operand:SI 2 "s_register_operand" "%0,l,*l,1,1,1")
7491 (match_operand:SI 3 "reg_or_int_operand" "IJ,lL,*l,lIJ,lIJ,lIJ"))
7492 (const_int 0)])
7493 (label_ref (match_operand 5 "" ""))
7494 (pc)))
7495 (set
7496 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
7497 (plus:SI (match_dup 2) (match_dup 3)))
7498 (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
7499 "TARGET_THUMB1
7500 && (GET_CODE (operands[4]) == EQ
7501 || GET_CODE (operands[4]) == NE
7502 || GET_CODE (operands[4]) == GE
7503 || GET_CODE (operands[4]) == LT)"
7504 "*
7505 {
7506 rtx cond[3];
7507
7508 cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
7509 cond[1] = operands[2];
7510 cond[2] = operands[3];
7511
7512 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
7513 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
7514 else
7515 output_asm_insn (\"add\\t%0, %1, %2\", cond);
7516
7517 if (which_alternative >= 2
7518 && which_alternative < 4)
7519 output_asm_insn (\"mov\\t%0, %1\", operands);
7520 else if (which_alternative >= 4)
7521 output_asm_insn (\"str\\t%1, %0\", operands);
7522
7523 switch (get_attr_length (insn) - ((which_alternative >= 2) ? 2 : 0))
7524 {
7525 case 4:
7526 return \"b%d4\\t%l5\";
7527 case 6:
7528 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7529 default:
7530 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7531 }
7532 }
7533 "
7534 [(set (attr "far_jump")
7535 (if_then_else
7536 (ior (and (lt (symbol_ref ("which_alternative"))
7537 (const_int 2))
7538 (eq_attr "length" "8"))
7539 (eq_attr "length" "10"))
7540 (const_string "yes")
7541 (const_string "no")))
7542 (set (attr "length")
7543 (if_then_else
7544 (lt (symbol_ref ("which_alternative"))
7545 (const_int 2))
7546 (if_then_else
7547 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7548 (le (minus (match_dup 5) (pc)) (const_int 256)))
7549 (const_int 4)
7550 (if_then_else
7551 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7552 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7553 (const_int 6)
7554 (const_int 8)))
7555 (if_then_else
7556 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7557 (le (minus (match_dup 5) (pc)) (const_int 256)))
7558 (const_int 6)
7559 (if_then_else
7560 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7561 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7562 (const_int 8)
7563 (const_int 10)))))]
7564)
7565
7566(define_insn "*addsi3_cbranch_scratch"
7567 [(set (pc)
7568 (if_then_else
7569 (match_operator 3 "arm_comparison_operator"
7570 [(plus:SI
7571 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
7572 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
7573 (const_int 0)])
7574 (label_ref (match_operand 4 "" ""))
7575 (pc)))
7576 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
7577 "TARGET_THUMB1
7578 && (GET_CODE (operands[3]) == EQ
7579 || GET_CODE (operands[3]) == NE
7580 || GET_CODE (operands[3]) == GE
7581 || GET_CODE (operands[3]) == LT)"
7582 "*
7583 {
7584 switch (which_alternative)
7585 {
7586 case 0:
7587 output_asm_insn (\"cmp\t%1, #%n2\", operands);
7588 break;
7589 case 1:
7590 output_asm_insn (\"cmn\t%1, %2\", operands);
7591 break;
7592 case 2:
7593 if (INTVAL (operands[2]) < 0)
7594 output_asm_insn (\"sub\t%0, %1, %2\", operands);
7595 else
7596 output_asm_insn (\"add\t%0, %1, %2\", operands);
7597 break;
7598 case 3:
7599 if (INTVAL (operands[2]) < 0)
7600 output_asm_insn (\"sub\t%0, %0, %2\", operands);
7601 else
7602 output_asm_insn (\"add\t%0, %0, %2\", operands);
7603 break;
7604 }
7605
7606 switch (get_attr_length (insn))
7607 {
7608 case 4:
7609 return \"b%d3\\t%l4\";
7610 case 6:
7611 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7612 default:
7613 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7614 }
7615 }
7616 "
7617 [(set (attr "far_jump")
7618 (if_then_else
7619 (eq_attr "length" "8")
7620 (const_string "yes")
7621 (const_string "no")))
7622 (set (attr "length")
7623 (if_then_else
7624 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7625 (le (minus (match_dup 4) (pc)) (const_int 256)))
7626 (const_int 4)
7627 (if_then_else
7628 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7629 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7630 (const_int 6)
7631 (const_int 8))))]
7632)
7633
7634
7635;; Comparison and test insns
7636
7637(define_insn "*arm_cmpsi_insn"
7638 [(set (reg:CC CC_REGNUM)
7639 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r")
7640 (match_operand:SI 1 "arm_add_operand" "Py,r,rI,L")))]
7641 "TARGET_32BIT"
7642 "@
7643 cmp%?\\t%0, %1
7644 cmp%?\\t%0, %1
7645 cmp%?\\t%0, %1
7646 cmn%?\\t%0, #%n1"
7647 [(set_attr "conds" "set")
7648 (set_attr "arch" "t2,t2,any,any")
7649 (set_attr "length" "2,2,4,4")
7650 (set_attr "predicable" "yes")]
7651)
7652
7653(define_insn "*cmpsi_shiftsi"
7654 [(set (reg:CC CC_REGNUM)
7655 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
7656 (match_operator:SI 3 "shift_operator"
7657 [(match_operand:SI 1 "s_register_operand" "r,r")
7658 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
7659 "TARGET_32BIT"
7660 "cmp%?\\t%0, %1%S3"
7661 [(set_attr "conds" "set")
7662 (set_attr "shift" "1")
7663 (set_attr "arch" "32,a")
7664 (set_attr "type" "alu_shift,alu_shift_reg")])
7665
7666(define_insn "*cmpsi_shiftsi_swp"
7667 [(set (reg:CC_SWP CC_REGNUM)
7668 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
7669 [(match_operand:SI 1 "s_register_operand" "r,r")
7670 (match_operand:SI 2 "shift_amount_operand" "M,rM")])
7671 (match_operand:SI 0 "s_register_operand" "r,r")))]
7672 "TARGET_32BIT"
7673 "cmp%?\\t%0, %1%S3"
7674 [(set_attr "conds" "set")
7675 (set_attr "shift" "1")
7676 (set_attr "arch" "32,a")
7677 (set_attr "type" "alu_shift,alu_shift_reg")])
7678
7679(define_insn "*arm_cmpsi_negshiftsi_si"
7680 [(set (reg:CC_Z CC_REGNUM)
7681 (compare:CC_Z
7682 (neg:SI (match_operator:SI 1 "shift_operator"
7683 [(match_operand:SI 2 "s_register_operand" "r")
7684 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7685 (match_operand:SI 0 "s_register_operand" "r")))]
7686 "TARGET_ARM"
7687 "cmn%?\\t%0, %2%S1"
7688 [(set_attr "conds" "set")
7689 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7690 (const_string "alu_shift")
7691 (const_string "alu_shift_reg")))
7692 (set_attr "predicable" "yes")]
7693)
7694
7695;; DImode comparisons. The generic code generates branches that
7696;; if-conversion can not reduce to a conditional compare, so we do
7697;; that directly.
7698
7699(define_insn "*arm_cmpdi_insn"
7700 [(set (reg:CC_NCV CC_REGNUM)
7701 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7702 (match_operand:DI 1 "arm_di_operand" "rDi")))
7703 (clobber (match_scratch:SI 2 "=r"))]
7704 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
7705 "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7706 [(set_attr "conds" "set")
7707 (set_attr "length" "8")]
7708)
7709
7710(define_insn "*arm_cmpdi_unsigned"
7711 [(set (reg:CC_CZ CC_REGNUM)
7712 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "r")
7713 (match_operand:DI 1 "arm_di_operand" "rDi")))]
7714 "TARGET_32BIT"
7715 "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
7716 [(set_attr "conds" "set")
7717 (set_attr "length" "8")]
7718)
7719
7720(define_insn "*arm_cmpdi_zero"
7721 [(set (reg:CC_Z CC_REGNUM)
7722 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7723 (const_int 0)))
7724 (clobber (match_scratch:SI 1 "=r"))]
7725 "TARGET_32BIT"
7726 "orr%.\\t%1, %Q0, %R0"
7727 [(set_attr "conds" "set")]
7728)
7729
7730(define_insn "*thumb_cmpdi_zero"
7731 [(set (reg:CC_Z CC_REGNUM)
7732 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
7733 (const_int 0)))
7734 (clobber (match_scratch:SI 1 "=l"))]
7735 "TARGET_THUMB1"
7736 "orr\\t%1, %Q0, %R0"
7737 [(set_attr "conds" "set")
7738 (set_attr "length" "2")]
7739)
7740
7741;; Cirrus SF compare instruction
7742(define_insn "*cirrus_cmpsf"
7743 [(set (reg:CCFP CC_REGNUM)
7744 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7745 (match_operand:SF 1 "cirrus_fp_register" "v")))]
7746 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7747 "cfcmps%?\\tr15, %V0, %V1"
7748 [(set_attr "type" "mav_farith")
7749 (set_attr "cirrus" "compare")]
7750)
7751
7752;; Cirrus DF compare instruction
7753(define_insn "*cirrus_cmpdf"
7754 [(set (reg:CCFP CC_REGNUM)
7755 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7756 (match_operand:DF 1 "cirrus_fp_register" "v")))]
7757 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7758 "cfcmpd%?\\tr15, %V0, %V1"
7759 [(set_attr "type" "mav_farith")
7760 (set_attr "cirrus" "compare")]
7761)
7762
7763(define_insn "*cirrus_cmpdi"
7764 [(set (reg:CC CC_REGNUM)
7765 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7766 (match_operand:DI 1 "cirrus_fp_register" "v")))]
7767 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7768 "cfcmp64%?\\tr15, %V0, %V1"
7769 [(set_attr "type" "mav_farith")
7770 (set_attr "cirrus" "compare")]
7771)
7772
7773; This insn allows redundant compares to be removed by cse, nothing should
7774; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7775; is deleted later on. The match_dup will match the mode here, so that
7776; mode changes of the condition codes aren't lost by this even though we don't
7777; specify what they are.
7778
7779(define_insn "*deleted_compare"
7780 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
7781 "TARGET_32BIT"
7782 "\\t%@ deleted compare"
7783 [(set_attr "conds" "set")
7784 (set_attr "length" "0")]
7785)
7786
7787\f
7788;; Conditional branch insns
7789
7790(define_expand "cbranch_cc"
7791 [(set (pc)
7792 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7793 (match_operand 2 "" "")])
7794 (label_ref (match_operand 3 "" ""))
7795 (pc)))]
7796 "TARGET_32BIT"
7797 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
7798 operands[1], operands[2], NULL_RTX);
7799 operands[2] = const0_rtx;"
7800)
7801
7802;;
7803;; Patterns to match conditional branch insns.
7804;;
7805
7806(define_insn "arm_cond_branch"
7807 [(set (pc)
7808 (if_then_else (match_operator 1 "arm_comparison_operator"
7809 [(match_operand 2 "cc_register" "") (const_int 0)])
7810 (label_ref (match_operand 0 "" ""))
7811 (pc)))]
7812 "TARGET_32BIT"
7813 "*
7814 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7815 {
7816 arm_ccfsm_state += 2;
7817 return \"\";
7818 }
7819 return \"b%d1\\t%l0\";
7820 "
7821 [(set_attr "conds" "use")
7822 (set_attr "type" "branch")
7823 (set (attr "length")
7824 (if_then_else
7825 (and (match_test "TARGET_THUMB2")
7826 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7827 (le (minus (match_dup 0) (pc)) (const_int 256))))
7828 (const_int 2)
7829 (const_int 4)))]
7830)
7831
7832(define_insn "*arm_cond_branch_reversed"
7833 [(set (pc)
7834 (if_then_else (match_operator 1 "arm_comparison_operator"
7835 [(match_operand 2 "cc_register" "") (const_int 0)])
7836 (pc)
7837 (label_ref (match_operand 0 "" ""))))]
7838 "TARGET_32BIT"
7839 "*
7840 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7841 {
7842 arm_ccfsm_state += 2;
7843 return \"\";
7844 }
7845 return \"b%D1\\t%l0\";
7846 "
7847 [(set_attr "conds" "use")
7848 (set_attr "type" "branch")
7849 (set (attr "length")
7850 (if_then_else
7851 (and (match_test "TARGET_THUMB2")
7852 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7853 (le (minus (match_dup 0) (pc)) (const_int 256))))
7854 (const_int 2)
7855 (const_int 4)))]
7856)
7857
7858\f
7859
7860; scc insns
7861
7862(define_expand "cstore_cc"
7863 [(set (match_operand:SI 0 "s_register_operand" "")
7864 (match_operator:SI 1 "" [(match_operand 2 "" "")
7865 (match_operand 3 "" "")]))]
7866 "TARGET_32BIT"
7867 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7868 operands[2], operands[3], NULL_RTX);
7869 operands[3] = const0_rtx;"
7870)
7871
7872(define_insn "*mov_scc"
7873 [(set (match_operand:SI 0 "s_register_operand" "=r")
7874 (match_operator:SI 1 "arm_comparison_operator"
7875 [(match_operand 2 "cc_register" "") (const_int 0)]))]
7876 "TARGET_ARM"
7877 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7878 [(set_attr "conds" "use")
7879 (set_attr "insn" "mov")
7880 (set_attr "length" "8")]
7881)
7882
7883(define_insn "*mov_negscc"
7884 [(set (match_operand:SI 0 "s_register_operand" "=r")
7885 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7886 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7887 "TARGET_ARM"
7888 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7889 [(set_attr "conds" "use")
7890 (set_attr "insn" "mov")
7891 (set_attr "length" "8")]
7892)
7893
7894(define_insn "*mov_notscc"
7895 [(set (match_operand:SI 0 "s_register_operand" "=r")
7896 (not:SI (match_operator:SI 1 "arm_comparison_operator"
7897 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7898 "TARGET_ARM"
7899 "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7900 [(set_attr "conds" "use")
7901 (set_attr "insn" "mov")
7902 (set_attr "length" "8")]
7903)
7904
7905(define_expand "cstoresi4"
7906 [(set (match_operand:SI 0 "s_register_operand" "")
7907 (match_operator:SI 1 "expandable_comparison_operator"
7908 [(match_operand:SI 2 "s_register_operand" "")
7909 (match_operand:SI 3 "reg_or_int_operand" "")]))]
7910 "TARGET_32BIT || TARGET_THUMB1"
7911 "{
7912 rtx op3, scratch, scratch2;
7913
7914 if (!TARGET_THUMB1)
7915 {
7916 if (!arm_add_operand (operands[3], SImode))
7917 operands[3] = force_reg (SImode, operands[3]);
7918 emit_insn (gen_cstore_cc (operands[0], operands[1],
7919 operands[2], operands[3]));
7920 DONE;
7921 }
7922
7923 if (operands[3] == const0_rtx)
7924 {
7925 switch (GET_CODE (operands[1]))
7926 {
7927 case EQ:
7928 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
7929 break;
7930
7931 case NE:
7932 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
7933 break;
7934
7935 case LE:
7936 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7937 NULL_RTX, 0, OPTAB_WIDEN);
7938 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7939 NULL_RTX, 0, OPTAB_WIDEN);
7940 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7941 operands[0], 1, OPTAB_WIDEN);
7942 break;
7943
7944 case GE:
7945 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7946 NULL_RTX, 1);
7947 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7948 NULL_RTX, 1, OPTAB_WIDEN);
7949 break;
7950
7951 case GT:
7952 scratch = expand_binop (SImode, ashr_optab, operands[2],
7953 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7954 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7955 NULL_RTX, 0, OPTAB_WIDEN);
7956 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7957 0, OPTAB_WIDEN);
7958 break;
7959
7960 /* LT is handled by generic code. No need for unsigned with 0. */
7961 default:
7962 FAIL;
7963 }
7964 DONE;
7965 }
7966
7967 switch (GET_CODE (operands[1]))
7968 {
7969 case EQ:
7970 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7971 NULL_RTX, 0, OPTAB_WIDEN);
7972 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
7973 break;
7974
7975 case NE:
7976 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7977 NULL_RTX, 0, OPTAB_WIDEN);
7978 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
7979 break;
7980
7981 case LE:
7982 op3 = force_reg (SImode, operands[3]);
7983
7984 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7985 NULL_RTX, 1, OPTAB_WIDEN);
7986 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7987 NULL_RTX, 0, OPTAB_WIDEN);
7988 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
7989 op3, operands[2]));
7990 break;
7991
7992 case GE:
7993 op3 = operands[3];
7994 if (!thumb1_cmp_operand (op3, SImode))
7995 op3 = force_reg (SImode, op3);
7996 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7997 NULL_RTX, 0, OPTAB_WIDEN);
7998 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7999 NULL_RTX, 1, OPTAB_WIDEN);
8000 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
8001 operands[2], op3));
8002 break;
8003
8004 case LEU:
8005 op3 = force_reg (SImode, operands[3]);
8006 scratch = force_reg (SImode, const0_rtx);
8007 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
8008 op3, operands[2]));
8009 break;
8010
8011 case GEU:
8012 op3 = operands[3];
8013 if (!thumb1_cmp_operand (op3, SImode))
8014 op3 = force_reg (SImode, op3);
8015 scratch = force_reg (SImode, const0_rtx);
8016 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
8017 operands[2], op3));
8018 break;
8019
8020 case LTU:
8021 op3 = operands[3];
8022 if (!thumb1_cmp_operand (op3, SImode))
8023 op3 = force_reg (SImode, op3);
8024 scratch = gen_reg_rtx (SImode);
8025 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
8026 break;
8027
8028 case GTU:
8029 op3 = force_reg (SImode, operands[3]);
8030 scratch = gen_reg_rtx (SImode);
8031 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
8032 break;
8033
8034 /* No good sequences for GT, LT. */
8035 default:
8036 FAIL;
8037 }
8038 DONE;
8039}")
8040
8041(define_expand "cstoresf4"
8042 [(set (match_operand:SI 0 "s_register_operand" "")
8043 (match_operator:SI 1 "expandable_comparison_operator"
8044 [(match_operand:SF 2 "s_register_operand" "")
8045 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
8046 "TARGET_32BIT && TARGET_HARD_FLOAT"
8047 "emit_insn (gen_cstore_cc (operands[0], operands[1],
8048 operands[2], operands[3])); DONE;"
8049)
8050
8051(define_expand "cstoredf4"
8052 [(set (match_operand:SI 0 "s_register_operand" "")
8053 (match_operator:SI 1 "expandable_comparison_operator"
8054 [(match_operand:DF 2 "s_register_operand" "")
8055 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
8056 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
8057 "emit_insn (gen_cstore_cc (operands[0], operands[1],
8058 operands[2], operands[3])); DONE;"
8059)
8060
8061(define_expand "cstoredi4"
8062 [(set (match_operand:SI 0 "s_register_operand" "")
8063 (match_operator:SI 1 "expandable_comparison_operator"
8064 [(match_operand:DI 2 "cmpdi_operand" "")
8065 (match_operand:DI 3 "cmpdi_operand" "")]))]
8066 "TARGET_32BIT"
8067 "{
8068 rtx swap = NULL_RTX;
8069 enum rtx_code code = GET_CODE (operands[1]);
8070
8071 /* We should not have two constants. */
8072 gcc_assert (GET_MODE (operands[2]) == DImode
8073 || GET_MODE (operands[3]) == DImode);
8074
8075 /* Flip unimplemented DImode comparisons to a form that
8076 arm_gen_compare_reg can handle. */
8077 switch (code)
8078 {
8079 case GT:
8080 swap = gen_rtx_LT (VOIDmode, operands[3], operands[2]); break;
8081 case LE:
8082 swap = gen_rtx_GE (VOIDmode, operands[3], operands[2]); break;
8083 case GTU:
8084 swap = gen_rtx_LTU (VOIDmode, operands[3], operands[2]); break;
8085 case LEU:
8086 swap = gen_rtx_GEU (VOIDmode, operands[3], operands[2]); break;
8087 default:
8088 break;
8089 }
8090 if (swap)
8091 emit_insn (gen_cstore_cc (operands[0], swap, operands[3],
8092 operands[2]));
8093 else
8094 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
8095 operands[3]));
8096 DONE;
8097 }"
8098)
8099
8100(define_expand "cstoresi_eq0_thumb1"
8101 [(parallel
8102 [(set (match_operand:SI 0 "s_register_operand" "")
8103 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8104 (const_int 0)))
8105 (clobber (match_dup:SI 2))])]
8106 "TARGET_THUMB1"
8107 "operands[2] = gen_reg_rtx (SImode);"
8108)
8109
8110(define_expand "cstoresi_ne0_thumb1"
8111 [(parallel
8112 [(set (match_operand:SI 0 "s_register_operand" "")
8113 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8114 (const_int 0)))
8115 (clobber (match_dup:SI 2))])]
8116 "TARGET_THUMB1"
8117 "operands[2] = gen_reg_rtx (SImode);"
8118)
8119
8120(define_insn "*cstoresi_eq0_thumb1_insn"
8121 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
8122 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
8123 (const_int 0)))
8124 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
8125 "TARGET_THUMB1"
8126 "@
8127 neg\\t%0, %1\;adc\\t%0, %0, %1
8128 neg\\t%2, %1\;adc\\t%0, %1, %2"
8129 [(set_attr "length" "4")]
8130)
8131
8132(define_insn "*cstoresi_ne0_thumb1_insn"
8133 [(set (match_operand:SI 0 "s_register_operand" "=l")
8134 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
8135 (const_int 0)))
8136 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
8137 "TARGET_THUMB1"
8138 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
8139 [(set_attr "length" "4")]
8140)
8141
8142;; Used as part of the expansion of thumb ltu and gtu sequences
8143(define_insn "cstoresi_nltu_thumb1"
8144 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
8145 (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
8146 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
8147 "TARGET_THUMB1"
8148 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
8149 [(set_attr "length" "4")]
8150)
8151
8152(define_insn_and_split "cstoresi_ltu_thumb1"
8153 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
8154 (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
8155 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
8156 "TARGET_THUMB1"
8157 "#"
8158 "TARGET_THUMB1"
8159 [(set (match_dup 3)
8160 (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
8161 (set (match_dup 0) (neg:SI (match_dup 3)))]
8162 "operands[3] = gen_reg_rtx (SImode);"
8163 [(set_attr "length" "4")]
8164)
8165
8166;; Used as part of the expansion of thumb les sequence.
8167(define_insn "thumb1_addsi3_addgeu"
8168 [(set (match_operand:SI 0 "s_register_operand" "=l")
8169 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8170 (match_operand:SI 2 "s_register_operand" "l"))
8171 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
8172 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
8173 "TARGET_THUMB1"
8174 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
8175 [(set_attr "length" "4")]
8176)
8177
8178\f
8179;; Conditional move insns
8180
8181(define_expand "movsicc"
8182 [(set (match_operand:SI 0 "s_register_operand" "")
8183 (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
8184 (match_operand:SI 2 "arm_not_operand" "")
8185 (match_operand:SI 3 "arm_not_operand" "")))]
8186 "TARGET_32BIT"
8187 "
8188 {
8189 enum rtx_code code = GET_CODE (operands[1]);
8190 rtx ccreg;
8191
8192 if (code == UNEQ || code == LTGT)
8193 FAIL;
8194
8195 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8196 XEXP (operands[1], 1), NULL_RTX);
8197 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
8198 }"
8199)
8200
8201(define_expand "movsfcc"
8202 [(set (match_operand:SF 0 "s_register_operand" "")
8203 (if_then_else:SF (match_operand 1 "expandable_comparison_operator" "")
8204 (match_operand:SF 2 "s_register_operand" "")
8205 (match_operand:SF 3 "nonmemory_operand" "")))]
8206 "TARGET_32BIT && TARGET_HARD_FLOAT"
8207 "
8208 {
8209 enum rtx_code code = GET_CODE (operands[1]);
8210 rtx ccreg;
8211
8212 if (code == UNEQ || code == LTGT)
8213 FAIL;
8214
8215 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
8216 Otherwise, ensure it is a valid FP add operand */
8217 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
8218 || (!arm_float_add_operand (operands[3], SFmode)))
8219 operands[3] = force_reg (SFmode, operands[3]);
8220
8221 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8222 XEXP (operands[1], 1), NULL_RTX);
8223 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
8224 }"
8225)
8226
8227(define_expand "movdfcc"
8228 [(set (match_operand:DF 0 "s_register_operand" "")
8229 (if_then_else:DF (match_operand 1 "expandable_comparison_operator" "")
8230 (match_operand:DF 2 "s_register_operand" "")
8231 (match_operand:DF 3 "arm_float_add_operand" "")))]
8232 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
8233 "
8234 {
8235 enum rtx_code code = GET_CODE (operands[1]);
8236 rtx ccreg;
8237
8238 if (code == UNEQ || code == LTGT)
8239 FAIL;
8240
8241 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8242 XEXP (operands[1], 1), NULL_RTX);
8243 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
8244 }"
8245)
8246
8247(define_insn "*movsicc_insn"
8248 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8249 (if_then_else:SI
8250 (match_operator 3 "arm_comparison_operator"
8251 [(match_operand 4 "cc_register" "") (const_int 0)])
8252 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8253 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
8254 "TARGET_ARM"
8255 "@
8256 mov%D3\\t%0, %2
8257 mvn%D3\\t%0, #%B2
8258 mov%d3\\t%0, %1
8259 mvn%d3\\t%0, #%B1
8260 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8261 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8262 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8263 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
8264 [(set_attr "length" "4,4,4,4,8,8,8,8")
8265 (set_attr "conds" "use")
8266 (set_attr "insn" "mov,mvn,mov,mvn,mov,mov,mvn,mvn")]
8267)
8268
8269(define_insn "*movsfcc_soft_insn"
8270 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8271 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8272 [(match_operand 4 "cc_register" "") (const_int 0)])
8273 (match_operand:SF 1 "s_register_operand" "0,r")
8274 (match_operand:SF 2 "s_register_operand" "r,0")))]
8275 "TARGET_ARM && TARGET_SOFT_FLOAT"
8276 "@
8277 mov%D3\\t%0, %2
8278 mov%d3\\t%0, %1"
8279 [(set_attr "conds" "use")
8280 (set_attr "insn" "mov")]
8281)
8282
8283\f
8284;; Jump and linkage insns
8285
8286(define_expand "jump"
8287 [(set (pc)
8288 (label_ref (match_operand 0 "" "")))]
8289 "TARGET_EITHER"
8290 ""
8291)
8292
8293(define_insn "*arm_jump"
8294 [(set (pc)
8295 (label_ref (match_operand 0 "" "")))]
8296 "TARGET_32BIT"
8297 "*
8298 {
8299 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8300 {
8301 arm_ccfsm_state += 2;
8302 return \"\";
8303 }
8304 return \"b%?\\t%l0\";
8305 }
8306 "
8307 [(set_attr "predicable" "yes")
8308 (set (attr "length")
8309 (if_then_else
8310 (and (match_test "TARGET_THUMB2")
8311 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8312 (le (minus (match_dup 0) (pc)) (const_int 2048))))
8313 (const_int 2)
8314 (const_int 4)))]
8315)
8316
8317(define_insn "*thumb_jump"
8318 [(set (pc)
8319 (label_ref (match_operand 0 "" "")))]
8320 "TARGET_THUMB1"
8321 "*
8322 if (get_attr_length (insn) == 2)
8323 return \"b\\t%l0\";
8324 return \"bl\\t%l0\\t%@ far jump\";
8325 "
8326 [(set (attr "far_jump")
8327 (if_then_else
8328 (eq_attr "length" "4")
8329 (const_string "yes")
8330 (const_string "no")))
8331 (set (attr "length")
8332 (if_then_else
8333 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8334 (le (minus (match_dup 0) (pc)) (const_int 2048)))
8335 (const_int 2)
8336 (const_int 4)))]
8337)
8338
8339(define_expand "call"
8340 [(parallel [(call (match_operand 0 "memory_operand" "")
8341 (match_operand 1 "general_operand" ""))
8342 (use (match_operand 2 "" ""))
8343 (clobber (reg:SI LR_REGNUM))])]
8344 "TARGET_EITHER"
8345 "
8346 {
8347 rtx callee, pat;
8348
8349 /* In an untyped call, we can get NULL for operand 2. */
8350 if (operands[2] == NULL_RTX)
8351 operands[2] = const0_rtx;
8352
8353 /* Decide if we should generate indirect calls by loading the
8354 32-bit address of the callee into a register before performing the
8355 branch and link. */
8356 callee = XEXP (operands[0], 0);
8357 if (GET_CODE (callee) == SYMBOL_REF
8358 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8359 : !REG_P (callee))
8360 XEXP (operands[0], 0) = force_reg (Pmode, callee);
8361
8362 pat = gen_call_internal (operands[0], operands[1], operands[2]);
8363 arm_emit_call_insn (pat, XEXP (operands[0], 0));
8364 DONE;
8365 }"
8366)
8367
8368(define_expand "call_internal"
8369 [(parallel [(call (match_operand 0 "memory_operand" "")
8370 (match_operand 1 "general_operand" ""))
8371 (use (match_operand 2 "" ""))
8372 (clobber (reg:SI LR_REGNUM))])])
8373
8374(define_insn "*call_reg_armv5"
8375 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8376 (match_operand 1 "" ""))
8377 (use (match_operand 2 "" ""))
8378 (clobber (reg:SI LR_REGNUM))]
8379 "TARGET_ARM && arm_arch5"
8380 "blx%?\\t%0"
8381 [(set_attr "type" "call")]
8382)
8383
8384(define_insn "*call_reg_arm"
8385 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8386 (match_operand 1 "" ""))
8387 (use (match_operand 2 "" ""))
8388 (clobber (reg:SI LR_REGNUM))]
8389 "TARGET_ARM && !arm_arch5"
8390 "*
8391 return output_call (operands);
8392 "
8393 ;; length is worst case, normally it is only two
8394 [(set_attr "length" "12")
8395 (set_attr "type" "call")]
8396)
8397
8398
8399;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
8400;; considered a function call by the branch predictor of some cores (PR40887).
8401;; Falls back to blx rN (*call_reg_armv5).
8402
8403(define_insn "*call_mem"
8404 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
8405 (match_operand 1 "" ""))
8406 (use (match_operand 2 "" ""))
8407 (clobber (reg:SI LR_REGNUM))]
8408 "TARGET_ARM && !arm_arch5"
8409 "*
8410 return output_call_mem (operands);
8411 "
8412 [(set_attr "length" "12")
8413 (set_attr "type" "call")]
8414)
8415
8416(define_insn "*call_reg_thumb1_v5"
8417 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8418 (match_operand 1 "" ""))
8419 (use (match_operand 2 "" ""))
8420 (clobber (reg:SI LR_REGNUM))]
8421 "TARGET_THUMB1 && arm_arch5"
8422 "blx\\t%0"
8423 [(set_attr "length" "2")
8424 (set_attr "type" "call")]
8425)
8426
8427(define_insn "*call_reg_thumb1"
8428 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8429 (match_operand 1 "" ""))
8430 (use (match_operand 2 "" ""))
8431 (clobber (reg:SI LR_REGNUM))]
8432 "TARGET_THUMB1 && !arm_arch5"
8433 "*
8434 {
8435 if (!TARGET_CALLER_INTERWORKING)
8436 return thumb_call_via_reg (operands[0]);
8437 else if (operands[1] == const0_rtx)
8438 return \"bl\\t%__interwork_call_via_%0\";
8439 else if (frame_pointer_needed)
8440 return \"bl\\t%__interwork_r7_call_via_%0\";
8441 else
8442 return \"bl\\t%__interwork_r11_call_via_%0\";
8443 }"
8444 [(set_attr "type" "call")]
8445)
8446
8447(define_expand "call_value"
8448 [(parallel [(set (match_operand 0 "" "")
8449 (call (match_operand 1 "memory_operand" "")
8450 (match_operand 2 "general_operand" "")))
8451 (use (match_operand 3 "" ""))
8452 (clobber (reg:SI LR_REGNUM))])]
8453 "TARGET_EITHER"
8454 "
8455 {
8456 rtx pat, callee;
8457
8458 /* In an untyped call, we can get NULL for operand 2. */
8459 if (operands[3] == 0)
8460 operands[3] = const0_rtx;
8461
8462 /* Decide if we should generate indirect calls by loading the
8463 32-bit address of the callee into a register before performing the
8464 branch and link. */
8465 callee = XEXP (operands[1], 0);
8466 if (GET_CODE (callee) == SYMBOL_REF
8467 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8468 : !REG_P (callee))
8469 XEXP (operands[1], 0) = force_reg (Pmode, callee);
8470
8471 pat = gen_call_value_internal (operands[0], operands[1],
8472 operands[2], operands[3]);
8473 arm_emit_call_insn (pat, XEXP (operands[1], 0));
8474 DONE;
8475 }"
8476)
8477
8478(define_expand "call_value_internal"
8479 [(parallel [(set (match_operand 0 "" "")
8480 (call (match_operand 1 "memory_operand" "")
8481 (match_operand 2 "general_operand" "")))
8482 (use (match_operand 3 "" ""))
8483 (clobber (reg:SI LR_REGNUM))])])
8484
8485(define_insn "*call_value_reg_armv5"
8486 [(set (match_operand 0 "" "")
8487 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8488 (match_operand 2 "" "")))
8489 (use (match_operand 3 "" ""))
8490 (clobber (reg:SI LR_REGNUM))]
8491 "TARGET_ARM && arm_arch5"
8492 "blx%?\\t%1"
8493 [(set_attr "type" "call")]
8494)
8495
8496(define_insn "*call_value_reg_arm"
8497 [(set (match_operand 0 "" "")
8498 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8499 (match_operand 2 "" "")))
8500 (use (match_operand 3 "" ""))
8501 (clobber (reg:SI LR_REGNUM))]
8502 "TARGET_ARM && !arm_arch5"
8503 "*
8504 return output_call (&operands[1]);
8505 "
8506 [(set_attr "length" "12")
8507 (set_attr "type" "call")]
8508)
8509
8510;; Note: see *call_mem
8511
8512(define_insn "*call_value_mem"
8513 [(set (match_operand 0 "" "")
8514 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
8515 (match_operand 2 "" "")))
8516 (use (match_operand 3 "" ""))
8517 (clobber (reg:SI LR_REGNUM))]
8518 "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
8519 "*
8520 return output_call_mem (&operands[1]);
8521 "
8522 [(set_attr "length" "12")
8523 (set_attr "type" "call")]
8524)
8525
8526(define_insn "*call_value_reg_thumb1_v5"
8527 [(set (match_operand 0 "" "")
8528 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8529 (match_operand 2 "" "")))
8530 (use (match_operand 3 "" ""))
8531 (clobber (reg:SI LR_REGNUM))]
8532 "TARGET_THUMB1 && arm_arch5"
8533 "blx\\t%1"
8534 [(set_attr "length" "2")
8535 (set_attr "type" "call")]
8536)
8537
8538(define_insn "*call_value_reg_thumb1"
8539 [(set (match_operand 0 "" "")
8540 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8541 (match_operand 2 "" "")))
8542 (use (match_operand 3 "" ""))
8543 (clobber (reg:SI LR_REGNUM))]
8544 "TARGET_THUMB1 && !arm_arch5"
8545 "*
8546 {
8547 if (!TARGET_CALLER_INTERWORKING)
8548 return thumb_call_via_reg (operands[1]);
8549 else if (operands[2] == const0_rtx)
8550 return \"bl\\t%__interwork_call_via_%1\";
8551 else if (frame_pointer_needed)
8552 return \"bl\\t%__interwork_r7_call_via_%1\";
8553 else
8554 return \"bl\\t%__interwork_r11_call_via_%1\";
8555 }"
8556 [(set_attr "type" "call")]
8557)
8558
8559;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8560;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8561
8562(define_insn "*call_symbol"
8563 [(call (mem:SI (match_operand:SI 0 "" ""))
8564 (match_operand 1 "" ""))
8565 (use (match_operand 2 "" ""))
8566 (clobber (reg:SI LR_REGNUM))]
8567 "TARGET_32BIT
8568 && (GET_CODE (operands[0]) == SYMBOL_REF)
8569 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
8570 "*
8571 {
8572 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
8573 }"
8574 [(set_attr "type" "call")]
8575)
8576
8577(define_insn "*call_value_symbol"
8578 [(set (match_operand 0 "" "")
8579 (call (mem:SI (match_operand:SI 1 "" ""))
8580 (match_operand:SI 2 "" "")))
8581 (use (match_operand 3 "" ""))
8582 (clobber (reg:SI LR_REGNUM))]
8583 "TARGET_32BIT
8584 && (GET_CODE (operands[1]) == SYMBOL_REF)
8585 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
8586 "*
8587 {
8588 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
8589 }"
8590 [(set_attr "type" "call")]
8591)
8592
8593(define_insn "*call_insn"
8594 [(call (mem:SI (match_operand:SI 0 "" ""))
8595 (match_operand:SI 1 "" ""))
8596 (use (match_operand 2 "" ""))
8597 (clobber (reg:SI LR_REGNUM))]
8598 "TARGET_THUMB1
8599 && GET_CODE (operands[0]) == SYMBOL_REF
8600 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
8601 "bl\\t%a0"
8602 [(set_attr "length" "4")
8603 (set_attr "type" "call")]
8604)
8605
8606(define_insn "*call_value_insn"
8607 [(set (match_operand 0 "" "")
8608 (call (mem:SI (match_operand 1 "" ""))
8609 (match_operand 2 "" "")))
8610 (use (match_operand 3 "" ""))
8611 (clobber (reg:SI LR_REGNUM))]
8612 "TARGET_THUMB1
8613 && GET_CODE (operands[1]) == SYMBOL_REF
8614 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
8615 "bl\\t%a1"
8616 [(set_attr "length" "4")
8617 (set_attr "type" "call")]
8618)
8619
8620;; We may also be able to do sibcalls for Thumb, but it's much harder...
8621(define_expand "sibcall"
8622 [(parallel [(call (match_operand 0 "memory_operand" "")
8623 (match_operand 1 "general_operand" ""))
8624 (return)
8625 (use (match_operand 2 "" ""))])]
8626 "TARGET_32BIT"
8627 "
8628 {
8629 if (operands[2] == NULL_RTX)
8630 operands[2] = const0_rtx;
8631 }"
8632)
8633
8634(define_expand "sibcall_value"
8635 [(parallel [(set (match_operand 0 "" "")
8636 (call (match_operand 1 "memory_operand" "")
8637 (match_operand 2 "general_operand" "")))
8638 (return)
8639 (use (match_operand 3 "" ""))])]
8640 "TARGET_32BIT"
8641 "
8642 {
8643 if (operands[3] == NULL_RTX)
8644 operands[3] = const0_rtx;
8645 }"
8646)
8647
8648(define_insn "*sibcall_insn"
8649 [(call (mem:SI (match_operand:SI 0 "" "X"))
8650 (match_operand 1 "" ""))
8651 (return)
8652 (use (match_operand 2 "" ""))]
8653 "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF"
8654 "*
8655 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8656 "
8657 [(set_attr "type" "call")]
8658)
8659
8660(define_insn "*sibcall_value_insn"
8661 [(set (match_operand 0 "" "")
8662 (call (mem:SI (match_operand:SI 1 "" "X"))
8663 (match_operand 2 "" "")))
8664 (return)
8665 (use (match_operand 3 "" ""))]
8666 "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF"
8667 "*
8668 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8669 "
8670 [(set_attr "type" "call")]
8671)
8672
8673(define_expand "return"
8674 [(return)]
8675 "TARGET_32BIT && USE_RETURN_INSN (FALSE)"
8676 "")
8677
8678;; Often the return insn will be the same as loading from memory, so set attr
8679(define_insn "*arm_return"
8680 [(return)]
8681 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
8682 "*
8683 {
8684 if (arm_ccfsm_state == 2)
8685 {
8686 arm_ccfsm_state += 2;
8687 return \"\";
8688 }
8689 return output_return_instruction (const_true_rtx, TRUE, FALSE);
8690 }"
8691 [(set_attr "type" "load1")
8692 (set_attr "length" "12")
8693 (set_attr "predicable" "yes")]
8694)
8695
8696(define_insn "*cond_return"
8697 [(set (pc)
8698 (if_then_else (match_operator 0 "arm_comparison_operator"
8699 [(match_operand 1 "cc_register" "") (const_int 0)])
8700 (return)
8701 (pc)))]
8702 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8703 "*
8704 {
8705 if (arm_ccfsm_state == 2)
8706 {
8707 arm_ccfsm_state += 2;
8708 return \"\";
8709 }
8710 return output_return_instruction (operands[0], TRUE, FALSE);
8711 }"
8712 [(set_attr "conds" "use")
8713 (set_attr "length" "12")
8714 (set_attr "type" "load1")]
8715)
8716
8717(define_insn "*cond_return_inverted"
8718 [(set (pc)
8719 (if_then_else (match_operator 0 "arm_comparison_operator"
8720 [(match_operand 1 "cc_register" "") (const_int 0)])
8721 (pc)
8722 (return)))]
8723 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8724 "*
8725 {
8726 if (arm_ccfsm_state == 2)
8727 {
8728 arm_ccfsm_state += 2;
8729 return \"\";
8730 }
8731 return output_return_instruction (operands[0], TRUE, TRUE);
8732 }"
8733 [(set_attr "conds" "use")
8734 (set_attr "length" "12")
8735 (set_attr "type" "load1")]
8736)
8737
8738;; Generate a sequence of instructions to determine if the processor is
8739;; in 26-bit or 32-bit mode, and return the appropriate return address
8740;; mask.
8741
8742(define_expand "return_addr_mask"
8743 [(set (match_dup 1)
8744 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8745 (const_int 0)))
8746 (set (match_operand:SI 0 "s_register_operand" "")
8747 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8748 (const_int -1)
8749 (const_int 67108860)))] ; 0x03fffffc
8750 "TARGET_ARM"
8751 "
8752 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
8753 ")
8754
8755(define_insn "*check_arch2"
8756 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8757 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8758 (const_int 0)))]
8759 "TARGET_ARM"
8760 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8761 [(set_attr "length" "8")
8762 (set_attr "conds" "set")]
8763)
8764
8765;; Call subroutine returning any type.
8766
8767(define_expand "untyped_call"
8768 [(parallel [(call (match_operand 0 "" "")
8769 (const_int 0))
8770 (match_operand 1 "" "")
8771 (match_operand 2 "" "")])]
8772 "TARGET_EITHER"
8773 "
8774 {
8775 int i;
8776 rtx par = gen_rtx_PARALLEL (VOIDmode,
8777 rtvec_alloc (XVECLEN (operands[2], 0)));
8778 rtx addr = gen_reg_rtx (Pmode);
8779 rtx mem;
8780 int size = 0;
8781
8782 emit_move_insn (addr, XEXP (operands[1], 0));
8783 mem = change_address (operands[1], BLKmode, addr);
8784
8785 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8786 {
8787 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
8788
8789 /* Default code only uses r0 as a return value, but we could
8790 be using anything up to 4 registers. */
8791 if (REGNO (src) == R0_REGNUM)
8792 src = gen_rtx_REG (TImode, R0_REGNUM);
8793
8794 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8795 GEN_INT (size));
8796 size += GET_MODE_SIZE (GET_MODE (src));
8797 }
8798
8799 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8800 const0_rtx));
8801
8802 size = 0;
8803
8804 for (i = 0; i < XVECLEN (par, 0); i++)
8805 {
8806 HOST_WIDE_INT offset = 0;
8807 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8808
8809 if (size != 0)
8810 emit_move_insn (addr, plus_constant (Pmode, addr, size));
8811
8812 mem = change_address (mem, GET_MODE (reg), NULL);
8813 if (REGNO (reg) == R0_REGNUM)
8814 {
8815 /* On thumb we have to use a write-back instruction. */
8816 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8817 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8818 size = TARGET_ARM ? 16 : 0;
8819 }
8820 else
8821 {
8822 emit_move_insn (mem, reg);
8823 size = GET_MODE_SIZE (GET_MODE (reg));
8824 }
8825 }
8826
8827 /* The optimizer does not know that the call sets the function value
8828 registers we stored in the result block. We avoid problems by
8829 claiming that all hard registers are used and clobbered at this
8830 point. */
8831 emit_insn (gen_blockage ());
8832
8833 DONE;
8834 }"
8835)
8836
8837(define_expand "untyped_return"
8838 [(match_operand:BLK 0 "memory_operand" "")
8839 (match_operand 1 "" "")]
8840 "TARGET_EITHER"
8841 "
8842 {
8843 int i;
8844 rtx addr = gen_reg_rtx (Pmode);
8845 rtx mem;
8846 int size = 0;
8847
8848 emit_move_insn (addr, XEXP (operands[0], 0));
8849 mem = change_address (operands[0], BLKmode, addr);
8850
8851 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8852 {
8853 HOST_WIDE_INT offset = 0;
8854 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8855
8856 if (size != 0)
8857 emit_move_insn (addr, plus_constant (Pmode, addr, size));
8858
8859 mem = change_address (mem, GET_MODE (reg), NULL);
8860 if (REGNO (reg) == R0_REGNUM)
8861 {
8862 /* On thumb we have to use a write-back instruction. */
8863 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8864 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8865 size = TARGET_ARM ? 16 : 0;
8866 }
8867 else
8868 {
8869 emit_move_insn (reg, mem);
8870 size = GET_MODE_SIZE (GET_MODE (reg));
8871 }
8872 }
8873
8874 /* Emit USE insns before the return. */
8875 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8876 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
8877
8878 /* Construct the return. */
8879 expand_naked_return ();
8880
8881 DONE;
8882 }"
8883)
8884
8885;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8886;; all of memory. This blocks insns from being moved across this point.
8887
8888(define_insn "blockage"
8889 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8890 "TARGET_EITHER"
8891 ""
8892 [(set_attr "length" "0")
8893 (set_attr "type" "block")]
8894)
8895
8896(define_expand "casesi"
8897 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8898 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8899 (match_operand:SI 2 "const_int_operand" "") ; total range
8900 (match_operand:SI 3 "" "") ; table label
8901 (match_operand:SI 4 "" "")] ; Out of range label
8902 "TARGET_32BIT || optimize_size || flag_pic"
8903 "
8904 {
8905 enum insn_code code;
8906 if (operands[1] != const0_rtx)
8907 {
8908 rtx reg = gen_reg_rtx (SImode);
8909
8910 emit_insn (gen_addsi3 (reg, operands[0],
8911 gen_int_mode (-INTVAL (operands[1]),
8912 SImode)));
8913 operands[0] = reg;
8914 }
8915
8916 if (TARGET_ARM)
8917 code = CODE_FOR_arm_casesi_internal;
8918 else if (TARGET_THUMB1)
8919 code = CODE_FOR_thumb1_casesi_internal_pic;
8920 else if (flag_pic)
8921 code = CODE_FOR_thumb2_casesi_internal_pic;
8922 else
8923 code = CODE_FOR_thumb2_casesi_internal;
8924
8925 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8926 operands[2] = force_reg (SImode, operands[2]);
8927
8928 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8929 operands[3], operands[4]));
8930 DONE;
8931 }"
8932)
8933
8934;; The USE in this pattern is needed to tell flow analysis that this is
8935;; a CASESI insn. It has no other purpose.
8936(define_insn "arm_casesi_internal"
8937 [(parallel [(set (pc)
8938 (if_then_else
8939 (leu (match_operand:SI 0 "s_register_operand" "r")
8940 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8941 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8942 (label_ref (match_operand 2 "" ""))))
8943 (label_ref (match_operand 3 "" ""))))
8944 (clobber (reg:CC CC_REGNUM))
8945 (use (label_ref (match_dup 2)))])]
8946 "TARGET_ARM"
8947 "*
8948 if (flag_pic)
8949 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8950 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8951 "
8952 [(set_attr "conds" "clob")
8953 (set_attr "length" "12")]
8954)
8955
8956(define_expand "thumb1_casesi_internal_pic"
8957 [(match_operand:SI 0 "s_register_operand" "")
8958 (match_operand:SI 1 "thumb1_cmp_operand" "")
8959 (match_operand 2 "" "")
8960 (match_operand 3 "" "")]
8961 "TARGET_THUMB1"
8962 {
8963 rtx reg0;
8964 rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
8965 emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
8966 operands[3]));
8967 reg0 = gen_rtx_REG (SImode, 0);
8968 emit_move_insn (reg0, operands[0]);
8969 emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
8970 DONE;
8971 }
8972)
8973
8974(define_insn "thumb1_casesi_dispatch"
8975 [(parallel [(set (pc) (unspec [(reg:SI 0)
8976 (label_ref (match_operand 0 "" ""))
8977;; (label_ref (match_operand 1 "" ""))
8978]
8979 UNSPEC_THUMB1_CASESI))
8980 (clobber (reg:SI IP_REGNUM))
8981 (clobber (reg:SI LR_REGNUM))])]
8982 "TARGET_THUMB1"
8983 "* return thumb1_output_casesi(operands);"
8984 [(set_attr "length" "4")]
8985)
8986
8987(define_expand "indirect_jump"
8988 [(set (pc)
8989 (match_operand:SI 0 "s_register_operand" ""))]
8990 "TARGET_EITHER"
8991 "
8992 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8993 address and use bx. */
8994 if (TARGET_THUMB2)
8995 {
8996 rtx tmp;
8997 tmp = gen_reg_rtx (SImode);
8998 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8999 operands[0] = tmp;
9000 }
9001 "
9002)
9003
9004;; NB Never uses BX.
9005(define_insn "*arm_indirect_jump"
9006 [(set (pc)
9007 (match_operand:SI 0 "s_register_operand" "r"))]
9008 "TARGET_ARM"
9009 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
9010 [(set_attr "predicable" "yes")]
9011)
9012
9013(define_insn "*load_indirect_jump"
9014 [(set (pc)
9015 (match_operand:SI 0 "memory_operand" "m"))]
9016 "TARGET_ARM"
9017 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
9018 [(set_attr "type" "load1")
9019 (set_attr "pool_range" "4096")
9020 (set_attr "neg_pool_range" "4084")
9021 (set_attr "predicable" "yes")]
9022)
9023
9024;; NB Never uses BX.
9025(define_insn "*thumb1_indirect_jump"
9026 [(set (pc)
9027 (match_operand:SI 0 "register_operand" "l*r"))]
9028 "TARGET_THUMB1"
9029 "mov\\tpc, %0"
9030 [(set_attr "conds" "clob")
9031 (set_attr "length" "2")]
9032)
9033
9034\f
9035;; Misc insns
9036
9037(define_insn "nop"
9038 [(const_int 0)]
9039 "TARGET_EITHER"
9040 "*
9041 if (TARGET_UNIFIED_ASM)
9042 return \"nop\";
9043 if (TARGET_ARM)
9044 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
9045 return \"mov\\tr8, r8\";
9046 "
9047 [(set (attr "length")
9048 (if_then_else (eq_attr "is_thumb" "yes")
9049 (const_int 2)
9050 (const_int 4)))]
9051)
9052
9053\f
9054;; Patterns to allow combination of arithmetic, cond code and shifts
9055
9056(define_insn "*arith_shiftsi"
9057 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9058 (match_operator:SI 1 "shiftable_operator"
9059 [(match_operator:SI 3 "shift_operator"
9060 [(match_operand:SI 4 "s_register_operand" "r,r,r,r")
9061 (match_operand:SI 5 "shift_amount_operand" "M,M,M,r")])
9062 (match_operand:SI 2 "s_register_operand" "rk,rk,r,rk")]))]
9063 "TARGET_32BIT"
9064 "%i1%?\\t%0, %2, %4%S3"
9065 [(set_attr "predicable" "yes")
9066 (set_attr "shift" "4")
9067 (set_attr "arch" "a,t2,t2,a")
9068 ;; Thumb2 doesn't allow the stack pointer to be used for
9069 ;; operand1 for all operations other than add and sub. In this case
9070 ;; the minus operation is a candidate for an rsub and hence needs
9071 ;; to be disabled.
9072 ;; We have to make sure to disable the fourth alternative if
9073 ;; the shift_operator is MULT, since otherwise the insn will
9074 ;; also match a multiply_accumulate pattern and validate_change
9075 ;; will allow a replacement of the constant with a register
9076 ;; despite the checks done in shift_operator.
9077 (set_attr_alternative "insn_enabled"
9078 [(const_string "yes")
9079 (if_then_else
9080 (match_operand:SI 1 "add_operator" "")
9081 (const_string "yes") (const_string "no"))
9082 (const_string "yes")
9083 (if_then_else
9084 (match_operand:SI 3 "mult_operator" "")
9085 (const_string "no") (const_string "yes"))])
9086 (set_attr "type" "alu_shift,alu_shift,alu_shift,alu_shift_reg")])
9087
9088(define_split
9089 [(set (match_operand:SI 0 "s_register_operand" "")
9090 (match_operator:SI 1 "shiftable_operator"
9091 [(match_operator:SI 2 "shiftable_operator"
9092 [(match_operator:SI 3 "shift_operator"
9093 [(match_operand:SI 4 "s_register_operand" "")
9094 (match_operand:SI 5 "reg_or_int_operand" "")])
9095 (match_operand:SI 6 "s_register_operand" "")])
9096 (match_operand:SI 7 "arm_rhs_operand" "")]))
9097 (clobber (match_operand:SI 8 "s_register_operand" ""))]
9098 "TARGET_32BIT"
9099 [(set (match_dup 8)
9100 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9101 (match_dup 6)]))
9102 (set (match_dup 0)
9103 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
9104 "")
9105
9106(define_insn "*arith_shiftsi_compare0"
9107 [(set (reg:CC_NOOV CC_REGNUM)
9108 (compare:CC_NOOV
9109 (match_operator:SI 1 "shiftable_operator"
9110 [(match_operator:SI 3 "shift_operator"
9111 [(match_operand:SI 4 "s_register_operand" "r,r")
9112 (match_operand:SI 5 "shift_amount_operand" "M,r")])
9113 (match_operand:SI 2 "s_register_operand" "r,r")])
9114 (const_int 0)))
9115 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9116 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9117 (match_dup 2)]))]
9118 "TARGET_32BIT"
9119 "%i1%.\\t%0, %2, %4%S3"
9120 [(set_attr "conds" "set")
9121 (set_attr "shift" "4")
9122 (set_attr "arch" "32,a")
9123 (set_attr "type" "alu_shift,alu_shift_reg")])
9124
9125(define_insn "*arith_shiftsi_compare0_scratch"
9126 [(set (reg:CC_NOOV CC_REGNUM)
9127 (compare:CC_NOOV
9128 (match_operator:SI 1 "shiftable_operator"
9129 [(match_operator:SI 3 "shift_operator"
9130 [(match_operand:SI 4 "s_register_operand" "r,r")
9131 (match_operand:SI 5 "shift_amount_operand" "M,r")])
9132 (match_operand:SI 2 "s_register_operand" "r,r")])
9133 (const_int 0)))
9134 (clobber (match_scratch:SI 0 "=r,r"))]
9135 "TARGET_32BIT"
9136 "%i1%.\\t%0, %2, %4%S3"
9137 [(set_attr "conds" "set")
9138 (set_attr "shift" "4")
9139 (set_attr "arch" "32,a")
9140 (set_attr "type" "alu_shift,alu_shift_reg")])
9141
9142(define_insn "*sub_shiftsi"
9143 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9144 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9145 (match_operator:SI 2 "shift_operator"
9146 [(match_operand:SI 3 "s_register_operand" "r,r")
9147 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
9148 "TARGET_32BIT"
9149 "sub%?\\t%0, %1, %3%S2"
9150 [(set_attr "predicable" "yes")
9151 (set_attr "shift" "3")
9152 (set_attr "arch" "32,a")
9153 (set_attr "type" "alu_shift,alu_shift_reg")])
9154
9155(define_insn "*sub_shiftsi_compare0"
9156 [(set (reg:CC_NOOV CC_REGNUM)
9157 (compare:CC_NOOV
9158 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9159 (match_operator:SI 2 "shift_operator"
9160 [(match_operand:SI 3 "s_register_operand" "r,r")
9161 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
9162 (const_int 0)))
9163 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9164 (minus:SI (match_dup 1)
9165 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
9166 "TARGET_32BIT"
9167 "sub%.\\t%0, %1, %3%S2"
9168 [(set_attr "conds" "set")
9169 (set_attr "shift" "3")
9170 (set_attr "arch" "32,a")
9171 (set_attr "type" "alu_shift,alu_shift_reg")])
9172
9173(define_insn "*sub_shiftsi_compare0_scratch"
9174 [(set (reg:CC_NOOV CC_REGNUM)
9175 (compare:CC_NOOV
9176 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9177 (match_operator:SI 2 "shift_operator"
9178 [(match_operand:SI 3 "s_register_operand" "r,r")
9179 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
9180 (const_int 0)))
9181 (clobber (match_scratch:SI 0 "=r,r"))]
9182 "TARGET_32BIT"
9183 "sub%.\\t%0, %1, %3%S2"
9184 [(set_attr "conds" "set")
9185 (set_attr "shift" "3")
9186 (set_attr "arch" "32,a")
9187 (set_attr "type" "alu_shift,alu_shift_reg")])
9188\f
9189
9190(define_insn "*and_scc"
9191 [(set (match_operand:SI 0 "s_register_operand" "=r")
9192 (and:SI (match_operator:SI 1 "arm_comparison_operator"
9193 [(match_operand 3 "cc_register" "") (const_int 0)])
9194 (match_operand:SI 2 "s_register_operand" "r")))]
9195 "TARGET_ARM"
9196 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
9197 [(set_attr "conds" "use")
9198 (set_attr "insn" "mov")
9199 (set_attr "length" "8")]
9200)
9201
9202(define_insn "*ior_scc"
9203 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9204 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
9205 [(match_operand 3 "cc_register" "") (const_int 0)])
9206 (match_operand:SI 1 "s_register_operand" "0,?r")))]
9207 "TARGET_ARM"
9208 "@
9209 orr%d2\\t%0, %1, #1
9210 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
9211 [(set_attr "conds" "use")
9212 (set_attr "length" "4,8")]
9213)
9214
9215; A series of splitters for the compare_scc pattern below. Note that
9216; order is important.
9217(define_split
9218 [(set (match_operand:SI 0 "s_register_operand" "")
9219 (lt:SI (match_operand:SI 1 "s_register_operand" "")
9220 (const_int 0)))
9221 (clobber (reg:CC CC_REGNUM))]
9222 "TARGET_32BIT && reload_completed"
9223 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
9224
9225(define_split
9226 [(set (match_operand:SI 0 "s_register_operand" "")
9227 (ge:SI (match_operand:SI 1 "s_register_operand" "")
9228 (const_int 0)))
9229 (clobber (reg:CC CC_REGNUM))]
9230 "TARGET_32BIT && reload_completed"
9231 [(set (match_dup 0) (not:SI (match_dup 1)))
9232 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
9233
9234(define_split
9235 [(set (match_operand:SI 0 "s_register_operand" "")
9236 (eq:SI (match_operand:SI 1 "s_register_operand" "")
9237 (const_int 0)))
9238 (clobber (reg:CC CC_REGNUM))]
9239 "TARGET_32BIT && reload_completed"
9240 [(parallel
9241 [(set (reg:CC CC_REGNUM)
9242 (compare:CC (const_int 1) (match_dup 1)))
9243 (set (match_dup 0)
9244 (minus:SI (const_int 1) (match_dup 1)))])
9245 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
9246 (set (match_dup 0) (const_int 0)))])
9247
9248(define_split
9249 [(set (match_operand:SI 0 "s_register_operand" "")
9250 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9251 (match_operand:SI 2 "const_int_operand" "")))
9252 (clobber (reg:CC CC_REGNUM))]
9253 "TARGET_32BIT && reload_completed"
9254 [(parallel
9255 [(set (reg:CC CC_REGNUM)
9256 (compare:CC (match_dup 1) (match_dup 2)))
9257 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
9258 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
9259 (set (match_dup 0) (const_int 1)))]
9260{
9261 operands[3] = GEN_INT (-INTVAL (operands[2]));
9262})
9263
9264(define_split
9265 [(set (match_operand:SI 0 "s_register_operand" "")
9266 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9267 (match_operand:SI 2 "arm_add_operand" "")))
9268 (clobber (reg:CC CC_REGNUM))]
9269 "TARGET_32BIT && reload_completed"
9270 [(parallel
9271 [(set (reg:CC_NOOV CC_REGNUM)
9272 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
9273 (const_int 0)))
9274 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
9275 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
9276 (set (match_dup 0) (const_int 1)))])
9277
9278(define_insn_and_split "*compare_scc"
9279 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9280 (match_operator:SI 1 "arm_comparison_operator"
9281 [(match_operand:SI 2 "s_register_operand" "r,r")
9282 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
9283 (clobber (reg:CC CC_REGNUM))]
9284 "TARGET_32BIT"
9285 "#"
9286 "&& reload_completed"
9287 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
9288 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
9289 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
9290{
9291 rtx tmp1;
9292 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9293 operands[2], operands[3]);
9294 enum rtx_code rc = GET_CODE (operands[1]);
9295
9296 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
9297
9298 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9299 if (mode == CCFPmode || mode == CCFPEmode)
9300 rc = reverse_condition_maybe_unordered (rc);
9301 else
9302 rc = reverse_condition (rc);
9303 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9304})
9305
9306;; Attempt to improve the sequence generated by the compare_scc splitters
9307;; not to use conditional execution.
9308(define_peephole2
9309 [(set (reg:CC CC_REGNUM)
9310 (compare:CC (match_operand:SI 1 "register_operand" "")
9311 (match_operand:SI 2 "arm_rhs_operand" "")))
9312 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9313 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9314 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9315 (set (match_dup 0) (const_int 1)))
9316 (match_scratch:SI 3 "r")]
9317 "TARGET_32BIT"
9318 [(parallel
9319 [(set (reg:CC CC_REGNUM)
9320 (compare:CC (match_dup 1) (match_dup 2)))
9321 (set (match_dup 3) (minus:SI (match_dup 1) (match_dup 2)))])
9322 (parallel
9323 [(set (reg:CC CC_REGNUM)
9324 (compare:CC (const_int 0) (match_dup 3)))
9325 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
9326 (parallel
9327 [(set (match_dup 0)
9328 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
9329 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))
9330 (clobber (reg:CC CC_REGNUM))])])
9331
9332(define_insn "*cond_move"
9333 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9334 (if_then_else:SI (match_operator 3 "equality_operator"
9335 [(match_operator 4 "arm_comparison_operator"
9336 [(match_operand 5 "cc_register" "") (const_int 0)])
9337 (const_int 0)])
9338 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9339 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
9340 "TARGET_ARM"
9341 "*
9342 if (GET_CODE (operands[3]) == NE)
9343 {
9344 if (which_alternative != 1)
9345 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9346 if (which_alternative != 0)
9347 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9348 return \"\";
9349 }
9350 if (which_alternative != 0)
9351 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9352 if (which_alternative != 1)
9353 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9354 return \"\";
9355 "
9356 [(set_attr "conds" "use")
9357 (set_attr "insn" "mov")
9358 (set_attr "length" "4,4,8")]
9359)
9360
9361(define_insn "*cond_arith"
9362 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9363 (match_operator:SI 5 "shiftable_operator"
9364 [(match_operator:SI 4 "arm_comparison_operator"
9365 [(match_operand:SI 2 "s_register_operand" "r,r")
9366 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9367 (match_operand:SI 1 "s_register_operand" "0,?r")]))
9368 (clobber (reg:CC CC_REGNUM))]
9369 "TARGET_ARM"
9370 "*
9371 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9372 return \"%i5\\t%0, %1, %2, lsr #31\";
9373
9374 output_asm_insn (\"cmp\\t%2, %3\", operands);
9375 if (GET_CODE (operands[5]) == AND)
9376 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9377 else if (GET_CODE (operands[5]) == MINUS)
9378 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9379 else if (which_alternative != 0)
9380 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9381 return \"%i5%d4\\t%0, %1, #1\";
9382 "
9383 [(set_attr "conds" "clob")
9384 (set_attr "length" "12")]
9385)
9386
9387(define_insn "*cond_sub"
9388 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9389 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
9390 (match_operator:SI 4 "arm_comparison_operator"
9391 [(match_operand:SI 2 "s_register_operand" "r,r")
9392 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9393 (clobber (reg:CC CC_REGNUM))]
9394 "TARGET_ARM"
9395 "*
9396 output_asm_insn (\"cmp\\t%2, %3\", operands);
9397 if (which_alternative != 0)
9398 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9399 return \"sub%d4\\t%0, %1, #1\";
9400 "
9401 [(set_attr "conds" "clob")
9402 (set_attr "length" "8,12")]
9403)
9404
9405(define_insn "*cmp_ite0"
9406 [(set (match_operand 6 "dominant_cc_register" "")
9407 (compare
9408 (if_then_else:SI
9409 (match_operator 4 "arm_comparison_operator"
9410 [(match_operand:SI 0 "s_register_operand"
9411 "l,l,l,r,r,r,r,r,r")
9412 (match_operand:SI 1 "arm_add_operand"
9413 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
9414 (match_operator:SI 5 "arm_comparison_operator"
9415 [(match_operand:SI 2 "s_register_operand"
9416 "l,r,r,l,l,r,r,r,r")
9417 (match_operand:SI 3 "arm_add_operand"
9418 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
9419 (const_int 0))
9420 (const_int 0)))]
9421 "TARGET_32BIT"
9422 "*
9423 {
9424 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9425 {
9426 {\"cmp%d5\\t%0, %1\",
9427 \"cmp%d4\\t%2, %3\"},
9428 {\"cmn%d5\\t%0, #%n1\",
9429 \"cmp%d4\\t%2, %3\"},
9430 {\"cmp%d5\\t%0, %1\",
9431 \"cmn%d4\\t%2, #%n3\"},
9432 {\"cmn%d5\\t%0, #%n1\",
9433 \"cmn%d4\\t%2, #%n3\"}
9434 };
9435 static const char * const cmp2[NUM_OF_COND_CMP][2] =
9436 {
9437 {\"cmp\\t%2, %3\",
9438 \"cmp\\t%0, %1\"},
9439 {\"cmp\\t%2, %3\",
9440 \"cmn\\t%0, #%n1\"},
9441 {\"cmn\\t%2, #%n3\",
9442 \"cmp\\t%0, %1\"},
9443 {\"cmn\\t%2, #%n3\",
9444 \"cmn\\t%0, #%n1\"}
9445 };
9446 static const char * const ite[2] =
9447 {
9448 \"it\\t%d5\",
9449 \"it\\t%d4\"
9450 };
9451 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9452 CMP_CMP, CMN_CMP, CMP_CMP,
9453 CMN_CMP, CMP_CMN, CMN_CMN};
9454 int swap =
9455 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9456
9457 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9458 if (TARGET_THUMB2) {
9459 output_asm_insn (ite[swap], operands);
9460 }
9461 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9462 return \"\";
9463 }"
9464 [(set_attr "conds" "set")
9465 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9466 (set_attr_alternative "length"
9467 [(const_int 6)
9468 (const_int 8)
9469 (const_int 8)
9470 (const_int 8)
9471 (const_int 8)
9472 (if_then_else (eq_attr "is_thumb" "no")
9473 (const_int 8)
9474 (const_int 10))
9475 (if_then_else (eq_attr "is_thumb" "no")
9476 (const_int 8)
9477 (const_int 10))
9478 (if_then_else (eq_attr "is_thumb" "no")
9479 (const_int 8)
9480 (const_int 10))
9481 (if_then_else (eq_attr "is_thumb" "no")
9482 (const_int 8)
9483 (const_int 10))])]
9484)
9485
9486(define_insn "*cmp_ite1"
9487 [(set (match_operand 6 "dominant_cc_register" "")
9488 (compare
9489 (if_then_else:SI
9490 (match_operator 4 "arm_comparison_operator"
9491 [(match_operand:SI 0 "s_register_operand"
9492 "l,l,l,r,r,r,r,r,r")
9493 (match_operand:SI 1 "arm_add_operand"
9494 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
9495 (match_operator:SI 5 "arm_comparison_operator"
9496 [(match_operand:SI 2 "s_register_operand"
9497 "l,r,r,l,l,r,r,r,r")
9498 (match_operand:SI 3 "arm_add_operand"
9499 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
9500 (const_int 1))
9501 (const_int 0)))]
9502 "TARGET_32BIT"
9503 "*
9504 {
9505 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9506 {
9507 {\"cmp\\t%0, %1\",
9508 \"cmp\\t%2, %3\"},
9509 {\"cmn\\t%0, #%n1\",
9510 \"cmp\\t%2, %3\"},
9511 {\"cmp\\t%0, %1\",
9512 \"cmn\\t%2, #%n3\"},
9513 {\"cmn\\t%0, #%n1\",
9514 \"cmn\\t%2, #%n3\"}
9515 };
9516 static const char * const cmp2[NUM_OF_COND_CMP][2] =
9517 {
9518 {\"cmp%d4\\t%2, %3\",
9519 \"cmp%D5\\t%0, %1\"},
9520 {\"cmp%d4\\t%2, %3\",
9521 \"cmn%D5\\t%0, #%n1\"},
9522 {\"cmn%d4\\t%2, #%n3\",
9523 \"cmp%D5\\t%0, %1\"},
9524 {\"cmn%d4\\t%2, #%n3\",
9525 \"cmn%D5\\t%0, #%n1\"}
9526 };
9527 static const char * const ite[2] =
9528 {
9529 \"it\\t%d4\",
9530 \"it\\t%D5\"
9531 };
9532 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9533 CMP_CMP, CMN_CMP, CMP_CMP,
9534 CMN_CMP, CMP_CMN, CMN_CMN};
9535 int swap =
9536 comparison_dominates_p (GET_CODE (operands[5]),
9537 reverse_condition (GET_CODE (operands[4])));
9538
9539 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9540 if (TARGET_THUMB2) {
9541 output_asm_insn (ite[swap], operands);
9542 }
9543 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9544 return \"\";
9545 }"
9546 [(set_attr "conds" "set")
9547 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9548 (set_attr_alternative "length"
9549 [(const_int 6)
9550 (const_int 8)
9551 (const_int 8)
9552 (const_int 8)
9553 (const_int 8)
9554 (if_then_else (eq_attr "is_thumb" "no")
9555 (const_int 8)
9556 (const_int 10))
9557 (if_then_else (eq_attr "is_thumb" "no")
9558 (const_int 8)
9559 (const_int 10))
9560 (if_then_else (eq_attr "is_thumb" "no")
9561 (const_int 8)
9562 (const_int 10))
9563 (if_then_else (eq_attr "is_thumb" "no")
9564 (const_int 8)
9565 (const_int 10))])]
9566)
9567
9568(define_insn "*cmp_and"
9569 [(set (match_operand 6 "dominant_cc_register" "")
9570 (compare
9571 (and:SI
9572 (match_operator 4 "arm_comparison_operator"
9573 [(match_operand:SI 0 "s_register_operand"
9574 "l,l,l,r,r,r,r,r,r")
9575 (match_operand:SI 1 "arm_add_operand"
9576 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
9577 (match_operator:SI 5 "arm_comparison_operator"
9578 [(match_operand:SI 2 "s_register_operand"
9579 "l,r,r,l,l,r,r,r,r")
9580 (match_operand:SI 3 "arm_add_operand"
9581 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
9582 (const_int 0)))]
9583 "TARGET_32BIT"
9584 "*
9585 {
9586 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9587 {
9588 {\"cmp%d5\\t%0, %1\",
9589 \"cmp%d4\\t%2, %3\"},
9590 {\"cmn%d5\\t%0, #%n1\",
9591 \"cmp%d4\\t%2, %3\"},
9592 {\"cmp%d5\\t%0, %1\",
9593 \"cmn%d4\\t%2, #%n3\"},
9594 {\"cmn%d5\\t%0, #%n1\",
9595 \"cmn%d4\\t%2, #%n3\"}
9596 };
9597 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9598 {
9599 {\"cmp\\t%2, %3\",
9600 \"cmp\\t%0, %1\"},
9601 {\"cmp\\t%2, %3\",
9602 \"cmn\\t%0, #%n1\"},
9603 {\"cmn\\t%2, #%n3\",
9604 \"cmp\\t%0, %1\"},
9605 {\"cmn\\t%2, #%n3\",
9606 \"cmn\\t%0, #%n1\"}
9607 };
9608 static const char *const ite[2] =
9609 {
9610 \"it\\t%d5\",
9611 \"it\\t%d4\"
9612 };
9613 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9614 CMP_CMP, CMN_CMP, CMP_CMP,
9615 CMN_CMP, CMP_CMN, CMN_CMN};
9616 int swap =
9617 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9618
9619 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9620 if (TARGET_THUMB2) {
9621 output_asm_insn (ite[swap], operands);
9622 }
9623 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9624 return \"\";
9625 }"
9626 [(set_attr "conds" "set")
9627 (set_attr "predicable" "no")
9628 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9629 (set_attr_alternative "length"
9630 [(const_int 6)
9631 (const_int 8)
9632 (const_int 8)
9633 (const_int 8)
9634 (const_int 8)
9635 (if_then_else (eq_attr "is_thumb" "no")
9636 (const_int 8)
9637 (const_int 10))
9638 (if_then_else (eq_attr "is_thumb" "no")
9639 (const_int 8)
9640 (const_int 10))
9641 (if_then_else (eq_attr "is_thumb" "no")
9642 (const_int 8)
9643 (const_int 10))
9644 (if_then_else (eq_attr "is_thumb" "no")
9645 (const_int 8)
9646 (const_int 10))])]
9647)
9648
9649(define_insn "*cmp_ior"
9650 [(set (match_operand 6 "dominant_cc_register" "")
9651 (compare
9652 (ior:SI
9653 (match_operator 4 "arm_comparison_operator"
9654 [(match_operand:SI 0 "s_register_operand"
9655 "l,l,l,r,r,r,r,r,r")
9656 (match_operand:SI 1 "arm_add_operand"
9657 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
9658 (match_operator:SI 5 "arm_comparison_operator"
9659 [(match_operand:SI 2 "s_register_operand"
9660 "l,r,r,l,l,r,r,r,r")
9661 (match_operand:SI 3 "arm_add_operand"
9662 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
9663 (const_int 0)))]
9664 "TARGET_32BIT"
9665 "*
9666 {
9667 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9668 {
9669 {\"cmp\\t%0, %1\",
9670 \"cmp\\t%2, %3\"},
9671 {\"cmn\\t%0, #%n1\",
9672 \"cmp\\t%2, %3\"},
9673 {\"cmp\\t%0, %1\",
9674 \"cmn\\t%2, #%n3\"},
9675 {\"cmn\\t%0, #%n1\",
9676 \"cmn\\t%2, #%n3\"}
9677 };
9678 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9679 {
9680 {\"cmp%D4\\t%2, %3\",
9681 \"cmp%D5\\t%0, %1\"},
9682 {\"cmp%D4\\t%2, %3\",
9683 \"cmn%D5\\t%0, #%n1\"},
9684 {\"cmn%D4\\t%2, #%n3\",
9685 \"cmp%D5\\t%0, %1\"},
9686 {\"cmn%D4\\t%2, #%n3\",
9687 \"cmn%D5\\t%0, #%n1\"}
9688 };
9689 static const char *const ite[2] =
9690 {
9691 \"it\\t%D4\",
9692 \"it\\t%D5\"
9693 };
9694 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9695 CMP_CMP, CMN_CMP, CMP_CMP,
9696 CMN_CMP, CMP_CMN, CMN_CMN};
9697 int swap =
9698 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9699
9700 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9701 if (TARGET_THUMB2) {
9702 output_asm_insn (ite[swap], operands);
9703 }
9704 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9705 return \"\";
9706 }
9707 "
9708 [(set_attr "conds" "set")
9709 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9710 (set_attr_alternative "length"
9711 [(const_int 6)
9712 (const_int 8)
9713 (const_int 8)
9714 (const_int 8)
9715 (const_int 8)
9716 (if_then_else (eq_attr "is_thumb" "no")
9717 (const_int 8)
9718 (const_int 10))
9719 (if_then_else (eq_attr "is_thumb" "no")
9720 (const_int 8)
9721 (const_int 10))
9722 (if_then_else (eq_attr "is_thumb" "no")
9723 (const_int 8)
9724 (const_int 10))
9725 (if_then_else (eq_attr "is_thumb" "no")
9726 (const_int 8)
9727 (const_int 10))])]
9728)
9729
9730(define_insn_and_split "*ior_scc_scc"
9731 [(set (match_operand:SI 0 "s_register_operand" "=r")
9732 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9733 [(match_operand:SI 1 "s_register_operand" "r")
9734 (match_operand:SI 2 "arm_add_operand" "rIL")])
9735 (match_operator:SI 6 "arm_comparison_operator"
9736 [(match_operand:SI 4 "s_register_operand" "r")
9737 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9738 (clobber (reg:CC CC_REGNUM))]
9739 "TARGET_32BIT
9740 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9741 != CCmode)"
9742 "#"
9743 "TARGET_32BIT && reload_completed"
9744 [(set (match_dup 7)
9745 (compare
9746 (ior:SI
9747 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9748 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9749 (const_int 0)))
9750 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9751 "operands[7]
9752 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9753 DOM_CC_X_OR_Y),
9754 CC_REGNUM);"
9755 [(set_attr "conds" "clob")
9756 (set_attr "length" "16")])
9757
9758; If the above pattern is followed by a CMP insn, then the compare is
9759; redundant, since we can rework the conditional instruction that follows.
9760(define_insn_and_split "*ior_scc_scc_cmp"
9761 [(set (match_operand 0 "dominant_cc_register" "")
9762 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9763 [(match_operand:SI 1 "s_register_operand" "r")
9764 (match_operand:SI 2 "arm_add_operand" "rIL")])
9765 (match_operator:SI 6 "arm_comparison_operator"
9766 [(match_operand:SI 4 "s_register_operand" "r")
9767 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9768 (const_int 0)))
9769 (set (match_operand:SI 7 "s_register_operand" "=r")
9770 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9771 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9772 "TARGET_32BIT"
9773 "#"
9774 "TARGET_32BIT && reload_completed"
9775 [(set (match_dup 0)
9776 (compare
9777 (ior:SI
9778 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9779 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9780 (const_int 0)))
9781 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9782 ""
9783 [(set_attr "conds" "set")
9784 (set_attr "length" "16")])
9785
9786(define_insn_and_split "*and_scc_scc"
9787 [(set (match_operand:SI 0 "s_register_operand" "=r")
9788 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9789 [(match_operand:SI 1 "s_register_operand" "r")
9790 (match_operand:SI 2 "arm_add_operand" "rIL")])
9791 (match_operator:SI 6 "arm_comparison_operator"
9792 [(match_operand:SI 4 "s_register_operand" "r")
9793 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9794 (clobber (reg:CC CC_REGNUM))]
9795 "TARGET_32BIT
9796 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9797 != CCmode)"
9798 "#"
9799 "TARGET_32BIT && reload_completed
9800 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9801 != CCmode)"
9802 [(set (match_dup 7)
9803 (compare
9804 (and:SI
9805 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9806 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9807 (const_int 0)))
9808 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9809 "operands[7]
9810 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9811 DOM_CC_X_AND_Y),
9812 CC_REGNUM);"
9813 [(set_attr "conds" "clob")
9814 (set_attr "length" "16")])
9815
9816; If the above pattern is followed by a CMP insn, then the compare is
9817; redundant, since we can rework the conditional instruction that follows.
9818(define_insn_and_split "*and_scc_scc_cmp"
9819 [(set (match_operand 0 "dominant_cc_register" "")
9820 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9821 [(match_operand:SI 1 "s_register_operand" "r")
9822 (match_operand:SI 2 "arm_add_operand" "rIL")])
9823 (match_operator:SI 6 "arm_comparison_operator"
9824 [(match_operand:SI 4 "s_register_operand" "r")
9825 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9826 (const_int 0)))
9827 (set (match_operand:SI 7 "s_register_operand" "=r")
9828 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9829 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9830 "TARGET_32BIT"
9831 "#"
9832 "TARGET_32BIT && reload_completed"
9833 [(set (match_dup 0)
9834 (compare
9835 (and:SI
9836 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9837 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9838 (const_int 0)))
9839 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9840 ""
9841 [(set_attr "conds" "set")
9842 (set_attr "length" "16")])
9843
9844;; If there is no dominance in the comparison, then we can still save an
9845;; instruction in the AND case, since we can know that the second compare
9846;; need only zero the value if false (if true, then the value is already
9847;; correct).
9848(define_insn_and_split "*and_scc_scc_nodom"
9849 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9850 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9851 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9852 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9853 (match_operator:SI 6 "arm_comparison_operator"
9854 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9855 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9856 (clobber (reg:CC CC_REGNUM))]
9857 "TARGET_32BIT
9858 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9859 == CCmode)"
9860 "#"
9861 "TARGET_32BIT && reload_completed"
9862 [(parallel [(set (match_dup 0)
9863 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9864 (clobber (reg:CC CC_REGNUM))])
9865 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9866 (set (match_dup 0)
9867 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9868 (match_dup 0)
9869 (const_int 0)))]
9870 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9871 operands[4], operands[5]),
9872 CC_REGNUM);
9873 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9874 operands[5]);"
9875 [(set_attr "conds" "clob")
9876 (set_attr "length" "20")])
9877
9878(define_split
9879 [(set (reg:CC_NOOV CC_REGNUM)
9880 (compare:CC_NOOV (ior:SI
9881 (and:SI (match_operand:SI 0 "s_register_operand" "")
9882 (const_int 1))
9883 (match_operator:SI 1 "arm_comparison_operator"
9884 [(match_operand:SI 2 "s_register_operand" "")
9885 (match_operand:SI 3 "arm_add_operand" "")]))
9886 (const_int 0)))
9887 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9888 "TARGET_ARM"
9889 [(set (match_dup 4)
9890 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9891 (match_dup 0)))
9892 (set (reg:CC_NOOV CC_REGNUM)
9893 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9894 (const_int 0)))]
9895 "")
9896
9897(define_split
9898 [(set (reg:CC_NOOV CC_REGNUM)
9899 (compare:CC_NOOV (ior:SI
9900 (match_operator:SI 1 "arm_comparison_operator"
9901 [(match_operand:SI 2 "s_register_operand" "")
9902 (match_operand:SI 3 "arm_add_operand" "")])
9903 (and:SI (match_operand:SI 0 "s_register_operand" "")
9904 (const_int 1)))
9905 (const_int 0)))
9906 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9907 "TARGET_ARM"
9908 [(set (match_dup 4)
9909 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9910 (match_dup 0)))
9911 (set (reg:CC_NOOV CC_REGNUM)
9912 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9913 (const_int 0)))]
9914 "")
9915;; ??? The conditional patterns above need checking for Thumb-2 usefulness
9916
9917(define_insn "*negscc"
9918 [(set (match_operand:SI 0 "s_register_operand" "=r")
9919 (neg:SI (match_operator 3 "arm_comparison_operator"
9920 [(match_operand:SI 1 "s_register_operand" "r")
9921 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
9922 (clobber (reg:CC CC_REGNUM))]
9923 "TARGET_ARM"
9924 "*
9925 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9926 return \"mov\\t%0, %1, asr #31\";
9927
9928 if (GET_CODE (operands[3]) == NE)
9929 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9930
9931 output_asm_insn (\"cmp\\t%1, %2\", operands);
9932 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9933 return \"mvn%d3\\t%0, #0\";
9934 "
9935 [(set_attr "conds" "clob")
9936 (set_attr "length" "12")]
9937)
9938
9939(define_insn "movcond"
9940 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9941 (if_then_else:SI
9942 (match_operator 5 "arm_comparison_operator"
9943 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9944 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9945 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9946 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
9947 (clobber (reg:CC CC_REGNUM))]
9948 "TARGET_ARM"
9949 "*
9950 if (GET_CODE (operands[5]) == LT
9951 && (operands[4] == const0_rtx))
9952 {
9953 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9954 {
9955 if (operands[2] == const0_rtx)
9956 return \"and\\t%0, %1, %3, asr #31\";
9957 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9958 }
9959 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9960 {
9961 if (operands[1] == const0_rtx)
9962 return \"bic\\t%0, %2, %3, asr #31\";
9963 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9964 }
9965 /* The only case that falls through to here is when both ops 1 & 2
9966 are constants. */
9967 }
9968
9969 if (GET_CODE (operands[5]) == GE
9970 && (operands[4] == const0_rtx))
9971 {
9972 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9973 {
9974 if (operands[2] == const0_rtx)
9975 return \"bic\\t%0, %1, %3, asr #31\";
9976 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9977 }
9978 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9979 {
9980 if (operands[1] == const0_rtx)
9981 return \"and\\t%0, %2, %3, asr #31\";
9982 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9983 }
9984 /* The only case that falls through to here is when both ops 1 & 2
9985 are constants. */
9986 }
9987 if (GET_CODE (operands[4]) == CONST_INT
9988 && !const_ok_for_arm (INTVAL (operands[4])))
9989 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9990 else
9991 output_asm_insn (\"cmp\\t%3, %4\", operands);
9992 if (which_alternative != 0)
9993 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9994 if (which_alternative != 1)
9995 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9996 return \"\";
9997 "
9998 [(set_attr "conds" "clob")
9999 (set_attr "length" "8,8,12")]
10000)
10001
10002;; ??? The patterns below need checking for Thumb-2 usefulness.
10003
10004(define_insn "*ifcompare_plus_move"
10005 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10006 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
10007 [(match_operand:SI 4 "s_register_operand" "r,r")
10008 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10009 (plus:SI
10010 (match_operand:SI 2 "s_register_operand" "r,r")
10011 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
10012 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
10013 (clobber (reg:CC CC_REGNUM))]
10014 "TARGET_ARM"
10015 "#"
10016 [(set_attr "conds" "clob")
10017 (set_attr "length" "8,12")]
10018)
10019
10020(define_insn "*if_plus_move"
10021 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
10022 (if_then_else:SI
10023 (match_operator 4 "arm_comparison_operator"
10024 [(match_operand 5 "cc_register" "") (const_int 0)])
10025 (plus:SI
10026 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
10027 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
10028 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
10029 "TARGET_ARM"
10030 "@
10031 add%d4\\t%0, %2, %3
10032 sub%d4\\t%0, %2, #%n3
10033 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
10034 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
10035 [(set_attr "conds" "use")
10036 (set_attr "length" "4,4,8,8")
10037 (set_attr "type" "*,*,*,*")]
10038)
10039
10040(define_insn "*ifcompare_move_plus"
10041 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10042 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
10043 [(match_operand:SI 4 "s_register_operand" "r,r")
10044 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10045 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10046 (plus:SI
10047 (match_operand:SI 2 "s_register_operand" "r,r")
10048 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
10049 (clobber (reg:CC CC_REGNUM))]
10050 "TARGET_ARM"
10051 "#"
10052 [(set_attr "conds" "clob")
10053 (set_attr "length" "8,12")]
10054)
10055
10056(define_insn "*if_move_plus"
10057 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
10058 (if_then_else:SI
10059 (match_operator 4 "arm_comparison_operator"
10060 [(match_operand 5 "cc_register" "") (const_int 0)])
10061 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
10062 (plus:SI
10063 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
10064 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
10065 "TARGET_ARM"
10066 "@
10067 add%D4\\t%0, %2, %3
10068 sub%D4\\t%0, %2, #%n3
10069 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
10070 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
10071 [(set_attr "conds" "use")
10072 (set_attr "length" "4,4,8,8")
10073 (set_attr "type" "*,*,*,*")]
10074)
10075
10076(define_insn "*ifcompare_arith_arith"
10077 [(set (match_operand:SI 0 "s_register_operand" "=r")
10078 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
10079 [(match_operand:SI 5 "s_register_operand" "r")
10080 (match_operand:SI 6 "arm_add_operand" "rIL")])
10081 (match_operator:SI 8 "shiftable_operator"
10082 [(match_operand:SI 1 "s_register_operand" "r")
10083 (match_operand:SI 2 "arm_rhs_operand" "rI")])
10084 (match_operator:SI 7 "shiftable_operator"
10085 [(match_operand:SI 3 "s_register_operand" "r")
10086 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
10087 (clobber (reg:CC CC_REGNUM))]
10088 "TARGET_ARM"
10089 "#"
10090 [(set_attr "conds" "clob")
10091 (set_attr "length" "12")]
10092)
10093
10094(define_insn "*if_arith_arith"
10095 [(set (match_operand:SI 0 "s_register_operand" "=r")
10096 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
10097 [(match_operand 8 "cc_register" "") (const_int 0)])
10098 (match_operator:SI 6 "shiftable_operator"
10099 [(match_operand:SI 1 "s_register_operand" "r")
10100 (match_operand:SI 2 "arm_rhs_operand" "rI")])
10101 (match_operator:SI 7 "shiftable_operator"
10102 [(match_operand:SI 3 "s_register_operand" "r")
10103 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
10104 "TARGET_ARM"
10105 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
10106 [(set_attr "conds" "use")
10107 (set_attr "length" "8")]
10108)
10109
10110(define_insn "*ifcompare_arith_move"
10111 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10112 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
10113 [(match_operand:SI 2 "s_register_operand" "r,r")
10114 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
10115 (match_operator:SI 7 "shiftable_operator"
10116 [(match_operand:SI 4 "s_register_operand" "r,r")
10117 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
10118 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
10119 (clobber (reg:CC CC_REGNUM))]
10120 "TARGET_ARM"
10121 "*
10122 /* If we have an operation where (op x 0) is the identity operation and
10123 the conditional operator is LT or GE and we are comparing against zero and
10124 everything is in registers then we can do this in two instructions. */
10125 if (operands[3] == const0_rtx
10126 && GET_CODE (operands[7]) != AND
10127 && GET_CODE (operands[5]) == REG
10128 && GET_CODE (operands[1]) == REG
10129 && REGNO (operands[1]) == REGNO (operands[4])
10130 && REGNO (operands[4]) != REGNO (operands[0]))
10131 {
10132 if (GET_CODE (operands[6]) == LT)
10133 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
10134 else if (GET_CODE (operands[6]) == GE)
10135 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
10136 }
10137 if (GET_CODE (operands[3]) == CONST_INT
10138 && !const_ok_for_arm (INTVAL (operands[3])))
10139 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
10140 else
10141 output_asm_insn (\"cmp\\t%2, %3\", operands);
10142 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
10143 if (which_alternative != 0)
10144 return \"mov%D6\\t%0, %1\";
10145 return \"\";
10146 "
10147 [(set_attr "conds" "clob")
10148 (set_attr "length" "8,12")]
10149)
10150
10151(define_insn "*if_arith_move"
10152 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10153 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10154 [(match_operand 6 "cc_register" "") (const_int 0)])
10155 (match_operator:SI 5 "shiftable_operator"
10156 [(match_operand:SI 2 "s_register_operand" "r,r")
10157 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
10158 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
10159 "TARGET_ARM"
10160 "@
10161 %I5%d4\\t%0, %2, %3
10162 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
10163 [(set_attr "conds" "use")
10164 (set_attr "length" "4,8")
10165 (set_attr "type" "*,*")]
10166)
10167
10168(define_insn "*ifcompare_move_arith"
10169 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10170 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
10171 [(match_operand:SI 4 "s_register_operand" "r,r")
10172 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10173 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10174 (match_operator:SI 7 "shiftable_operator"
10175 [(match_operand:SI 2 "s_register_operand" "r,r")
10176 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
10177 (clobber (reg:CC CC_REGNUM))]
10178 "TARGET_ARM"
10179 "*
10180 /* If we have an operation where (op x 0) is the identity operation and
10181 the conditional operator is LT or GE and we are comparing against zero and
10182 everything is in registers then we can do this in two instructions */
10183 if (operands[5] == const0_rtx
10184 && GET_CODE (operands[7]) != AND
10185 && GET_CODE (operands[3]) == REG
10186 && GET_CODE (operands[1]) == REG
10187 && REGNO (operands[1]) == REGNO (operands[2])
10188 && REGNO (operands[2]) != REGNO (operands[0]))
10189 {
10190 if (GET_CODE (operands[6]) == GE)
10191 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
10192 else if (GET_CODE (operands[6]) == LT)
10193 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
10194 }
10195
10196 if (GET_CODE (operands[5]) == CONST_INT
10197 && !const_ok_for_arm (INTVAL (operands[5])))
10198 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
10199 else
10200 output_asm_insn (\"cmp\\t%4, %5\", operands);
10201
10202 if (which_alternative != 0)
10203 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
10204 return \"%I7%D6\\t%0, %2, %3\";
10205 "
10206 [(set_attr "conds" "clob")
10207 (set_attr "length" "8,12")]
10208)
10209
10210(define_insn "*if_move_arith"
10211 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10212 (if_then_else:SI
10213 (match_operator 4 "arm_comparison_operator"
10214 [(match_operand 6 "cc_register" "") (const_int 0)])
10215 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10216 (match_operator:SI 5 "shiftable_operator"
10217 [(match_operand:SI 2 "s_register_operand" "r,r")
10218 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
10219 "TARGET_ARM"
10220 "@
10221 %I5%D4\\t%0, %2, %3
10222 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
10223 [(set_attr "conds" "use")
10224 (set_attr "length" "4,8")
10225 (set_attr "type" "*,*")]
10226)
10227
10228(define_insn "*ifcompare_move_not"
10229 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10230 (if_then_else:SI
10231 (match_operator 5 "arm_comparison_operator"
10232 [(match_operand:SI 3 "s_register_operand" "r,r")
10233 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10234 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10235 (not:SI
10236 (match_operand:SI 2 "s_register_operand" "r,r"))))
10237 (clobber (reg:CC CC_REGNUM))]
10238 "TARGET_ARM"
10239 "#"
10240 [(set_attr "conds" "clob")
10241 (set_attr "length" "8,12")]
10242)
10243
10244(define_insn "*if_move_not"
10245 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10246 (if_then_else:SI
10247 (match_operator 4 "arm_comparison_operator"
10248 [(match_operand 3 "cc_register" "") (const_int 0)])
10249 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10250 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
10251 "TARGET_ARM"
10252 "@
10253 mvn%D4\\t%0, %2
10254 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
10255 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
10256 [(set_attr "conds" "use")
10257 (set_attr "insn" "mvn")
10258 (set_attr "length" "4,8,8")]
10259)
10260
10261(define_insn "*ifcompare_not_move"
10262 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10263 (if_then_else:SI
10264 (match_operator 5 "arm_comparison_operator"
10265 [(match_operand:SI 3 "s_register_operand" "r,r")
10266 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10267 (not:SI
10268 (match_operand:SI 2 "s_register_operand" "r,r"))
10269 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10270 (clobber (reg:CC CC_REGNUM))]
10271 "TARGET_ARM"
10272 "#"
10273 [(set_attr "conds" "clob")
10274 (set_attr "length" "8,12")]
10275)
10276
10277(define_insn "*if_not_move"
10278 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10279 (if_then_else:SI
10280 (match_operator 4 "arm_comparison_operator"
10281 [(match_operand 3 "cc_register" "") (const_int 0)])
10282 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10283 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10284 "TARGET_ARM"
10285 "@
10286 mvn%d4\\t%0, %2
10287 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
10288 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
10289 [(set_attr "conds" "use")
10290 (set_attr "insn" "mvn")
10291 (set_attr "length" "4,8,8")]
10292)
10293
10294(define_insn "*ifcompare_shift_move"
10295 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10296 (if_then_else:SI
10297 (match_operator 6 "arm_comparison_operator"
10298 [(match_operand:SI 4 "s_register_operand" "r,r")
10299 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10300 (match_operator:SI 7 "shift_operator"
10301 [(match_operand:SI 2 "s_register_operand" "r,r")
10302 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
10303 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10304 (clobber (reg:CC CC_REGNUM))]
10305 "TARGET_ARM"
10306 "#"
10307 [(set_attr "conds" "clob")
10308 (set_attr "length" "8,12")]
10309)
10310
10311(define_insn "*if_shift_move"
10312 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10313 (if_then_else:SI
10314 (match_operator 5 "arm_comparison_operator"
10315 [(match_operand 6 "cc_register" "") (const_int 0)])
10316 (match_operator:SI 4 "shift_operator"
10317 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10318 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
10319 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10320 "TARGET_ARM"
10321 "@
10322 mov%d5\\t%0, %2%S4
10323 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
10324 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
10325 [(set_attr "conds" "use")
10326 (set_attr "shift" "2")
10327 (set_attr "length" "4,8,8")
10328 (set_attr "insn" "mov")
10329 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10330 (const_string "alu_shift")
10331 (const_string "alu_shift_reg")))]
10332)
10333
10334(define_insn "*ifcompare_move_shift"
10335 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10336 (if_then_else:SI
10337 (match_operator 6 "arm_comparison_operator"
10338 [(match_operand:SI 4 "s_register_operand" "r,r")
10339 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10340 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10341 (match_operator:SI 7 "shift_operator"
10342 [(match_operand:SI 2 "s_register_operand" "r,r")
10343 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
10344 (clobber (reg:CC CC_REGNUM))]
10345 "TARGET_ARM"
10346 "#"
10347 [(set_attr "conds" "clob")
10348 (set_attr "length" "8,12")]
10349)
10350
10351(define_insn "*if_move_shift"
10352 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10353 (if_then_else:SI
10354 (match_operator 5 "arm_comparison_operator"
10355 [(match_operand 6 "cc_register" "") (const_int 0)])
10356 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10357 (match_operator:SI 4 "shift_operator"
10358 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10359 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
10360 "TARGET_ARM"
10361 "@
10362 mov%D5\\t%0, %2%S4
10363 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10364 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
10365 [(set_attr "conds" "use")
10366 (set_attr "shift" "2")
10367 (set_attr "length" "4,8,8")
10368 (set_attr "insn" "mov")
10369 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10370 (const_string "alu_shift")
10371 (const_string "alu_shift_reg")))]
10372)
10373
10374(define_insn "*ifcompare_shift_shift"
10375 [(set (match_operand:SI 0 "s_register_operand" "=r")
10376 (if_then_else:SI
10377 (match_operator 7 "arm_comparison_operator"
10378 [(match_operand:SI 5 "s_register_operand" "r")
10379 (match_operand:SI 6 "arm_add_operand" "rIL")])
10380 (match_operator:SI 8 "shift_operator"
10381 [(match_operand:SI 1 "s_register_operand" "r")
10382 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10383 (match_operator:SI 9 "shift_operator"
10384 [(match_operand:SI 3 "s_register_operand" "r")
10385 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
10386 (clobber (reg:CC CC_REGNUM))]
10387 "TARGET_ARM"
10388 "#"
10389 [(set_attr "conds" "clob")
10390 (set_attr "length" "12")]
10391)
10392
10393(define_insn "*if_shift_shift"
10394 [(set (match_operand:SI 0 "s_register_operand" "=r")
10395 (if_then_else:SI
10396 (match_operator 5 "arm_comparison_operator"
10397 [(match_operand 8 "cc_register" "") (const_int 0)])
10398 (match_operator:SI 6 "shift_operator"
10399 [(match_operand:SI 1 "s_register_operand" "r")
10400 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10401 (match_operator:SI 7 "shift_operator"
10402 [(match_operand:SI 3 "s_register_operand" "r")
10403 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
10404 "TARGET_ARM"
10405 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
10406 [(set_attr "conds" "use")
10407 (set_attr "shift" "1")
10408 (set_attr "length" "8")
10409 (set_attr "insn" "mov")
10410 (set (attr "type") (if_then_else
10411 (and (match_operand 2 "const_int_operand" "")
10412 (match_operand 4 "const_int_operand" ""))
10413 (const_string "alu_shift")
10414 (const_string "alu_shift_reg")))]
10415)
10416
10417(define_insn "*ifcompare_not_arith"
10418 [(set (match_operand:SI 0 "s_register_operand" "=r")
10419 (if_then_else:SI
10420 (match_operator 6 "arm_comparison_operator"
10421 [(match_operand:SI 4 "s_register_operand" "r")
10422 (match_operand:SI 5 "arm_add_operand" "rIL")])
10423 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10424 (match_operator:SI 7 "shiftable_operator"
10425 [(match_operand:SI 2 "s_register_operand" "r")
10426 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
10427 (clobber (reg:CC CC_REGNUM))]
10428 "TARGET_ARM"
10429 "#"
10430 [(set_attr "conds" "clob")
10431 (set_attr "length" "12")]
10432)
10433
10434(define_insn "*if_not_arith"
10435 [(set (match_operand:SI 0 "s_register_operand" "=r")
10436 (if_then_else:SI
10437 (match_operator 5 "arm_comparison_operator"
10438 [(match_operand 4 "cc_register" "") (const_int 0)])
10439 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10440 (match_operator:SI 6 "shiftable_operator"
10441 [(match_operand:SI 2 "s_register_operand" "r")
10442 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
10443 "TARGET_ARM"
10444 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
10445 [(set_attr "conds" "use")
10446 (set_attr "insn" "mvn")
10447 (set_attr "length" "8")]
10448)
10449
10450(define_insn "*ifcompare_arith_not"
10451 [(set (match_operand:SI 0 "s_register_operand" "=r")
10452 (if_then_else:SI
10453 (match_operator 6 "arm_comparison_operator"
10454 [(match_operand:SI 4 "s_register_operand" "r")
10455 (match_operand:SI 5 "arm_add_operand" "rIL")])
10456 (match_operator:SI 7 "shiftable_operator"
10457 [(match_operand:SI 2 "s_register_operand" "r")
10458 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10459 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
10460 (clobber (reg:CC CC_REGNUM))]
10461 "TARGET_ARM"
10462 "#"
10463 [(set_attr "conds" "clob")
10464 (set_attr "length" "12")]
10465)
10466
10467(define_insn "*if_arith_not"
10468 [(set (match_operand:SI 0 "s_register_operand" "=r")
10469 (if_then_else:SI
10470 (match_operator 5 "arm_comparison_operator"
10471 [(match_operand 4 "cc_register" "") (const_int 0)])
10472 (match_operator:SI 6 "shiftable_operator"
10473 [(match_operand:SI 2 "s_register_operand" "r")
10474 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10475 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
10476 "TARGET_ARM"
10477 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
10478 [(set_attr "conds" "use")
10479 (set_attr "insn" "mvn")
10480 (set_attr "length" "8")]
10481)
10482
10483(define_insn "*ifcompare_neg_move"
10484 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10485 (if_then_else:SI
10486 (match_operator 5 "arm_comparison_operator"
10487 [(match_operand:SI 3 "s_register_operand" "r,r")
10488 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10489 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10490 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10491 (clobber (reg:CC CC_REGNUM))]
10492 "TARGET_ARM"
10493 "#"
10494 [(set_attr "conds" "clob")
10495 (set_attr "length" "8,12")]
10496)
10497
10498(define_insn "*if_neg_move"
10499 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10500 (if_then_else:SI
10501 (match_operator 4 "arm_comparison_operator"
10502 [(match_operand 3 "cc_register" "") (const_int 0)])
10503 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10504 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10505 "TARGET_ARM"
10506 "@
10507 rsb%d4\\t%0, %2, #0
10508 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
10509 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
10510 [(set_attr "conds" "use")
10511 (set_attr "length" "4,8,8")]
10512)
10513
10514(define_insn "*ifcompare_move_neg"
10515 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10516 (if_then_else:SI
10517 (match_operator 5 "arm_comparison_operator"
10518 [(match_operand:SI 3 "s_register_operand" "r,r")
10519 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10520 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10521 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
10522 (clobber (reg:CC CC_REGNUM))]
10523 "TARGET_ARM"
10524 "#"
10525 [(set_attr "conds" "clob")
10526 (set_attr "length" "8,12")]
10527)
10528
10529(define_insn "*if_move_neg"
10530 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10531 (if_then_else:SI
10532 (match_operator 4 "arm_comparison_operator"
10533 [(match_operand 3 "cc_register" "") (const_int 0)])
10534 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10535 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
10536 "TARGET_ARM"
10537 "@
10538 rsb%D4\\t%0, %2, #0
10539 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
10540 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
10541 [(set_attr "conds" "use")
10542 (set_attr "length" "4,8,8")]
10543)
10544
10545(define_insn "*arith_adjacentmem"
10546 [(set (match_operand:SI 0 "s_register_operand" "=r")
10547 (match_operator:SI 1 "shiftable_operator"
10548 [(match_operand:SI 2 "memory_operand" "m")
10549 (match_operand:SI 3 "memory_operand" "m")]))
10550 (clobber (match_scratch:SI 4 "=r"))]
10551 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
10552 "*
10553 {
10554 rtx ldm[3];
10555 rtx arith[4];
10556 rtx base_reg;
10557 HOST_WIDE_INT val1 = 0, val2 = 0;
10558
10559 if (REGNO (operands[0]) > REGNO (operands[4]))
10560 {
10561 ldm[1] = operands[4];
10562 ldm[2] = operands[0];
10563 }
10564 else
10565 {
10566 ldm[1] = operands[0];
10567 ldm[2] = operands[4];
10568 }
10569
10570 base_reg = XEXP (operands[2], 0);
10571
10572 if (!REG_P (base_reg))
10573 {
10574 val1 = INTVAL (XEXP (base_reg, 1));
10575 base_reg = XEXP (base_reg, 0);
10576 }
10577
10578 if (!REG_P (XEXP (operands[3], 0)))
10579 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
10580
10581 arith[0] = operands[0];
10582 arith[3] = operands[1];
10583
10584 if (val1 < val2)
10585 {
10586 arith[1] = ldm[1];
10587 arith[2] = ldm[2];
10588 }
10589 else
10590 {
10591 arith[1] = ldm[2];
10592 arith[2] = ldm[1];
10593 }
10594
10595 ldm[0] = base_reg;
10596 if (val1 !=0 && val2 != 0)
10597 {
10598 rtx ops[3];
10599
10600 if (val1 == 4 || val2 == 4)
10601 /* Other val must be 8, since we know they are adjacent and neither
10602 is zero. */
10603 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
10604 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
10605 {
10606 ldm[0] = ops[0] = operands[4];
10607 ops[1] = base_reg;
10608 ops[2] = GEN_INT (val1);
10609 output_add_immediate (ops);
10610 if (val1 < val2)
10611 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10612 else
10613 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10614 }
10615 else
10616 {
10617 /* Offset is out of range for a single add, so use two ldr. */
10618 ops[0] = ldm[1];
10619 ops[1] = base_reg;
10620 ops[2] = GEN_INT (val1);
10621 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10622 ops[0] = ldm[2];
10623 ops[2] = GEN_INT (val2);
10624 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10625 }
10626 }
10627 else if (val1 != 0)
10628 {
10629 if (val1 < val2)
10630 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10631 else
10632 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10633 }
10634 else
10635 {
10636 if (val1 < val2)
10637 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10638 else
10639 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10640 }
10641 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10642 return \"\";
10643 }"
10644 [(set_attr "length" "12")
10645 (set_attr "predicable" "yes")
10646 (set_attr "type" "load1")]
10647)
10648
10649; This pattern is never tried by combine, so do it as a peephole
10650
10651(define_peephole2
10652 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10653 (match_operand:SI 1 "arm_general_register_operand" ""))
10654 (set (reg:CC CC_REGNUM)
10655 (compare:CC (match_dup 1) (const_int 0)))]
10656 "TARGET_ARM"
10657 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10658 (set (match_dup 0) (match_dup 1))])]
10659 ""
10660)
10661
10662(define_split
10663 [(set (match_operand:SI 0 "s_register_operand" "")
10664 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10665 (const_int 0))
10666 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
10667 [(match_operand:SI 3 "s_register_operand" "")
10668 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10669 (clobber (match_operand:SI 5 "s_register_operand" ""))]
10670 "TARGET_ARM"
10671 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10672 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10673 (match_dup 5)))]
10674 ""
10675)
10676
10677;; This split can be used because CC_Z mode implies that the following
10678;; branch will be an equality, or an unsigned inequality, so the sign
10679;; extension is not needed.
10680
10681(define_split
10682 [(set (reg:CC_Z CC_REGNUM)
10683 (compare:CC_Z
10684 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
10685 (const_int 24))
10686 (match_operand 1 "const_int_operand" "")))
10687 (clobber (match_scratch:SI 2 ""))]
10688 "TARGET_ARM
10689 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10690 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
10691 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
10692 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
10693 "
10694 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
10695 "
10696)
10697;; ??? Check the patterns above for Thumb-2 usefulness
10698
10699(define_expand "prologue"
10700 [(clobber (const_int 0))]
10701 "TARGET_EITHER"
10702 "if (TARGET_32BIT)
10703 arm_expand_prologue ();
10704 else
10705 thumb1_expand_prologue ();
10706 DONE;
10707 "
10708)
10709
10710(define_expand "epilogue"
10711 [(clobber (const_int 0))]
10712 "TARGET_EITHER"
10713 "
10714 if (crtl->calls_eh_return)
10715 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
10716 if (TARGET_THUMB1)
10717 thumb1_expand_epilogue ();
10718 else if (USE_RETURN_INSN (FALSE))
10719 {
10720 emit_jump_insn (gen_return ());
10721 DONE;
10722 }
10723 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10724 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10725 DONE;
10726 "
10727)
10728
10729(define_insn "prologue_thumb1_interwork"
10730 [(unspec_volatile [(const_int 0)] VUNSPEC_THUMB1_INTERWORK)]
10731 "TARGET_THUMB1"
10732 "* return thumb1_output_interwork ();"
10733 [(set_attr "length" "8")]
10734)
10735
10736;; Note - although unspec_volatile's USE all hard registers,
10737;; USEs are ignored after relaod has completed. Thus we need
10738;; to add an unspec of the link register to ensure that flow
10739;; does not think that it is unused by the sibcall branch that
10740;; will replace the standard function epilogue.
10741(define_insn "sibcall_epilogue"
10742 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10743 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10744 "TARGET_32BIT"
10745 "*
10746 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
10747 return output_return_instruction (const_true_rtx, FALSE, FALSE);
10748 return arm_output_epilogue (next_nonnote_insn (insn));
10749 "
10750;; Length is absolute worst case
10751 [(set_attr "length" "44")
10752 (set_attr "type" "block")
10753 ;; We don't clobber the conditions, but the potential length of this
10754 ;; operation is sufficient to make conditionalizing the sequence
10755 ;; unlikely to be profitable.
10756 (set_attr "conds" "clob")]
10757)
10758
10759(define_insn "*epilogue_insns"
10760 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
10761 "TARGET_EITHER"
10762 "*
10763 if (TARGET_32BIT)
10764 return arm_output_epilogue (NULL);
10765 else /* TARGET_THUMB1 */
10766 return thumb1_unexpanded_epilogue ();
10767 "
10768 ; Length is absolute worst case
10769 [(set_attr "length" "44")
10770 (set_attr "type" "block")
10771 ;; We don't clobber the conditions, but the potential length of this
10772 ;; operation is sufficient to make conditionalizing the sequence
10773 ;; unlikely to be profitable.
10774 (set_attr "conds" "clob")]
10775)
10776
10777(define_expand "eh_epilogue"
10778 [(use (match_operand:SI 0 "register_operand" ""))
10779 (use (match_operand:SI 1 "register_operand" ""))
10780 (use (match_operand:SI 2 "register_operand" ""))]
10781 "TARGET_EITHER"
10782 "
10783 {
10784 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10785 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10786 {
10787 rtx ra = gen_rtx_REG (Pmode, 2);
10788
10789 emit_move_insn (ra, operands[2]);
10790 operands[2] = ra;
10791 }
10792 /* This is a hack -- we may have crystalized the function type too
10793 early. */
10794 cfun->machine->func_type = 0;
10795 }"
10796)
10797
10798;; This split is only used during output to reduce the number of patterns
10799;; that need assembler instructions adding to them. We allowed the setting
10800;; of the conditions to be implicit during rtl generation so that
10801;; the conditional compare patterns would work. However this conflicts to
10802;; some extent with the conditional data operations, so we have to split them
10803;; up again here.
10804
10805;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10806;; conditional execution sufficient?
10807
10808(define_split
10809 [(set (match_operand:SI 0 "s_register_operand" "")
10810 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10811 [(match_operand 2 "" "") (match_operand 3 "" "")])
10812 (match_dup 0)
10813 (match_operand 4 "" "")))
10814 (clobber (reg:CC CC_REGNUM))]
10815 "TARGET_ARM && reload_completed"
10816 [(set (match_dup 5) (match_dup 6))
10817 (cond_exec (match_dup 7)
10818 (set (match_dup 0) (match_dup 4)))]
10819 "
10820 {
10821 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10822 operands[2], operands[3]);
10823 enum rtx_code rc = GET_CODE (operands[1]);
10824
10825 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10826 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10827 if (mode == CCFPmode || mode == CCFPEmode)
10828 rc = reverse_condition_maybe_unordered (rc);
10829 else
10830 rc = reverse_condition (rc);
10831
10832 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10833 }"
10834)
10835
10836(define_split
10837 [(set (match_operand:SI 0 "s_register_operand" "")
10838 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10839 [(match_operand 2 "" "") (match_operand 3 "" "")])
10840 (match_operand 4 "" "")
10841 (match_dup 0)))
10842 (clobber (reg:CC CC_REGNUM))]
10843 "TARGET_ARM && reload_completed"
10844 [(set (match_dup 5) (match_dup 6))
10845 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10846 (set (match_dup 0) (match_dup 4)))]
10847 "
10848 {
10849 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10850 operands[2], operands[3]);
10851
10852 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10853 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10854 }"
10855)
10856
10857(define_split
10858 [(set (match_operand:SI 0 "s_register_operand" "")
10859 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10860 [(match_operand 2 "" "") (match_operand 3 "" "")])
10861 (match_operand 4 "" "")
10862 (match_operand 5 "" "")))
10863 (clobber (reg:CC CC_REGNUM))]
10864 "TARGET_ARM && reload_completed"
10865 [(set (match_dup 6) (match_dup 7))
10866 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10867 (set (match_dup 0) (match_dup 4)))
10868 (cond_exec (match_dup 8)
10869 (set (match_dup 0) (match_dup 5)))]
10870 "
10871 {
10872 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10873 operands[2], operands[3]);
10874 enum rtx_code rc = GET_CODE (operands[1]);
10875
10876 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10877 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10878 if (mode == CCFPmode || mode == CCFPEmode)
10879 rc = reverse_condition_maybe_unordered (rc);
10880 else
10881 rc = reverse_condition (rc);
10882
10883 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10884 }"
10885)
10886
10887(define_split
10888 [(set (match_operand:SI 0 "s_register_operand" "")
10889 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10890 [(match_operand:SI 2 "s_register_operand" "")
10891 (match_operand:SI 3 "arm_add_operand" "")])
10892 (match_operand:SI 4 "arm_rhs_operand" "")
10893 (not:SI
10894 (match_operand:SI 5 "s_register_operand" ""))))
10895 (clobber (reg:CC CC_REGNUM))]
10896 "TARGET_ARM && reload_completed"
10897 [(set (match_dup 6) (match_dup 7))
10898 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10899 (set (match_dup 0) (match_dup 4)))
10900 (cond_exec (match_dup 8)
10901 (set (match_dup 0) (not:SI (match_dup 5))))]
10902 "
10903 {
10904 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10905 operands[2], operands[3]);
10906 enum rtx_code rc = GET_CODE (operands[1]);
10907
10908 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10909 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10910 if (mode == CCFPmode || mode == CCFPEmode)
10911 rc = reverse_condition_maybe_unordered (rc);
10912 else
10913 rc = reverse_condition (rc);
10914
10915 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10916 }"
10917)
10918
10919(define_insn "*cond_move_not"
10920 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10921 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10922 [(match_operand 3 "cc_register" "") (const_int 0)])
10923 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10924 (not:SI
10925 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10926 "TARGET_ARM"
10927 "@
10928 mvn%D4\\t%0, %2
10929 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10930 [(set_attr "conds" "use")
10931 (set_attr "insn" "mvn")
10932 (set_attr "length" "4,8")]
10933)
10934
10935;; The next two patterns occur when an AND operation is followed by a
10936;; scc insn sequence
10937
10938(define_insn "*sign_extract_onebit"
10939 [(set (match_operand:SI 0 "s_register_operand" "=r")
10940 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10941 (const_int 1)
10942 (match_operand:SI 2 "const_int_operand" "n")))
10943 (clobber (reg:CC CC_REGNUM))]
10944 "TARGET_ARM"
10945 "*
10946 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10947 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10948 return \"mvnne\\t%0, #0\";
10949 "
10950 [(set_attr "conds" "clob")
10951 (set_attr "length" "8")]
10952)
10953
10954(define_insn "*not_signextract_onebit"
10955 [(set (match_operand:SI 0 "s_register_operand" "=r")
10956 (not:SI
10957 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10958 (const_int 1)
10959 (match_operand:SI 2 "const_int_operand" "n"))))
10960 (clobber (reg:CC CC_REGNUM))]
10961 "TARGET_ARM"
10962 "*
10963 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10964 output_asm_insn (\"tst\\t%1, %2\", operands);
10965 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10966 return \"movne\\t%0, #0\";
10967 "
10968 [(set_attr "conds" "clob")
10969 (set_attr "length" "12")]
10970)
10971;; ??? The above patterns need auditing for Thumb-2
10972
10973;; Push multiple registers to the stack. Registers are in parallel (use ...)
10974;; expressions. For simplicity, the first register is also in the unspec
10975;; part.
10976;; To avoid the usage of GNU extension, the length attribute is computed
10977;; in a C function arm_attr_length_push_multi.
10978(define_insn "*push_multi"
10979 [(match_parallel 2 "multi_register_push"
10980 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
10981 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
10982 UNSPEC_PUSH_MULT))])]
10983 ""
10984 "*
10985 {
10986 int num_saves = XVECLEN (operands[2], 0);
10987
10988 /* For the StrongARM at least it is faster to
10989 use STR to store only a single register.
10990 In Thumb mode always use push, and the assembler will pick
10991 something appropriate. */
10992 if (num_saves == 1 && TARGET_ARM)
10993 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
10994 else
10995 {
10996 int i;
10997 char pattern[100];
10998
10999 if (TARGET_ARM)
11000 strcpy (pattern, \"stm%(fd%)\\t%m0!, {%1\");
11001 else if (TARGET_THUMB2)
11002 strcpy (pattern, \"push%?\\t{%1\");
11003 else
11004 strcpy (pattern, \"push\\t{%1\");
11005
11006 for (i = 1; i < num_saves; i++)
11007 {
11008 strcat (pattern, \", %|\");
11009 strcat (pattern,
11010 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
11011 }
11012
11013 strcat (pattern, \"}\");
11014 output_asm_insn (pattern, operands);
11015 }
11016
11017 return \"\";
11018 }"
11019 [(set_attr "type" "store4")
11020 (set (attr "length")
11021 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
11022)
11023
11024(define_insn "stack_tie"
11025 [(set (mem:BLK (scratch))
11026 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
11027 (match_operand:SI 1 "s_register_operand" "rk")]
11028 UNSPEC_PRLG_STK))]
11029 ""
11030 ""
11031 [(set_attr "length" "0")]
11032)
11033
11034;; Similarly for the floating point registers
11035(define_insn "*push_fp_multi"
11036 [(match_parallel 2 "multi_register_push"
11037 [(set (match_operand:BLK 0 "memory_operand" "=m")
11038 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "")]
11039 UNSPEC_PUSH_MULT))])]
11040 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
11041 "*
11042 {
11043 char pattern[100];
11044
11045 sprintf (pattern, \"sfm%%(fd%%)\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
11046 output_asm_insn (pattern, operands);
11047 return \"\";
11048 }"
11049 [(set_attr "type" "f_fpa_store")]
11050)
11051
11052;; Special patterns for dealing with the constant pool
11053
11054(define_insn "align_4"
11055 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
11056 "TARGET_EITHER"
11057 "*
11058 assemble_align (32);
11059 return \"\";
11060 "
11061)
11062
11063(define_insn "align_8"
11064 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
11065 "TARGET_EITHER"
11066 "*
11067 assemble_align (64);
11068 return \"\";
11069 "
11070)
11071
11072(define_insn "consttable_end"
11073 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
11074 "TARGET_EITHER"
11075 "*
11076 making_const_table = FALSE;
11077 return \"\";
11078 "
11079)
11080
11081(define_insn "consttable_1"
11082 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
11083 "TARGET_THUMB1"
11084 "*
11085 making_const_table = TRUE;
11086 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
11087 assemble_zeros (3);
11088 return \"\";
11089 "
11090 [(set_attr "length" "4")]
11091)
11092
11093(define_insn "consttable_2"
11094 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
11095 "TARGET_THUMB1"
11096 "*
11097 making_const_table = TRUE;
11098 gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
11099 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
11100 assemble_zeros (2);
11101 return \"\";
11102 "
11103 [(set_attr "length" "4")]
11104)
11105
11106(define_insn "consttable_4"
11107 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
11108 "TARGET_EITHER"
11109 "*
11110 {
11111 rtx x = operands[0];
11112 making_const_table = TRUE;
11113 switch (GET_MODE_CLASS (GET_MODE (x)))
11114 {
11115 case MODE_FLOAT:
11116 if (GET_MODE (x) == HFmode)
11117 arm_emit_fp16_const (x);
11118 else
11119 {
11120 REAL_VALUE_TYPE r;
11121 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
11122 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
11123 }
11124 break;
11125 default:
11126 /* XXX: Sometimes gcc does something really dumb and ends up with
11127 a HIGH in a constant pool entry, usually because it's trying to
11128 load into a VFP register. We know this will always be used in
11129 combination with a LO_SUM which ignores the high bits, so just
11130 strip off the HIGH. */
11131 if (GET_CODE (x) == HIGH)
11132 x = XEXP (x, 0);
11133 assemble_integer (x, 4, BITS_PER_WORD, 1);
11134 mark_symbol_refs_as_used (x);
11135 break;
11136 }
11137 return \"\";
11138 }"
11139 [(set_attr "length" "4")]
11140)
11141
11142(define_insn "consttable_8"
11143 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
11144 "TARGET_EITHER"
11145 "*
11146 {
11147 making_const_table = TRUE;
11148 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11149 {
11150 case MODE_FLOAT:
11151 {
11152 REAL_VALUE_TYPE r;
11153 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
11154 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
11155 break;
11156 }
11157 default:
11158 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
11159 break;
11160 }
11161 return \"\";
11162 }"
11163 [(set_attr "length" "8")]
11164)
11165
11166(define_insn "consttable_16"
11167 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
11168 "TARGET_EITHER"
11169 "*
11170 {
11171 making_const_table = TRUE;
11172 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11173 {
11174 case MODE_FLOAT:
11175 {
11176 REAL_VALUE_TYPE r;
11177 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
11178 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
11179 break;
11180 }
11181 default:
11182 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
11183 break;
11184 }
11185 return \"\";
11186 }"
11187 [(set_attr "length" "16")]
11188)
11189
11190;; Miscellaneous Thumb patterns
11191
11192(define_expand "tablejump"
11193 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
11194 (use (label_ref (match_operand 1 "" "")))])]
11195 "TARGET_THUMB1"
11196 "
11197 if (flag_pic)
11198 {
11199 /* Hopefully, CSE will eliminate this copy. */
11200 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
11201 rtx reg2 = gen_reg_rtx (SImode);
11202
11203 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
11204 operands[0] = reg2;
11205 }
11206 "
11207)
11208
11209;; NB never uses BX.
11210(define_insn "*thumb1_tablejump"
11211 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
11212 (use (label_ref (match_operand 1 "" "")))]
11213 "TARGET_THUMB1"
11214 "mov\\t%|pc, %0"
11215 [(set_attr "length" "2")]
11216)
11217
11218;; V5 Instructions,
11219
11220(define_insn "clzsi2"
11221 [(set (match_operand:SI 0 "s_register_operand" "=r")
11222 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
11223 "TARGET_32BIT && arm_arch5"
11224 "clz%?\\t%0, %1"
11225 [(set_attr "predicable" "yes")
11226 (set_attr "insn" "clz")])
11227
11228(define_insn "rbitsi2"
11229 [(set (match_operand:SI 0 "s_register_operand" "=r")
11230 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
11231 "TARGET_32BIT && arm_arch_thumb2"
11232 "rbit%?\\t%0, %1"
11233 [(set_attr "predicable" "yes")
11234 (set_attr "insn" "clz")])
11235
11236(define_expand "ctzsi2"
11237 [(set (match_operand:SI 0 "s_register_operand" "")
11238 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
11239 "TARGET_32BIT && arm_arch_thumb2"
11240 "
11241 {
11242 rtx tmp = gen_reg_rtx (SImode);
11243 emit_insn (gen_rbitsi2 (tmp, operands[1]));
11244 emit_insn (gen_clzsi2 (operands[0], tmp));
11245 }
11246 DONE;
11247 "
11248)
11249
11250;; V5E instructions.
11251
11252(define_insn "prefetch"
11253 [(prefetch (match_operand:SI 0 "address_operand" "p")
11254 (match_operand:SI 1 "" "")
11255 (match_operand:SI 2 "" ""))]
11256 "TARGET_32BIT && arm_arch5e"
11257 "pld\\t%a0")
11258
11259;; General predication pattern
11260
11261(define_cond_exec
11262 [(match_operator 0 "arm_comparison_operator"
11263 [(match_operand 1 "cc_register" "")
11264 (const_int 0)])]
11265 "TARGET_32BIT"
11266 ""
11267)
11268
11269(define_insn "prologue_use"
11270 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
11271 ""
11272 "%@ %0 needed for prologue"
11273 [(set_attr "length" "0")]
11274)
11275
11276
11277;; Patterns for exception handling
11278
11279(define_expand "eh_return"
11280 [(use (match_operand 0 "general_operand" ""))]
11281 "TARGET_EITHER"
11282 "
11283 {
11284 if (TARGET_32BIT)
11285 emit_insn (gen_arm_eh_return (operands[0]));
11286 else
11287 emit_insn (gen_thumb_eh_return (operands[0]));
11288 DONE;
11289 }"
11290)
11291
11292;; We can't expand this before we know where the link register is stored.
11293(define_insn_and_split "arm_eh_return"
11294 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11295 VUNSPEC_EH_RETURN)
11296 (clobber (match_scratch:SI 1 "=&r"))]
11297 "TARGET_ARM"
11298 "#"
11299 "&& reload_completed"
11300 [(const_int 0)]
11301 "
11302 {
11303 arm_set_return_address (operands[0], operands[1]);
11304 DONE;
11305 }"
11306)
11307
11308(define_insn_and_split "thumb_eh_return"
11309 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
11310 VUNSPEC_EH_RETURN)
11311 (clobber (match_scratch:SI 1 "=&l"))]
11312 "TARGET_THUMB1"
11313 "#"
11314 "&& reload_completed"
11315 [(const_int 0)]
11316 "
11317 {
11318 thumb_set_return_address (operands[0], operands[1]);
11319 DONE;
11320 }"
11321)
11322
11323\f
11324;; TLS support
11325
11326(define_insn "load_tp_hard"
11327 [(set (match_operand:SI 0 "register_operand" "=r")
11328 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11329 "TARGET_HARD_TP"
11330 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
11331 [(set_attr "predicable" "yes")]
11332)
11333
11334;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11335(define_insn "load_tp_soft"
11336 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11337 (clobber (reg:SI LR_REGNUM))
11338 (clobber (reg:SI IP_REGNUM))
11339 (clobber (reg:CC CC_REGNUM))]
11340 "TARGET_SOFT_TP"
11341 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
11342 [(set_attr "conds" "clob")]
11343)
11344
11345;; tls descriptor call
11346(define_insn "tlscall"
11347 [(set (reg:SI R0_REGNUM)
11348 (unspec:SI [(reg:SI R0_REGNUM)
11349 (match_operand:SI 0 "" "X")
11350 (match_operand 1 "" "")] UNSPEC_TLS))
11351 (clobber (reg:SI R1_REGNUM))
11352 (clobber (reg:SI LR_REGNUM))
11353 (clobber (reg:SI CC_REGNUM))]
11354 "TARGET_GNU2_TLS"
11355 {
11356 targetm.asm_out.internal_label (asm_out_file, "LPIC",
11357 INTVAL (operands[1]));
11358 return "bl\\t%c0(tlscall)";
11359 }
11360 [(set_attr "conds" "clob")
11361 (set_attr "length" "4")]
11362)
11363
11364;;
11365
11366;; We only care about the lower 16 bits of the constant
11367;; being inserted into the upper 16 bits of the register.
11368(define_insn "*arm_movtas_ze"
11369 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
11370 (const_int 16)
11371 (const_int 16))
11372 (match_operand:SI 1 "const_int_operand" ""))]
11373 "arm_arch_thumb2"
11374 "movt%?\t%0, %L1"
11375 [(set_attr "predicable" "yes")
11376 (set_attr "length" "4")]
11377)
11378
11379(define_insn "*arm_rev"
11380 [(set (match_operand:SI 0 "s_register_operand" "=r")
11381 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
11382 "TARGET_32BIT && arm_arch6"
11383 "rev%?\t%0, %1"
11384 [(set_attr "predicable" "yes")
11385 (set_attr "length" "4")]
11386)
11387
11388(define_insn "*thumb1_rev"
11389 [(set (match_operand:SI 0 "s_register_operand" "=l")
11390 (bswap:SI (match_operand:SI 1 "s_register_operand" "l")))]
11391 "TARGET_THUMB1 && arm_arch6"
11392 "rev\t%0, %1"
11393 [(set_attr "length" "2")]
11394)
11395
11396(define_expand "arm_legacy_rev"
11397 [(set (match_operand:SI 2 "s_register_operand" "")
11398 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
11399 (const_int 16))
11400 (match_dup 1)))
11401 (set (match_dup 2)
11402 (lshiftrt:SI (match_dup 2)
11403 (const_int 8)))
11404 (set (match_operand:SI 3 "s_register_operand" "")
11405 (rotatert:SI (match_dup 1)
11406 (const_int 8)))
11407 (set (match_dup 2)
11408 (and:SI (match_dup 2)
11409 (const_int -65281)))
11410 (set (match_operand:SI 0 "s_register_operand" "")
11411 (xor:SI (match_dup 3)
11412 (match_dup 2)))]
11413 "TARGET_32BIT"
11414 ""
11415)
11416
11417;; Reuse temporaries to keep register pressure down.
11418(define_expand "thumb_legacy_rev"
11419 [(set (match_operand:SI 2 "s_register_operand" "")
11420 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
11421 (const_int 24)))
11422 (set (match_operand:SI 3 "s_register_operand" "")
11423 (lshiftrt:SI (match_dup 1)
11424 (const_int 24)))
11425 (set (match_dup 3)
11426 (ior:SI (match_dup 3)
11427 (match_dup 2)))
11428 (set (match_operand:SI 4 "s_register_operand" "")
11429 (const_int 16))
11430 (set (match_operand:SI 5 "s_register_operand" "")
11431 (rotatert:SI (match_dup 1)
11432 (match_dup 4)))
11433 (set (match_dup 2)
11434 (ashift:SI (match_dup 5)
11435 (const_int 24)))
11436 (set (match_dup 5)
11437 (lshiftrt:SI (match_dup 5)
11438 (const_int 24)))
11439 (set (match_dup 5)
11440 (ior:SI (match_dup 5)
11441 (match_dup 2)))
11442 (set (match_dup 5)
11443 (rotatert:SI (match_dup 5)
11444 (match_dup 4)))
11445 (set (match_operand:SI 0 "s_register_operand" "")
11446 (ior:SI (match_dup 5)
11447 (match_dup 3)))]
11448 "TARGET_THUMB"
11449 ""
11450)
11451
11452(define_expand "bswapsi2"
11453 [(set (match_operand:SI 0 "s_register_operand" "=r")
11454 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
11455"TARGET_EITHER && (arm_arch6 || !optimize_size)"
11456"
11457 if (!arm_arch6)
11458 {
11459 rtx op2 = gen_reg_rtx (SImode);
11460 rtx op3 = gen_reg_rtx (SImode);
11461
11462 if (TARGET_THUMB)
11463 {
11464 rtx op4 = gen_reg_rtx (SImode);
11465 rtx op5 = gen_reg_rtx (SImode);
11466
11467 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11468 op2, op3, op4, op5));
11469 }
11470 else
11471 {
11472 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11473 op2, op3));
11474 }
11475
11476 DONE;
11477 }
11478 "
11479)
11480
11481;; Load the load/store multiple patterns
11482(include "ldmstm.md")
11483;; Load the FPA co-processor patterns
11484(include "fpa.md")
11485;; Load the Maverick co-processor patterns
11486(include "cirrus.md")
11487;; Vector bits common to IWMMXT and Neon
11488(include "vec-common.md")
11489;; Load the Intel Wireless Multimedia Extension patterns
11490(include "iwmmxt.md")
11491;; Load the VFP co-processor patterns
11492(include "vfp.md")
11493;; Thumb-2 patterns
11494(include "thumb2.md")
11495;; Neon patterns
11496(include "neon.md")
11497;; Synchronization Primitives
11498(include "sync.md")
11499;; Fixed-point patterns
11500(include "arm-fixed.md")