]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
2012-05-22 Dimitrios Apostolou <jimis@gmx.net>
[thirdparty/gcc.git] / gcc / config / arm / arm.md
CommitLineData
129a2fe4 1;;- Machine description for ARM for GNU compiler
063a05c7 2;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
2d05dfad 3;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
934a1e72 4;; Free Software Foundation, Inc.
b11cae9e 5;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
f082f1c4 6;; and Martin Simmons (@harleqn.co.uk).
129a2fe4 7;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
b11cae9e 8
acf6ed70 9;; This file is part of GCC.
b11cae9e 10
acf6ed70 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
038d1e19 13;; by the Free Software Foundation; either version 3, or (at your
acf6ed70 14;; option) any later version.
b11cae9e 15
acf6ed70 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.
b11cae9e 20
21;; You should have received a copy of the GNU General Public License
038d1e19 22;; along with GCC; see the file COPYING3. If not see
23;; <http://www.gnu.org/licenses/>.
b11cae9e 24
25;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
9c08d1fa 27\f
e1159bbe 28;;---------------------------------------------------------------------------
29;; Constants
30
31;; Register numbers
32(define_constants
ccd90aaa 33 [(R0_REGNUM 0) ; First CORE register
f41e4452 34 (R1_REGNUM 1) ; Second CORE register
ccd90aaa 35 (IP_REGNUM 12) ; Scratch register
e1159bbe 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
ccd90aaa 40 (LAST_ARM_REGNUM 15) ;
41 (FPA_F0_REGNUM 16) ; FIRST_FPA_REGNUM
42 (FPA_F7_REGNUM 23) ; LAST_FPA_REGNUM
e1159bbe 43 ]
44)
3c5afce6 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)
2ff91fec 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)
e1159bbe 61
9c08d1fa 62;; UNSPEC Usage:
8a18b90c 63;; Note: sin and cos are no-longer used.
e7d6d136 64;; Unspec enumerators for Neon are defined in neon.md.
e1159bbe 65
e7d6d136 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.
e7d6d136 106 UNSPEC_PIC_OFFSET ; A symbolic 12-bit OFFSET that has been treated
107 ; correctly for PIC usage.
851d9296 108 UNSPEC_GOTSYM_OFF ; The offset of the start of the GOT from a
e7d6d136 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.
eb04cafb 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.
350ccca5 119 UNSPEC_PIC_UNIFIED ; Create a common pic addressing form.
ab1e18de 120 UNSPEC_LL ; Represent an unpaired load-register-exclusive.
e7d6d136 121])
e1159bbe 122
215b30b3 123;; UNSPEC_VOLATILE Usage:
e1159bbe 124
e7d6d136 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.
7571d3f7 132 VUNSPEC_THUMB1_INTERWORK ; `prologue_thumb1_interwork' insn, used to swap
133 ; modes from arm to thumb.
e7d6d136 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.
e1b93706 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.
e7d6d136 161])
b11cae9e 162\f
e1159bbe 163;;---------------------------------------------------------------------------
9c08d1fa 164;; Attributes
165
a651f34d 166;; Processor type. This is created automatically from arm-cores.def.
167(include "arm-tune.md")
168
215b30b3 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.
1c494086 172(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
cffb2a26 173
ef51b8e1 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
747b7458 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
331beb1a 180;; Operand number of an input operand that is shifted. Zero if the
181;; given instruction does not shift one of its input operands.
331beb1a 182(define_attr "shift" "" (const_int 0))
183
3d91c5d6 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).
4fea7d65 187(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
c7f506fd 188 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 189
094e994f 190; LENGTH of an instruction (in bytes)
06df6b17 191(define_attr "length" ""
e1b93706 192 (const_int 4))
9c08d1fa 193
d5d4dc8d 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.
10efb95f 200(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,onlya8,neon_onlya8,nota8,neon_nota8"
d5d4dc8d 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")
0bf497f5 208 (match_test "TARGET_ARM"))
d5d4dc8d 209 (const_string "yes")
210
211 (and (eq_attr "arch" "t")
0bf497f5 212 (match_test "TARGET_THUMB"))
d5d4dc8d 213 (const_string "yes")
214
215 (and (eq_attr "arch" "t1")
0bf497f5 216 (match_test "TARGET_THUMB1"))
d5d4dc8d 217 (const_string "yes")
218
219 (and (eq_attr "arch" "t2")
0bf497f5 220 (match_test "TARGET_THUMB2"))
d5d4dc8d 221 (const_string "yes")
222
223 (and (eq_attr "arch" "32")
0bf497f5 224 (match_test "TARGET_32BIT"))
d5d4dc8d 225 (const_string "yes")
226
227 (and (eq_attr "arch" "v6")
0bf497f5 228 (match_test "TARGET_32BIT && arm_arch6"))
d5d4dc8d 229 (const_string "yes")
230
231 (and (eq_attr "arch" "nov6")
0bf497f5 232 (match_test "TARGET_32BIT && !arm_arch6"))
a651f34d 233 (const_string "yes")
234
235 (and (eq_attr "arch" "onlya8")
236 (eq_attr "tune" "cortexa8"))
237 (const_string "yes")
238
10efb95f 239 (and (eq_attr "arch" "neon_onlya8")
240 (eq_attr "tune" "cortexa8")
241 (match_test "TARGET_NEON"))
242 (const_string "yes")
243
a651f34d 244 (and (eq_attr "arch" "nota8")
245 (not (eq_attr "tune" "cortexa8")))
10efb95f 246 (const_string "yes")
247
248 (and (eq_attr "arch" "neon_nota8")
249 (not (eq_attr "tune" "cortexa8"))
250 (match_test "TARGET_NEON"))
d5d4dc8d 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.
93b431d9 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")))
d5d4dc8d 266
56d27660 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.
cffb2a26 270; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
8848d797 271; before its address. It is set to <max_range> - (8 + <data_size>).
cde1623a 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")))
56d27660 283
215b30b3 284; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 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.
9c08d1fa 287(define_asm_attributes
4d7a8451 288 [(set_attr "conds" "clob")
289 (set_attr "length" "4")
290 (set_attr "pool_range" "250")])
9c08d1fa 291
a2cd141b 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"
b49e3742 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"
a2cd141b 298 (const_string "other"))
299
9c08d1fa 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
607978a1 306; Note: vfp.md has different meanings for some of these, and some further
307; types as well. See that file for details.
a2cd141b 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
f7fbdd4a 314; mult a multiply instruction
9c08d1fa 315; block blockage insn, this blocks all functional units
316; float a floating point arithmetic operation (subject to expansion)
3d91c5d6 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)
9c08d1fa 323; float_em a floating point arithmetic operation that is normally emulated
3d91c5d6 324; even on a machine with an fpa.
013b9671 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.
c0e1af52 329; f_flag a transfer of co-processor flags to the CPSR
9c08d1fa 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
c0e1af52 334; f_cvt convert floating<->integral
a2cd141b 335; branch a branch
9c08d1fa 336; call a subroutine call
a2cd141b 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
9c08d1fa 343; store2 store 2 words
344; store3 store 3 words
a2cd141b 345; store4 store 4 (or more) words
2c6c7d8b 346; Additions for Cirrus Maverick co-processor:
347; mav_farith Floating point arithmetic (4 cycle)
348; mav_dmult Double multiplies (7 cycle)
9c08d1fa 349;
bcaec148 350
9c08d1fa 351(define_attr "type"
013b9671 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"
a2cd141b 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")))
9c08d1fa 357
65f2f758 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
9888ad6d 365; Load scheduling, set from the arm_ld_sched variable
4c834714 366; initialized by arm_option_override()
9888ad6d 367(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 368
c52acdd2 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
f7fbdd4a 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.
215b30b3 441;
f7fbdd4a 442; USE means that the condition codes are used by the insn in the process of
215b30b3 443; outputting code, this means (at present) that we can't use the insn in
444; inlined branches
445;
f7fbdd4a 446; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 447; well defined manner.
448;
f7fbdd4a 449; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 450; they are altered at all
451;
ad6d3e2a 452; UNCONDITIONAL means the instruction can not be conditionally executed and
453; that the instruction does not use or alter the condition codes.
c52acdd2 454;
ad6d3e2a 455; NOCOND means that the instruction does not use or alter the condition
456; codes but can be converted into a conditionally exectuted instruction.
f7fbdd4a 457
b0694be0 458(define_attr "conds" "use,set,clob,unconditional,nocond"
747b7458 459 (if_then_else
460 (ior (eq_attr "is_thumb1" "yes")
461 (eq_attr "type" "call"))
c1a66faf 462 (const_string "clob")
c52acdd2 463 (if_then_else (eq_attr "neon_type" "none")
464 (const_string "nocond")
465 (const_string "unconditional"))))
f7fbdd4a 466
215b30b3 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.
0d66636f 471(define_attr "predicable" "no,yes" (const_string "no"))
472
129a2fe4 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
8d232dc7 475; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 476; affect the schedule).
74a71f7d 477(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 478
215b30b3 479; WRITE_CONFLICT implies that a read following an unrelated write is likely
480; to stall the processor. Used with model_wbuf above.
9c08d1fa 481(define_attr "write_conflict" "no,yes"
482 (if_then_else (eq_attr "type"
013b9671 483 "block,float_em,f_fpa_load,f_fpa_store,f_mem_r,r_mem_f,call,load1")
9c08d1fa 484 (const_string "yes")
485 (const_string "no")))
486
215b30b3 487; Classify the insns into those that take one cycle and those that take more
488; than one on the main cpu execution unit.
f7fbdd4a 489(define_attr "core_cycles" "single,multi"
490 (if_then_else (eq_attr "type"
a2cd141b 491 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
f7fbdd4a 492 (const_string "single")
493 (const_string "multi")))
494
cffb2a26 495;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 496;; distant label. Only applicable to Thumb code.
cffb2a26 497(define_attr "far_jump" "yes,no" (const_string "no"))
498
d51f92df 499
25f905c2 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
d51f92df 504;;---------------------------------------------------------------------------
fd781bb2 505;; Mode iterators
d51f92df 506
3de0dec6 507(include "iterators.md")
03770691 508
d51f92df 509;;---------------------------------------------------------------------------
510;; Predicates
511
9c9db025 512(include "predicates.md")
234f6557 513(include "constraints.md")
9c9db025 514
a2cd141b 515;;---------------------------------------------------------------------------
516;; Pipeline descriptions
215b30b3 517
e3879fd0 518(define_attr "tune_cortexr4" "yes,no"
519 (const (if_then_else
7d3cda8c 520 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
e3879fd0 521 (const_string "yes")
522 (const_string "no"))))
523
a2cd141b 524;; True if the generic scheduling description should be used.
525
526(define_attr "generic_sched" "yes,no"
2546d93a 527 (const (if_then_else
65f2f758 528 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa5,cortexa8,cortexa9,cortexa15,cortexm4")
2546d93a 529 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 530 (const_string "no")
531 (const_string "yes"))))
532
c0e1af52 533(define_attr "generic_vfp" "yes,no"
534 (const (if_then_else
535 (and (eq_attr "fpu" "vfp")
2546d93a 536 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa8,cortexa9,cortexm4")
e3879fd0 537 (eq_attr "tune_cortexr4" "no"))
c0e1af52 538 (const_string "yes")
539 (const_string "no"))))
540
a2cd141b 541(include "arm-generic.md")
542(include "arm926ejs.md")
c0e1af52 543(include "arm1020e.md")
a2cd141b 544(include "arm1026ejs.md")
545(include "arm1136jfs.md")
0e266d06 546(include "fa526.md")
547(include "fa606te.md")
548(include "fa626te.md")
549(include "fmp626.md")
550(include "fa726te.md")
3f1e069f 551(include "cortex-a5.md")
bcaec148 552(include "cortex-a8.md")
036068af 553(include "cortex-a9.md")
65f2f758 554(include "cortex-a15.md")
934a1e72 555(include "cortex-r4.md")
e3879fd0 556(include "cortex-r4f.md")
2546d93a 557(include "cortex-m4.md")
558(include "cortex-m4-fpu.md")
55e3ada8 559(include "vfp11.md")
3586df96 560
9c08d1fa 561\f
215b30b3 562;;---------------------------------------------------------------------------
e1159bbe 563;; Insn patterns
564;;
a0f94409 565;; Addition insns.
215b30b3 566
9c08d1fa 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.
7d57ec45 570;; Cirrus 64bit additions should not be split because we have a native
571;; 64bit addition instructions.
9c08d1fa 572
cffb2a26 573(define_expand "adddi3"
574 [(parallel
215b30b3 575 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 576 (plus:DI (match_operand:DI 1 "s_register_operand" "")
577 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 578 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 579 "TARGET_EITHER"
580 "
a2cd141b 581 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
7d57ec45 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
25f905c2 591 if (TARGET_THUMB1)
cffb2a26 592 {
593 if (GET_CODE (operands[1]) != REG)
bc5a93af 594 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 595 if (GET_CODE (operands[2]) != REG)
bc5a93af 596 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 597 }
598 "
599)
600
25f905c2 601(define_insn "*thumb1_adddi3"
cffb2a26 602 [(set (match_operand:DI 0 "register_operand" "=l")
603 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 604 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 605 (clobber (reg:CC CC_REGNUM))
cffb2a26 606 ]
25f905c2 607 "TARGET_THUMB1"
cffb2a26 608 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
609 [(set_attr "length" "4")]
610)
611
a0f94409 612(define_insn_and_split "*arm_adddi3"
cffb2a26 613 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
215b30b3 614 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
615 (match_operand:DI 2 "s_register_operand" "r, 0")))
bd5b4116 616 (clobber (reg:CC CC_REGNUM))]
94829feb 617 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK) && !TARGET_NEON"
33782ec7 618 "#"
94829feb 619 "TARGET_32BIT && reload_completed
620 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
a0f94409 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)))])
080c0b9a 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))))]
a0f94409 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 }"
cffb2a26 636 [(set_attr "conds" "clob")
637 (set_attr "length" "8")]
638)
9c08d1fa 639
a0f94409 640(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 641 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
642 (plus:DI (sign_extend:DI
97499065 643 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 644 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 645 (clobber (reg:CC CC_REGNUM))]
25f905c2 646 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 647 "#"
25f905c2 648 "TARGET_32BIT && reload_completed"
a0f94409 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)))])
080c0b9a 653 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 654 (const_int 31))
080c0b9a 655 (match_dup 4))
656 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 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 }"
215b30b3 665 [(set_attr "conds" "clob")
666 (set_attr "length" "8")]
667)
9c08d1fa 668
a0f94409 669(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 670 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
671 (plus:DI (zero_extend:DI
97499065 672 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 673 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 674 (clobber (reg:CC CC_REGNUM))]
25f905c2 675 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 676 "#"
25f905c2 677 "TARGET_32BIT && reload_completed"
a0f94409 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)))])
080c0b9a 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))))]
a0f94409 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 }"
cffb2a26 692 [(set_attr "conds" "clob")
693 (set_attr "length" "8")]
694)
b11cae9e 695
87b22bf7 696(define_expand "addsi3"
cffb2a26 697 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 698 (plus:SI (match_operand:SI 1 "s_register_operand" "")
699 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 700 "TARGET_EITHER"
87b22bf7 701 "
25f905c2 702 if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
87b22bf7 703 {
96f57e36 704 arm_split_constant (PLUS, SImode, NULL_RTX,
705 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 706 optimize && can_create_pseudo_p ());
87b22bf7 707 DONE;
708 }
cffb2a26 709 "
710)
87b22bf7 711
5bd751ff 712; If there is a scratch available, this will be faster than synthesizing the
a0f94409 713; addition.
714(define_peephole2
715 [(match_scratch:SI 3 "r")
372575c7 716 (set (match_operand:SI 0 "arm_general_register_operand" "")
717 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 718 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 719 "TARGET_32BIT &&
a0f94409 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)
87b22bf7 727
2f02c19f 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.
a0f94409 731(define_insn_and_split "*arm_addsi3"
d5cbae34 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")))]
25f905c2 735 "TARGET_32BIT"
5565501b 736 "@
737 add%?\\t%0, %1, %2
aaa37ad6 738 add%?\\t%0, %1, %2
2f02c19f 739 add%?\\t%0, %2, %1
d5cbae34 740 addw%?\\t%0, %1, %2
741 addw%?\\t%0, %1, %2
aaa37ad6 742 sub%?\\t%0, %1, #%n2
87b22bf7 743 sub%?\\t%0, %1, #%n2
d5cbae34 744 subw%?\\t%0, %1, #%n2
745 subw%?\\t%0, %1, #%n2
87b22bf7 746 #"
a3ffc315 747 "TARGET_32BIT
748 && GET_CODE (operands[2]) == CONST_INT
d5cbae34 749 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
a3ffc315 750 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 751 [(clobber (const_int 0))]
752 "
96f57e36 753 arm_split_constant (PLUS, SImode, curr_insn,
754 INTVAL (operands[2]), operands[0],
a0f94409 755 operands[1], 0);
756 DONE;
757 "
d5cbae34 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,*")]
cffb2a26 761)
762
0bdb6455 763(define_insn_and_split "*thumb1_addsi3"
bf7bc2f6 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")))]
25f905c2 767 "TARGET_THUMB1"
cffb2a26 768 "*
0d66636f 769 static const char * const asms[] =
cffb2a26 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\",
0bdb6455 777 \"add\\t%0, %1, %2\",
778 \"#\",
bf7bc2f6 779 \"#\",
0bdb6455 780 \"#\"
cffb2a26 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 "
0bdb6455 788 "&& reload_completed && CONST_INT_P (operands[2])
bf7bc2f6 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))"
0bdb6455 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]);
bf7bc2f6 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 }
0bdb6455 806 operands[3] = GEN_INT (offset);
807 operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
808 }
bf7bc2f6 809 [(set_attr "length" "2,2,2,2,2,2,2,4,4,4")]
cffb2a26 810)
811
812;; Reloading and elimination of the frame pointer can
813;; sometimes cause this optimization to be missed.
a0f94409 814(define_peephole2
372575c7 815 [(set (match_operand:SI 0 "arm_general_register_operand" "")
a058e94a 816 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 817 (set (match_dup 0)
372575c7 818 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
25f905c2 819 "TARGET_THUMB1
cffb2a26 820 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
821 && (INTVAL (operands[1]) & 3) == 0"
372575c7 822 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
a0f94409 823 ""
cffb2a26 824)
b11cae9e 825
90c2bcf0 826(define_insn "addsi3_compare0"
bd5b4116 827 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 828 (compare:CC_NOOV
215b30b3 829 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
830 (match_operand:SI 2 "arm_add_operand" "rI,L"))
5565501b 831 (const_int 0)))
832 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 833 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 834 "TARGET_ARM"
5565501b 835 "@
25f905c2 836 add%.\\t%0, %1, %2
837 sub%.\\t%0, %1, #%n2"
cffb2a26 838 [(set_attr "conds" "set")]
839)
9c08d1fa 840
aea4c774 841(define_insn "*addsi3_compare0_scratch"
bd5b4116 842 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 843 (compare:CC_NOOV
215b30b3 844 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
845 (match_operand:SI 1 "arm_add_operand" "rI,L"))
aea4c774 846 (const_int 0)))]
ec792a7b 847 "TARGET_ARM"
cffb2a26 848 "@
849 cmn%?\\t%0, %1
850 cmp%?\\t%0, #%n1"
596e5e8f 851 [(set_attr "conds" "set")
852 (set_attr "predicable" "yes")]
0d66636f 853)
cffb2a26 854
aed179ae 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")))]
25f905c2 860 "TARGET_32BIT"
aed179ae 861 "cmn%?\\t%1, %0"
596e5e8f 862 [(set_attr "conds" "set")
863 (set_attr "predicable" "yes")]
0d66636f 864)
aea4c774 865
203c488f 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")
2a977b78 872 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 873 (set (match_operand:SI 0 "s_register_operand" "=r,r")
874 (plus:SI (match_dup 1)
2a977b78 875 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 876 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 877 "@
2a977b78 878 add%.\\t%0, %1, %3
879 sub%.\\t%0, %1, #%n3"
203c488f 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
372575c7 893 [(set (match_operand:SI 0 "arm_general_register_operand" "")
894 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 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 "" "")))]
25f905c2 903 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 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
ebcc79bc 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"
bd5b4116 925 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 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)))]
25f905c2 932 "TARGET_32BIT"
ebcc79bc 933 "@
25f905c2 934 add%.\\t%0, %1, %2
935 sub%.\\t%0, %1, #%n2"
0d66636f 936 [(set_attr "conds" "set")]
937)
ebcc79bc 938
939(define_insn "*addsi3_compare_op2"
bd5b4116 940 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 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)))
5565501b 945 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 946 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 947 "TARGET_32BIT"
5565501b 948 "@
25f905c2 949 add%.\\t%0, %1, %2
950 sub%.\\t%0, %1, #%n2"
0d66636f 951 [(set_attr "conds" "set")]
952)
9c08d1fa 953
ebcc79bc 954(define_insn "*compare_addsi2_op0"
bd5b4116 955 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 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)))]
25f905c2 960 "TARGET_32BIT"
ebcc79bc 961 "@
962 cmn%?\\t%0, %1
963 cmp%?\\t%0, #%n1"
596e5e8f 964 [(set_attr "conds" "set")
965 (set_attr "predicable" "yes")]
0d66636f 966)
ebcc79bc 967
968(define_insn "*compare_addsi2_op1"
bd5b4116 969 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 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)))]
25f905c2 974 "TARGET_32BIT"
ebcc79bc 975 "@
976 cmn%?\\t%0, %1
977 cmp%?\\t%0, #%n1"
596e5e8f 978 [(set_attr "conds" "set")
979 (set_attr "predicable" "yes")]
0d66636f 980)
ebcc79bc 981
080c0b9a 982(define_insn "*addsi3_carryin_<optab>"
ebcc79bc 983 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 984 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
ebcc79bc 985 (match_operand:SI 2 "arm_rhs_operand" "rI"))
080c0b9a 986 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 987 "TARGET_32BIT"
ebcc79bc 988 "adc%?\\t%0, %1, %2"
cffb2a26 989 [(set_attr "conds" "use")]
990)
ebcc79bc 991
080c0b9a 992(define_insn "*addsi3_carryin_alt2_<optab>"
ebcc79bc 993 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 994 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
995 (match_operand:SI 1 "s_register_operand" "%r"))
ebcc79bc 996 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 997 "TARGET_32BIT"
ebcc79bc 998 "adc%?\\t%0, %1, %2"
0d66636f 999 [(set_attr "conds" "use")]
1000)
ebcc79bc 1001
080c0b9a 1002(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 1003 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 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))))]
25f905c2 1010 "TARGET_32BIT"
080c0b9a 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")))]
cffb2a26 1016)
ebcc79bc 1017
922b6913 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
25f905c2 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"
9c08d1fa 1039 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 1040 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1041 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
9c08d1fa 1042 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 1043 "TARGET_ARM"
5565501b 1044 "@
1045 add%d2\\t%0, %1, #1
1046 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
8fa3ba89 1047 [(set_attr "conds" "use")
215b30b3 1048 (set_attr "length" "4,8")]
1049)
9c08d1fa 1050
d795fb69 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" ""))]
25f905c2 1058 "TARGET_32BIT"
d795fb69 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
604f3a0a 1065(define_expand "addsf3"
1066 [(set (match_operand:SF 0 "s_register_operand" "")
1067 (plus:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1068 (match_operand:SF 2 "arm_float_add_operand" "")))]
25f905c2 1069 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1070 "
a2cd141b 1071 if (TARGET_MAVERICK
604f3a0a 1072 && !cirrus_fp_register (operands[2], SFmode))
1073 operands[2] = force_reg (SFmode, operands[2]);
1074")
1075
604f3a0a 1076(define_expand "adddf3"
1077 [(set (match_operand:DF 0 "s_register_operand" "")
1078 (plus:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1079 (match_operand:DF 2 "arm_float_add_operand" "")))]
a50d7267 1080 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1081 "
a2cd141b 1082 if (TARGET_MAVERICK
604f3a0a 1083 && !cirrus_fp_register (operands[2], DFmode))
1084 operands[2] = force_reg (DFmode, operands[2]);
1085")
1086
cffb2a26 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" "")))
bd5b4116 1092 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 1093 "TARGET_EITHER"
1094 "
a2cd141b 1095 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
25f905c2 1096 && TARGET_32BIT
7d57ec45 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
25f905c2 1104 if (TARGET_THUMB1)
cffb2a26 1105 {
1106 if (GET_CODE (operands[1]) != REG)
5aa8c5f0 1107 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 1108 if (GET_CODE (operands[2]) != REG)
5aa8c5f0 1109 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 1110 }
1111 "
1112)
1113
1114(define_insn "*arm_subdi3"
1115 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 1116 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1117 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 1118 (clobber (reg:CC CC_REGNUM))]
94829feb 1119 "TARGET_32BIT && !TARGET_NEON"
97499065 1120 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
cffb2a26 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")))
bd5b4116 1129 (clobber (reg:CC CC_REGNUM))]
25f905c2 1130 "TARGET_THUMB1"
cffb2a26 1131 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
1132 [(set_attr "length" "4")]
1133)
9c08d1fa 1134
f7fbdd4a 1135(define_insn "*subdi_di_zesidi"
cffb2a26 1136 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1137 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1138 (zero_extend:DI
cffb2a26 1139 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1140 (clobber (reg:CC CC_REGNUM))]
25f905c2 1141 "TARGET_32BIT"
97499065 1142 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
cffb2a26 1143 [(set_attr "conds" "clob")
1144 (set_attr "length" "8")]
1145)
9c08d1fa 1146
f7fbdd4a 1147(define_insn "*subdi_di_sesidi"
cffb2a26 1148 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1149 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1150 (sign_extend:DI
cffb2a26 1151 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1152 (clobber (reg:CC CC_REGNUM))]
25f905c2 1153 "TARGET_32BIT"
97499065 1154 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
cffb2a26 1155 [(set_attr "conds" "clob")
1156 (set_attr "length" "8")]
1157)
9c08d1fa 1158
f7fbdd4a 1159(define_insn "*subdi_zesidi_di"
cffb2a26 1160 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1161 (minus:DI (zero_extend:DI
cffb2a26 1162 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1163 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1164 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1165 "TARGET_ARM"
97499065 1166 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
cffb2a26 1167 [(set_attr "conds" "clob")
1168 (set_attr "length" "8")]
1169)
9c08d1fa 1170
f7fbdd4a 1171(define_insn "*subdi_sesidi_di"
cffb2a26 1172 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1173 (minus:DI (sign_extend:DI
cffb2a26 1174 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1175 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1176 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1177 "TARGET_ARM"
97499065 1178 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
cffb2a26 1179 [(set_attr "conds" "clob")
1180 (set_attr "length" "8")]
1181)
9c08d1fa 1182
f7fbdd4a 1183(define_insn "*subdi_zesidi_zesidi"
cffb2a26 1184 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1185 (minus:DI (zero_extend:DI
cffb2a26 1186 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1187 (zero_extend:DI
cffb2a26 1188 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1189 (clobber (reg:CC CC_REGNUM))]
25f905c2 1190 "TARGET_32BIT"
1191 "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
cffb2a26 1192 [(set_attr "conds" "clob")
1193 (set_attr "length" "8")]
1194)
b11cae9e 1195
87b22bf7 1196(define_expand "subsi3"
cffb2a26 1197 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1198 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1199 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1200 "TARGET_EITHER"
87b22bf7 1201 "
1202 if (GET_CODE (operands[1]) == CONST_INT)
1203 {
25f905c2 1204 if (TARGET_32BIT)
cffb2a26 1205 {
96f57e36 1206 arm_split_constant (MINUS, SImode, NULL_RTX,
1207 INTVAL (operands[1]), operands[0],
e1ba4a27 1208 operands[2], optimize && can_create_pseudo_p ());
cffb2a26 1209 DONE;
1210 }
25f905c2 1211 else /* TARGET_THUMB1 */
cffb2a26 1212 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1213 }
cffb2a26 1214 "
1215)
87b22bf7 1216
747b7458 1217(define_insn "thumb1_subsi3_insn"
cffb2a26 1218 [(set (match_operand:SI 0 "register_operand" "=l")
1219 (minus:SI (match_operand:SI 1 "register_operand" "l")
747b7458 1220 (match_operand:SI 2 "reg_or_int_operand" "lPd")))]
25f905c2 1221 "TARGET_THUMB1"
cffb2a26 1222 "sub\\t%0, %1, %2"
747b7458 1223 [(set_attr "length" "2")
1224 (set_attr "conds" "set")])
cffb2a26 1225
25f905c2 1226; ??? Check Thumb-2 split length
a0f94409 1227(define_insn_and_split "*arm_subsi3_insn"
91a5e339 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")))]
25f905c2 1231 "TARGET_32BIT"
e2348bcb 1232 "@
87b22bf7 1233 rsb%?\\t%0, %2, %1
aaa37ad6 1234 sub%?\\t%0, %1, %2
080c0b9a 1235 sub%?\\t%0, %1, %2
87b22bf7 1236 #"
91a5e339 1237 "&& (GET_CODE (operands[1]) == CONST_INT
1238 && !const_ok_for_arm (INTVAL (operands[1])))"
87b22bf7 1239 [(clobber (const_int 0))]
1240 "
96f57e36 1241 arm_split_constant (MINUS, SImode, curr_insn,
1242 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1243 DONE;
cffb2a26 1244 "
91a5e339 1245 [(set_attr "length" "4,4,4,16")
a0f94409 1246 (set_attr "predicable" "yes")]
1247)
1248
1249(define_peephole2
1250 [(match_scratch:SI 3 "r")
372575c7 1251 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1252 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1253 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1254 "TARGET_32BIT
a0f94409 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 ""
cffb2a26 1260)
b11cae9e 1261
f7fbdd4a 1262(define_insn "*subsi3_compare0"
bd5b4116 1263 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 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)))
9c08d1fa 1268 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1269 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1270 "TARGET_32BIT"
e2348bcb 1271 "@
25f905c2 1272 sub%.\\t%0, %1, %2
1273 rsb%.\\t%0, %2, %1"
cffb2a26 1274 [(set_attr "conds" "set")]
1275)
9c08d1fa 1276
080c0b9a 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")))
2df9477b 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
25f905c2 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"
cffb2a26 1300 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1301 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 1302 (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1303 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1304 "TARGET_ARM"
e2348bcb 1305 "@
215b30b3 1306 sub%d2\\t%0, %1, #1
1307 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
cffb2a26 1308 [(set_attr "conds" "use")
1309 (set_attr "length" "*,8")]
1310)
9c08d1fa 1311
604f3a0a 1312(define_expand "subsf3"
1313 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1314 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1315 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1316 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1317 "
a2cd141b 1318 if (TARGET_MAVERICK)
604f3a0a 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
604f3a0a 1327(define_expand "subdf3"
1328 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1329 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1330 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1331 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1332 "
a2cd141b 1333 if (TARGET_MAVERICK)
604f3a0a 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
b11cae9e 1342\f
1343;; Multiplication insns
1344
cffb2a26 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
9c08d1fa 1353;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1354(define_insn "*arm_mulsi3"
1355 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1356 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1357 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1358 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1359 "mul%?\\t%0, %2, %1"
a2cd141b 1360 [(set_attr "insn" "mul")
0d66636f 1361 (set_attr "predicable" "yes")]
cffb2a26 1362)
1363
58d7d654 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
215b30b3 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.
cffb2a26 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")))]
58d7d654 1383 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 1384 "*
1385 if (which_alternative < 2)
20c4e896 1386 return \"mov\\t%0, %1\;mul\\t%0, %2\";
cffb2a26 1387 else
20c4e896 1388 return \"mul\\t%0, %2\";
cffb2a26 1389 "
1390 [(set_attr "length" "4,4,2")
a2cd141b 1391 (set_attr "insn" "mul")]
cffb2a26 1392)
b11cae9e 1393
58d7d654 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 "@
1490694c 1400 mul\\t%0, %2
1401 mul\\t%0, %1
58d7d654 1402 mul\\t%0, %1"
1403 [(set_attr "length" "2")
1404 (set_attr "insn" "mul")]
1405)
1406
f7fbdd4a 1407(define_insn "*mulsi3_compare0"
bd5b4116 1408 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1409 (compare:CC_NOOV (mult:SI
1410 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1411 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1412 (const_int 0)))
1413 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1414 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 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"
25f905c2 1430 "mul%.\\t%0, %2, %1"
cffb2a26 1431 [(set_attr "conds" "set")
a2cd141b 1432 (set_attr "insn" "muls")]
cffb2a26 1433)
9c08d1fa 1434
f7fbdd4a 1435(define_insn "*mulsi_compare0_scratch"
bd5b4116 1436 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1437 (compare:CC_NOOV (mult:SI
1438 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1439 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1440 (const_int 0)))
1441 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 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"
25f905c2 1456 "mul%.\\t%0, %2, %1"
cffb2a26 1457 [(set_attr "conds" "set")
a2cd141b 1458 (set_attr "insn" "muls")]
cffb2a26 1459)
9c08d1fa 1460
b11cae9e 1461;; Unnamed templates to match MLA instruction.
1462
f7fbdd4a 1463(define_insn "*mulsi3addsi"
9c08d1fa 1464 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1465 (plus:SI
9c08d1fa 1466 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1467 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1468 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 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"
f7fbdd4a 1482 "mla%?\\t%0, %2, %1, %3"
a2cd141b 1483 [(set_attr "insn" "mla")
0d66636f 1484 (set_attr "predicable" "yes")]
1485)
b11cae9e 1486
f7fbdd4a 1487(define_insn "*mulsi3addsi_compare0"
bd5b4116 1488 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1489 (compare:CC_NOOV
1490 (plus:SI (mult:SI
1491 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1492 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1493 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1494 (const_int 0)))
9c08d1fa 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)))]
58d7d654 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"
25f905c2 1516 "mla%.\\t%0, %2, %1, %3"
0d66636f 1517 [(set_attr "conds" "set")
a2cd141b 1518 (set_attr "insn" "mlas")]
0d66636f 1519)
9c08d1fa 1520
f7fbdd4a 1521(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1522 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1523 (compare:CC_NOOV
1524 (plus:SI (mult:SI
1525 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1526 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1527 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1528 (const_int 0)))
9c08d1fa 1529 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 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"
25f905c2 1546 "mla%.\\t%0, %2, %1, %3"
cffb2a26 1547 [(set_attr "conds" "set")
a2cd141b 1548 (set_attr "insn" "mlas")]
cffb2a26 1549)
f7fbdd4a 1550
89545238 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
5cdca009 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 "")
82b85d08 1572
1573(define_insn "*mulsidi3adddi"
fe8dbf85 1574 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1575 (plus:DI
215b30b3 1576 (mult:DI
fe8dbf85 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")))]
58d7d654 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"
fe8dbf85 1594 "smlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1595 [(set_attr "insn" "smlal")
0d66636f 1596 (set_attr "predicable" "yes")]
1597)
82b85d08 1598
957788b0 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"
f7fbdd4a 1615 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 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"))))]
58d7d654 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
957788b0 1625(define_insn "*mulsidi3_v6"
58d7d654 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"
97499065 1631 "smull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1632 [(set_attr "insn" "smull")
0d66636f 1633 (set_attr "predicable" "yes")]
1634)
f7fbdd4a 1635
957788b0 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"
f7fbdd4a 1646 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 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"))))]
58d7d654 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
957788b0 1656(define_insn "*umulsidi3_v6"
58d7d654 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"
97499065 1662 "umull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1663 [(set_attr "insn" "umull")
0d66636f 1664 (set_attr "predicable" "yes")]
1665)
b11cae9e 1666
5cdca009 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 "")
82b85d08 1676
1677(define_insn "*umulsidi3adddi"
8ead09f9 1678 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1679 (plus:DI
215b30b3 1680 (mult:DI
fe8dbf85 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")))]
58d7d654 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"
fe8dbf85 1698 "umlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1699 [(set_attr "insn" "umlal")
0d66636f 1700 (set_attr "predicable" "yes")]
1701)
82b85d08 1702
957788b0 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"
f082f1c4 1718 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1719 (truncate:SI
1720 (lshiftrt:DI
215b30b3 1721 (mult:DI
e5fea38e 1722 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1723 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1724 (const_int 32))))
1725 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 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
957788b0 1732(define_insn "*smulsi3_highpart_v6"
58d7d654 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"
f082f1c4 1742 "smull%?\\t%3, %0, %2, %1"
a2cd141b 1743 [(set_attr "insn" "smull")
0d66636f 1744 (set_attr "predicable" "yes")]
cffb2a26 1745)
f082f1c4 1746
957788b0 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"
f082f1c4 1762 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1763 (truncate:SI
1764 (lshiftrt:DI
215b30b3 1765 (mult:DI
e5fea38e 1766 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1767 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1768 (const_int 32))))
1769 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 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
957788b0 1776(define_insn "*umulsi3_highpart_v6"
58d7d654 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"
f082f1c4 1786 "umull%?\\t%3, %0, %2, %1"
a2cd141b 1787 [(set_attr "insn" "umull")
0d66636f 1788 (set_attr "predicable" "yes")]
cffb2a26 1789)
f082f1c4 1790
331beb1a 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"))))]
25f905c2 1797 "TARGET_DSP_MULTIPLY"
61a2d04c 1798 "smulbb%?\\t%0, %1, %2"
a2cd141b 1799 [(set_attr "insn" "smulxy")
fec538d9 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"))))]
25f905c2 1810 "TARGET_DSP_MULTIPLY"
fec538d9 1811 "smultb%?\\t%0, %1, %2"
a2cd141b 1812 [(set_attr "insn" "smulxy")
fec538d9 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))))]
25f905c2 1823 "TARGET_DSP_MULTIPLY"
fec538d9 1824 "smulbt%?\\t%0, %1, %2"
a2cd141b 1825 [(set_attr "insn" "smulxy")
fec538d9 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))))]
25f905c2 1837 "TARGET_DSP_MULTIPLY"
fec538d9 1838 "smultt%?\\t%0, %1, %2"
a2cd141b 1839 [(set_attr "insn" "smulxy")
fec538d9 1840 (set_attr "predicable" "yes")]
331beb1a 1841)
1842
5cdca009 1843(define_insn "maddhisi4"
331beb1a 1844 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 1845 (plus:SI (mult:SI (sign_extend:SI
1846 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1847 (sign_extend:SI
cfa6c608 1848 (match_operand:HI 2 "s_register_operand" "r")))
1849 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 1850 "TARGET_DSP_MULTIPLY"
5cdca009 1851 "smlabb%?\\t%0, %1, %2, %3"
a2cd141b 1852 [(set_attr "insn" "smlaxy")
fec538d9 1853 (set_attr "predicable" "yes")]
331beb1a 1854)
1855
9a92f368 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
aff5fb4d 1886(define_insn "maddhidi4"
331beb1a 1887 [(set (match_operand:DI 0 "s_register_operand" "=r")
1888 (plus:DI
331beb1a 1889 (mult:DI (sign_extend:DI
cfa6c608 1890 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1891 (sign_extend:DI
cfa6c608 1892 (match_operand:HI 2 "s_register_operand" "r")))
1893 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 1894 "TARGET_DSP_MULTIPLY"
5cdca009 1895 "smlalbb%?\\t%Q0, %R0, %1, %2"
a2cd141b 1896 [(set_attr "insn" "smlalxy")
fec538d9 1897 (set_attr "predicable" "yes")])
331beb1a 1898
9a92f368 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
604f3a0a 1932(define_expand "mulsf3"
1933 [(set (match_operand:SF 0 "s_register_operand" "")
1934 (mult:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1935 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1936 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1937 "
a2cd141b 1938 if (TARGET_MAVERICK
604f3a0a 1939 && !cirrus_fp_register (operands[2], SFmode))
1940 operands[2] = force_reg (SFmode, operands[2]);
1941")
1942
604f3a0a 1943(define_expand "muldf3"
1944 [(set (match_operand:DF 0 "s_register_operand" "")
1945 (mult:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1946 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1947 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1948 "
a2cd141b 1949 if (TARGET_MAVERICK
604f3a0a 1950 && !cirrus_fp_register (operands[2], DFmode))
1951 operands[2] = force_reg (DFmode, operands[2]);
1952")
b11cae9e 1953\f
1954;; Division insns
1955
7db9af5d 1956(define_expand "divsf3"
1957 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1958 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1959 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1960 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1961 "")
9c08d1fa 1962
7db9af5d 1963(define_expand "divdf3"
1964 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1965 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1966 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1967 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7db9af5d 1968 "")
b11cae9e 1969\f
1970;; Modulo insns
1971
7db9af5d 1972(define_expand "modsf3"
1973 [(set (match_operand:SF 0 "s_register_operand" "")
1974 (mod:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1975 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1976 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1977 "")
9c08d1fa 1978
7db9af5d 1979(define_expand "moddf3"
1980 [(set (match_operand:DF 0 "s_register_operand" "")
1981 (mod:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1982 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1983 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1984 "")
b11cae9e 1985\f
1986;; Boolean and,ior,xor insns
1987
f6ebffac 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" "")]))]
25f905c2 1997 "TARGET_32BIT && reload_completed
e2669ea7 1998 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 1999 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 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 "
215b30b3 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)
f6ebffac 2012
f6ebffac 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" "")]))]
25f905c2 2018 "TARGET_32BIT && reload_completed"
f6ebffac 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 "
215b30b3 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)
f6ebffac 2033
f6ebffac 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" "")))]
25f905c2 2041 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2042 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
2043 (set (match_dup 3) (match_dup 4))]
2044 "
215b30b3 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)
f6ebffac 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" "")))]
25f905c2 2060 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2061 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
2062 (set (match_dup 3) (match_dup 4))]
2063 "
215b30b3 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)
f6ebffac 2071
e2669ea7 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"
cffb2a26 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")))]
e2669ea7 2084 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2085 "#"
215b30b3 2086 [(set_attr "length" "8")]
2087)
b11cae9e 2088
a0f94409 2089(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 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"))
e5fea38e 2093 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2094 "TARGET_32BIT"
f6ebffac 2095 "#"
25f905c2 2096 "TARGET_32BIT && reload_completed"
a0f94409 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 }"
215b30b3 2107 [(set_attr "length" "8")]
2108)
b11cae9e 2109
f7fbdd4a 2110(define_insn "*anddi_sesdi_di"
cffb2a26 2111 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 2112 (and:DI (sign_extend:DI
2113 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2114 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2115 "TARGET_32BIT"
f6ebffac 2116 "#"
cffb2a26 2117 [(set_attr "length" "8")]
2118)
b11cae9e 2119
87b22bf7 2120(define_expand "andsi3"
cffb2a26 2121 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2122 (and:SI (match_operand:SI 1 "s_register_operand" "")
2123 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2124 "TARGET_EITHER"
87b22bf7 2125 "
25f905c2 2126 if (TARGET_32BIT)
87b22bf7 2127 {
cffb2a26 2128 if (GET_CODE (operands[2]) == CONST_INT)
2129 {
47b5b27b 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 ());
615caa51 2141
cffb2a26 2142 DONE;
2143 }
87b22bf7 2144 }
25f905c2 2145 else /* TARGET_THUMB1 */
cffb2a26 2146 {
2147 if (GET_CODE (operands[2]) != CONST_INT)
923ffadb 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 }
cffb2a26 2158 else
2159 {
2160 int i;
2161
215b30b3 2162 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2163 {
215b30b3 2164 operands[2] = force_reg (SImode,
2165 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2166
747b7458 2167 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2168
2169 DONE;
2170 }
87b22bf7 2171
cffb2a26 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 }
215b30b3 2180 else if ((((HOST_WIDE_INT) 1) << i) - 1
2181 == ~INTVAL (operands[2]))
cffb2a26 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 }
215b30b3 2195 }
2196 "
cffb2a26 2197)
2198
25f905c2 2199; ??? Check split length for Thumb-2
a0f94409 2200(define_insn_and_split "*arm_andsi3_insn"
cffb2a26 2201 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87b22bf7 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")))]
25f905c2 2204 "TARGET_32BIT"
5565501b 2205 "@
2206 and%?\\t%0, %1, %2
87b22bf7 2207 bic%?\\t%0, %1, #%B2
2208 #"
25f905c2 2209 "TARGET_32BIT
a0f94409 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 "
96f57e36 2215 arm_split_constant (AND, SImode, curr_insn,
2216 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2217 DONE;
2218 "
0d66636f 2219 [(set_attr "length" "4,4,16")
2220 (set_attr "predicable" "yes")]
cffb2a26 2221)
2222
25f905c2 2223(define_insn "*thumb1_andsi3_insn"
cffb2a26 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")))]
25f905c2 2227 "TARGET_THUMB1"
747b7458 2228 "and\\t%0, %2"
2229 [(set_attr "length" "2")
2230 (set_attr "conds" "set")])
87b22bf7 2231
f7fbdd4a 2232(define_insn "*andsi3_compare0"
bd5b4116 2233 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 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)))
cffb2a26 2238 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 2239 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2240 "TARGET_32BIT"
5565501b 2241 "@
25f905c2 2242 and%.\\t%0, %1, %2
2243 bic%.\\t%0, %1, #%B2"
cffb2a26 2244 [(set_attr "conds" "set")]
2245)
9c08d1fa 2246
f7fbdd4a 2247(define_insn "*andsi3_compare0_scratch"
bd5b4116 2248 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 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)))
dd193d7c 2253 (clobber (match_scratch:SI 2 "=X,r"))]
25f905c2 2254 "TARGET_32BIT"
5565501b 2255 "@
2256 tst%?\\t%0, %1
25f905c2 2257 bic%.\\t%2, %0, #%B1"
0d66636f 2258 [(set_attr "conds" "set")]
2259)
9c08d1fa 2260
f7fbdd4a 2261(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2262 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2263 (compare:CC_NOOV (zero_extract:SI
2264 (match_operand:SI 0 "s_register_operand" "r")
206ee9a2 2265 (match_operand 1 "const_int_operand" "n")
2266 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2267 (const_int 0)))]
25f905c2 2268 "TARGET_32BIT
cffb2a26 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)"
9c08d1fa 2273 "*
5c49a439 2274 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2275 << INTVAL (operands[2]));
40dbec34 2276 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2277 return \"\";
0d66636f 2278 "
596e5e8f 2279 [(set_attr "conds" "set")
2280 (set_attr "predicable" "yes")]
0d66636f 2281)
9c08d1fa 2282
f4462328 2283(define_insn_and_split "*ne_zeroextractsi"
c4034607 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"))
3b8c7f7a 2289 (const_int 0)))
2290 (clobber (reg:CC CC_REGNUM))]
25f905c2 2291 "TARGET_32BIT
cffb2a26 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)"
f4462328 2296 "#"
25f905c2 2297 "TARGET_32BIT
f4462328 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")
25f905c2 2314 (set (attr "length")
2315 (if_then_else (eq_attr "is_thumb" "yes")
2316 (const_int 12)
2317 (const_int 8)))]
f4462328 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
f8d7bf2f 2359 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2360 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 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
f8d7bf2f 2366 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2367 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 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 "
c4034607 2376 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 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))]
f8d7bf2f 2393 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2394 "#"
f8d7bf2f 2395 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 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]));
0d66636f 2405 "
2406 [(set_attr "conds" "clob")
215b30b3 2407 (set_attr "length" "8")]
2408)
9c08d1fa 2409
58d6528b 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" ""))]
25f905c2 2416 "TARGET_THUMB1"
58d6528b 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
25f905c2 2427;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 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
58d6528b 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" "")))]
25f905c2 2455 "TARGET_THUMB1"
58d6528b 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
d7863cfe 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
a42059fd 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,
ceb2fe0f 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
a42059fd 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
8a18b90c 2497(define_expand "insv"
eb04cafb 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" ""))]
8b054d5a 2502 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2503 "
215b30b3 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
8b054d5a 2510 if (arm_arch_thumb2)
2511 {
eb04cafb 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)
8b054d5a 2515 {
eb04cafb 2516 rtx base_addr;
2517
2518 if (BYTES_BIG_ENDIAN)
2519 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2520 - start_bit;
8b054d5a 2521
eb04cafb 2522 if (width == 32)
8b054d5a 2523 {
eb04cafb 2524 base_addr = adjust_address (operands[0], SImode,
2525 start_bit / BITS_PER_UNIT);
2526 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
8b054d5a 2527 }
eb04cafb 2528 else
2529 {
2530 rtx tmp = gen_reg_rtx (HImode);
8b054d5a 2531
eb04cafb 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;
8b054d5a 2538 }
eb04cafb 2539 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
8b054d5a 2540 {
eb04cafb 2541 bool use_bfi = TRUE;
8b054d5a 2542
eb04cafb 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 }
8b054d5a 2568 }
eb04cafb 2569 else
2570 FAIL;
8b054d5a 2571 }
2572
eb04cafb 2573 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2574 FAIL;
2575
3f8fde42 2576 target = copy_rtx (operands[0]);
215b30b3 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;
8a18b90c 2588
215b30b3 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
c5b3a71b 2602 emit_insn (gen_andsi3 (op1, operands[0],
2603 gen_int_mode (~mask2, SImode)));
215b30b3 2604 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2605 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 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
5910bb95 2614 the third might be mergeable into another op. */
215b30b3 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. */
8a18b90c 2630
215b30b3 2631 rtx op0 = gen_reg_rtx (SImode);
2632 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2633
215b30b3 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 {
c5b3a71b 2641 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2642 rtx op1 = gen_reg_rtx (SImode);
2643 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2644
215b30b3 2645 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2646 {
2647 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2648
215b30b3 2649 emit_insn (gen_movsi (tmp, op0));
2650 op0 = tmp;
2651 }
8a18b90c 2652
215b30b3 2653 /* Mask out any bits in operand[3] that are not needed. */
2654 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2655
215b30b3 2656 if (GET_CODE (op0) == CONST_INT
2657 && (const_ok_for_arm (mask << start_bit)
2658 || const_ok_for_arm (~(mask << start_bit))))
2659 {
c5b3a71b 2660 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 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);
8a18b90c 2668
215b30b3 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]));
a42059fd 2675
215b30b3 2676 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2677 }
8a18b90c 2678
215b30b3 2679 if (start_bit != 0)
2680 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2681
215b30b3 2682 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2683 }
f082f1c4 2684
215b30b3 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 }
8a18b90c 2694
215b30b3 2695 DONE;
2696 }"
2697)
8a18b90c 2698
8b054d5a 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
215b30b3 2721; constants for op 2 will never be given to these patterns.
a0f94409 2722(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2723 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2724 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2725 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2726 "TARGET_32BIT"
f6ebffac 2727 "#"
e2669ea7 2728 "TARGET_32BIT && reload_completed
2729 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2730 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 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 }"
0d66636f 2742 [(set_attr "length" "8")
2743 (set_attr "predicable" "yes")]
2744)
9c08d1fa 2745
a0f94409 2746(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 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")))
e2348bcb 2750 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2751 "TARGET_32BIT"
e2348bcb 2752 "@
97499065 2753 bic%?\\t%Q0, %Q1, %2
f6ebffac 2754 #"
a0f94409 2755 ; (not (zero_extend ...)) allows us to just copy the high word from
2756 ; operand1 to operand0.
25f905c2 2757 "TARGET_32BIT
a0f94409 2758 && reload_completed
2759 && operands[0] != operands[1]"
5a097f7d 2760 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 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 }"
0d66636f 2769 [(set_attr "length" "4,8")
2770 (set_attr "predicable" "yes")]
2771)
9c08d1fa 2772
a0f94409 2773(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 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")))
5a097f7d 2777 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2778 "TARGET_32BIT"
f6ebffac 2779 "#"
25f905c2 2780 "TARGET_32BIT && reload_completed"
5a097f7d 2781 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 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 }"
0d66636f 2792 [(set_attr "length" "8")
2793 (set_attr "predicable" "yes")]
2794)
9c08d1fa 2795
8a18b90c 2796(define_insn "andsi_notsi_si"
9c08d1fa 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")))]
25f905c2 2800 "TARGET_32BIT"
0d66636f 2801 "bic%?\\t%0, %1, %2"
2802 [(set_attr "predicable" "yes")]
2803)
b11cae9e 2804
747b7458 2805(define_insn "thumb1_bicsi3"
cffb2a26 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")))]
25f905c2 2809 "TARGET_THUMB1"
747b7458 2810 "bic\\t%0, %1"
2811 [(set_attr "length" "2")
2812 (set_attr "conds" "set")])
cffb2a26 2813
8a18b90c 2814(define_insn "andsi_not_shiftsi_si"
a2cd141b 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")))]
cffb2a26 2820 "TARGET_ARM"
6c4c2133 2821 "bic%?\\t%0, %1, %2%S4"
344495ea 2822 [(set_attr "predicable" "yes")
331beb1a 2823 (set_attr "shift" "2")
a2cd141b 2824 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2825 (const_string "alu_shift")
2826 (const_string "alu_shift_reg")))]
6c4c2133 2827)
8a18b90c 2828
f7fbdd4a 2829(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2830 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 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)))
9c08d1fa 2835 (set (match_operand:SI 0 "s_register_operand" "=r")
2836 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2837 "TARGET_32BIT"
2838 "bic%.\\t%0, %1, %2"
0d66636f 2839 [(set_attr "conds" "set")]
2840)
9c08d1fa 2841
f7fbdd4a 2842(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2843 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 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)))
9c08d1fa 2848 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2849 "TARGET_32BIT"
2850 "bic%.\\t%0, %1, %2"
0d66636f 2851 [(set_attr "conds" "set")]
2852)
9c08d1fa 2853
e2669ea7 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"
cffb2a26 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")))]
e2669ea7 2866 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2867 "#"
0d66636f 2868 [(set_attr "length" "8")
2869 (set_attr "predicable" "yes")]
cffb2a26 2870)
9c08d1fa 2871
f7fbdd4a 2872(define_insn "*iordi_zesidi_di"
9c08d1fa 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"))
e2348bcb 2876 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2877 "TARGET_32BIT"
e2348bcb 2878 "@
97499065 2879 orr%?\\t%Q0, %Q1, %2
f6ebffac 2880 #"
0d66636f 2881 [(set_attr "length" "4,8")
2882 (set_attr "predicable" "yes")]
cffb2a26 2883)
9c08d1fa 2884
f7fbdd4a 2885(define_insn "*iordi_sesidi_di"
9c08d1fa 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"))
e5fea38e 2889 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2890 "TARGET_32BIT"
f6ebffac 2891 "#"
0d66636f 2892 [(set_attr "length" "8")
2893 (set_attr "predicable" "yes")]
cffb2a26 2894)
9c08d1fa 2895
87b22bf7 2896(define_expand "iorsi3"
cffb2a26 2897 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2898 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2899 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2900 "TARGET_EITHER"
87b22bf7 2901 "
2902 if (GET_CODE (operands[2]) == CONST_INT)
2903 {
25f905c2 2904 if (TARGET_32BIT)
cffb2a26 2905 {
96f57e36 2906 arm_split_constant (IOR, SImode, NULL_RTX,
2907 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 2908 optimize && can_create_pseudo_p ());
cffb2a26 2909 DONE;
2910 }
25f905c2 2911 else /* TARGET_THUMB1 */
923ffadb 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 }
87b22bf7 2922 }
cffb2a26 2923 "
2924)
87b22bf7 2925
d5d4dc8d 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"
87b22bf7 2931 "@
2932 orr%?\\t%0, %1, %2
d5d4dc8d 2933 orn%?\\t%0, %1, #%B2
87b22bf7 2934 #"
d5d4dc8d 2935 "TARGET_32BIT
a0f94409 2936 && GET_CODE (operands[2]) == CONST_INT
d5d4dc8d 2937 && !(const_ok_for_arm (INTVAL (operands[2]))
2938 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 2939 [(clobber (const_int 0))]
d5d4dc8d 2940{
96f57e36 2941 arm_split_constant (IOR, SImode, curr_insn,
2942 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2943 DONE;
d5d4dc8d 2944}
2945 [(set_attr "length" "4,4,16")
2946 (set_attr "arch" "32,t2,32")
2947 (set_attr "predicable" "yes")])
cffb2a26 2948
747b7458 2949(define_insn "*thumb1_iorsi3_insn"
cffb2a26 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")))]
25f905c2 2953 "TARGET_THUMB1"
747b7458 2954 "orr\\t%0, %2"
2955 [(set_attr "length" "2")
2956 (set_attr "conds" "set")])
9c08d1fa 2957
a0f94409 2958(define_peephole2
2959 [(match_scratch:SI 3 "r")
372575c7 2960 (set (match_operand:SI 0 "arm_general_register_operand" "")
2961 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2962 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 2963 "TARGET_ARM
a0f94409 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 ""
215b30b3 2969)
a0f94409 2970
f7fbdd4a 2971(define_insn "*iorsi3_compare0"
bd5b4116 2972 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 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)))]
25f905c2 2978 "TARGET_32BIT"
2979 "orr%.\\t%0, %1, %2"
cffb2a26 2980 [(set_attr "conds" "set")]
2981)
9c08d1fa 2982
f7fbdd4a 2983(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2984 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 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"))]
25f905c2 2989 "TARGET_32BIT"
2990 "orr%.\\t%0, %1, %2"
0d66636f 2991 [(set_attr "conds" "set")]
2992)
9c08d1fa 2993
e2669ea7 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"
cffb2a26 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")))]
e2669ea7 3006 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 3007 "#"
0d66636f 3008 [(set_attr "length" "8")
3009 (set_attr "predicable" "yes")]
cffb2a26 3010)
9c08d1fa 3011
f7fbdd4a 3012(define_insn "*xordi_zesidi_di"
9c08d1fa 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"))
e2348bcb 3016 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3017 "TARGET_32BIT"
e2348bcb 3018 "@
97499065 3019 eor%?\\t%Q0, %Q1, %2
f6ebffac 3020 #"
0d66636f 3021 [(set_attr "length" "4,8")
3022 (set_attr "predicable" "yes")]
cffb2a26 3023)
9c08d1fa 3024
f7fbdd4a 3025(define_insn "*xordi_sesidi_di"
9c08d1fa 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"))
e5fea38e 3029 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3030 "TARGET_32BIT"
f6ebffac 3031 "#"
0d66636f 3032 [(set_attr "length" "8")
3033 (set_attr "predicable" "yes")]
cffb2a26 3034)
9c08d1fa 3035
cffb2a26 3036(define_expand "xorsi3"
3037 [(set (match_operand:SI 0 "s_register_operand" "")
3038 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 3039 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3040 "TARGET_EITHER"
923ffadb 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 }"
cffb2a26 3062)
3063
5dcb35d9 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")))]
25f905c2 3068 "TARGET_32BIT"
5dcb35d9 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")]
cffb2a26 3083)
3084
747b7458 3085(define_insn "*thumb1_xorsi3_insn"
cffb2a26 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")))]
25f905c2 3089 "TARGET_THUMB1"
747b7458 3090 "eor\\t%0, %2"
3091 [(set_attr "length" "2")
3092 (set_attr "conds" "set")])
9c08d1fa 3093
f7fbdd4a 3094(define_insn "*xorsi3_compare0"
bd5b4116 3095 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 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)))]
25f905c2 3101 "TARGET_32BIT"
3102 "eor%.\\t%0, %1, %2"
0d66636f 3103 [(set_attr "conds" "set")]
3104)
9c08d1fa 3105
f7fbdd4a 3106(define_insn "*xorsi3_compare0_scratch"
bd5b4116 3107 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 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)))]
25f905c2 3111 "TARGET_32BIT"
40dbec34 3112 "teq%?\\t%0, %1"
cffb2a26 3113 [(set_attr "conds" "set")]
3114)
9c08d1fa 3115
215b30b3 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.
9c08d1fa 3119
3120(define_split
a058e94a 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" ""))]
25f905c2 3126 "TARGET_32BIT"
9c08d1fa 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
f7fbdd4a 3133(define_insn "*andsi_iorsi3_notsi"
9c08d1fa 3134 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 3135 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 3136 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3137 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 3138 "TARGET_32BIT"
40dbec34 3139 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
0d66636f 3140 [(set_attr "length" "8")
25f905c2 3141 (set_attr "ce_count" "2")
0d66636f 3142 (set_attr "predicable" "yes")]
cffb2a26 3143)
9c08d1fa 3144
25f905c2 3145; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3146; insns are available?
d7863cfe 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" ""))]
25f905c2 3158 "TARGET_32BIT
d7863cfe 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" ""))]
25f905c2 3184 "TARGET_32BIT
d7863cfe 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" ""))]
25f905c2 3210 "TARGET_32BIT
d7863cfe 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" ""))]
25f905c2 3236 "TARGET_32BIT
d7863cfe 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")
9c08d1fa 3250\f
3251
3252;; Minimum and maximum insns
3253
8b9dc177 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))])]
25f905c2 3260 "TARGET_32BIT"
8b9dc177 3261 "
8774928b 3262 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 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)))]
25f905c2 3276 "TARGET_32BIT"
8b9dc177 3277 "bic%?\\t%0, %1, %1, asr #31"
3278 [(set_attr "predicable" "yes")]
3279)
3280
8774928b 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)))]
25f905c2 3285 "TARGET_32BIT"
8774928b 3286 "orr%?\\t%0, %1, %1, asr #31"
3287 [(set_attr "predicable" "yes")]
3288)
3289
25f905c2 3290(define_insn "*arm_smax_insn"
8b9dc177 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")))
bd5b4116 3294 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3295 "TARGET_ARM"
e2348bcb 3296 "@
3297 cmp\\t%1, %2\;movlt\\t%0, %2
e2348bcb 3298 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
cffb2a26 3299 [(set_attr "conds" "clob")
8b9dc177 3300 (set_attr "length" "8,12")]
cffb2a26 3301)
9c08d1fa 3302
8b9dc177 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))])]
25f905c2 3309 "TARGET_32BIT"
8b9dc177 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)))]
25f905c2 3325 "TARGET_32BIT"
8b9dc177 3326 "and%?\\t%0, %1, %1, asr #31"
3327 [(set_attr "predicable" "yes")]
3328)
3329
25f905c2 3330(define_insn "*arm_smin_insn"
8b9dc177 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")))
bd5b4116 3334 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3335 "TARGET_ARM"
e2348bcb 3336 "@
3337 cmp\\t%1, %2\;movge\\t%0, %2
e2348bcb 3338 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
0d66636f 3339 [(set_attr "conds" "clob")
8b9dc177 3340 (set_attr "length" "8,12")]
0d66636f 3341)
9c08d1fa 3342
25f905c2 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"
9c08d1fa 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")))
bd5b4116 3357 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3358 "TARGET_ARM"
e2348bcb 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"
0d66636f 3363 [(set_attr "conds" "clob")
3364 (set_attr "length" "8,8,12")]
3365)
9c08d1fa 3366
25f905c2 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"
9c08d1fa 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")))
bd5b4116 3381 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3382 "TARGET_ARM"
e2348bcb 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"
0d66636f 3387 [(set_attr "conds" "clob")
3388 (set_attr "length" "8,8,12")]
3389)
9c08d1fa 3390
8a18b90c 3391(define_insn "*store_minmaxsi"
9c08d1fa 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")]))
bd5b4116 3396 (clobber (reg:CC CC_REGNUM))]
25f905c2 3397 "TARGET_32BIT"
9c08d1fa 3398 "*
dc55b8a9 3399 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3400 operands[1], operands[2]);
e2348bcb 3401 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3402 if (TARGET_THUMB2)
3403 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3404 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3405 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3406 return \"\";
0d66636f 3407 "
3408 [(set_attr "conds" "clob")
25f905c2 3409 (set (attr "length")
3410 (if_then_else (eq_attr "is_thumb" "yes")
3411 (const_int 14)
3412 (const_int 12)))
0d66636f 3413 (set_attr "type" "store1")]
3414)
9c08d1fa 3415
8a18b90c 3416; Reject the frame pointer in operand[1], since reloading this after
3417; it has been eliminated can cause carnage.
f7fbdd4a 3418(define_insn "*minmax_arithsi"
9c08d1fa 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")]))
bd5b4116 3425 (clobber (reg:CC CC_REGNUM))]
25f905c2 3426 "TARGET_32BIT && !arm_eliminable_register (operands[1])"
9c08d1fa 3427 "*
0d66636f 3428 {
3429 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3430 bool need_else;
3431
3432 if (which_alternative != 0 || operands[3] != const0_rtx
ca0fc5a2 3433 || (code != PLUS && code != IOR && code != XOR))
25f905c2 3434 need_else = true;
3435 else
3436 need_else = false;
0d66636f 3437
dc55b8a9 3438 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3439 operands[2], operands[3]);
0d66636f 3440 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 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 }
0d66636f 3448 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3449 if (need_else)
0d66636f 3450 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3451 return \"\";
215b30b3 3452 }"
0d66636f 3453 [(set_attr "conds" "clob")
25f905c2 3454 (set (attr "length")
3455 (if_then_else (eq_attr "is_thumb" "yes")
3456 (const_int 14)
3457 (const_int 12)))]
0d66636f 3458)
9c08d1fa 3459
b49e3742 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")])
b11cae9e 3514\f
3515;; Shift and rotation insns
3516
a2cd141b 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" "")))]
25f905c2 3521 "TARGET_32BIT"
a2cd141b 3522 "
ffcc986d 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
a2cd141b 3527 {
ffcc986d 3528 rtx scratch1, scratch2;
3529
3530 if (CONST_INT_P (operands[2])
3531 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3532 {
3533 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3534 DONE;
3535 }
ffcc986d 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;
a2cd141b 3553 }
a2cd141b 3554 "
3555)
3556
3557(define_insn "arm_ashldi3_1bit"
50ad1bf9 3558 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3559 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3560 (const_int 1)))
3561 (clobber (reg:CC CC_REGNUM))]
25f905c2 3562 "TARGET_32BIT"
a2cd141b 3563 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3564 [(set_attr "conds" "clob")
3565 (set_attr "length" "8")]
3566)
3567
87b22bf7 3568(define_expand "ashlsi3"
cffb2a26 3569 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3570 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3571 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3572 "TARGET_EITHER"
87b22bf7 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 }
cffb2a26 3580 "
3581)
3582
25f905c2 3583(define_insn "*thumb1_ashlsi3"
cffb2a26 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")))]
25f905c2 3587 "TARGET_THUMB1"
cffb2a26 3588 "lsl\\t%0, %1, %2"
747b7458 3589 [(set_attr "length" "2")
3590 (set_attr "conds" "set")])
b11cae9e 3591
a2cd141b 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" "")))]
25f905c2 3596 "TARGET_32BIT"
a2cd141b 3597 "
ffcc986d 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
a2cd141b 3602 {
ffcc986d 3603 rtx scratch1, scratch2;
3604
3605 if (CONST_INT_P (operands[2])
3606 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3607 {
3608 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3609 DONE;
3610 }
ffcc986d 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;
a2cd141b 3628 }
a2cd141b 3629 "
3630)
3631
3632(define_insn "arm_ashrdi3_1bit"
50ad1bf9 3633 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3634 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3635 (const_int 1)))
3636 (clobber (reg:CC CC_REGNUM))]
25f905c2 3637 "TARGET_32BIT"
a2cd141b 3638 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3639 [(set_attr "conds" "clob")
d2a518d1 3640 (set_attr "insn" "mov")
a2cd141b 3641 (set_attr "length" "8")]
3642)
3643
87b22bf7 3644(define_expand "ashrsi3"
cffb2a26 3645 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3646 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3647 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3648 "TARGET_EITHER"
87b22bf7 3649 "
3650 if (GET_CODE (operands[2]) == CONST_INT
3651 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3652 operands[2] = GEN_INT (31);
cffb2a26 3653 "
3654)
3655
25f905c2 3656(define_insn "*thumb1_ashrsi3"
cffb2a26 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")))]
25f905c2 3660 "TARGET_THUMB1"
cffb2a26 3661 "asr\\t%0, %1, %2"
747b7458 3662 [(set_attr "length" "2")
3663 (set_attr "conds" "set")])
b11cae9e 3664
a2cd141b 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" "")))]
25f905c2 3669 "TARGET_32BIT"
a2cd141b 3670 "
ffcc986d 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
a2cd141b 3675 {
ffcc986d 3676 rtx scratch1, scratch2;
3677
3678 if (CONST_INT_P (operands[2])
3679 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
a2cd141b 3680 {
3681 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3682 DONE;
3683 }
ffcc986d 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;
a2cd141b 3701 }
a2cd141b 3702 "
3703)
3704
3705(define_insn "arm_lshrdi3_1bit"
50ad1bf9 3706 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3707 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3708 (const_int 1)))
3709 (clobber (reg:CC CC_REGNUM))]
25f905c2 3710 "TARGET_32BIT"
a2cd141b 3711 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3712 [(set_attr "conds" "clob")
d2a518d1 3713 (set_attr "insn" "mov")
a2cd141b 3714 (set_attr "length" "8")]
3715)
3716
87b22bf7 3717(define_expand "lshrsi3"
cffb2a26 3718 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3719 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3720 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3721 "TARGET_EITHER"
87b22bf7 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 }
cffb2a26 3729 "
3730)
3731
25f905c2 3732(define_insn "*thumb1_lshrsi3"
cffb2a26 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")))]
25f905c2 3736 "TARGET_THUMB1"
cffb2a26 3737 "lsr\\t%0, %1, %2"
747b7458 3738 [(set_attr "length" "2")
3739 (set_attr "conds" "set")])
b11cae9e 3740
87b22bf7 3741(define_expand "rotlsi3"
cffb2a26 3742 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3743 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3744 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3745 "TARGET_32BIT"
87b22bf7 3746 "
3747 if (GET_CODE (operands[2]) == CONST_INT)
3748 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3749 else
b11cae9e 3750 {
87b22bf7 3751 rtx reg = gen_reg_rtx (SImode);
3752 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3753 operands[2] = reg;
b11cae9e 3754 }
cffb2a26 3755 "
3756)
9c08d1fa 3757
87b22bf7 3758(define_expand "rotrsi3"
cffb2a26 3759 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3760 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3761 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3762 "TARGET_EITHER"
87b22bf7 3763 "
25f905c2 3764 if (TARGET_32BIT)
cffb2a26 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 }
25f905c2 3770 else /* TARGET_THUMB1 */
cffb2a26 3771 {
3772 if (GET_CODE (operands [2]) == CONST_INT)
3773 operands [2] = force_reg (SImode, operands[2]);
3774 }
3775 "
3776)
87b22bf7 3777
25f905c2 3778(define_insn "*thumb1_rotrsi3"
cffb2a26 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")))]
25f905c2 3782 "TARGET_THUMB1"
cffb2a26 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")
87b22bf7 3791 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
25f905c2 3792 "TARGET_32BIT"
3793 "* return arm_output_shift(operands, 0);"
344495ea 3794 [(set_attr "predicable" "yes")
331beb1a 3795 (set_attr "shift" "1")
a2cd141b 3796 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3797 (const_string "alu_shift")
3798 (const_string "alu_shift_reg")))]
6c4c2133 3799)
87b22bf7 3800
f7fbdd4a 3801(define_insn "*shiftsi3_compare0"
bd5b4116 3802 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 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")])
9c08d1fa 3806 (const_int 0)))
3807 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3808 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3809 "TARGET_32BIT"
3810 "* return arm_output_shift(operands, 1);"
344495ea 3811 [(set_attr "conds" "set")
331beb1a 3812 (set_attr "shift" "1")
a2cd141b 3813 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3814 (const_string "alu_shift")
3815 (const_string "alu_shift_reg")))]
0d66636f 3816)
9c08d1fa 3817
f7fbdd4a 3818(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3819 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 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")])
9c08d1fa 3823 (const_int 0)))
3824 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3825 "TARGET_32BIT"
3826 "* return arm_output_shift(operands, 1);"
344495ea 3827 [(set_attr "conds" "set")
a2cd141b 3828 (set_attr "shift" "1")]
0d66636f 3829)
9c08d1fa 3830
d5d4dc8d 3831(define_insn "*not_shiftsi"
3832 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3833 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 3834 [(match_operand:SI 1 "s_register_operand" "r,r")
3835 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3836 "TARGET_32BIT"
6c4c2133 3837 "mvn%?\\t%0, %1%S3"
344495ea 3838 [(set_attr "predicable" "yes")
331beb1a 3839 (set_attr "shift" "1")
d2a518d1 3840 (set_attr "insn" "mvn")
d5d4dc8d 3841 (set_attr "arch" "32,a")
3842 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3843
d5d4dc8d 3844(define_insn "*not_shiftsi_compare0"
bd5b4116 3845 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 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")
87b22bf7 3852 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 3853 "TARGET_32BIT"
25f905c2 3854 "mvn%.\\t%0, %1%S3"
344495ea 3855 [(set_attr "conds" "set")
331beb1a 3856 (set_attr "shift" "1")
d2a518d1 3857 (set_attr "insn" "mvn")
d5d4dc8d 3858 (set_attr "arch" "32,a")
3859 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3860
d5d4dc8d 3861(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 3862 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 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"
25f905c2 3870 "mvn%.\\t%0, %1%S3"
344495ea 3871 [(set_attr "conds" "set")
331beb1a 3872 (set_attr "shift" "1")
d2a518d1 3873 (set_attr "insn" "mvn")
d5d4dc8d 3874 (set_attr "arch" "32,a")
3875 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3876
cffb2a26 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"
eb04cafb 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" "")))]
8b054d5a 3885 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 3886 "
3887 {
3888 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3889 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3890
8b054d5a 3891 if (arm_arch_thumb2)
3892 {
eb04cafb 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;
8b054d5a 3940 }
eb04cafb 3941
3942 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
3943 FAIL;
8b054d5a 3944
cffb2a26 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
eb04cafb 3953 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
3954 operands[3], gen_reg_rtx (SImode)));
3955 DONE;
215b30b3 3956 }"
cffb2a26 3957)
3958
eb04cafb 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"
8b054d5a 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
7d3cda8c 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
b11cae9e 4144\f
4145;; Unary arithmetic insns
4146
cffb2a26 4147(define_expand "negdi2"
4148 [(parallel
8135a42b 4149 [(set (match_operand:DI 0 "s_register_operand" "")
4150 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 4151 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 4152 "TARGET_EITHER"
774d2fbb 4153 {
4154 if (TARGET_NEON)
4155 {
4156 emit_insn (gen_negdi2_neon (operands[0], operands[1]));
4157 DONE;
4158 }
4159 }
cffb2a26 4160)
4161
4162;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 4163;; The first alternative allows the common case of a *full* overlap.
cffb2a26 4164(define_insn "*arm_negdi2"
458a8706 4165 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4166 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 4167 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4168 "TARGET_ARM"
97499065 4169 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
cffb2a26 4170 [(set_attr "conds" "clob")
4171 (set_attr "length" "8")]
4172)
b11cae9e 4173
25f905c2 4174(define_insn "*thumb1_negdi2"
8135a42b 4175 [(set (match_operand:DI 0 "register_operand" "=&l")
4176 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 4177 (clobber (reg:CC CC_REGNUM))]
25f905c2 4178 "TARGET_THUMB1"
cffb2a26 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"
b11cae9e 4187 ""
cffb2a26 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")))]
25f905c2 4193 "TARGET_32BIT"
cffb2a26 4194 "rsb%?\\t%0, %1, #0"
0d66636f 4195 [(set_attr "predicable" "yes")]
cffb2a26 4196)
4197
25f905c2 4198(define_insn "*thumb1_negsi2"
cffb2a26 4199 [(set (match_operand:SI 0 "register_operand" "=l")
4200 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 4201 "TARGET_THUMB1"
cffb2a26 4202 "neg\\t%0, %1"
4203 [(set_attr "length" "2")]
4204)
b11cae9e 4205
604f3a0a 4206(define_expand "negsf2"
4207 [(set (match_operand:SF 0 "s_register_operand" "")
4208 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 4209 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 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" "")))]
a50d7267 4216 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
604f3a0a 4217 "")
4218
9c08d1fa 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
604f3a0a 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" "")))
ba156559 4228 (clobber (match_dup 2))])]
4229 "TARGET_EITHER"
4230 "
25f905c2 4231 if (TARGET_THUMB1)
ba156559 4232 operands[2] = gen_rtx_SCRATCH (SImode);
4233 else
4234 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4235")
604f3a0a 4236
7d57ec45 4237(define_insn "*arm_abssi2"
ba156559 4238 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 4239 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 4240 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4241 "TARGET_ARM"
e2348bcb 4242 "@
4243 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
40dbec34 4244 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
cffb2a26 4245 [(set_attr "conds" "clob,*")
331beb1a 4246 (set_attr "shift" "1")
0d66636f 4247 ;; predicable can't be set based on the variant, so left as no
cffb2a26 4248 (set_attr "length" "8")]
4249)
9c08d1fa 4250
25f905c2 4251(define_insn_and_split "*thumb1_abssi2"
ba156559 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"))]
25f905c2 4255 "TARGET_THUMB1"
ba156559 4256 "#"
25f905c2 4257 "TARGET_THUMB1 && reload_completed"
ba156559 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"
9c08d1fa 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"))))
bd5b4116 4268 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4269 "TARGET_ARM"
e2348bcb 4270 "@
4271 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
40dbec34 4272 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
cffb2a26 4273 [(set_attr "conds" "clob,*")
331beb1a 4274 (set_attr "shift" "1")
0d66636f 4275 ;; predicable can't be set based on the variant, so left as no
cffb2a26 4276 (set_attr "length" "8")]
4277)
b11cae9e 4278
25f905c2 4279(define_insn_and_split "*thumb1_neg_abssi2"
ba156559 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"))]
25f905c2 4283 "TARGET_THUMB1"
ba156559 4284 "#"
25f905c2 4285 "TARGET_THUMB1 && reload_completed"
ba156559 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
604f3a0a 4293(define_expand "abssf2"
4294 [(set (match_operand:SF 0 "s_register_operand" "")
4295 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 4296 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4297 "")
4298
604f3a0a 4299(define_expand "absdf2"
4300 [(set (match_operand:DF 0 "s_register_operand" "")
4301 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4302 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4303 "")
4304
7db9af5d 4305(define_expand "sqrtsf2"
4306 [(set (match_operand:SF 0 "s_register_operand" "")
4307 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 4308 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 4309 "")
9c08d1fa 4310
7db9af5d 4311(define_expand "sqrtdf2"
4312 [(set (match_operand:DF 0 "s_register_operand" "")
4313 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4314 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7db9af5d 4315 "")
9c08d1fa 4316
a0f94409 4317(define_insn_and_split "one_cmpldi2"
10efb95f 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")))]
25f905c2 4320 "TARGET_32BIT"
10efb95f 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)"
a0f94409 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 }"
10efb95f 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")]
cffb2a26 4341)
b11cae9e 4342
cffb2a26 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"
b11cae9e 4347 ""
cffb2a26 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")))]
25f905c2 4353 "TARGET_32BIT"
cffb2a26 4354 "mvn%?\\t%0, %1"
d2a518d1 4355 [(set_attr "predicable" "yes")
4356 (set_attr "insn" "mvn")]
cffb2a26 4357)
4358
25f905c2 4359(define_insn "*thumb1_one_cmplsi2"
cffb2a26 4360 [(set (match_operand:SI 0 "register_operand" "=l")
4361 (not:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 4362 "TARGET_THUMB1"
cffb2a26 4363 "mvn\\t%0, %1"
d2a518d1 4364 [(set_attr "length" "2")
4365 (set_attr "insn" "mvn")]
cffb2a26 4366)
9c08d1fa 4367
f7fbdd4a 4368(define_insn "*notsi_compare0"
bd5b4116 4369 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 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)))]
25f905c2 4374 "TARGET_32BIT"
4375 "mvn%.\\t%0, %1"
d2a518d1 4376 [(set_attr "conds" "set")
4377 (set_attr "insn" "mvn")]
cffb2a26 4378)
9c08d1fa 4379
f7fbdd4a 4380(define_insn "*notsi_compare0_scratch"
bd5b4116 4381 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 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"))]
25f905c2 4385 "TARGET_32BIT"
4386 "mvn%.\\t%0, %1"
d2a518d1 4387 [(set_attr "conds" "set")
4388 (set_attr "insn" "mvn")]
cffb2a26 4389)
b11cae9e 4390\f
4391;; Fixed <--> Floating conversion insns
4392
9b8516be 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
604f3a0a 4421(define_expand "floatsisf2"
4422 [(set (match_operand:SF 0 "s_register_operand" "")
4423 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 4424 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4425 "
a2cd141b 4426 if (TARGET_MAVERICK)
604f3a0a 4427 {
4428 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
4429 DONE;
4430 }
4431")
4432
604f3a0a 4433(define_expand "floatsidf2"
4434 [(set (match_operand:DF 0 "s_register_operand" "")
4435 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 4436 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4437 "
a2cd141b 4438 if (TARGET_MAVERICK)
604f3a0a 4439 {
4440 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
4441 DONE;
4442 }
4443")
4444
9b8516be 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
604f3a0a 4469(define_expand "fix_truncsfsi2"
4470 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4471 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 4472 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4473 "
a2cd141b 4474 if (TARGET_MAVERICK)
604f3a0a 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
604f3a0a 4485(define_expand "fix_truncdfsi2"
4486 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4487 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 4488 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4489 "
a2cd141b 4490 if (TARGET_MAVERICK)
604f3a0a 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
f544c6d2 4499;; Truncation insns
b11cae9e 4500
604f3a0a 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" "")))]
a50d7267 4505 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4506 ""
4507)
9b8516be 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)
b11cae9e 4524\f
9c08d1fa 4525;; Zero and sign extension instructions.
b11cae9e 4526
848e66ac 4527(define_insn "zero_extend<mode>di2"
4528 [(set (match_operand:DI 0 "s_register_operand" "=r")
6d97728e 4529 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
4530 "<qhs_zextenddi_cstr>")))]
848e66ac 4531 "TARGET_32BIT <qhs_zextenddi_cond>"
4532 "#"
4533 [(set_attr "length" "8")
4534 (set_attr "ce_count" "2")
4535 (set_attr "predicable" "yes")]
25f905c2 4536)
4537
848e66ac 4538(define_insn "extend<mode>di2"
9c08d1fa 4539 [(set (match_operand:DI 0 "s_register_operand" "=r")
63d204a8 4540 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4541 "<qhs_extenddi_cstr>")))]
848e66ac 4542 "TARGET_32BIT <qhs_sextenddi_cond>"
4543 "#"
0d66636f 4544 [(set_attr "length" "8")
848e66ac 4545 (set_attr "ce_count" "2")
4546 (set_attr "shift" "1")
0d66636f 4547 (set_attr "predicable" "yes")]
4548)
9c08d1fa 4549
848e66ac 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" "")))]
25f905c2 4554 "TARGET_32BIT"
848e66ac 4555 [(set (match_dup 0) (match_dup 1))]
4556{
848e66ac 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})
9c08d1fa 4576
848e66ac 4577(define_split
25f905c2 4578 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 4579 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
25f905c2 4580 "TARGET_32BIT"
848e66ac 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]);
25f905c2 4585
848e66ac 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})
9c08d1fa 4602
4603(define_expand "zero_extendhisi2"
ef51b8e1 4604 [(set (match_operand:SI 0 "s_register_operand" "")
4605 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4606 "TARGET_EITHER"
ef51b8e1 4607{
4608 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 4609 {
ef51b8e1 4610 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4611 DONE;
25f7a26e 4612 }
ef51b8e1 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})
9c08d1fa 4622
ef51b8e1 4623(define_split
b146458f 4624 [(set (match_operand:SI 0 "s_register_operand" "")
4625 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 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"
a2cd141b 4634 [(set (match_operand:SI 0 "register_operand" "=l,l")
4635 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
ef51b8e1 4636 "TARGET_THUMB1"
848e66ac 4637{
a2cd141b 4638 rtx mem;
4639
ef51b8e1 4640 if (which_alternative == 0 && arm_arch6)
848e66ac 4641 return "uxth\t%0, %1";
ef51b8e1 4642 if (which_alternative == 0)
848e66ac 4643 return "#";
a2cd141b 4644
4645 mem = XEXP (operands[1], 0);
4646
4647 if (GET_CODE (mem) == CONST)
4648 mem = XEXP (mem, 0);
4649
a2cd141b 4650 if (GET_CODE (mem) == PLUS)
4651 {
4652 rtx a = XEXP (mem, 0);
a2cd141b 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
848e66ac 4661 output_asm_insn ("mov\t%0, %1", ops);
a2cd141b 4662
4663 XEXP (mem, 0) = operands[0];
4664 }
a2cd141b 4665 }
4666
848e66ac 4667 return "ldrh\t%0, %1";
4668}
ef51b8e1 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)])
848e66ac 4673 (set_attr "type" "alu_shift,load_byte")]
a2cd141b 4674)
4675
cffb2a26 4676(define_insn "*arm_zero_extendhisi2"
ef51b8e1 4677 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4678 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4679 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4680 "@
4681 #
4682 ldr%(h%)\\t%0, %1"
4683 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4684 (set_attr "predicable" "yes")]
cffb2a26 4685)
f7fbdd4a 4686
a2cd141b 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
25f905c2 4693 ldr%(h%)\\t%0, %1"
a2cd141b 4694 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4695 (set_attr "predicable" "yes")]
a2cd141b 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")))]
25f905c2 4702 "TARGET_INT_SIMD"
a2cd141b 4703 "uxtah%?\\t%0, %2, %1"
4704 [(set_attr "type" "alu_shift")
4705 (set_attr "predicable" "yes")]
4706)
4707
87b22bf7 4708(define_expand "zero_extendqisi2"
cffb2a26 4709 [(set (match_operand:SI 0 "s_register_operand" "")
4710 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4711 "TARGET_EITHER"
ef51b8e1 4712{
4713 if (TARGET_ARM && !arm_arch6 && GET_CODE (operands[1]) != MEM)
87b22bf7 4714 {
ef51b8e1 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})
cffb2a26 4729
ef51b8e1 4730(define_split
b146458f 4731 [(set (match_operand:SI 0 "s_register_operand" "")
4732 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 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)));
87b22bf7 4741 DONE;
4742 }
ef51b8e1 4743})
9c08d1fa 4744
25f905c2 4745(define_insn "*thumb1_zero_extendqisi2"
ef51b8e1 4746 [(set (match_operand:SI 0 "register_operand" "=l,l")
4747 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4748 "TARGET_THUMB1 && !arm_arch6"
ef51b8e1 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")]
cffb2a26 4755)
4756
25f905c2 4757(define_insn "*thumb1_zero_extendqisi2_v6"
a2cd141b 4758 [(set (match_operand:SI 0 "register_operand" "=l,l")
4759 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4760 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4761 "@
4762 uxtb\\t%0, %1
4763 ldrb\\t%0, %1"
848e66ac 4764 [(set_attr "length" "2")
4765 (set_attr "type" "alu_shift,load_byte")]
a2cd141b 4766)
4767
cffb2a26 4768(define_insn "*arm_zero_extendqisi2"
ef51b8e1 4769 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4770 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4771 "TARGET_ARM && !arm_arch6"
ef51b8e1 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")
848e66ac 4777 (set_attr "predicable" "yes")]
cffb2a26 4778)
87b22bf7 4779
a2cd141b 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 "@
25f905c2 4785 uxtb%(%)\\t%0, %1
4786 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 4787 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4788 (set_attr "predicable" "yes")]
a2cd141b 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")))]
25f905c2 4795 "TARGET_INT_SIMD"
a2cd141b 4796 "uxtab%?\\t%0, %2, %1"
4797 [(set_attr "predicable" "yes")
bcaec148 4798 (set_attr "insn" "xtab")
a2cd141b 4799 (set_attr "type" "alu_shift")]
4800)
4801
87b22bf7 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" ""))]
25f905c2 4806 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
87b22bf7 4807 [(set (match_dup 2) (match_dup 1))
4808 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 4809 ""
4810)
9c08d1fa 4811
8a4d25d6 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" ""))]
25f905c2 4816 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
8a4d25d6 4817 [(set (match_dup 2) (match_dup 1))
4818 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4819 ""
4820)
4821
1c274529 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
63787642 4833 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
1c274529 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
f7fbdd4a 4843(define_insn "*compareqi_eq0"
bd5b4116 4844 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 4845 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 4846 (const_int 0)))]
25f905c2 4847 "TARGET_32BIT"
596e5e8f 4848 "tst%?\\t%0, #255"
4849 [(set_attr "conds" "set")
4850 (set_attr "predicable" "yes")]
cffb2a26 4851)
b11cae9e 4852
b11cae9e 4853(define_expand "extendhisi2"
ef51b8e1 4854 [(set (match_operand:SI 0 "s_register_operand" "")
4855 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4856 "TARGET_EITHER"
ef51b8e1 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 }
ed29c566 4868
ef51b8e1 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})
cffb2a26 4878
ef51b8e1 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})
25f7a26e 4890
a2cd141b 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
ed29c566 4894;; address also needs reloading; this causes us to die later on when
a2cd141b 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.
ef51b8e1 4898(define_insn "thumb1_extendhisi2"
a2cd141b 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"))]
ef51b8e1 4902 "TARGET_THUMB1"
a2cd141b 4903 "*
4904 {
4905 rtx ops[4];
4906 rtx mem;
4907
ef51b8e1 4908 if (which_alternative == 0 && !arm_arch6)
4909 return \"#\";
a2cd141b 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
ed29c566 4947 gcc_assert (GET_CODE (ops[1]) == REG);
a2cd141b 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 }"
ef51b8e1 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)])
a2cd141b 4961 (set_attr "type" "alu_shift,load_byte")
4962 (set_attr "pool_range" "*,1020")]
4963)
4964
25f905c2 4965;; This pattern will only be used when ldsh is not available
25f7a26e 4966(define_expand "extendhisi2_mem"
eab14235 4967 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4968 (set (match_dup 3)
eab14235 4969 (zero_extend:SI (match_dup 7)))
25f7a26e 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)))]
cffb2a26 4973 "TARGET_ARM"
25f7a26e 4974 "
215b30b3 4975 {
4976 rtx mem1, mem2;
4977 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4978
788fcce0 4979 mem1 = change_address (operands[1], QImode, addr);
29c05e22 4980 mem2 = change_address (operands[1], QImode,
4981 plus_constant (Pmode, addr, 1));
215b30b3 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;
25f7a26e 4988
215b30b3 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)
b11cae9e 5001
ef51b8e1 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
a2cd141b 5012(define_insn "*arm_extendhisi2"
ef51b8e1 5013 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5014 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 5015 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5016 "@
5017 #
5018 ldr%(sh%)\\t%0, %1"
5019 [(set_attr "length" "8,4")
5020 (set_attr "type" "alu_shift,load_byte")
0d66636f 5021 (set_attr "predicable" "yes")
ef51b8e1 5022 (set_attr "pool_range" "*,256")
5023 (set_attr "neg_pool_range" "*,244")]
cffb2a26 5024)
f7fbdd4a 5025
25f905c2 5026;; ??? Check Thumb-2 pool range
a2cd141b 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")))]
25f905c2 5030 "TARGET_32BIT && arm_arch6"
a2cd141b 5031 "@
5032 sxth%?\\t%0, %1
25f905c2 5033 ldr%(sh%)\\t%0, %1"
a2cd141b 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")))]
25f905c2 5044 "TARGET_INT_SIMD"
a2cd141b 5045 "sxtah%?\\t%0, %2, %1"
5046)
5047
c8f69309 5048(define_expand "extendqihi2"
5049 [(set (match_dup 2)
bed7d9a5 5050 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 5051 (const_int 24)))
9c08d1fa 5052 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 5053 (ashiftrt:SI (match_dup 2)
5054 (const_int 24)))]
cffb2a26 5055 "TARGET_ARM"
c8f69309 5056 "
215b30b3 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)
f7fbdd4a 5072
25f905c2 5073(define_insn "*arm_extendqihi_insn"
b4e8a300 5074 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 5075 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 5076 "TARGET_ARM && arm_arch4"
25f905c2 5077 "ldr%(sb%)\\t%0, %1"
a2cd141b 5078 [(set_attr "type" "load_byte")
0d66636f 5079 (set_attr "predicable" "yes")
cffb2a26 5080 (set_attr "pool_range" "256")
5081 (set_attr "neg_pool_range" "244")]
5082)
3fc2009e 5083
b11cae9e 5084(define_expand "extendqisi2"
ef51b8e1 5085 [(set (match_operand:SI 0 "s_register_operand" "")
5086 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 5087 "TARGET_EITHER"
ef51b8e1 5088{
5089 if (!arm_arch4 && MEM_P (operands[1]))
5090 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 5091
ef51b8e1 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})
a2cd141b 5101
ef51b8e1 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})
f7fbdd4a 5111
a2cd141b 5112(define_insn "*arm_extendqisi"
ef51b8e1 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")))]
a2cd141b 5115 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5116 "@
5117 #
5118 ldr%(sb%)\\t%0, %1"
5119 [(set_attr "length" "8,4")
5120 (set_attr "type" "alu_shift,load_byte")
0d66636f 5121 (set_attr "predicable" "yes")
ef51b8e1 5122 (set_attr "pool_range" "*,256")
5123 (set_attr "neg_pool_range" "*,244")]
cffb2a26 5124)
3fc2009e 5125
a2cd141b 5126(define_insn "*arm_extendqisi_v6"
5127 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 5128 (sign_extend:SI
5129 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5130 "TARGET_ARM && arm_arch6"
b4e8a300 5131 "@
5132 sxtb%?\\t%0, %1
25f905c2 5133 ldr%(sb%)\\t%0, %1"
a2cd141b 5134 [(set_attr "type" "alu_shift,load_byte")
5135 (set_attr "predicable" "yes")
a2cd141b 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")))]
25f905c2 5144 "TARGET_INT_SIMD"
a2cd141b 5145 "sxtab%?\\t%0, %2, %1"
5146 [(set_attr "type" "alu_shift")
bcaec148 5147 (set_attr "insn" "xtab")
a2cd141b 5148 (set_attr "predicable" "yes")]
5149)
5150
ef51b8e1 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);
cffb2a26 5159
ef51b8e1 5160 if (GET_CODE (addr) == CONST)
5161 addr = XEXP (addr, 0);
cffb2a26 5162
ef51b8e1 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 }
cffb2a26 5197
ef51b8e1 5198 operands[3] = change_address (operands[1], QImode, addr);
5199})
5200
8a3b73a1 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
ef51b8e1 5222(define_insn "thumb1_extendqisi2"
a2cd141b 5223 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
5224 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
ef51b8e1 5225 "TARGET_THUMB1"
5226{
5227 rtx addr;
a2cd141b 5228
ef51b8e1 5229 if (which_alternative == 0 && arm_arch6)
5230 return "sxtb\\t%0, %1";
5231 if (which_alternative == 0)
5232 return "#";
a2cd141b 5233
ef51b8e1 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";
a2cd141b 5238
ef51b8e1 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")]
a2cd141b 5248)
5249
caedf871 5250(define_expand "extendsfdf2"
5251 [(set (match_operand:DF 0 "s_register_operand" "")
5252 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 5253 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 5254 ""
5255)
9b8516be 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)
b11cae9e 5271\f
5272;; Move insns (including loads and stores)
5273
5274;; XXX Just some ideas about movti.
9c08d1fa 5275;; I don't think these are a good idea on the arm, there just aren't enough
5276;; registers
b11cae9e 5277;;(define_expand "loadti"
9c08d1fa 5278;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 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" ""))
9c08d1fa 5284;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 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
a2f10574 5308;; Recognize garbage generated above.
b11cae9e 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);
0d66636f 5317;; register const char *template;
b11cae9e 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;; }
e2348bcb 5329;; output_asm_insn (template, operands);
5330;; return \"\";
b11cae9e 5331;; }")
5332
cffb2a26 5333(define_expand "movdi"
5334 [(set (match_operand:DI 0 "general_operand" "")
5335 (match_operand:DI 1 "general_operand" ""))]
5336 "TARGET_EITHER"
5337 "
e1ba4a27 5338 if (can_create_pseudo_p ())
cffb2a26 5339 {
b2778788 5340 if (GET_CODE (operands[0]) != REG)
5341 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 5342 }
5343 "
5344)
b11cae9e 5345
cffb2a26 5346(define_insn "*arm_movdi"
d51f92df 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"))]
cde1623a 5349 "TARGET_32BIT
b2778788 5350 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
5351 && !TARGET_IWMMXT
5352 && ( register_operand (operands[0], DImode)
5353 || register_operand (operands[1], DImode))"
b11cae9e 5354 "*
d51f92df 5355 switch (which_alternative)
5356 {
5357 case 0:
5358 case 1:
5359 case 2:
5360 return \"#\";
5361 default:
26ff80c0 5362 return output_move_double (operands, true, NULL);
d51f92df 5363 }
cffb2a26 5364 "
359a6e9f 5365 [(set_attr "length" "8,12,16,8,8")
5366 (set_attr "type" "*,*,*,load2,store2")
cde1623a 5367 (set_attr "arm_pool_range" "*,*,*,1020,*")
8848d797 5368 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 5369 (set_attr "thumb2_pool_range" "*,*,*,4096,*")
5370 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 5371)
5372
d51f92df 5373(define_split
5374 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5375 (match_operand:ANY64 1 "const_double_operand" ""))]
25f905c2 5376 "TARGET_32BIT
d51f92df 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
e5ba9289 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
d51f92df 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
a8a3b539 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
cffb2a26 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.
25f905c2 5468(define_insn "*thumb1_movdi_insn"
215b30b3 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"))]
25f905c2 5471 "TARGET_THUMB1
a2cd141b 5472 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
cffb2a26 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:
1a83b3ff 5496 operands[2] = gen_rtx_MEM (SImode,
29c05e22 5497 plus_constant (Pmode, XEXP (operands[0], 0), 4));
cffb2a26 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")
a2cd141b 5507 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
d2a518d1 5508 (set_attr "insn" "*,mov,*,*,*,*,*,mov")
cffb2a26 5509 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
5510)
b11cae9e 5511
9c08d1fa 5512(define_expand "movsi"
5513 [(set (match_operand:SI 0 "general_operand" "")
5514 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5515 "TARGET_EITHER"
9c08d1fa 5516 "
befb0bac 5517 {
e348ff3e 5518 rtx base, offset, tmp;
5519
25f905c2 5520 if (TARGET_32BIT)
9c08d1fa 5521 {
674a8f0b 5522 /* Everything except mem = const or mem = mem can be done easily. */
cffb2a26 5523 if (GET_CODE (operands[0]) == MEM)
5524 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5525 if (arm_general_register_operand (operands[0], SImode)
5526 && GET_CODE (operands[1]) == CONST_INT
cffb2a26 5527 && !(const_ok_for_arm (INTVAL (operands[1]))
5528 || const_ok_for_arm (~INTVAL (operands[1]))))
5529 {
96f57e36 5530 arm_split_constant (SET, SImode, NULL_RTX,
5531 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 5532 optimize && can_create_pseudo_p ());
cffb2a26 5533 DONE;
5534 }
d0e6a121 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 }
cffb2a26 5543 }
25f905c2 5544 else /* TARGET_THUMB1... */
cffb2a26 5545 {
e1ba4a27 5546 if (can_create_pseudo_p ())
cffb2a26 5547 {
5548 if (GET_CODE (operands[0]) != REG)
5549 operands[1] = force_reg (SImode, operands[1]);
5550 }
9c08d1fa 5551 }
f655717d 5552
e348ff3e 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 {
b308ddcf 5559 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 5560 emit_move_insn (tmp, base);
5561 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5562 DONE;
5563 }
5564 }
5565
f655717d 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
e1ba4a27 5582 tmp = legitimize_tls_address (tmp,
5583 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 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,
e1ba4a27 5596 (!can_create_pseudo_p ()
5597 ? operands[0]
5598 : 0));
befb0bac 5599 }
215b30b3 5600 "
5601)
9c08d1fa 5602
d0e6a121 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")))]
c9b2ce40 5610 "arm_arch_thumb2"
d0e6a121 5611 "movt%?\t%0, #:upper16:%c2"
5612 [(set_attr "predicable" "yes")
5613 (set_attr "length" "4")]
5614)
5615
cffb2a26 5616(define_insn "*arm_movsi_insn"
aaa37ad6 5617 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5618 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
755eb2b4 5619 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 5620 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 5621 && ( register_operand (operands[0], SImode)
5622 || register_operand (operands[1], SImode))"
f7fbdd4a 5623 "@
aaa37ad6 5624 mov%?\\t%0, %1
f7fbdd4a 5625 mov%?\\t%0, %1
5626 mvn%?\\t%0, #%B1
25f905c2 5627 movw%?\\t%0, %1
f7fbdd4a 5628 ldr%?\\t%0, %1
5629 str%?\\t%1, %0"
aaa37ad6 5630 [(set_attr "type" "*,*,*,*,load1,store1")
d2a518d1 5631 (set_attr "insn" "mov,mov,mvn,mov,*,*")
0d66636f 5632 (set_attr "predicable" "yes")
aaa37ad6 5633 (set_attr "pool_range" "*,*,*,*,4096,*")
5634 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5635)
87b22bf7 5636
5637(define_split
a2cd141b 5638 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5639 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5640 "TARGET_32BIT
215b30b3 5641 && (!(const_ok_for_arm (INTVAL (operands[1]))
5642 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5643 [(clobber (const_int 0))]
5644 "
96f57e36 5645 arm_split_constant (SET, SImode, NULL_RTX,
5646 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5647 DONE;
215b30b3 5648 "
5649)
9c08d1fa 5650
25f905c2 5651(define_insn "*thumb1_movsi_insn"
55a0d64c 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"))]
25f905c2 5654 "TARGET_THUMB1
cffb2a26 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")
a2cd141b 5668 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
747b7458 5669 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")
5670 (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")])
cffb2a26 5671
5672(define_split
5673 [(set (match_operand:SI 0 "register_operand" "")
5674 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5675 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
1276f1b8 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 }"
cffb2a26 5683)
5684
5685(define_split
5686 [(set (match_operand:SI 0 "register_operand" "")
5687 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5688 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
1276f1b8 5689 [(set (match_dup 2) (match_dup 1))
5690 (set (match_dup 0) (ashift:SI (match_dup 2) (match_dup 3)))]
cffb2a26 5691 "
5692 {
e4aeee53 5693 unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
cffb2a26 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
1276f1b8 5701 /* Don't split if the shift is zero. */
cffb2a26 5702 if (i == 0)
5703 FAIL;
5704
5705 operands[1] = GEN_INT (val >> i);
1276f1b8 5706 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5707 operands[3] = GEN_INT (i);
cffb2a26 5708 }"
5709)
5710
c5b75283 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
67336bcf 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
94f8caca 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
350ccca5 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
67336bcf 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.
849170fd 5786
b3cd5f55 5787(define_insn "pic_load_addr_32bit"
849170fd 5788 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5789 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 5790 "TARGET_32BIT && flag_pic"
67336bcf 5791 "ldr%?\\t%0, %1"
a2cd141b 5792 [(set_attr "type" "load1")
b3cd5f55 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)))]
8c4d8060 5798)
5799
25f905c2 5800(define_insn "pic_load_addr_thumb1"
8c4d8060 5801 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5802 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5803 "TARGET_THUMB1 && flag_pic"
8c4d8060 5804 "ldr\\t%0, %1"
a2cd141b 5805 [(set_attr "type" "load1")
8c4d8060 5806 (set (attr "pool_range") (const_int 1024))]
cffb2a26 5807)
849170fd 5808
cffb2a26 5809(define_insn "pic_add_dot_plus_four"
15d5d060 5810 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5811 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5812 (const_int 4)
beef0fb5 5813 (match_operand 2 "" "")]
5814 UNSPEC_PIC_BASE))]
b3cd5f55 5815 "TARGET_THUMB"
cffb2a26 5816 "*
6cdcb15c 5817 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5818 INTVAL (operands[2]));
cffb2a26 5819 return \"add\\t%0, %|pc\";
5820 "
5821 [(set_attr "length" "2")]
5822)
849170fd 5823
5824(define_insn "pic_add_dot_plus_eight"
15d5d060 5825 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5826 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5827 (const_int 8)
beef0fb5 5828 (match_operand 2 "" "")]
5829 UNSPEC_PIC_BASE))]
f655717d 5830 "TARGET_ARM"
c4034607 5831 "*
6cdcb15c 5832 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5833 INTVAL (operands[2]));
15d5d060 5834 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5835 "
0d66636f 5836 [(set_attr "predicable" "yes")]
cffb2a26 5837)
849170fd 5838
f655717d 5839(define_insn "tls_load_dot_plus_eight"
cc071db6 5840 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5841 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5842 (const_int 8)
beef0fb5 5843 (match_operand 2 "" "")]
5844 UNSPEC_PIC_BASE)))]
f655717d 5845 "TARGET_ARM"
5846 "*
6cdcb15c 5847 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5848 INTVAL (operands[2]));
f655717d 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
c0c1fba5 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))
2d05dfad 5864 (set (match_operand:SI 2 "arm_general_register_operand" "")
5865 (mem:SI (match_dup 0)))]
f655717d 5866 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 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)))]
f655717d 5872 ""
5873)
5874
bac7fc85 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
95373f08 5885(define_expand "builtin_setjmp_receiver"
5886 [(label_ref (match_operand 0 "" ""))]
5887 "flag_pic"
5888 "
5889{
b935b306 5890 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5891 register. */
2cb7d577 5892 if (arm_pic_register != INVALID_REGNUM)
5893 arm_load_pic_register (1UL << 3);
95373f08 5894 DONE;
5895}")
5896
9c08d1fa 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
f7fbdd4a 5901(define_insn "*movsi_compare0"
bd5b4116 5902 [(set (reg:CC CC_REGNUM)
cffb2a26 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))]
25f905c2 5907 "TARGET_32BIT"
e2348bcb 5908 "@
40dbec34 5909 cmp%?\\t%0, #0
25f905c2 5910 sub%.\\t%0, %1, #0"
cffb2a26 5911 [(set_attr "conds" "set")]
5912)
b11cae9e 5913
b11cae9e 5914;; Subroutine to store a half word from a register into memory.
5915;; Operand 0 is the source register (HImode)
c8f69309 5916;; Operand 1 is the destination address in a register (SImode)
b11cae9e 5917
9c08d1fa 5918;; In both this routine and the next, we must be careful not to spill
01cc3b75 5919;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 5920;; can generate unrecognizable rtl.
5921
b11cae9e 5922(define_expand "storehi"
c8f69309 5923 [;; store the low byte
f082f1c4 5924 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 5925 ;; extract the high byte
c8f69309 5926 (set (match_dup 2)
5927 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 5928 ;; store the high byte
787f8210 5929 (set (match_dup 4) (match_dup 5))]
cffb2a26 5930 "TARGET_ARM"
b11cae9e 5931 "
215b30b3 5932 {
537ffcfc 5933 rtx op1 = operands[1];
5934 rtx addr = XEXP (op1, 0);
215b30b3 5935 enum rtx_code code = GET_CODE (addr);
5936
5937 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5938 || code == MINUS)
537ffcfc 5939 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5940
537ffcfc 5941 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5942 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5943 operands[3] = gen_lowpart (QImode, operands[0]);
5944 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5945 operands[2] = gen_reg_rtx (SImode);
5946 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5947 }"
5948)
b11cae9e 5949
c7597b5d 5950(define_expand "storehi_bigend"
f082f1c4 5951 [(set (match_dup 4) (match_dup 3))
c7597b5d 5952 (set (match_dup 2)
5953 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5954 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5955 "TARGET_ARM"
b11cae9e 5956 "
215b30b3 5957 {
537ffcfc 5958 rtx op1 = operands[1];
5959 rtx addr = XEXP (op1, 0);
215b30b3 5960 enum rtx_code code = GET_CODE (addr);
5961
5962 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5963 || code == MINUS)
537ffcfc 5964 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5965
537ffcfc 5966 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5967 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5968 operands[3] = gen_lowpart (QImode, operands[0]);
5969 operands[0] = gen_lowpart (SImode, operands[0]);
5970 operands[2] = gen_reg_rtx (SImode);
787f8210 5971 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5972 }"
5973)
c7597b5d 5974
5975;; Subroutine to store a half word integer constant into memory.
5976(define_expand "storeinthi"
f082f1c4 5977 [(set (match_operand 0 "" "")
787f8210 5978 (match_operand 1 "" ""))
9e8503e6 5979 (set (match_dup 3) (match_dup 2))]
cffb2a26 5980 "TARGET_ARM"
c7597b5d 5981 "
215b30b3 5982 {
5983 HOST_WIDE_INT value = INTVAL (operands[1]);
5984 rtx addr = XEXP (operands[0], 0);
537ffcfc 5985 rtx op0 = operands[0];
215b30b3 5986 enum rtx_code code = GET_CODE (addr);
c7597b5d 5987
215b30b3 5988 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5989 || code == MINUS)
537ffcfc 5990 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 5991
215b30b3 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 }
c7597b5d 6015
537ffcfc 6016 operands[3] = adjust_address (op0, QImode, 1);
e513d163 6017 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 6018 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 6019 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 6020 }"
6021)
b11cae9e 6022
f7fbdd4a 6023(define_expand "storehi_single_op"
6024 [(set (match_operand:HI 0 "memory_operand" "")
6025 (match_operand:HI 1 "general_operand" ""))]
25f905c2 6026 "TARGET_32BIT && arm_arch4"
f7fbdd4a 6027 "
215b30b3 6028 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 6029 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 6030 "
6031)
f7fbdd4a 6032
b11cae9e 6033(define_expand "movhi"
6034 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 6035 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 6036 "TARGET_EITHER"
b11cae9e 6037 "
cffb2a26 6038 if (TARGET_ARM)
b11cae9e 6039 {
e1ba4a27 6040 if (can_create_pseudo_p ())
cffb2a26 6041 {
6042 if (GET_CODE (operands[0]) == MEM)
b11cae9e 6043 {
cffb2a26 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]));
c7597b5d 6051 else
cffb2a26 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;
b11cae9e 6061 }
cffb2a26 6062 /* Sign extend a constant, and keep it in an SImode reg. */
6063 else if (GET_CODE (operands[1]) == CONST_INT)
9c08d1fa 6064 {
cffb2a26 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. */
215b30b3 6069 if (!const_ok_for_arm (val))
cffb2a26 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
215b30b3 6075 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 6076 val |= ~0xffff;
6077 else if (val & 0x8000)
6078 val |= ~0xffff;
6079 }
6080
6081 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 6082 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 6083 }
e1ba4a27 6084 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0045890a 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 }
215b30b3 6092 else if (!arm_arch4)
f7fbdd4a 6093 {
cffb2a26 6094 if (GET_CODE (operands[1]) == MEM)
6095 {
c1a66faf 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)
206ee9a2 6107 {
8deb3959 6108 rtx new_rtx;
c1a66faf 6109
8deb3959 6110 new_rtx = widen_memory_access (operands[1], SImode,
6111 ((INTVAL (offset) & ~3)
6112 - INTVAL (offset)));
6113 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 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 }
206ee9a2 6122 }
c1a66faf 6123 else
6124 emit_insn (gen_movhi_bytes (reg, operands[1]));
6125
6126 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 6127 }
6128 }
6129 }
674a8f0b 6130 /* Handle loading a large integer during reload. */
cffb2a26 6131 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 6132 && !const_ok_for_arm (INTVAL (operands[1]))
6133 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 6134 {
6135 /* Writing a constant to memory needs a scratch, which should
6136 be handled with SECONDARY_RELOADs. */
ed29c566 6137 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 6138
6139 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6140 emit_insn (gen_movsi (operands[0], operands[1]));
6141 DONE;
6142 }
6143 }
25f905c2 6144 else if (TARGET_THUMB2)
6145 {
6146 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 6147 if (can_create_pseudo_p ())
25f905c2 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 */
cffb2a26 6163 {
e1ba4a27 6164 if (can_create_pseudo_p ())
cffb2a26 6165 {
6cffc037 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 }
cffb2a26 6173
6174 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6175 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6176 virtual register (also rejected as illegitimate for HImode/QImode)
6177 relative address. */
cffb2a26 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
215b30b3 6183 && !memory_address_p (GET_MODE (operands[0]),
6184 XEXP (operands[0], 0)))
537ffcfc 6185 operands[0]
6186 = replace_equiv_address (operands[0],
6187 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 6188
6189 if (GET_CODE (operands[1]) == MEM
215b30b3 6190 && !memory_address_p (GET_MODE (operands[1]),
6191 XEXP (operands[1], 0)))
537ffcfc 6192 operands[1]
6193 = replace_equiv_address (operands[1],
6194 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 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]);
cffb2a26 6206 }
cffb2a26 6207 else if (GET_CODE (operands[1]) == CONST_INT
234f6557 6208 && !satisfies_constraint_I (operands[1]))
cffb2a26 6209 {
6cffc037 6210 /* Handle loading a large integer during reload. */
6211
cffb2a26 6212 /* Writing a constant to memory needs a scratch, which should
6213 be handled with SECONDARY_RELOADs. */
ed29c566 6214 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 6215
1a83b3ff 6216 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 6217 emit_insn (gen_movsi (operands[0], operands[1]));
6218 DONE;
6219 }
b11cae9e 6220 }
cffb2a26 6221 "
6222)
6223
25f905c2 6224(define_insn "*thumb1_movhi_insn"
a941568e 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"))]
25f905c2 6227 "TARGET_THUMB1
cffb2a26 6228 && ( register_operand (operands[0], HImode)
6229 || register_operand (operands[1], HImode))"
6230 "*
6231 switch (which_alternative)
d79300ac 6232 {
cffb2a26 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\";
ed29c566 6238 default: gcc_unreachable ();
cffb2a26 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")
747b7458 6258 (set_attr "type" "*,load1,store1,*,*,*")
6259 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
d79300ac 6260
b11cae9e 6261
25f7a26e 6262(define_expand "movhi_bytes"
eab14235 6263 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 6264 (set (match_dup 3)
eab14235 6265 (zero_extend:SI (match_dup 6)))
25f7a26e 6266 (set (match_operand:SI 0 "" "")
6267 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 6268 "TARGET_ARM"
25f7a26e 6269 "
215b30b3 6270 {
6271 rtx mem1, mem2;
6272 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6273
788fcce0 6274 mem1 = change_address (operands[1], QImode, addr);
29c05e22 6275 mem2 = change_address (operands[1], QImode,
6276 plus_constant (Pmode, addr, 1));
215b30b3 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;
25f7a26e 6282
215b30b3 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)
25f7a26e 6295
c7597b5d 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" "")
787f8210 6303 (match_dup 4))]
cffb2a26 6304 "TARGET_ARM"
c7597b5d 6305 "
6306 operands[2] = gen_reg_rtx (SImode);
6307 operands[3] = gen_reg_rtx (SImode);
787f8210 6308 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 6309 "
6310)
b11cae9e 6311
a2f10574 6312;; Pattern to recognize insn generated default case above
f7fbdd4a 6313(define_insn "*movhi_insn_arch4"
cde1623a 6314 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
85e02ccb 6315 (match_operand:HI 1 "general_operand" "rI,K,r,mi"))]
cffb2a26 6316 "TARGET_ARM
6317 && arm_arch4
85e02ccb 6318 && (register_operand (operands[0], HImode)
6319 || register_operand (operands[1], HImode))"
f7fbdd4a 6320 "@
6321 mov%?\\t%0, %1\\t%@ movhi
6322 mvn%?\\t%0, #%B1\\t%@ movhi
25f905c2 6323 str%(h%)\\t%1, %0\\t%@ movhi
6324 ldr%(h%)\\t%0, %1\\t%@ movhi"
a2cd141b 6325 [(set_attr "type" "*,*,store1,load1")
0d66636f 6326 (set_attr "predicable" "yes")
d2a518d1 6327 (set_attr "insn" "mov,mvn,*,*")
cffb2a26 6328 (set_attr "pool_range" "*,*,*,256")
6329 (set_attr "neg_pool_range" "*,*,*,244")]
6330)
f7fbdd4a 6331
f7fbdd4a 6332(define_insn "*movhi_bytes"
25f7a26e 6333 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
6334 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
c1a66faf 6335 "TARGET_ARM"
25f7a26e 6336 "@
6337 mov%?\\t%0, %1\\t%@ movhi
0d66636f 6338 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 6339 [(set_attr "predicable" "yes")
6340 (set_attr "insn" "mov,mvn")]
0d66636f 6341)
25f7a26e 6342
f90b51f1 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" ""))]
25f905c2 6347 "TARGET_THUMB1"
f90b51f1 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 "
cffb2a26 6358)
6359
bc5c7e08 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.
d3373b54 6363(define_expand "reload_outhi"
cffb2a26 6364 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 6365 (match_operand:HI 1 "s_register_operand" "r")
6366 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 6367 "TARGET_EITHER"
6368 "if (TARGET_ARM)
6369 arm_reload_out_hi (operands);
6370 else
6371 thumb_reload_out_hi (operands);
d3373b54 6372 DONE;
cffb2a26 6373 "
6374)
d3373b54 6375
25f7a26e 6376(define_expand "reload_inhi"
6377 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 6378 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 6379 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 6380 "TARGET_EITHER"
25f7a26e 6381 "
cffb2a26 6382 if (TARGET_ARM)
6383 arm_reload_in_hi (operands);
6384 else
6385 thumb_reload_out_hi (operands);
25f7a26e 6386 DONE;
6387")
6388
9c08d1fa 6389(define_expand "movqi"
6390 [(set (match_operand:QI 0 "general_operand" "")
6391 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 6392 "TARGET_EITHER"
9c08d1fa 6393 "
6cffc037 6394 /* Everything except mem = const or mem = mem can be done easily */
0045890a 6395
e1ba4a27 6396 if (can_create_pseudo_p ())
cffb2a26 6397 {
6cffc037 6398 if (GET_CODE (operands[1]) == CONST_INT)
6399 {
6400 rtx reg = gen_reg_rtx (SImode);
6401
03770691 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
6cffc037 6407 emit_insn (gen_movsi (reg, operands[1]));
6408 operands[1] = gen_lowpart (QImode, reg);
6409 }
cffb2a26 6410
6cffc037 6411 if (TARGET_THUMB)
6412 {
cffb2a26 6413 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6414 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6415 virtual register (also rejected as illegitimate for HImode/QImode)
6416 relative address. */
cffb2a26 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
215b30b3 6422 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 6423 XEXP (operands[0], 0)))
537ffcfc 6424 operands[0]
6425 = replace_equiv_address (operands[0],
6426 copy_to_reg (XEXP (operands[0], 0)));
215b30b3 6427 if (GET_CODE (operands[1]) == MEM
6428 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 6429 XEXP (operands[1], 0)))
537ffcfc 6430 operands[1]
6431 = replace_equiv_address (operands[1],
6432 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 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
234f6557 6448 && !satisfies_constraint_I (operands[1]))
6cffc037 6449 {
674a8f0b 6450 /* Handle loading a large integer during reload. */
cffb2a26 6451
6cffc037 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;
cffb2a26 6459 }
6460 "
6461)
b11cae9e 6462
9c08d1fa 6463
cffb2a26 6464(define_insn "*arm_movqi_insn"
a54e3e7b 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"))]
25f905c2 6467 "TARGET_32BIT
cffb2a26 6468 && ( register_operand (operands[0], QImode)
6469 || register_operand (operands[1], QImode))"
5565501b 6470 "@
6471 mov%?\\t%0, %1
6472 mvn%?\\t%0, #%B1
25f905c2 6473 ldr%(b%)\\t%0, %1
a54e3e7b 6474 str%(b%)\\t%1, %0
6475 ldr%(b%)\\t%0, %1
25f905c2 6476 str%(b%)\\t%1, %0"
a54e3e7b 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")]
cffb2a26 6482)
6483
25f905c2 6484(define_insn "*thumb1_movqi_insn"
cffb2a26 6485 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 6486 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
25f905c2 6487 "TARGET_THUMB1
cffb2a26 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")
a2cd141b 6498 (set_attr "type" "*,load1,store1,*,*,*")
d2a518d1 6499 (set_attr "insn" "*,*,*,mov,mov,mov")
747b7458 6500 (set_attr "pool_range" "*,32,*,*,*,*")
6501 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
b11cae9e 6502
9b8516be 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"))]
a50d7267 6528 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
9b8516be 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,*,*")
d2a518d1 6565 (set_attr "insn" "*,*,mov,mov")
9b8516be 6566 (set_attr "length" "4,4,4,8")
d2a518d1 6567 (set_attr "predicable" "yes")]
9b8516be 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,*,*")
d2a518d1 6601 (set_attr "insn" "mov,*,*,mov,mov")
747b7458 6602 (set_attr "pool_range" "*,1020,*,*,*")
6603 (set_attr "conds" "clob,nocond,nocond,nocond,nocond")])
9b8516be 6604
87b22bf7 6605(define_expand "movsf"
6606 [(set (match_operand:SF 0 "general_operand" "")
6607 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6608 "TARGET_EITHER"
87b22bf7 6609 "
25f905c2 6610 if (TARGET_32BIT)
cffb2a26 6611 {
6612 if (GET_CODE (operands[0]) == MEM)
6613 operands[1] = force_reg (SFmode, operands[1]);
6614 }
25f905c2 6615 else /* TARGET_THUMB1 */
cffb2a26 6616 {
e1ba4a27 6617 if (can_create_pseudo_p ())
cffb2a26 6618 {
6619 if (GET_CODE (operands[0]) != REG)
6620 operands[1] = force_reg (SFmode, operands[1]);
6621 }
6622 }
6623 "
6624)
6625
03d440a6 6626;; Transform a floating-point move of a constant into a core register into
6627;; an SImode operation.
cffb2a26 6628(define_split
03d440a6 6629 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6630 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6631 "TARGET_EITHER
cffb2a26 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;
215b30b3 6640 "
6641)
87b22bf7 6642
cffb2a26 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"))]
cde1623a 6646 "TARGET_32BIT
cffb2a26 6647 && TARGET_SOFT_FLOAT
215b30b3 6648 && (GET_CODE (operands[0]) != MEM
6649 || register_operand (operands[1], SFmode))"
9a1112d7 6650 "@
6651 mov%?\\t%0, %1
6652 ldr%?\\t%0, %1\\t%@ float
6653 str%?\\t%1, %0\\t%@ float"
cde1623a 6654 [(set_attr "predicable" "yes")
a2cd141b 6655 (set_attr "type" "*,load1,store1")
d2a518d1 6656 (set_attr "insn" "mov,*,*")
cffb2a26 6657 (set_attr "pool_range" "*,4096,*")
cde1623a 6658 (set_attr "arm_neg_pool_range" "*,4084,*")
6659 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 6660)
6661
6662;;; ??? This should have alternatives for constants.
25f905c2 6663(define_insn "*thumb1_movsf_insn"
215b30b3 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"))]
25f905c2 6666 "TARGET_THUMB1
cffb2a26 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")
a2cd141b 6678 (set_attr "type" "*,load1,store1,load1,store1,*,*")
747b7458 6679 (set_attr "pool_range" "*,*,*,1020,*,*,*")
d2a518d1 6680 (set_attr "insn" "*,*,*,*,*,mov,mov")
747b7458 6681 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,nocond,nocond")]
cffb2a26 6682)
9a1112d7 6683
9c08d1fa 6684(define_expand "movdf"
87b22bf7 6685 [(set (match_operand:DF 0 "general_operand" "")
6686 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 6687 "TARGET_EITHER"
9c08d1fa 6688 "
25f905c2 6689 if (TARGET_32BIT)
cffb2a26 6690 {
6691 if (GET_CODE (operands[0]) == MEM)
6692 operands[1] = force_reg (DFmode, operands[1]);
6693 }
6694 else /* TARGET_THUMB */
6695 {
e1ba4a27 6696 if (can_create_pseudo_p ())
cffb2a26 6697 {
6698 if (GET_CODE (operands[0]) != REG)
6699 operands[1] = force_reg (DFmode, operands[1]);
6700 }
6701 }
6702 "
6703)
b11cae9e 6704
9c08d1fa 6705;; Reloading a df mode value stored in integer regs to memory can require a
6706;; scratch reg.
6707(define_expand "reload_outdf"
cffb2a26 6708 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6709 (match_operand:DF 1 "s_register_operand" "r")
6710 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 6711 "TARGET_THUMB2"
87b22bf7 6712 "
215b30b3 6713 {
6714 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6715
215b30b3 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);
f7fbdd4a 6728
215b30b3 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)));
f7fbdd4a 6737
788fcce0 6738 emit_insn (gen_rtx_SET (VOIDmode,
6739 replace_equiv_address (operands[0], operands[2]),
215b30b3 6740 operands[1]));
f7fbdd4a 6741
215b30b3 6742 if (code == POST_DEC)
6743 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6744
6745 DONE;
6746 }"
6747)
9c08d1fa 6748
9a1112d7 6749(define_insn "*movdf_soft_insn"
359a6e9f 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"))]
cde1623a 6752 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 6753 && ( register_operand (operands[0], DFmode)
6754 || register_operand (operands[1], DFmode))"
d51f92df 6755 "*
6756 switch (which_alternative)
6757 {
6758 case 0:
6759 case 1:
6760 case 2:
6761 return \"#\";
6762 default:
26ff80c0 6763 return output_move_double (operands, true, NULL);
d51f92df 6764 }
6765 "
359a6e9f 6766 [(set_attr "length" "8,12,16,8,8")
6767 (set_attr "type" "*,*,*,load2,store2")
cde1623a 6768 (set_attr "pool_range" "*,*,*,1020,*")
8848d797 6769 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 6770 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 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"
215b30b3 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"))]
25f905c2 6780 "TARGET_THUMB1
cffb2a26 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:
1a83b3ff 6798 operands[2] = gen_rtx_MEM (SImode,
29c05e22 6799 plus_constant (Pmode,
6800 XEXP (operands[0], 0), 4));
cffb2a26 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")
a2cd141b 6810 (set_attr "type" "*,load2,store2,load2,store2,*")
d2a518d1 6811 (set_attr "insn" "*,*,*,*,*,mov")
cffb2a26 6812 (set_attr "pool_range" "*,*,*,1020,*,*")]
6813)
755eb2b4 6814
ccd90aaa 6815(define_expand "movxf"
6816 [(set (match_operand:XF 0 "general_operand" "")
6817 (match_operand:XF 1 "general_operand" ""))]
25f905c2 6818 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
ccd90aaa 6819 "
6820 if (GET_CODE (operands[0]) == MEM)
6821 operands[1] = force_reg (XFmode, operands[1]);
6822 "
6823)
6824
b11cae9e 6825\f
b11cae9e 6826
9c08d1fa 6827;; load- and store-multiple insns
6828;; The arm can load/store any set of registers, provided that they are in
320ea44d 6829;; ascending order, but these expanders assume a contiguous set.
b11cae9e 6830
9c08d1fa 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 "" ""))])]
25f905c2 6835 "TARGET_32BIT"
9580c25f 6836{
6837 HOST_WIDE_INT offset = 0;
6838
bd5b4116 6839 /* Support only fixed point registers. */
9c08d1fa 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
bd5b4116 6845 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6846 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6847 FAIL;
6848
6849 operands[3]
320ea44d 6850 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6851 INTVAL (operands[2]),
f082f1c4 6852 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 6853 FALSE, operands[1], &offset);
9580c25f 6854})
b11cae9e 6855
9c08d1fa 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 "" ""))])]
25f905c2 6860 "TARGET_32BIT"
9580c25f 6861{
6862 HOST_WIDE_INT offset = 0;
6863
674a8f0b 6864 /* Support only fixed point registers. */
9c08d1fa 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
bd5b4116 6870 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6871 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6872 FAIL;
6873
6874 operands[3]
320ea44d 6875 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6876 INTVAL (operands[2]),
f082f1c4 6877 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 6878 FALSE, operands[0], &offset);
9580c25f 6879})
b11cae9e 6880
9c08d1fa 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
008c057d 6886(define_expand "movmemqi"
34191dd1 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" "")]
cffb2a26 6891 "TARGET_EITHER"
9c08d1fa 6892 "
25f905c2 6893 if (TARGET_32BIT)
cffb2a26 6894 {
008c057d 6895 if (arm_gen_movmemqi (operands))
cffb2a26 6896 DONE;
6897 FAIL;
6898 }
25f905c2 6899 else /* TARGET_THUMB1 */
cffb2a26 6900 {
6901 if ( INTVAL (operands[3]) != 4
6902 || INTVAL (operands[2]) > 48)
6903 FAIL;
6904
008c057d 6905 thumb_expand_movmemqi (operands);
cffb2a26 6906 DONE;
6907 }
6908 "
6909)
6910
2162064c 6911;; Thumb block-move insns
cffb2a26 6912
6913(define_insn "movmem12b"
960f3acf 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"))]
25f905c2 6927 "TARGET_THUMB1"
cffb2a26 6928 "* return thumb_output_move_mem_multiple (3, operands);"
6929 [(set_attr "length" "4")
215b30b3 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
cffb2a26 6932 (set_attr "type" "store3")]
6933)
6934
6935(define_insn "movmem8b"
960f3acf 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"))]
25f905c2 6946 "TARGET_THUMB1"
cffb2a26 6947 "* return thumb_output_move_mem_multiple (2, operands);"
6948 [(set_attr "length" "4")
215b30b3 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
cffb2a26 6951 (set_attr "type" "store2")]
6952)
6953
9c08d1fa 6954\f
b11cae9e 6955
341940e8 6956;; Compare & branch insns
8d232dc7 6957;; The range calculations are based as follows:
341940e8 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).
cffb2a26 6972
aeac46d4 6973(define_expand "cbranchsi4"
6974 [(set (pc) (if_then_else
aa06947a 6975 (match_operator 0 "expandable_comparison_operator"
aeac46d4 6976 [(match_operand:SI 1 "s_register_operand" "")
6977 (match_operand:SI 2 "nonmemory_operand" "")])
6978 (label_ref (match_operand 3 "" ""))
6979 (pc)))]
74f4459c 6980 "TARGET_THUMB1 || TARGET_32BIT"
aeac46d4 6981 "
74f4459c 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 }
25f905c2 6990 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6991 {
6992 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6993 operands[3], operands[0]));
6994 DONE;
6995 }
25f905c2 6996 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6997 operands[2] = force_reg (SImode, operands[2]);
6998 ")
6999
a8e6c15d 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{
d0f6c30d 7013 rtx xops[4];
a8e6c15d 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
74f4459c 7024(define_expand "cbranchsf4"
7025 [(set (pc) (if_then_else
aa06947a 7026 (match_operator 0 "expandable_comparison_operator"
74f4459c 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
aa06947a 7038 (match_operator 0 "expandable_comparison_operator"
74f4459c 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)))]
a50d7267 7043 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7044 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7045 operands[3])); DONE;"
7046)
7047
74f4459c 7048(define_expand "cbranchdi4"
7049 [(set (pc) (if_then_else
aa06947a 7050 (match_operator 0 "expandable_comparison_operator"
a8045a4f 7051 [(match_operand:DI 1 "cmpdi_operand" "")
7052 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 7053 (label_ref (match_operand 3 "" ""))
7054 (pc)))]
a8045a4f 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 }"
74f4459c 7087)
7088
d60047aa 7089(define_insn "cbranchsi4_insn"
aeac46d4 7090 [(set (pc) (if_then_else
7091 (match_operator 0 "arm_comparison_operator"
747b7458 7092 [(match_operand:SI 1 "s_register_operand" "l,l*h")
25f905c2 7093 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
aeac46d4 7094 (label_ref (match_operand 3 "" ""))
7095 (pc)))]
25f905c2 7096 "TARGET_THUMB1"
747b7458 7097{
7098 rtx t = cfun->machine->thumb1_cc_insn;
7099 if (t != NULL_RTX)
d60047aa 7100 {
747b7458 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)
d60047aa 7110 t = NULL_RTX;
7111 }
d60047aa 7112 if (t == NULL_RTX)
747b7458 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);
aeac46d4 7124
cffb2a26 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 }
747b7458 7131}
cffb2a26 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))
341940e8 7144 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 7145 (const_int 6)
7146 (const_int 8))))]
7147)
7148
aeac46d4 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")
25f905c2 7153 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
aeac46d4 7154 (label_ref (match_operand 3 "" ""))
7155 (pc)))
7156 (clobber (match_scratch:SI 0 "=l,l"))]
25f905c2 7157 "TARGET_THUMB1"
aeac46d4 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)
446a1e96 7184
747b7458 7185;; Two peepholes to generate subtract of 0 instead of a move if the
7186;; condition codes will be useful.
446a1e96 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"
747b7458 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)])
446a1e96 7199 (label_ref (match_dup 3))
747b7458 7200 (pc)))]
7201 "")
446a1e96 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
07d32235 7205;; arm_class_likely_spilled_p.
446a1e96 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"
747b7458 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)])
446a1e96 7218 (label_ref (match_dup 3))
747b7458 7219 (pc)))]
7220 "")
446a1e96 7221
cffb2a26 7222(define_insn "*negated_cbranchsi4"
7223 [(set (pc)
7224 (if_then_else
aed179ae 7225 (match_operator 0 "equality_operator"
aeac46d4 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 "" ""))
215b30b3 7229 (pc)))]
25f905c2 7230 "TARGET_THUMB1"
cffb2a26 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))
341940e8 7248 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 7249 (const_int 4)
7250 (if_then_else
341940e8 7251 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7252 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 7253 (const_int 6)
7254 (const_int 8))))]
7255)
7256
58d6528b 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"))]
25f905c2 7268 "TARGET_THUMB1"
58d6528b 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
86efa74d 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"))]
25f905c2 7312 "TARGET_THUMB1"
86efa74d 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
58d6528b 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)
747b7458 7344
aeac46d4 7345(define_insn "*tstsi3_cbranch"
58d6528b 7346 [(set (pc)
7347 (if_then_else
aeac46d4 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"))
58d6528b 7351 (const_int 0)])
aeac46d4 7352 (label_ref (match_operand 2 "" ""))
7353 (pc)))]
25f905c2 7354 "TARGET_THUMB1"
58d6528b 7355 "*
7356 {
aeac46d4 7357 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 7358 switch (get_attr_length (insn))
7359 {
aeac46d4 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%=:\";
58d6528b 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
aeac46d4 7372 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
7373 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 7374 (const_int 4)
7375 (if_then_else
aeac46d4 7376 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
7377 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 7378 (const_int 6)
7379 (const_int 8))))]
7380)
7381
203c488f 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)))
aeac46d4 7389 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 7390 (plus:SI (match_dup 2) (const_int -1)))
7391 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7392 "TARGET_THUMB1"
203c488f 7393 "*
7394 {
7395 rtx cond[2];
7396 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
7397 ? GEU : LTU),
58d6528b 7398 VOIDmode, operands[2], const1_rtx);
203c488f 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:
8aea555f 7422 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 7423 return \"\";
7424 case 6:
8aea555f 7425 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 7426 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
7427 default:
8aea555f 7428 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 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)
cffb2a26 7484
58d6528b 7485(define_insn "*addsi3_cbranch"
7486 [(set (pc)
7487 (if_then_else
b0694be0 7488 (match_operator 4 "arm_comparison_operator"
58d6528b 7489 [(plus:SI
e54011cb 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"))
58d6528b 7492 (const_int 0)])
7493 (label_ref (match_operand 5 "" ""))
7494 (pc)))
aeac46d4 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)))
956a6170 7498 (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
25f905c2 7499 "TARGET_THUMB1
58d6528b 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
956a6170 7508 cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
58d6528b 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
956a6170 7517 if (which_alternative >= 2
58d6528b 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
d0f6c30d 7523 switch (get_attr_length (insn) - ((which_alternative >= 2) ? 2 : 0))
58d6528b 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"))
d0f6c30d 7537 (const_int 2))
58d6528b 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"))
d0f6c30d 7545 (const_int 2))
58d6528b 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
b0694be0 7569 (match_operator 3 "arm_comparison_operator"
58d6528b 7570 [(plus:SI
7571 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 7572 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 7573 (const_int 0)])
7574 (label_ref (match_operand 4 "" ""))
7575 (pc)))
7576 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
25f905c2 7577 "TARGET_THUMB1
58d6528b 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;
0f5e9701 7592 case 2:
3a445a04 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);
58d6528b 7597 break;
0f5e9701 7598 case 3:
3a445a04 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);
58d6528b 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
58d6528b 7634
9c08d1fa 7635;; Comparison and test insns
7636
cffb2a26 7637(define_insn "*arm_cmpsi_insn"
bd5b4116 7638 [(set (reg:CC CC_REGNUM)
a6864a24 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")))]
25f905c2 7641 "TARGET_32BIT"
5565501b 7642 "@
a6864a24 7643 cmp%?\\t%0, %1
7644 cmp%?\\t%0, %1
aea4c774 7645 cmp%?\\t%0, %1
7646 cmn%?\\t%0, #%n1"
a6864a24 7647 [(set_attr "conds" "set")
7648 (set_attr "arch" "t2,t2,any,any")
596e5e8f 7649 (set_attr "length" "2,2,4,4")
7650 (set_attr "predicable" "yes")]
cffb2a26 7651)
b11cae9e 7652
d5d4dc8d 7653(define_insn "*cmpsi_shiftsi"
bd5b4116 7654 [(set (reg:CC CC_REGNUM)
d5d4dc8d 7655 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 7656 (match_operator:SI 3 "shift_operator"
d5d4dc8d 7657 [(match_operand:SI 1 "s_register_operand" "r,r")
7658 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
7659 "TARGET_32BIT"
aea4c774 7660 "cmp%?\\t%0, %1%S3"
344495ea 7661 [(set_attr "conds" "set")
331beb1a 7662 (set_attr "shift" "1")
d5d4dc8d 7663 (set_attr "arch" "32,a")
7664 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7665
d5d4dc8d 7666(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 7667 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7668 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d5d4dc8d 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"
aea4c774 7673 "cmp%?\\t%0, %1%S3"
344495ea 7674 [(set_attr "conds" "set")
331beb1a 7675 (set_attr "shift" "1")
d5d4dc8d 7676 (set_attr "arch" "32,a")
7677 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7678
25f905c2 7679(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 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")))]
cffb2a26 7686 "TARGET_ARM"
aed179ae 7687 "cmn%?\\t%0, %2%S1"
344495ea 7688 [(set_attr "conds" "set")
aed179ae 7689 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7690 (const_string "alu_shift")
596e5e8f 7691 (const_string "alu_shift_reg")))
7692 (set_attr "predicable" "yes")]
0d66636f 7693)
b11cae9e 7694
a8045a4f 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")))]
48a98053 7714 "TARGET_32BIT"
7715 "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
a8045a4f 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
7d57ec45 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")))]
a2cd141b 7746 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7747 "cfcmps%?\\tr15, %V0, %V1"
2c6c7d8b 7748 [(set_attr "type" "mav_farith")
7d57ec45 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")))]
a2cd141b 7757 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7758 "cfcmpd%?\\tr15, %V0, %V1"
2c6c7d8b 7759 [(set_attr "type" "mav_farith")
7d57ec45 7760 (set_attr "cirrus" "compare")]
7761)
7762
7d57ec45 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")))]
a2cd141b 7767 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7768 "cfcmp64%?\\tr15, %V0, %V1"
2c6c7d8b 7769 [(set_attr "type" "mav_farith")
7d57ec45 7770 (set_attr "cirrus" "compare")]
7771)
7772
9c08d1fa 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
8a18b90c 7779(define_insn "*deleted_compare"
9c08d1fa 7780 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7781 "TARGET_32BIT"
40dbec34 7782 "\\t%@ deleted compare"
cffb2a26 7783 [(set_attr "conds" "set")
7784 (set_attr "length" "0")]
7785)
9c08d1fa 7786
7787\f
7788;; Conditional branch insns
7789
74f4459c 7790(define_expand "cbranch_cc"
9c08d1fa 7791 [(set (pc)
74f4459c 7792 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7793 (match_operand 2 "" "")])
7794 (label_ref (match_operand 3 "" ""))
9c08d1fa 7795 (pc)))]
25f905c2 7796 "TARGET_32BIT"
74f4459c 7797 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
e1b93706 7798 operands[1], operands[2], NULL_RTX);
74f4459c 7799 operands[2] = const0_rtx;"
8fa3ba89 7800)
7801
7802;;
7803;; Patterns to match conditional branch insns.
7804;;
7805
ffcc986d 7806(define_insn "arm_cond_branch"
9c08d1fa 7807 [(set (pc)
8fa3ba89 7808 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7809 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7810 (label_ref (match_operand 0 "" ""))
7811 (pc)))]
25f905c2 7812 "TARGET_32BIT"
d75350ce 7813 "*
9c08d1fa 7814 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7815 {
7816 arm_ccfsm_state += 2;
7817 return \"\";
7818 }
e2348bcb 7819 return \"b%d1\\t%l0\";
cffb2a26 7820 "
a2cd141b 7821 [(set_attr "conds" "use")
a6864a24 7822 (set_attr "type" "branch")
7823 (set (attr "length")
7824 (if_then_else
0bf497f5 7825 (and (match_test "TARGET_THUMB2")
a6864a24 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)))]
cffb2a26 7830)
d75350ce 7831
cffb2a26 7832(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7833 [(set (pc)
8fa3ba89 7834 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7835 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7836 (pc)
7837 (label_ref (match_operand 0 "" ""))))]
25f905c2 7838 "TARGET_32BIT"
d75350ce 7839 "*
9c08d1fa 7840 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7841 {
7842 arm_ccfsm_state += 2;
7843 return \"\";
7844 }
e2348bcb 7845 return \"b%D1\\t%l0\";
cffb2a26 7846 "
a2cd141b 7847 [(set_attr "conds" "use")
a6864a24 7848 (set_attr "type" "branch")
7849 (set (attr "length")
7850 (if_then_else
0bf497f5 7851 (and (match_test "TARGET_THUMB2")
a6864a24 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)))]
cffb2a26 7856)
7857
b11cae9e 7858\f
9c08d1fa 7859
7860; scc insns
7861
74f4459c 7862(define_expand "cstore_cc"
7db9af5d 7863 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7864 (match_operator:SI 1 "" [(match_operand 2 "" "")
7865 (match_operand 3 "" "")]))]
25f905c2 7866 "TARGET_32BIT"
74f4459c 7867 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
e1b93706 7868 operands[2], operands[3], NULL_RTX);
74f4459c 7869 operands[3] = const0_rtx;"
8fa3ba89 7870)
7871
f7fbdd4a 7872(define_insn "*mov_scc"
9c08d1fa 7873 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7874 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7875 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7876 "TARGET_ARM"
4d61e570 7877 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 7878 [(set_attr "conds" "use")
d2a518d1 7879 (set_attr "insn" "mov")
cffb2a26 7880 (set_attr "length" "8")]
7881)
9c08d1fa 7882
f7fbdd4a 7883(define_insn "*mov_negscc"
9c08d1fa 7884 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7885 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7886 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7887 "TARGET_ARM"
4d61e570 7888 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 7889 [(set_attr "conds" "use")
d2a518d1 7890 (set_attr "insn" "mov")
cffb2a26 7891 (set_attr "length" "8")]
7892)
9c08d1fa 7893
f7fbdd4a 7894(define_insn "*mov_notscc"
9c08d1fa 7895 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7896 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7897 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7898 "TARGET_ARM"
7d0a3bab 7899 "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 7900 [(set_attr "conds" "use")
d2a518d1 7901 (set_attr "insn" "mov")
cffb2a26 7902 (set_attr "length" "8")]
7903)
9c08d1fa 7904
595d88b5 7905(define_expand "cstoresi4"
7906 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7907 (match_operator:SI 1 "expandable_comparison_operator"
595d88b5 7908 [(match_operand:SI 2 "s_register_operand" "")
7909 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7910 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7911 "{
7912 rtx op3, scratch, scratch2;
7913
74f4459c 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
595d88b5 7923 if (operands[3] == const0_rtx)
7924 {
7925 switch (GET_CODE (operands[1]))
7926 {
7927 case EQ:
25f905c2 7928 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7929 break;
7930
7931 case NE:
25f905c2 7932 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 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);
25f905c2 7972 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7973 break;
7974
7975 case NE:
7976 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7977 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7978 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 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);
25f905c2 7988 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7989 op3, operands[2]));
7990 break;
7991
7992 case GE:
7993 op3 = operands[3];
25f905c2 7994 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 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);
25f905c2 8000 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 8001 operands[2], op3));
8002 break;
8003
8004 case LEU:
8005 op3 = force_reg (SImode, operands[3]);
8006 scratch = force_reg (SImode, const0_rtx);
25f905c2 8007 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 8008 op3, operands[2]));
8009 break;
8010
8011 case GEU:
8012 op3 = operands[3];
25f905c2 8013 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 8014 op3 = force_reg (SImode, op3);
8015 scratch = force_reg (SImode, const0_rtx);
25f905c2 8016 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 8017 operands[2], op3));
8018 break;
8019
8020 case LTU:
8021 op3 = operands[3];
25f905c2 8022 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 8023 op3 = force_reg (SImode, op3);
8024 scratch = gen_reg_rtx (SImode);
408b7ae5 8025 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 8026 break;
8027
8028 case GTU:
8029 op3 = force_reg (SImode, operands[3]);
8030 scratch = gen_reg_rtx (SImode);
408b7ae5 8031 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 8032 break;
8033
8034 /* No good sequences for GT, LT. */
8035 default:
8036 FAIL;
8037 }
8038 DONE;
8039}")
8040
74f4459c 8041(define_expand "cstoresf4"
8042 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 8043 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 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" "")
aa06947a 8053 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 8054 [(match_operand:DF 2 "s_register_operand" "")
8055 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
d63ed457 8056 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 8057 "emit_insn (gen_cstore_cc (operands[0], operands[1],
8058 operands[2], operands[3])); DONE;"
8059)
8060
74f4459c 8061(define_expand "cstoredi4"
8062 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 8063 (match_operator:SI 1 "expandable_comparison_operator"
a8045a4f 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 }"
74f4459c 8098)
8099
25f905c2 8100(define_expand "cstoresi_eq0_thumb1"
595d88b5 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))])]
25f905c2 8106 "TARGET_THUMB1"
595d88b5 8107 "operands[2] = gen_reg_rtx (SImode);"
8108)
8109
25f905c2 8110(define_expand "cstoresi_ne0_thumb1"
595d88b5 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))])]
25f905c2 8116 "TARGET_THUMB1"
595d88b5 8117 "operands[2] = gen_reg_rtx (SImode);"
8118)
8119
25f905c2 8120(define_insn "*cstoresi_eq0_thumb1_insn"
595d88b5 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"))]
25f905c2 8125 "TARGET_THUMB1"
595d88b5 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
25f905c2 8132(define_insn "*cstoresi_ne0_thumb1_insn"
595d88b5 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"))]
25f905c2 8137 "TARGET_THUMB1"
595d88b5 8138 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
8139 [(set_attr "length" "4")]
8140)
8141
408b7ae5 8142;; Used as part of the expansion of thumb ltu and gtu sequences
25f905c2 8143(define_insn "cstoresi_nltu_thumb1"
595d88b5 8144 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
a277ddf3 8145 (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 8146 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
8147 "TARGET_THUMB1"
595d88b5 8148 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
8149 [(set_attr "length" "4")]
8150)
8151
408b7ae5 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
595d88b5 8166;; Used as part of the expansion of thumb les sequence.
25f905c2 8167(define_insn "thumb1_addsi3_addgeu"
595d88b5 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")
25f905c2 8172 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
8173 "TARGET_THUMB1"
595d88b5 8174 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
8175 [(set_attr "length" "4")]
8176)
8177
9c08d1fa 8178\f
39b5e676 8179;; Conditional move insns
8180
8181(define_expand "movsicc"
8a18b90c 8182 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 8183 (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
aea4c774 8184 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 8185 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 8186 "TARGET_32BIT"
39b5e676 8187 "
215b30b3 8188 {
8189 enum rtx_code code = GET_CODE (operands[1]);
278b301d 8190 rtx ccreg;
8191
8192 if (code == UNEQ || code == LTGT)
8193 FAIL;
39b5e676 8194
74f4459c 8195 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 8196 XEXP (operands[1], 1), NULL_RTX);
29bb088d 8197 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8198 }"
8199)
39b5e676 8200
8201(define_expand "movsfcc"
8a18b90c 8202 [(set (match_operand:SF 0 "s_register_operand" "")
aa06947a 8203 (if_then_else:SF (match_operand 1 "expandable_comparison_operator" "")
8a18b90c 8204 (match_operand:SF 2 "s_register_operand" "")
8205 (match_operand:SF 3 "nonmemory_operand" "")))]
19f6bf8d 8206 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 8207 "
215b30b3 8208 {
8209 enum rtx_code code = GET_CODE (operands[1]);
8210 rtx ccreg;
f082f1c4 8211
278b301d 8212 if (code == UNEQ || code == LTGT)
8213 FAIL;
8214
215b30b3 8215 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
a2cd141b 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)))
215b30b3 8219 operands[3] = force_reg (SFmode, operands[3]);
39b5e676 8220
74f4459c 8221 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 8222 XEXP (operands[1], 1), NULL_RTX);
29bb088d 8223 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8224 }"
8225)
39b5e676 8226
8227(define_expand "movdfcc"
8a18b90c 8228 [(set (match_operand:DF 0 "s_register_operand" "")
aa06947a 8229 (if_then_else:DF (match_operand 1 "expandable_comparison_operator" "")
8a18b90c 8230 (match_operand:DF 2 "s_register_operand" "")
a2cd141b 8231 (match_operand:DF 3 "arm_float_add_operand" "")))]
a50d7267 8232 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
39b5e676 8233 "
215b30b3 8234 {
8235 enum rtx_code code = GET_CODE (operands[1]);
278b301d 8236 rtx ccreg;
39b5e676 8237
278b301d 8238 if (code == UNEQ || code == LTGT)
8239 FAIL;
8240
74f4459c 8241 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 8242 XEXP (operands[1], 1), NULL_RTX);
29bb088d 8243 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8244 }"
8245)
39b5e676 8246
8247(define_insn "*movsicc_insn"
f082f1c4 8248 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 8249 (if_then_else:SI
8fa3ba89 8250 (match_operator 3 "arm_comparison_operator"
8a18b90c 8251 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 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")))]
cffb2a26 8254 "TARGET_ARM"
39b5e676 8255 "@
8a18b90c 8256 mov%D3\\t%0, %2
8257 mvn%D3\\t%0, #%B2
f082f1c4 8258 mov%d3\\t%0, %1
8259 mvn%d3\\t%0, #%B1
8a18b90c 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"
f082f1c4 8264 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 8265 (set_attr "conds" "use")
8266 (set_attr "insn" "mov,mvn,mov,mvn,mov,mov,mvn,mvn")]
215b30b3 8267)
39b5e676 8268
39b5e676 8269(define_insn "*movsfcc_soft_insn"
f082f1c4 8270 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 8271 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 8272 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8273 (match_operand:SF 1 "s_register_operand" "0,r")
8274 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 8275 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 8276 "@
8277 mov%D3\\t%0, %2
8278 mov%d3\\t%0, %1"
d2a518d1 8279 [(set_attr "conds" "use")
8280 (set_attr "insn" "mov")]
8fa3ba89 8281)
39b5e676 8282
39b5e676 8283\f
9c08d1fa 8284;; Jump and linkage insns
8285
cffb2a26 8286(define_expand "jump"
9c08d1fa 8287 [(set (pc)
8288 (label_ref (match_operand 0 "" "")))]
cffb2a26 8289 "TARGET_EITHER"
9c08d1fa 8290 ""
cffb2a26 8291)
8292
8293(define_insn "*arm_jump"
8294 [(set (pc)
8295 (label_ref (match_operand 0 "" "")))]
25f905c2 8296 "TARGET_32BIT"
9c08d1fa 8297 "*
0d66636f 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 "
a6864a24 8307 [(set_attr "predicable" "yes")
8308 (set (attr "length")
8309 (if_then_else
0bf497f5 8310 (and (match_test "TARGET_THUMB2")
a6864a24 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)))]
0d66636f 8315)
9c08d1fa 8316
cffb2a26 8317(define_insn "*thumb_jump"
8318 [(set (pc)
8319 (label_ref (match_operand 0 "" "")))]
25f905c2 8320 "TARGET_THUMB1"
cffb2a26 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
911ed8af 8333 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8334 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 8335 (const_int 2)
8336 (const_int 4)))]
8337)
8338
d3373b54 8339(define_expand "call"
8340 [(parallel [(call (match_operand 0 "memory_operand" "")
8341 (match_operand 1 "general_operand" ""))
cffb2a26 8342 (use (match_operand 2 "" ""))
bd5b4116 8343 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8344 "TARGET_EITHER"
6c4c2133 8345 "
8346 {
bac7fc85 8347 rtx callee, pat;
bbe777ea 8348
bbe777ea 8349 /* In an untyped call, we can get NULL for operand 2. */
8350 if (operands[2] == NULL_RTX)
8351 operands[2] = const0_rtx;
8352
de55252a 8353 /* Decide if we should generate indirect calls by loading the
85c36fd1 8354 32-bit address of the callee into a register before performing the
de55252a 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))
bbe777ea 8360 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 8361
8362 pat = gen_call_internal (operands[0], operands[1], operands[2]);
8363 arm_emit_call_insn (pat, XEXP (operands[0], 0));
8364 DONE;
6c4c2133 8365 }"
8366)
d3373b54 8367
bac7fc85 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
f1039640 8374(define_insn "*call_reg_armv5"
d3373b54 8375 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 8376 (match_operand 1 "" ""))
8377 (use (match_operand 2 "" ""))
bd5b4116 8378 (clobber (reg:SI LR_REGNUM))]
f1039640 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"
9c08d1fa 8390 "*
5565501b 8391 return output_call (operands);
cffb2a26 8392 "
8393 ;; length is worst case, normally it is only two
8394 [(set_attr "length" "12")
8395 (set_attr "type" "call")]
8396)
9c08d1fa 8397
89504fc1 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
f7fbdd4a 8403(define_insn "*call_mem"
a3c63a9d 8404 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 8405 (match_operand 1 "" ""))
8406 (use (match_operand 2 "" ""))
bd5b4116 8407 (clobber (reg:SI LR_REGNUM))]
89504fc1 8408 "TARGET_ARM && !arm_arch5"
9c08d1fa 8409 "*
5565501b 8410 return output_call_mem (operands);
cffb2a26 8411 "
8412 [(set_attr "length" "12")
8413 (set_attr "type" "call")]
8414)
8415
25f905c2 8416(define_insn "*call_reg_thumb1_v5"
cffb2a26 8417 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8418 (match_operand 1 "" ""))
8419 (use (match_operand 2 "" ""))
bd5b4116 8420 (clobber (reg:SI LR_REGNUM))]
25f905c2 8421 "TARGET_THUMB1 && arm_arch5"
f1039640 8422 "blx\\t%0"
8423 [(set_attr "length" "2")
8424 (set_attr "type" "call")]
cffb2a26 8425)
8426
25f905c2 8427(define_insn "*call_reg_thumb1"
f1039640 8428 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8429 (match_operand 1 "" ""))
8430 (use (match_operand 2 "" ""))
bd5b4116 8431 (clobber (reg:SI LR_REGNUM))]
25f905c2 8432 "TARGET_THUMB1 && !arm_arch5"
cffb2a26 8433 "*
8434 {
150502c9 8435 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8436 return thumb_call_via_reg (operands[0]);
150502c9 8437 else if (operands[1] == const0_rtx)
f1039640 8438 return \"bl\\t%__interwork_call_via_%0\";
150502c9 8439 else if (frame_pointer_needed)
8440 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 8441 else
150502c9 8442 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 8443 }"
8444 [(set_attr "type" "call")]
8445)
9c08d1fa 8446
d3373b54 8447(define_expand "call_value"
e0698af7 8448 [(parallel [(set (match_operand 0 "" "")
8449 (call (match_operand 1 "memory_operand" "")
8450 (match_operand 2 "general_operand" "")))
cffb2a26 8451 (use (match_operand 3 "" ""))
bd5b4116 8452 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8453 "TARGET_EITHER"
6c4c2133 8454 "
8455 {
bac7fc85 8456 rtx pat, callee;
bbe777ea 8457
8458 /* In an untyped call, we can get NULL for operand 2. */
8459 if (operands[3] == 0)
8460 operands[3] = const0_rtx;
8461
de55252a 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))
78fe751b 8469 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 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;
6c4c2133 8475 }"
8476)
d3373b54 8477
bac7fc85 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
f1039640 8485(define_insn "*call_value_reg_armv5"
27ed6835 8486 [(set (match_operand 0 "" "")
755eb2b4 8487 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 8488 (match_operand 2 "" "")))
bbe777ea 8489 (use (match_operand 3 "" ""))
bd5b4116 8490 (clobber (reg:SI LR_REGNUM))]
f1039640 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"
9c08d1fa 8503 "*
215b30b3 8504 return output_call (&operands[1]);
cffb2a26 8505 "
8506 [(set_attr "length" "12")
8507 (set_attr "type" "call")]
8508)
9c08d1fa 8509
89504fc1 8510;; Note: see *call_mem
8511
f7fbdd4a 8512(define_insn "*call_value_mem"
27ed6835 8513 [(set (match_operand 0 "" "")
a3c63a9d 8514 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 8515 (match_operand 2 "" "")))
bbe777ea 8516 (use (match_operand 3 "" ""))
bd5b4116 8517 (clobber (reg:SI LR_REGNUM))]
89504fc1 8518 "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 8519 "*
215b30b3 8520 return output_call_mem (&operands[1]);
cffb2a26 8521 "
8522 [(set_attr "length" "12")
8523 (set_attr "type" "call")]
8524)
9c08d1fa 8525
25f905c2 8526(define_insn "*call_value_reg_thumb1_v5"
f1039640 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))]
25f905c2 8532 "TARGET_THUMB1 && arm_arch5"
f1039640 8533 "blx\\t%1"
8534 [(set_attr "length" "2")
8535 (set_attr "type" "call")]
8536)
8537
25f905c2 8538(define_insn "*call_value_reg_thumb1"
f1039640 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))]
25f905c2 8544 "TARGET_THUMB1 && !arm_arch5"
f1039640 8545 "*
8546 {
150502c9 8547 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8548 return thumb_call_via_reg (operands[1]);
150502c9 8549 else if (operands[2] == const0_rtx)
f1039640 8550 return \"bl\\t%__interwork_call_via_%1\";
150502c9 8551 else if (frame_pointer_needed)
8552 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 8553 else
150502c9 8554 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 8555 }"
8556 [(set_attr "type" "call")]
8557)
8558
9c08d1fa 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
f7fbdd4a 8562(define_insn "*call_symbol"
27ed6835 8563 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8564 (match_operand 1 "" ""))
bbe777ea 8565 (use (match_operand 2 "" ""))
bd5b4116 8566 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8567 "TARGET_32BIT
cffb2a26 8568 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8569 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8570 "*
8571 {
55c1e470 8572 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8573 }"
cffb2a26 8574 [(set_attr "type" "call")]
8575)
9c08d1fa 8576
f7fbdd4a 8577(define_insn "*call_value_symbol"
ccd90aaa 8578 [(set (match_operand 0 "" "")
27ed6835 8579 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8580 (match_operand:SI 2 "" "")))
bbe777ea 8581 (use (match_operand 3 "" ""))
bd5b4116 8582 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8583 "TARGET_32BIT
cffb2a26 8584 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8585 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8586 "*
8587 {
55c1e470 8588 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8589 }"
cffb2a26 8590 [(set_attr "type" "call")]
8591)
8592
8593(define_insn "*call_insn"
27ed6835 8594 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8595 (match_operand:SI 1 "" ""))
8596 (use (match_operand 2 "" ""))
bd5b4116 8597 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8598 "TARGET_THUMB1
1675c6e9 8599 && GET_CODE (operands[0]) == SYMBOL_REF
de55252a 8600 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
cffb2a26 8601 "bl\\t%a0"
8602 [(set_attr "length" "4")
8603 (set_attr "type" "call")]
8604)
8605
8606(define_insn "*call_value_insn"
ccd90aaa 8607 [(set (match_operand 0 "" "")
27ed6835 8608 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 8609 (match_operand 2 "" "")))
8610 (use (match_operand 3 "" ""))
bd5b4116 8611 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8612 "TARGET_THUMB1
1675c6e9 8613 && GET_CODE (operands[1]) == SYMBOL_REF
de55252a 8614 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
cffb2a26 8615 "bl\\t%a1"
8616 [(set_attr "length" "4")
8617 (set_attr "type" "call")]
8618)
9c08d1fa 8619
1c494086 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" ""))
2ba80634 8624 (return)
8625 (use (match_operand 2 "" ""))])]
d68c2c10 8626 "TARGET_32BIT"
1c494086 8627 "
8628 {
8629 if (operands[2] == NULL_RTX)
8630 operands[2] = const0_rtx;
1c494086 8631 }"
8632)
8633
8634(define_expand "sibcall_value"
ccd90aaa 8635 [(parallel [(set (match_operand 0 "" "")
1c494086 8636 (call (match_operand 1 "memory_operand" "")
8637 (match_operand 2 "general_operand" "")))
2ba80634 8638 (return)
8639 (use (match_operand 3 "" ""))])]
d68c2c10 8640 "TARGET_32BIT"
1c494086 8641 "
8642 {
8643 if (operands[3] == NULL_RTX)
8644 operands[3] = const0_rtx;
1c494086 8645 }"
8646)
8647
8648(define_insn "*sibcall_insn"
8649 [(call (mem:SI (match_operand:SI 0 "" "X"))
8650 (match_operand 1 "" ""))
2ba80634 8651 (return)
8652 (use (match_operand 2 "" ""))]
d68c2c10 8653 "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF"
1c494086 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"
ccd90aaa 8661 [(set (match_operand 0 "" "")
755eb2b4 8662 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 8663 (match_operand 2 "" "")))
2ba80634 8664 (return)
8665 (use (match_operand 3 "" ""))]
d68c2c10 8666 "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF"
1c494086 8667 "*
8668 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8669 "
8670 [(set_attr "type" "call")]
8671)
8672
d68c2c10 8673(define_expand "return"
8674 [(return)]
8675 "TARGET_32BIT && USE_RETURN_INSN (FALSE)"
8676 "")
8677
9c08d1fa 8678;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 8679(define_insn "*arm_return"
9c08d1fa 8680 [(return)]
cffb2a26 8681 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8682 "*
9c08d1fa 8683 {
cffb2a26 8684 if (arm_ccfsm_state == 2)
8685 {
8686 arm_ccfsm_state += 2;
8687 return \"\";
8688 }
5db468b7 8689 return output_return_instruction (const_true_rtx, TRUE, FALSE);
cffb2a26 8690 }"
a2cd141b 8691 [(set_attr "type" "load1")
755eb2b4 8692 (set_attr "length" "12")
0d66636f 8693 (set_attr "predicable" "yes")]
cffb2a26 8694)
9c08d1fa 8695
f7fbdd4a 8696(define_insn "*cond_return"
9c08d1fa 8697 [(set (pc)
8fa3ba89 8698 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8699 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8700 (return)
8701 (pc)))]
cffb2a26 8702 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8703 "*
8fa3ba89 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")
755eb2b4 8713 (set_attr "length" "12")
a2cd141b 8714 (set_attr "type" "load1")]
8fa3ba89 8715)
9c08d1fa 8716
f7fbdd4a 8717(define_insn "*cond_return_inverted"
9c08d1fa 8718 [(set (pc)
8fa3ba89 8719 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8720 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8721 (pc)
8722 (return)))]
cffb2a26 8723 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8724 "*
8fa3ba89 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")
37a1317b 8734 (set_attr "length" "12")
a2cd141b 8735 (set_attr "type" "load1")]
8fa3ba89 8736)
9c08d1fa 8737
68121397 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 "
62eddbd4 8752 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 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
9c08d1fa 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 "" "")])]
ccd90aaa 8772 "TARGET_EITHER"
9c08d1fa 8773 "
215b30b3 8774 {
8775 int i;
ccd90aaa 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;
9c08d1fa 8781
ccd90aaa 8782 emit_move_insn (addr, XEXP (operands[1], 0));
8783 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8784
215b30b3 8785 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8786 {
ccd90aaa 8787 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8788
ccd90aaa 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)
29c05e22 8810 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 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. */
320ea44d 8816 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8817 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 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 }
215b30b3 8825 }
9c08d1fa 8826
215b30b3 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)
9c08d1fa 8836
ccd90aaa 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)
29c05e22 8857 emit_move_insn (addr, plus_constant (Pmode, addr, size));
ccd90aaa 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. */
320ea44d 8863 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8864 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 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++)
18b42941 8876 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8877
8878 /* Construct the return. */
8879 expand_naked_return ();
8880
8881 DONE;
8882 }"
8883)
8884
9c08d1fa 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"
e1159bbe 8889 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8890 "TARGET_EITHER"
9c08d1fa 8891 ""
cffb2a26 8892 [(set_attr "length" "0")
8893 (set_attr "type" "block")]
8894)
9c08d1fa 8895
f7fbdd4a 8896(define_expand "casesi"
8897 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8898 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8899 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8900 (match_operand:SI 3 "" "") ; table label
8901 (match_operand:SI 4 "" "")] ; Out of range label
e6ac8414 8902 "TARGET_32BIT || optimize_size || flag_pic"
f7fbdd4a 8903 "
215b30b3 8904 {
e6ac8414 8905 enum insn_code code;
215b30b3 8906 if (operands[1] != const0_rtx)
8907 {
e6ac8414 8908 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8909
215b30b3 8910 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8911 gen_int_mode (-INTVAL (operands[1]),
8912 SImode)));
215b30b3 8913 operands[0] = reg;
8914 }
9c08d1fa 8915
25f905c2 8916 if (TARGET_ARM)
e6ac8414 8917 code = CODE_FOR_arm_casesi_internal;
3db2019b 8918 else if (TARGET_THUMB1)
e6ac8414 8919 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8920 else if (flag_pic)
e6ac8414 8921 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8922 else
e6ac8414 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]));
215b30b3 8930 DONE;
8931 }"
8932)
f7fbdd4a 8933
f082f1c4 8934;; The USE in this pattern is needed to tell flow analysis that this is
8935;; a CASESI insn. It has no other purpose.
25f905c2 8936(define_insn "arm_casesi_internal"
f082f1c4 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 "" ""))))
bd5b4116 8944 (clobber (reg:CC CC_REGNUM))
f082f1c4 8945 (use (label_ref (match_dup 2)))])]
cffb2a26 8946 "TARGET_ARM"
f7fbdd4a 8947 "*
0d66636f 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)
9c08d1fa 8955
e6ac8414 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 "" "")]
3db2019b 8961 "TARGET_THUMB1"
e6ac8414 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))])]
3db2019b 8982 "TARGET_THUMB1"
e6ac8414 8983 "* return thumb1_output_casesi(operands);"
8984 [(set_attr "length" "4")]
8985)
8986
cffb2a26 8987(define_expand "indirect_jump"
9c08d1fa 8988 [(set (pc)
cffb2a26 8989 (match_operand:SI 0 "s_register_operand" ""))]
8990 "TARGET_EITHER"
25f905c2 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 "
cffb2a26 9002)
9003
f1039640 9004;; NB Never uses BX.
cffb2a26 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"
0d66636f 9010 [(set_attr "predicable" "yes")]
cffb2a26 9011)
9c08d1fa 9012
f7fbdd4a 9013(define_insn "*load_indirect_jump"
9c08d1fa 9014 [(set (pc)
9015 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 9016 "TARGET_ARM"
9017 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 9018 [(set_attr "type" "load1")
61a2d04c 9019 (set_attr "pool_range" "4096")
9020 (set_attr "neg_pool_range" "4084")
0d66636f 9021 (set_attr "predicable" "yes")]
cffb2a26 9022)
9023
f1039640 9024;; NB Never uses BX.
25f905c2 9025(define_insn "*thumb1_indirect_jump"
cffb2a26 9026 [(set (pc)
9027 (match_operand:SI 0 "register_operand" "l*r"))]
25f905c2 9028 "TARGET_THUMB1"
cffb2a26 9029 "mov\\tpc, %0"
9030 [(set_attr "conds" "clob")
9031 (set_attr "length" "2")]
9032)
9033
9c08d1fa 9034\f
9035;; Misc insns
9036
9037(define_insn "nop"
9038 [(const_int 0)]
cffb2a26 9039 "TARGET_EITHER"
9040 "*
25f905c2 9041 if (TARGET_UNIFIED_ASM)
9042 return \"nop\";
cffb2a26 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
9c08d1fa 9053\f
9054;; Patterns to allow combination of arithmetic, cond code and shifts
9055
f7fbdd4a 9056(define_insn "*arith_shiftsi"
7392680c 9057 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9c08d1fa 9058 (match_operator:SI 1 "shiftable_operator"
9059 [(match_operator:SI 3 "shift_operator"
7392680c 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")]))]
d5d4dc8d 9063 "TARGET_32BIT"
6c4c2133 9064 "%i1%?\\t%0, %2, %4%S3"
344495ea 9065 [(set_attr "predicable" "yes")
331beb1a 9066 (set_attr "shift" "4")
7392680c 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
d5d4dc8d 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")
7392680c 9079 (if_then_else
9080 (match_operand:SI 1 "add_operator" "")
9081 (const_string "yes") (const_string "no"))
9082 (const_string "yes")
d5d4dc8d 9083 (if_then_else
9084 (match_operand:SI 3 "mult_operator" "")
9085 (const_string "no") (const_string "yes"))])
7392680c 9086 (set_attr "type" "alu_shift,alu_shift,alu_shift,alu_shift_reg")])
9c08d1fa 9087
d7863cfe 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" ""))]
d5d4dc8d 9098 "TARGET_32BIT"
d7863cfe 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
f7fbdd4a 9106(define_insn "*arith_shiftsi_compare0"
bd5b4116 9107 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 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")
9c08d1fa 9116 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9117 (match_dup 2)]))]
d5d4dc8d 9118 "TARGET_32BIT"
25f905c2 9119 "%i1%.\\t%0, %2, %4%S3"
344495ea 9120 [(set_attr "conds" "set")
331beb1a 9121 (set_attr "shift" "4")
d5d4dc8d 9122 (set_attr "arch" "32,a")
9123 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 9124
f7fbdd4a 9125(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 9126 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 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"
25f905c2 9136 "%i1%.\\t%0, %2, %4%S3"
344495ea 9137 [(set_attr "conds" "set")
331beb1a 9138 (set_attr "shift" "4")
d5d4dc8d 9139 (set_attr "arch" "32,a")
9140 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 9141
f7fbdd4a 9142(define_insn "*sub_shiftsi"
d5d4dc8d 9143 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9144 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 9145 (match_operator:SI 2 "shift_operator"
d5d4dc8d 9146 [(match_operand:SI 3 "s_register_operand" "r,r")
9147 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
9148 "TARGET_32BIT"
6c4c2133 9149 "sub%?\\t%0, %1, %3%S2"
344495ea 9150 [(set_attr "predicable" "yes")
331beb1a 9151 (set_attr "shift" "3")
d5d4dc8d 9152 (set_attr "arch" "32,a")
9153 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 9154
f7fbdd4a 9155(define_insn "*sub_shiftsi_compare0"
bd5b4116 9156 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 9157 (compare:CC_NOOV
d5d4dc8d 9158 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 9159 (match_operator:SI 2 "shift_operator"
d5d4dc8d 9160 [(match_operand:SI 3 "s_register_operand" "r,r")
9161 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 9162 (const_int 0)))
d5d4dc8d 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"
25f905c2 9167 "sub%.\\t%0, %1, %3%S2"
344495ea 9168 [(set_attr "conds" "set")
a2cd141b 9169 (set_attr "shift" "3")
d5d4dc8d 9170 (set_attr "arch" "32,a")
9171 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 9172
f7fbdd4a 9173(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 9174 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 9175 (compare:CC_NOOV
d5d4dc8d 9176 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 9177 (match_operator:SI 2 "shift_operator"
d5d4dc8d 9178 [(match_operand:SI 3 "s_register_operand" "r,r")
9179 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 9180 (const_int 0)))
d5d4dc8d 9181 (clobber (match_scratch:SI 0 "=r,r"))]
9182 "TARGET_32BIT"
25f905c2 9183 "sub%.\\t%0, %1, %3%S2"
344495ea 9184 [(set_attr "conds" "set")
a2cd141b 9185 (set_attr "shift" "3")
d5d4dc8d 9186 (set_attr "arch" "32,a")
9187 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 9188\f
9189
f7fbdd4a 9190(define_insn "*and_scc"
9c08d1fa 9191 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9192 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 9193 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 9194 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 9195 "TARGET_ARM"
e2348bcb 9196 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 9197 [(set_attr "conds" "use")
d2a518d1 9198 (set_attr "insn" "mov")
8fa3ba89 9199 (set_attr "length" "8")]
9200)
9c08d1fa 9201
f7fbdd4a 9202(define_insn "*ior_scc"
9c08d1fa 9203 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9204 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 9205 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 9206 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 9207 "TARGET_ARM"
e2348bcb 9208 "@
899850b0 9209 orr%d2\\t%0, %1, #1
9210 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 9211 [(set_attr "conds" "use")
9212 (set_attr "length" "4,8")]
9213)
9c08d1fa 9214
2df9477b 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
080c0b9a 9241 [(set (reg:CC CC_REGNUM)
9242 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 9243 (set (match_dup 0)
9244 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 9245 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 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"
5565501b 9279 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9280 (match_operator:SI 1 "arm_comparison_operator"
5565501b 9281 [(match_operand:SI 2 "s_register_operand" "r,r")
9282 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 9283 (clobber (reg:CC CC_REGNUM))]
2df9477b 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]);
e2348bcb 9295
2df9477b 9296 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 9297
2df9477b 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})
9c08d1fa 9305
080c0b9a 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"
922b6913 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)))])
080c0b9a 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)))])
922b6913 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))])])
080c0b9a 9331
f7fbdd4a 9332(define_insn "*cond_move"
9c08d1fa 9333 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 9334 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 9335 [(match_operator 4 "arm_comparison_operator"
8a18b90c 9336 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 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")))]
cffb2a26 9340 "TARGET_ARM"
9c08d1fa 9341 "*
8fa3ba89 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")
d2a518d1 9357 (set_attr "insn" "mov")
8fa3ba89 9358 (set_attr "length" "4,4,8")]
9359)
9c08d1fa 9360
f7fbdd4a 9361(define_insn "*cond_arith"
9c08d1fa 9362 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9363 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 9364 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 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")]))
bd5b4116 9368 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9369 "TARGET_ARM"
9c08d1fa 9370 "*
8fa3ba89 9371 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9372 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 9373
8fa3ba89 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)
9c08d1fa 9386
f7fbdd4a 9387(define_insn "*cond_sub"
9c08d1fa 9388 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9389 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 9390 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9391 [(match_operand:SI 2 "s_register_operand" "r,r")
9392 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9393 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9394 "TARGET_ARM"
9c08d1fa 9395 "*
8fa3ba89 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)
9c08d1fa 9404
aea4c774 9405(define_insn "*cmp_ite0"
cffb2a26 9406 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9407 (compare
9408 (if_then_else:SI
8fa3ba89 9409 (match_operator 4 "arm_comparison_operator"
2ff91fec 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")])
8fa3ba89 9414 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 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")])
aea4c774 9419 (const_int 0))
9420 (const_int 0)))]
2ff91fec 9421 "TARGET_32BIT"
9c08d1fa 9422 "*
aea4c774 9423 {
2ff91fec 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] =
8fa3ba89 9447 {
2ff91fec 9448 \"it\\t%d5\",
9449 \"it\\t%d4\"
8fa3ba89 9450 };
2ff91fec 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};
8fa3ba89 9454 int swap =
9455 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9456
2ff91fec 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 \"\";
8fa3ba89 9463 }"
9464 [(set_attr "conds" "set")
2ff91fec 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))])]
8fa3ba89 9484)
9c08d1fa 9485
aea4c774 9486(define_insn "*cmp_ite1"
cffb2a26 9487 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9488 (compare
9489 (if_then_else:SI
8fa3ba89 9490 (match_operator 4 "arm_comparison_operator"
2ff91fec 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")])
8fa3ba89 9495 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 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")])
aea4c774 9500 (const_int 1))
9501 (const_int 0)))]
2ff91fec 9502 "TARGET_32BIT"
9c08d1fa 9503 "*
9c08d1fa 9504 {
2ff91fec 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] =
215b30b3 9517 {
2ff91fec 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\"}
215b30b3 9526 };
2ff91fec 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};
215b30b3 9535 int swap =
9536 comparison_dominates_p (GET_CODE (operands[5]),
9537 reverse_condition (GET_CODE (operands[4])));
9538
2ff91fec 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 \"\";
215b30b3 9545 }"
8fa3ba89 9546 [(set_attr "conds" "set")
2ff91fec 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))])]
8fa3ba89 9566)
9c08d1fa 9567
f6c53574 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"
2ff91fec 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")])
f6c53574 9577 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 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")]))
f6c53574 9582 (const_int 0)))]
2ff91fec 9583 "TARGET_32BIT"
f6c53574 9584 "*
9585 {
2ff91fec 9586 static const char *const cmp1[NUM_OF_COND_CMP][2] =
f6c53574 9587 {
2ff91fec 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\"}
f6c53574 9596 };
2ff91fec 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};
f6c53574 9616 int swap =
9617 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9618
2ff91fec 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 \"\";
f6c53574 9625 }"
9626 [(set_attr "conds" "set")
9627 (set_attr "predicable" "no")
2ff91fec 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))])]
f6c53574 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"
2ff91fec 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")])
f6c53574 9658 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 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")]))
f6c53574 9663 (const_int 0)))]
2ff91fec 9664 "TARGET_32BIT"
f6c53574 9665 "*
f6c53574 9666 {
2ff91fec 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 "
f6c53574 9708 [(set_attr "conds" "set")
2ff91fec 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))])]
f6c53574 9728)
9729
3c5afce6 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))]
2ff91fec 9739 "TARGET_32BIT
3c5afce6 9740 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9741 != CCmode)"
9742 "#"
2ff91fec 9743 "TARGET_32BIT && reload_completed"
3c5afce6 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),
601f584c 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)])))]
2ff91fec 9772 "TARGET_32BIT"
601f584c 9773 "#"
2ff91fec 9774 "TARGET_32BIT && reload_completed"
601f584c 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")])
3c5afce6 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))]
2ff91fec 9795 "TARGET_32BIT
3c5afce6 9796 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9797 != CCmode)"
9798 "#"
2ff91fec 9799 "TARGET_32BIT && reload_completed
601f584c 9800 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9801 != CCmode)"
3c5afce6 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),
601f584c 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)])))]
2ff91fec 9830 "TARGET_32BIT"
601f584c 9831 "#"
2ff91fec 9832 "TARGET_32BIT && reload_completed"
601f584c 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))]
2ff91fec 9857 "TARGET_32BIT
601f584c 9858 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9859 == CCmode)"
9860 "#"
2ff91fec 9861 "TARGET_32BIT && reload_completed"
601f584c 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")])
3c5afce6 9877
3a0bdee0 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))
b0694be0 9883 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 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
b0694be0 9900 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 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 "")
25f905c2 9915;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9916
f7fbdd4a 9917(define_insn "*negscc"
9c08d1fa 9918 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9919 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9920 [(match_operand:SI 1 "s_register_operand" "r")
9921 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9922 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9923 "TARGET_ARM"
9c08d1fa 9924 "*
2ca2ec2e 9925 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
e2348bcb 9926 return \"mov\\t%0, %1, asr #31\";
9927
9c08d1fa 9928 if (GET_CODE (operands[3]) == NE)
e2348bcb 9929 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9930
e2348bcb 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\";
215b30b3 9934 "
8fa3ba89 9935 [(set_attr "conds" "clob")
9936 (set_attr "length" "12")]
9937)
9c08d1fa 9938
9939(define_insn "movcond"
9940 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9941 (if_then_else:SI
8fa3ba89 9942 (match_operator 5 "arm_comparison_operator"
5565501b 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")))
bd5b4116 9947 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9948 "TARGET_ARM"
9c08d1fa 9949 "*
9950 if (GET_CODE (operands[5]) == LT
9951 && (operands[4] == const0_rtx))
9952 {
5565501b 9953 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9c08d1fa 9954 {
9c08d1fa 9955 if (operands[2] == const0_rtx)
e2348bcb 9956 return \"and\\t%0, %1, %3, asr #31\";
9957 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9958 }
9959 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9960 {
9c08d1fa 9961 if (operands[1] == const0_rtx)
e2348bcb 9962 return \"bic\\t%0, %2, %3, asr #31\";
9963 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9964 }
9965 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9966 are constants. */
9c08d1fa 9967 }
e2348bcb 9968
9c08d1fa 9969 if (GET_CODE (operands[5]) == GE
9970 && (operands[4] == const0_rtx))
9971 {
9972 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9973 {
9c08d1fa 9974 if (operands[2] == const0_rtx)
e2348bcb 9975 return \"bic\\t%0, %1, %3, asr #31\";
9976 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9977 }
9978 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9979 {
9c08d1fa 9980 if (operands[1] == const0_rtx)
e2348bcb 9981 return \"and\\t%0, %2, %3, asr #31\";
9982 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9983 }
9984 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9985 are constants. */
9c08d1fa 9986 }
9987 if (GET_CODE (operands[4]) == CONST_INT
9988 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9989 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9990 else
e2348bcb 9991 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9992 if (which_alternative != 0)
e2348bcb 9993 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9994 if (which_alternative != 1)
e2348bcb 9995 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9996 return \"\";
215b30b3 9997 "
8fa3ba89 9998 [(set_attr "conds" "clob")
9999 (set_attr "length" "8,8,12")]
10000)
9c08d1fa 10001
25f905c2 10002;; ??? The patterns below need checking for Thumb-2 usefulness.
10003
8a18b90c 10004(define_insn "*ifcompare_plus_move"
10005 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10006 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 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"))
129a2fe4 10012 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 10013 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10014 "TARGET_ARM"
8a18b90c 10015 "#"
8fa3ba89 10016 [(set_attr "conds" "clob")
10017 (set_attr "length" "8,12")]
10018)
8a18b90c 10019
10020(define_insn "*if_plus_move"
129a2fe4 10021 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 10022 (if_then_else:SI
8fa3ba89 10023 (match_operator 4 "arm_comparison_operator"
8a18b90c 10024 [(match_operand 5 "cc_register" "") (const_int 0)])
10025 (plus:SI
129a2fe4 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")))]
cffb2a26 10029 "TARGET_ARM"
8a18b90c 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
129a2fe4 10034 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 10035 [(set_attr "conds" "use")
10036 (set_attr "length" "4,4,8,8")
10037 (set_attr "type" "*,*,*,*")]
10038)
8a18b90c 10039
10040(define_insn "*ifcompare_move_plus"
5565501b 10041 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10042 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 10043 [(match_operand:SI 4 "s_register_operand" "r,r")
10044 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 10045 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 10046 (plus:SI
10047 (match_operand:SI 2 "s_register_operand" "r,r")
10048 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 10049 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10050 "TARGET_ARM"
8a18b90c 10051 "#"
8fa3ba89 10052 [(set_attr "conds" "clob")
10053 (set_attr "length" "8,12")]
10054)
8a18b90c 10055
10056(define_insn "*if_move_plus"
129a2fe4 10057 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 10058 (if_then_else:SI
8fa3ba89 10059 (match_operator 4 "arm_comparison_operator"
8a18b90c 10060 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 10061 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 10062 (plus:SI
129a2fe4 10063 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
10064 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 10065 "TARGET_ARM"
8a18b90c 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
129a2fe4 10070 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 10071 [(set_attr "conds" "use")
10072 (set_attr "length" "4,4,8,8")
10073 (set_attr "type" "*,*,*,*")]
10074)
8a18b90c 10075
10076(define_insn "*ifcompare_arith_arith"
10077 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10078 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 10079 [(match_operand:SI 5 "s_register_operand" "r")
10080 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 10081 (match_operator:SI 8 "shiftable_operator"
8a18b90c 10082 [(match_operand:SI 1 "s_register_operand" "r")
10083 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 10084 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10085 [(match_operand:SI 3 "s_register_operand" "r")
10086 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 10087 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10088 "TARGET_ARM"
8a18b90c 10089 "#"
8fa3ba89 10090 [(set_attr "conds" "clob")
10091 (set_attr "length" "12")]
10092)
9c08d1fa 10093
8a18b90c 10094(define_insn "*if_arith_arith"
10095 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10096 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 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")])))]
cffb2a26 10104 "TARGET_ARM"
8a18b90c 10105 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 10106 [(set_attr "conds" "use")
10107 (set_attr "length" "8")]
10108)
8a18b90c 10109
f7fbdd4a 10110(define_insn "*ifcompare_arith_move"
9c08d1fa 10111 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10112 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 10113 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 10114 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 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")])
129a2fe4 10118 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 10119 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10120 "TARGET_ARM"
9c08d1fa 10121 "*
9c08d1fa 10122 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 10123 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 10124 everything is in registers then we can do this in two instructions. */
9c08d1fa 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)
40dbec34 10133 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 10134 else if (GET_CODE (operands[6]) == GE)
40dbec34 10135 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 10136 }
10137 if (GET_CODE (operands[3]) == CONST_INT
10138 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 10139 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 10140 else
e2348bcb 10141 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 10142 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 10143 if (which_alternative != 0)
129a2fe4 10144 return \"mov%D6\\t%0, %1\";
9c08d1fa 10145 return \"\";
215b30b3 10146 "
8fa3ba89 10147 [(set_attr "conds" "clob")
10148 (set_attr "length" "8,12")]
10149)
9c08d1fa 10150
8a18b90c 10151(define_insn "*if_arith_move"
129a2fe4 10152 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10153 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 10154 [(match_operand 6 "cc_register" "") (const_int 0)])
10155 (match_operator:SI 5 "shiftable_operator"
129a2fe4 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")))]
cffb2a26 10159 "TARGET_ARM"
8a18b90c 10160 "@
10161 %I5%d4\\t%0, %2, %3
129a2fe4 10162 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 10163 [(set_attr "conds" "use")
10164 (set_attr "length" "4,8")
10165 (set_attr "type" "*,*")]
10166)
8a18b90c 10167
f7fbdd4a 10168(define_insn "*ifcompare_move_arith"
9c08d1fa 10169 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10170 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 10171 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 10172 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 10173 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 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")])))
bd5b4116 10177 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10178 "TARGET_ARM"
9c08d1fa 10179 "*
9c08d1fa 10180 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 10181 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 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)
40dbec34 10191 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10192 else if (GET_CODE (operands[6]) == LT)
40dbec34 10193 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10194 }
40dbec34 10195
9c08d1fa 10196 if (GET_CODE (operands[5]) == CONST_INT
10197 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 10198 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 10199 else
e2348bcb 10200 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 10201
9c08d1fa 10202 if (which_alternative != 0)
129a2fe4 10203 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 10204 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 10205 "
8fa3ba89 10206 [(set_attr "conds" "clob")
10207 (set_attr "length" "8,12")]
10208)
9c08d1fa 10209
8a18b90c 10210(define_insn "*if_move_arith"
129a2fe4 10211 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10212 (if_then_else:SI
8fa3ba89 10213 (match_operator 4 "arm_comparison_operator"
8a18b90c 10214 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 10215 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 10216 (match_operator:SI 5 "shiftable_operator"
129a2fe4 10217 [(match_operand:SI 2 "s_register_operand" "r,r")
10218 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 10219 "TARGET_ARM"
8a18b90c 10220 "@
10221 %I5%D4\\t%0, %2, %3
129a2fe4 10222 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 10223 [(set_attr "conds" "use")
10224 (set_attr "length" "4,8")
10225 (set_attr "type" "*,*")]
10226)
8a18b90c 10227
10228(define_insn "*ifcompare_move_not"
9c08d1fa 10229 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10230 (if_then_else:SI
8fa3ba89 10231 (match_operator 5 "arm_comparison_operator"
8a18b90c 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"))))
bd5b4116 10237 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10238 "TARGET_ARM"
8a18b90c 10239 "#"
8fa3ba89 10240 [(set_attr "conds" "clob")
10241 (set_attr "length" "8,12")]
10242)
9c08d1fa 10243
8a18b90c 10244(define_insn "*if_move_not"
10245 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10246 (if_then_else:SI
8fa3ba89 10247 (match_operator 4 "arm_comparison_operator"
8a18b90c 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"))))]
cffb2a26 10251 "TARGET_ARM"
8a18b90c 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"
8fa3ba89 10256 [(set_attr "conds" "use")
d2a518d1 10257 (set_attr "insn" "mvn")
8fa3ba89 10258 (set_attr "length" "4,8,8")]
10259)
8a18b90c 10260
10261(define_insn "*ifcompare_not_move"
9c08d1fa 10262 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10263 (if_then_else:SI
8fa3ba89 10264 (match_operator 5 "arm_comparison_operator"
8a18b90c 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")))
bd5b4116 10270 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10271 "TARGET_ARM"
8a18b90c 10272 "#"
8fa3ba89 10273 [(set_attr "conds" "clob")
10274 (set_attr "length" "8,12")]
10275)
9c08d1fa 10276
8a18b90c 10277(define_insn "*if_not_move"
10278 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10279 (if_then_else:SI
8fa3ba89 10280 (match_operator 4 "arm_comparison_operator"
8a18b90c 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")))]
cffb2a26 10284 "TARGET_ARM"
8a18b90c 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"
8fa3ba89 10289 [(set_attr "conds" "use")
d2a518d1 10290 (set_attr "insn" "mvn")
8fa3ba89 10291 (set_attr "length" "4,8,8")]
10292)
8a18b90c 10293
10294(define_insn "*ifcompare_shift_move"
9c08d1fa 10295 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10296 (if_then_else:SI
8fa3ba89 10297 (match_operator 6 "arm_comparison_operator"
8a18b90c 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")))
bd5b4116 10304 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10305 "TARGET_ARM"
9c08d1fa 10306 "#"
8fa3ba89 10307 [(set_attr "conds" "clob")
10308 (set_attr "length" "8,12")]
10309)
9c08d1fa 10310
8a18b90c 10311(define_insn "*if_shift_move"
10312 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10313 (if_then_else:SI
8fa3ba89 10314 (match_operator 5 "arm_comparison_operator"
8a18b90c 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")))]
cffb2a26 10320 "TARGET_ARM"
5565501b 10321 "@
8a18b90c 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"
8fa3ba89 10325 [(set_attr "conds" "use")
331beb1a 10326 (set_attr "shift" "2")
a2cd141b 10327 (set_attr "length" "4,8,8")
d2a518d1 10328 (set_attr "insn" "mov")
a2cd141b 10329 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10330 (const_string "alu_shift")
10331 (const_string "alu_shift_reg")))]
8fa3ba89 10332)
5565501b 10333
8a18b90c 10334(define_insn "*ifcompare_move_shift"
10335 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10336 (if_then_else:SI
8fa3ba89 10337 (match_operator 6 "arm_comparison_operator"
8a18b90c 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")
5565501b 10341 (match_operator:SI 7 "shift_operator"
8a18b90c 10342 [(match_operand:SI 2 "s_register_operand" "r,r")
10343 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 10344 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10345 "TARGET_ARM"
8a18b90c 10346 "#"
8fa3ba89 10347 [(set_attr "conds" "clob")
10348 (set_attr "length" "8,12")]
10349)
5565501b 10350
8a18b90c 10351(define_insn "*if_move_shift"
10352 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 10353 (if_then_else:SI
8fa3ba89 10354 (match_operator 5 "arm_comparison_operator"
8a18b90c 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")])))]
cffb2a26 10360 "TARGET_ARM"
5565501b 10361 "@
8a18b90c 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"
8fa3ba89 10365 [(set_attr "conds" "use")
331beb1a 10366 (set_attr "shift" "2")
a2cd141b 10367 (set_attr "length" "4,8,8")
d2a518d1 10368 (set_attr "insn" "mov")
a2cd141b 10369 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10370 (const_string "alu_shift")
10371 (const_string "alu_shift_reg")))]
8fa3ba89 10372)
9c08d1fa 10373
f7fbdd4a 10374(define_insn "*ifcompare_shift_shift"
8a18b90c 10375 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10376 (if_then_else:SI
8fa3ba89 10377 (match_operator 7 "arm_comparison_operator"
8a18b90c 10378 [(match_operand:SI 5 "s_register_operand" "r")
10379 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 10380 (match_operator:SI 8 "shift_operator"
8a18b90c 10381 [(match_operand:SI 1 "s_register_operand" "r")
10382 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 10383 (match_operator:SI 9 "shift_operator"
8a18b90c 10384 [(match_operand:SI 3 "s_register_operand" "r")
10385 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 10386 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10387 "TARGET_ARM"
8a18b90c 10388 "#"
8fa3ba89 10389 [(set_attr "conds" "clob")
10390 (set_attr "length" "12")]
10391)
9c08d1fa 10392
8a18b90c 10393(define_insn "*if_shift_shift"
10394 [(set (match_operand:SI 0 "s_register_operand" "=r")
10395 (if_then_else:SI
8fa3ba89 10396 (match_operator 5 "arm_comparison_operator"
8a18b90c 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")])))]
cffb2a26 10404 "TARGET_ARM"
8a18b90c 10405 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 10406 [(set_attr "conds" "use")
331beb1a 10407 (set_attr "shift" "1")
a2cd141b 10408 (set_attr "length" "8")
d2a518d1 10409 (set_attr "insn" "mov")
a2cd141b 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")))]
8fa3ba89 10415)
8a18b90c 10416
f7fbdd4a 10417(define_insn "*ifcompare_not_arith"
8a18b90c 10418 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10419 (if_then_else:SI
8fa3ba89 10420 (match_operator 6 "arm_comparison_operator"
8a18b90c 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"))
5565501b 10424 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10425 [(match_operand:SI 2 "s_register_operand" "r")
10426 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 10427 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10428 "TARGET_ARM"
8a18b90c 10429 "#"
8fa3ba89 10430 [(set_attr "conds" "clob")
10431 (set_attr "length" "12")]
10432)
9c08d1fa 10433
8a18b90c 10434(define_insn "*if_not_arith"
10435 [(set (match_operand:SI 0 "s_register_operand" "=r")
10436 (if_then_else:SI
8fa3ba89 10437 (match_operator 5 "arm_comparison_operator"
8a18b90c 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")])))]
cffb2a26 10443 "TARGET_ARM"
8a18b90c 10444 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 10445 [(set_attr "conds" "use")
d2a518d1 10446 (set_attr "insn" "mvn")
8fa3ba89 10447 (set_attr "length" "8")]
10448)
8a18b90c 10449
10450(define_insn "*ifcompare_arith_not"
10451 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10452 (if_then_else:SI
8fa3ba89 10453 (match_operator 6 "arm_comparison_operator"
8a18b90c 10454 [(match_operand:SI 4 "s_register_operand" "r")
10455 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 10456 (match_operator:SI 7 "shiftable_operator"
8a18b90c 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"))))
bd5b4116 10460 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10461 "TARGET_ARM"
8a18b90c 10462 "#"
8fa3ba89 10463 [(set_attr "conds" "clob")
10464 (set_attr "length" "12")]
10465)
9c08d1fa 10466
8a18b90c 10467(define_insn "*if_arith_not"
10468 [(set (match_operand:SI 0 "s_register_operand" "=r")
10469 (if_then_else:SI
8fa3ba89 10470 (match_operator 5 "arm_comparison_operator"
8a18b90c 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"))))]
cffb2a26 10476 "TARGET_ARM"
8a18b90c 10477 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 10478 [(set_attr "conds" "use")
d2a518d1 10479 (set_attr "insn" "mvn")
8fa3ba89 10480 (set_attr "length" "8")]
10481)
8a18b90c 10482
f7fbdd4a 10483(define_insn "*ifcompare_neg_move"
8a18b90c 10484 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10485 (if_then_else:SI
8fa3ba89 10486 (match_operator 5 "arm_comparison_operator"
8a18b90c 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")))
bd5b4116 10491 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10492 "TARGET_ARM"
8a18b90c 10493 "#"
8fa3ba89 10494 [(set_attr "conds" "clob")
10495 (set_attr "length" "8,12")]
10496)
8a18b90c 10497
10498(define_insn "*if_neg_move"
10499 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10500 (if_then_else:SI
8fa3ba89 10501 (match_operator 4 "arm_comparison_operator"
8a18b90c 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")))]
cffb2a26 10505 "TARGET_ARM"
8a18b90c 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"
8fa3ba89 10510 [(set_attr "conds" "use")
10511 (set_attr "length" "4,8,8")]
10512)
9c08d1fa 10513
f7fbdd4a 10514(define_insn "*ifcompare_move_neg"
8a18b90c 10515 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10516 (if_then_else:SI
8fa3ba89 10517 (match_operator 5 "arm_comparison_operator"
8a18b90c 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"))))
bd5b4116 10522 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10523 "TARGET_ARM"
8a18b90c 10524 "#"
8fa3ba89 10525 [(set_attr "conds" "clob")
10526 (set_attr "length" "8,12")]
10527)
8a18b90c 10528
10529(define_insn "*if_move_neg"
10530 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10531 (if_then_else:SI
8fa3ba89 10532 (match_operator 4 "arm_comparison_operator"
8a18b90c 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"))))]
cffb2a26 10536 "TARGET_ARM"
8a18b90c 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"
0d66636f 10541 [(set_attr "conds" "use")
10542 (set_attr "length" "4,8,8")]
10543)
9c08d1fa 10544
f7fbdd4a 10545(define_insn "*arith_adjacentmem"
9c08d1fa 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"))]
cffb2a26 10551 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 10552 "*
215b30b3 10553 {
10554 rtx ldm[3];
10555 rtx arith[4];
94dee231 10556 rtx base_reg;
10557 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 10558
215b30b3 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 }
94dee231 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)))
215b30b3 10579 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10580
215b30b3 10581 arith[0] = operands[0];
10582 arith[3] = operands[1];
94dee231 10583
215b30b3 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 }
94dee231 10594
10595 ldm[0] = base_reg;
10596 if (val1 !=0 && val2 != 0)
215b30b3 10597 {
cdb1295a 10598 rtx ops[3];
10599
94dee231 10600 if (val1 == 4 || val2 == 4)
10601 /* Other val must be 8, since we know they are adjacent and neither
10602 is zero. */
25f905c2 10603 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 10604 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10605 {
94dee231 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)
25f905c2 10611 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 10612 else
25f905c2 10613 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 10614 }
cdb1295a 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 }
215b30b3 10626 }
94dee231 10627 else if (val1 != 0)
215b30b3 10628 {
215b30b3 10629 if (val1 < val2)
25f905c2 10630 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10631 else
25f905c2 10632 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10633 }
10634 else
10635 {
215b30b3 10636 if (val1 < val2)
25f905c2 10637 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10638 else
25f905c2 10639 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10640 }
10641 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10642 return \"\";
10643 }"
10644 [(set_attr "length" "12")
10645 (set_attr "predicable" "yes")
a2cd141b 10646 (set_attr "type" "load1")]
215b30b3 10647)
9c08d1fa 10648
9c08d1fa 10649; This pattern is never tried by combine, so do it as a peephole
10650
a0f94409 10651(define_peephole2
372575c7 10652 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10653 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10654 (set (reg:CC CC_REGNUM)
aea4c774 10655 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10656 "TARGET_ARM"
a0f94409 10657 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10658 (set (match_dup 0) (match_dup 1))])]
10659 ""
0d66636f 10660)
9c08d1fa 10661
9c08d1fa 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))
8fa3ba89 10666 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 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" ""))]
cffb2a26 10670 "TARGET_ARM"
9c08d1fa 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)))]
215b30b3 10674 ""
10675)
9c08d1fa 10676
aea4c774 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.
9c08d1fa 10680
aea4c774 10681(define_split
bd5b4116 10682 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10683 (compare:CC_Z
10684 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10685 (const_int 24))
aea4c774 10686 (match_operand 1 "const_int_operand" "")))
10687 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10688 "TARGET_ARM
10689 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10690 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 10691 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10692 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10693 "
9c08d1fa 10694 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10695 "
10696)
25f905c2 10697;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10698
87b22bf7 10699(define_expand "prologue"
10700 [(clobber (const_int 0))]
cffb2a26 10701 "TARGET_EITHER"
25f905c2 10702 "if (TARGET_32BIT)
cffb2a26 10703 arm_expand_prologue ();
10704 else
25f905c2 10705 thumb1_expand_prologue ();
87b22bf7 10706 DONE;
cffb2a26 10707 "
10708)
87b22bf7 10709
56d27660 10710(define_expand "epilogue"
4c44712e 10711 [(clobber (const_int 0))]
cffb2a26 10712 "TARGET_EITHER"
56d27660 10713 "
18d50ae6 10714 if (crtl->calls_eh_return)
4c44712e 10715 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10716 if (TARGET_THUMB1)
10717 thumb1_expand_epilogue ();
cffb2a26 10718 else if (USE_RETURN_INSN (FALSE))
56d27660 10719 {
10720 emit_jump_insn (gen_return ());
10721 DONE;
10722 }
cffb2a26 10723 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
1a860023 10724 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
cffb2a26 10725 DONE;
10726 "
10727)
56d27660 10728
7571d3f7 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
ef5651d0 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.
1c494086 10741(define_insn "sibcall_epilogue"
ef5651d0 10742 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10743 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
25f905c2 10744 "TARGET_32BIT"
1c494086 10745 "*
ffc9d00c 10746 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
5db468b7 10747 return output_return_instruction (const_true_rtx, FALSE, FALSE);
ffc9d00c 10748 return arm_output_epilogue (next_nonnote_insn (insn));
1c494086 10749 "
10750;; Length is absolute worst case
10751 [(set_attr "length" "44")
defc47cf 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")]
1c494086 10757)
10758
cffb2a26 10759(define_insn "*epilogue_insns"
e1159bbe 10760 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 10761 "TARGET_EITHER"
56d27660 10762 "*
25f905c2 10763 if (TARGET_32BIT)
ffc9d00c 10764 return arm_output_epilogue (NULL);
25f905c2 10765 else /* TARGET_THUMB1 */
e7fd8dfa 10766 return thumb1_unexpanded_epilogue ();
cffb2a26 10767 "
215b30b3 10768 ; Length is absolute worst case
cffb2a26 10769 [(set_attr "length" "44")
defc47cf 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")]
cffb2a26 10775)
10776
10777(define_expand "eh_epilogue"
7db9af5d 10778 [(use (match_operand:SI 0 "register_operand" ""))
10779 (use (match_operand:SI 1 "register_operand" ""))
10780 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10781 "TARGET_EITHER"
10782 "
215b30b3 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 }
5cf3595a 10792 /* This is a hack -- we may have crystalized the function type too
10793 early. */
10794 cfun->machine->func_type = 0;
215b30b3 10795 }"
10796)
56d27660 10797
9c08d1fa 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
8a18b90c 10802;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10803;; up again here.
10804
25f905c2 10805;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10806;; conditional execution sufficient?
10807
9c08d1fa 10808(define_split
10809 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 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 "" "")))
bd5b4116 10814 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10815 "TARGET_ARM && reload_completed"
8fa3ba89 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
bd5b4116 10825 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 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)))
bd5b4116 10842 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10843 "TARGET_ARM && reload_completed"
8fa3ba89 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
bd5b4116 10852 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 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"
9c08d1fa 10860 [(match_operand 2 "" "") (match_operand 3 "" "")])
10861 (match_operand 4 "" "")
10862 (match_operand 5 "" "")))
bd5b4116 10863 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10864 "TARGET_ARM && reload_completed"
8fa3ba89 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
bd5b4116 10876 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 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
cffb2a26 10887(define_split
10888 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10889 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 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" ""))))
bd5b4116 10895 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10896 "TARGET_ARM && reload_completed"
cffb2a26 10897 [(set (match_dup 6) (match_dup 7))
f6c53574 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))))]
cffb2a26 10902 "
215b30b3 10903 {
10904 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10905 operands[2], operands[3]);
f6c53574 10906 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10907
bd5b4116 10908 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10909 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 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);
215b30b3 10916 }"
10917)
cffb2a26 10918
10919(define_insn "*cond_move_not"
10920 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10921 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 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"
0d66636f 10930 [(set_attr "conds" "use")
d2a518d1 10931 (set_attr "insn" "mvn")
0d66636f 10932 (set_attr "length" "4,8")]
10933)
cffb2a26 10934
9c08d1fa 10935;; The next two patterns occur when an AND operation is followed by a
10936;; scc insn sequence
10937
f7fbdd4a 10938(define_insn "*sign_extract_onebit"
9c08d1fa 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)
ed750274 10942 (match_operand:SI 2 "const_int_operand" "n")))
10943 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10944 "TARGET_ARM"
9c08d1fa 10945 "*
0d66636f 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)
9c08d1fa 10953
f7fbdd4a 10954(define_insn "*not_signextract_onebit"
9c08d1fa 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)
ed750274 10959 (match_operand:SI 2 "const_int_operand" "n"))))
10960 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10961 "TARGET_ARM"
9c08d1fa 10962 "*
0d66636f 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)
25f905c2 10971;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10972
0d66636f 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.
08508cbf 10976;; To avoid the usage of GNU extension, the length attribute is computed
10977;; in a C function arm_attr_length_push_multi.
f7fbdd4a 10978(define_insn "*push_multi"
87b22bf7 10979 [(match_parallel 2 "multi_register_push"
7571d3f7 10980 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
3cc80a30 10981 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 10982 UNSPEC_PUSH_MULT))])]
7571d3f7 10983 ""
87b22bf7 10984 "*
215b30b3 10985 {
10986 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10987
215b30b3 10988 /* For the StrongARM at least it is faster to
25f905c2 10989 use STR to store only a single register.
542d5028 10990 In Thumb mode always use push, and the assembler will pick
10991 something appropriate. */
25f905c2 10992 if (num_saves == 1 && TARGET_ARM)
61309563 10993 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
215b30b3 10994 else
10995 {
10996 int i;
10997 char pattern[100];
ed593f11 10998
25f905c2 10999 if (TARGET_ARM)
61309563 11000 strcpy (pattern, \"stm%(fd%)\\t%m0!, {%1\");
11001 else if (TARGET_THUMB2)
11002 strcpy (pattern, \"push%?\\t{%1\");
25f905c2 11003 else
11004 strcpy (pattern, \"push\\t{%1\");
215b30b3 11005
6079f055 11006 for (i = 1; i < num_saves; i++)
215b30b3 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 }"
a6864a24 11019 [(set_attr "type" "store4")
11020 (set (attr "length")
08508cbf 11021 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 11022)
f7fbdd4a 11023
4c58c898 11024(define_insn "stack_tie"
11025 [(set (mem:BLK (scratch))
aaa37ad6 11026 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
11027 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 11028 UNSPEC_PRLG_STK))]
11029 ""
11030 ""
11031 [(set_attr "length" "0")]
11032)
11033
3398e91d 11034;; Similarly for the floating point registers
7b1d2fc4 11035(define_insn "*push_fp_multi"
11036 [(match_parallel 2 "multi_register_push"
11037 [(set (match_operand:BLK 0 "memory_operand" "=m")
3cc80a30 11038 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "")]
e1159bbe 11039 UNSPEC_PUSH_MULT))])]
25f905c2 11040 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7b1d2fc4 11041 "*
215b30b3 11042 {
11043 char pattern[100];
7b1d2fc4 11044
877cdec9 11045 sprintf (pattern, \"sfm%%(fd%%)\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
215b30b3 11046 output_asm_insn (pattern, operands);
11047 return \"\";
11048 }"
013b9671 11049 [(set_attr "type" "f_fpa_store")]
215b30b3 11050)
7b1d2fc4 11051
f7fbdd4a 11052;; Special patterns for dealing with the constant pool
11053
cffb2a26 11054(define_insn "align_4"
e1159bbe 11055 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 11056 "TARGET_EITHER"
f7fbdd4a 11057 "*
cffb2a26 11058 assemble_align (32);
f7fbdd4a 11059 return \"\";
cffb2a26 11060 "
11061)
f7fbdd4a 11062
755eb2b4 11063(define_insn "align_8"
11064 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 11065 "TARGET_EITHER"
755eb2b4 11066 "*
11067 assemble_align (64);
11068 return \"\";
11069 "
11070)
11071
cffb2a26 11072(define_insn "consttable_end"
e1159bbe 11073 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 11074 "TARGET_EITHER"
f7fbdd4a 11075 "*
cffb2a26 11076 making_const_table = FALSE;
f7fbdd4a 11077 return \"\";
cffb2a26 11078 "
11079)
f7fbdd4a 11080
cffb2a26 11081(define_insn "consttable_1"
e1159bbe 11082 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
25f905c2 11083 "TARGET_THUMB1"
f7fbdd4a 11084 "*
cffb2a26 11085 making_const_table = TRUE;
09d688ff 11086 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 11087 assemble_zeros (3);
f7fbdd4a 11088 return \"\";
cffb2a26 11089 "
11090 [(set_attr "length" "4")]
11091)
f7fbdd4a 11092
cffb2a26 11093(define_insn "consttable_2"
e1159bbe 11094 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
25f905c2 11095 "TARGET_THUMB1"
f7fbdd4a 11096 "*
cffb2a26 11097 making_const_table = TRUE;
9b8516be 11098 gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
09d688ff 11099 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 11100 assemble_zeros (2);
f7fbdd4a 11101 return \"\";
cffb2a26 11102 "
11103 [(set_attr "length" "4")]
11104)
11105
11106(define_insn "consttable_4"
e1159bbe 11107 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 11108 "TARGET_EITHER"
11109 "*
11110 {
9b8516be 11111 rtx x = operands[0];
cffb2a26 11112 making_const_table = TRUE;
9b8516be 11113 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 11114 {
11115 case MODE_FLOAT:
9b8516be 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;
cffb2a26 11125 default:
7b04c5d5 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);
9b8516be 11133 assemble_integer (x, 4, BITS_PER_WORD, 1);
11134 mark_symbol_refs_as_used (x);
cffb2a26 11135 break;
11136 }
11137 return \"\";
11138 }"
11139 [(set_attr "length" "4")]
11140)
11141
11142(define_insn "consttable_8"
e1159bbe 11143 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 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 {
badfe841 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);
cffb2a26 11155 break;
11156 }
11157 default:
09d688ff 11158 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 11159 break;
11160 }
11161 return \"\";
11162 }"
11163 [(set_attr "length" "8")]
11164)
11165
d98a3884 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
cffb2a26 11190;; Miscellaneous Thumb patterns
11191
fd957ef3 11192(define_expand "tablejump"
7db9af5d 11193 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 11194 (use (label_ref (match_operand 1 "" "")))])]
25f905c2 11195 "TARGET_THUMB1"
fd957ef3 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
f1039640 11209;; NB never uses BX.
25f905c2 11210(define_insn "*thumb1_tablejump"
cffb2a26 11211 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
11212 (use (label_ref (match_operand 1 "" "")))]
25f905c2 11213 "TARGET_THUMB1"
fd957ef3 11214 "mov\\t%|pc, %0"
cffb2a26 11215 [(set_attr "length" "2")]
11216)
0d66636f 11217
331beb1a 11218;; V5 Instructions,
11219
8f4be2be 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")))]
25f905c2 11223 "TARGET_32BIT && arm_arch5"
ee7cbe0e 11224 "clz%?\\t%0, %1"
bcaec148 11225 [(set_attr "predicable" "yes")
11226 (set_attr "insn" "clz")])
331beb1a 11227
099ad98b 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 "
30191172 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 }
099ad98b 11246 DONE;
11247 "
11248)
11249
e1159bbe 11250;; V5E instructions.
331beb1a 11251
11252(define_insn "prefetch"
f4e79814 11253 [(prefetch (match_operand:SI 0 "address_operand" "p")
11254 (match_operand:SI 1 "" "")
11255 (match_operand:SI 2 "" ""))]
25f905c2 11256 "TARGET_32BIT && arm_arch5e"
bcb7a8f6 11257 "pld\\t%a0")
331beb1a 11258
0d66636f 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)])]
25f905c2 11265 "TARGET_32BIT"
0d66636f 11266 ""
11267)
11268
063a05c7 11269(define_insn "prologue_use"
11270 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
11271 ""
11272 "%@ %0 needed for prologue"
02cfc9c9 11273 [(set_attr "length" "0")]
063a05c7 11274)
7db9af5d 11275
4c44712e 11276
11277;; Patterns for exception handling
11278
11279(define_expand "eh_return"
11280 [(use (match_operand 0 "general_operand" ""))]
11281 "TARGET_EITHER"
11282 "
11283 {
25f905c2 11284 if (TARGET_32BIT)
4c44712e 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"))]
25f905c2 11312 "TARGET_THUMB1"
4c44712e 11313 "#"
11314 "&& reload_completed"
11315 [(const_int 0)]
11316 "
11317 {
11318 thumb_set_return_address (operands[0], operands[1]);
11319 DONE;
11320 }"
11321)
11322
f655717d 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
f41e4452 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
aabe09ac 11366;; We only care about the lower 16 bits of the constant
11367;; being inserted into the upper 16 bits of the register.
eca5c984 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" ""))]
181ab277 11373 "arm_arch_thumb2"
aabe09ac 11374 "movt%?\t%0, %L1"
eca5c984 11375 [(set_attr "predicable" "yes")
11376 (set_attr "length" "4")]
11377)
11378
c0fc3696 11379(define_insn "*arm_rev"
ff82f757 11380 [(set (match_operand:SI 0 "s_register_operand" "=r")
11381 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
c0fc3696 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")]
ff82f757 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")))]
8d1af482 11455"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 11456"
8d1af482 11457 if (!arm_arch6)
11458 {
11459 rtx op2 = gen_reg_rtx (SImode);
11460 rtx op3 = gen_reg_rtx (SImode);
ff82f757 11461
8d1af482 11462 if (TARGET_THUMB)
11463 {
11464 rtx op4 = gen_reg_rtx (SImode);
11465 rtx op5 = gen_reg_rtx (SImode);
ff82f757 11466
8d1af482 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 }
ff82f757 11475
8d1af482 11476 DONE;
11477 }
ff82f757 11478 "
11479)
11480
320ea44d 11481;; Load the load/store multiple patterns
11482(include "ldmstm.md")
7db9af5d 11483;; Load the FPA co-processor patterns
11484(include "fpa.md")
11485;; Load the Maverick co-processor patterns
11486(include "cirrus.md")
d98a3884 11487;; Vector bits common to IWMMXT and Neon
11488(include "vec-common.md")
755eb2b4 11489;; Load the Intel Wireless Multimedia Extension patterns
11490(include "iwmmxt.md")
a2cd141b 11491;; Load the VFP co-processor patterns
11492(include "vfp.md")
25f905c2 11493;; Thumb-2 patterns
11494(include "thumb2.md")
d98a3884 11495;; Neon patterns
11496(include "neon.md")
06df6b17 11497;; Synchronization Primitives
11498(include "sync.md")
bbbe4599 11499;; Fixed-point patterns
11500(include "arm-fixed.md")