]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
* dwarf2out.c (comdat_symbol_id): Add const.
[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.
e7d6d136 120])
e1159bbe 121
215b30b3 122;; UNSPEC_VOLATILE Usage:
e1159bbe 123
e7d6d136 124(define_c_enum "unspecv" [
125 VUNSPEC_BLOCKAGE ; `blockage' insn to prevent scheduling across an
126 ; insn in the code.
127 VUNSPEC_EPILOGUE ; `epilogue' insn, used to represent any part of the
128 ; instruction epilogue sequence that isn't expanded
129 ; into normal RTL. Used for both normal and sibcall
130 ; epilogues.
7571d3f7 131 VUNSPEC_THUMB1_INTERWORK ; `prologue_thumb1_interwork' insn, used to swap
132 ; modes from arm to thumb.
e7d6d136 133 VUNSPEC_ALIGN ; `align' insn. Used at the head of a minipool table
134 ; for inlined constants.
135 VUNSPEC_POOL_END ; `end-of-table'. Used to mark the end of a minipool
136 ; table.
137 VUNSPEC_POOL_1 ; `pool-entry(1)'. An entry in the constant pool for
138 ; an 8-bit object.
139 VUNSPEC_POOL_2 ; `pool-entry(2)'. An entry in the constant pool for
140 ; a 16-bit object.
141 VUNSPEC_POOL_4 ; `pool-entry(4)'. An entry in the constant pool for
142 ; a 32-bit object.
143 VUNSPEC_POOL_8 ; `pool-entry(8)'. An entry in the constant pool for
144 ; a 64-bit object.
145 VUNSPEC_POOL_16 ; `pool-entry(16)'. An entry in the constant pool for
146 ; a 128-bit object.
147 VUNSPEC_TMRC ; Used by the iWMMXt TMRC instruction.
148 VUNSPEC_TMCR ; Used by the iWMMXt TMCR instruction.
149 VUNSPEC_ALIGN8 ; 8-byte alignment version of VUNSPEC_ALIGN
150 VUNSPEC_WCMP_EQ ; Used by the iWMMXt WCMPEQ instructions
151 VUNSPEC_WCMP_GTU ; Used by the iWMMXt WCMPGTU instructions
152 VUNSPEC_WCMP_GT ; Used by the iwMMXT WCMPGT instructions
153 VUNSPEC_EH_RETURN ; Use to override the return address for exception
154 ; handling.
e1b93706 155 VUNSPEC_ATOMIC_CAS ; Represent an atomic compare swap.
156 VUNSPEC_ATOMIC_XCHG ; Represent an atomic exchange.
157 VUNSPEC_ATOMIC_OP ; Represent an atomic operation.
158 VUNSPEC_LL ; Represent a load-register-exclusive.
159 VUNSPEC_SC ; Represent a store-register-exclusive.
e7d6d136 160])
b11cae9e 161\f
e1159bbe 162;;---------------------------------------------------------------------------
9c08d1fa 163;; Attributes
164
a651f34d 165;; Processor type. This is created automatically from arm-cores.def.
166(include "arm-tune.md")
167
215b30b3 168; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
169; generating ARM code. This is used to control the length of some insn
170; patterns that share the same RTL in both ARM and Thumb code.
1c494086 171(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
cffb2a26 172
ef51b8e1 173; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
174(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
175
747b7458 176; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
177(define_attr "is_thumb1" "no,yes" (const (symbol_ref "thumb1_code")))
178
331beb1a 179;; Operand number of an input operand that is shifted. Zero if the
180;; given instruction does not shift one of its input operands.
331beb1a 181(define_attr "shift" "" (const_int 0))
182
3d91c5d6 183; Floating Point Unit. If we only have floating point emulation, then there
184; is no point in scheduling the floating point insns. (Well, for best
185; performance we should try and group them together).
4fea7d65 186(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
c7f506fd 187 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 188
094e994f 189; LENGTH of an instruction (in bytes)
06df6b17 190(define_attr "length" ""
e1b93706 191 (const_int 4))
9c08d1fa 192
d5d4dc8d 193; The architecture which supports the instruction (or alternative).
194; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
195; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
196; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
197; arm_arch6. This attribute is used to compute attribute "enabled",
198; use type "any" to enable an alternative in all cases.
10efb95f 199(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,onlya8,neon_onlya8,nota8,neon_nota8"
d5d4dc8d 200 (const_string "any"))
201
202(define_attr "arch_enabled" "no,yes"
203 (cond [(eq_attr "arch" "any")
204 (const_string "yes")
205
206 (and (eq_attr "arch" "a")
0bf497f5 207 (match_test "TARGET_ARM"))
d5d4dc8d 208 (const_string "yes")
209
210 (and (eq_attr "arch" "t")
0bf497f5 211 (match_test "TARGET_THUMB"))
d5d4dc8d 212 (const_string "yes")
213
214 (and (eq_attr "arch" "t1")
0bf497f5 215 (match_test "TARGET_THUMB1"))
d5d4dc8d 216 (const_string "yes")
217
218 (and (eq_attr "arch" "t2")
0bf497f5 219 (match_test "TARGET_THUMB2"))
d5d4dc8d 220 (const_string "yes")
221
222 (and (eq_attr "arch" "32")
0bf497f5 223 (match_test "TARGET_32BIT"))
d5d4dc8d 224 (const_string "yes")
225
226 (and (eq_attr "arch" "v6")
0bf497f5 227 (match_test "TARGET_32BIT && arm_arch6"))
d5d4dc8d 228 (const_string "yes")
229
230 (and (eq_attr "arch" "nov6")
0bf497f5 231 (match_test "TARGET_32BIT && !arm_arch6"))
a651f34d 232 (const_string "yes")
233
234 (and (eq_attr "arch" "onlya8")
235 (eq_attr "tune" "cortexa8"))
236 (const_string "yes")
237
10efb95f 238 (and (eq_attr "arch" "neon_onlya8")
239 (eq_attr "tune" "cortexa8")
240 (match_test "TARGET_NEON"))
241 (const_string "yes")
242
a651f34d 243 (and (eq_attr "arch" "nota8")
244 (not (eq_attr "tune" "cortexa8")))
10efb95f 245 (const_string "yes")
246
247 (and (eq_attr "arch" "neon_nota8")
248 (not (eq_attr "tune" "cortexa8"))
249 (match_test "TARGET_NEON"))
d5d4dc8d 250 (const_string "yes")]
251 (const_string "no")))
252
253; Allows an insn to disable certain alternatives for reasons other than
254; arch support.
255(define_attr "insn_enabled" "no,yes"
256 (const_string "yes"))
257
258; Enable all alternatives that are both arch_enabled and insn_enabled.
93b431d9 259 (define_attr "enabled" "no,yes"
260 (if_then_else (eq_attr "insn_enabled" "yes")
261 (if_then_else (eq_attr "arch_enabled" "yes")
262 (const_string "yes")
263 (const_string "no"))
264 (const_string "no")))
d5d4dc8d 265
56d27660 266; POOL_RANGE is how far away from a constant pool entry that this insn
267; can be placed. If the distance is zero, then this insn will never
268; reference the pool.
cffb2a26 269; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
8848d797 270; before its address. It is set to <max_range> - (8 + <data_size>).
cde1623a 271(define_attr "arm_pool_range" "" (const_int 0))
272(define_attr "thumb2_pool_range" "" (const_int 0))
273(define_attr "arm_neg_pool_range" "" (const_int 0))
274(define_attr "thumb2_neg_pool_range" "" (const_int 0))
275
276(define_attr "pool_range" ""
277 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
278 (attr "arm_pool_range")))
279(define_attr "neg_pool_range" ""
280 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
281 (attr "arm_neg_pool_range")))
56d27660 282
215b30b3 283; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 284; If such an insn references the pool, then we have no way of knowing how,
285; so use the most conservative value for pool_range.
9c08d1fa 286(define_asm_attributes
4d7a8451 287 [(set_attr "conds" "clob")
288 (set_attr "length" "4")
289 (set_attr "pool_range" "250")])
9c08d1fa 290
a2cd141b 291;; The instruction used to implement a particular pattern. This
292;; information is used by pipeline descriptions to provide accurate
293;; scheduling information.
294
295(define_attr "insn"
b49e3742 296 "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 297 (const_string "other"))
298
9c08d1fa 299; TYPE attribute is used to detect floating point instructions which, if
300; running on a co-processor can run in parallel with other, basic instructions
301; If write-buffer scheduling is enabled then it can also be used in the
302; scheduling of writes.
303
304; Classification of each insn
607978a1 305; Note: vfp.md has different meanings for some of these, and some further
306; types as well. See that file for details.
a2cd141b 307; alu any alu instruction that doesn't hit memory or fp
308; regs or have a shifted source operand
309; alu_shift any data instruction that doesn't hit memory or fp
310; regs, but has a source operand shifted by a constant
311; alu_shift_reg any data instruction that doesn't hit memory or fp
312; regs, but has a source operand shifted by a register value
f7fbdd4a 313; mult a multiply instruction
9c08d1fa 314; block blockage insn, this blocks all functional units
315; float a floating point arithmetic operation (subject to expansion)
3d91c5d6 316; fdivd DFmode floating point division
317; fdivs SFmode floating point division
318; fmul Floating point multiply
319; ffmul Fast floating point multiply
320; farith Floating point arithmetic (4 cycle)
321; ffarith Fast floating point arithmetic (2 cycle)
9c08d1fa 322; float_em a floating point arithmetic operation that is normally emulated
3d91c5d6 323; even on a machine with an fpa.
013b9671 324; f_fpa_load a floating point load from memory. Only for the FPA.
325; f_fpa_store a floating point store to memory. Only for the FPA.
326; f_load[sd] A single/double load from memory. Used for VFP unit.
327; f_store[sd] A single/double store to memory. Used for VFP unit.
c0e1af52 328; f_flag a transfer of co-processor flags to the CPSR
9c08d1fa 329; f_mem_r a transfer of a floating point register to a real reg via mem
330; r_mem_f the reverse of f_mem_r
331; f_2_r fast transfer float to arm (no memory needed)
332; r_2_f fast transfer arm to float
c0e1af52 333; f_cvt convert floating<->integral
a2cd141b 334; branch a branch
9c08d1fa 335; call a subroutine call
a2cd141b 336; load_byte load byte(s) from memory to arm registers
337; load1 load 1 word from memory to arm registers
338; load2 load 2 words from memory to arm registers
339; load3 load 3 words from memory to arm registers
340; load4 load 4 words from memory to arm registers
341; store store 1 word to memory from arm registers
9c08d1fa 342; store2 store 2 words
343; store3 store 3 words
a2cd141b 344; store4 store 4 (or more) words
2c6c7d8b 345; Additions for Cirrus Maverick co-processor:
346; mav_farith Floating point arithmetic (4 cycle)
347; mav_dmult Double multiplies (7 cycle)
9c08d1fa 348;
bcaec148 349
9c08d1fa 350(define_attr "type"
013b9671 351 "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 352 (if_then_else
353 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
354 (const_string "mult")
355 (const_string "alu")))
9c08d1fa 356
65f2f758 357; Is this an (integer side) multiply with a 64-bit result?
358(define_attr "mul64" "no,yes"
359 (if_then_else
360 (eq_attr "insn" "smlalxy,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
361 (const_string "yes")
362 (const_string "no")))
363
9888ad6d 364; Load scheduling, set from the arm_ld_sched variable
4c834714 365; initialized by arm_option_override()
9888ad6d 366(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 367
c52acdd2 368;; Classification of NEON instructions for scheduling purposes.
369;; Do not set this attribute and the "type" attribute together in
370;; any one instruction pattern.
371(define_attr "neon_type"
372 "neon_int_1,\
373 neon_int_2,\
374 neon_int_3,\
375 neon_int_4,\
376 neon_int_5,\
377 neon_vqneg_vqabs,\
378 neon_vmov,\
379 neon_vaba,\
380 neon_vsma,\
381 neon_vaba_qqq,\
382 neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
383 neon_mul_qqq_8_16_32_ddd_32,\
384 neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
385 neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
386 neon_mla_qqq_8_16,\
387 neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
388 neon_mla_qqq_32_qqd_32_scalar,\
389 neon_mul_ddd_16_scalar_32_16_long_scalar,\
390 neon_mul_qqd_32_scalar,\
391 neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
392 neon_shift_1,\
393 neon_shift_2,\
394 neon_shift_3,\
395 neon_vshl_ddd,\
396 neon_vqshl_vrshl_vqrshl_qqq,\
397 neon_vsra_vrsra,\
398 neon_fp_vadd_ddd_vabs_dd,\
399 neon_fp_vadd_qqq_vabs_qq,\
400 neon_fp_vsum,\
401 neon_fp_vmul_ddd,\
402 neon_fp_vmul_qqd,\
403 neon_fp_vmla_ddd,\
404 neon_fp_vmla_qqq,\
405 neon_fp_vmla_ddd_scalar,\
406 neon_fp_vmla_qqq_scalar,\
407 neon_fp_vrecps_vrsqrts_ddd,\
408 neon_fp_vrecps_vrsqrts_qqq,\
409 neon_bp_simple,\
410 neon_bp_2cycle,\
411 neon_bp_3cycle,\
412 neon_ldr,\
413 neon_str,\
414 neon_vld1_1_2_regs,\
415 neon_vld1_3_4_regs,\
416 neon_vld2_2_regs_vld1_vld2_all_lanes,\
417 neon_vld2_4_regs,\
418 neon_vld3_vld4,\
419 neon_vst1_1_2_regs_vst2_2_regs,\
420 neon_vst1_3_4_regs,\
421 neon_vst2_4_regs_vst3_vst4,\
422 neon_vst3_vst4,\
423 neon_vld1_vld2_lane,\
424 neon_vld3_vld4_lane,\
425 neon_vst1_vst2_lane,\
426 neon_vst3_vst4_lane,\
427 neon_vld3_vld4_all_lanes,\
428 neon_mcr,\
429 neon_mcr_2_mcrr,\
430 neon_mrc,\
431 neon_mrrc,\
432 neon_ldm_2,\
433 neon_stm_2,\
434 none"
435 (const_string "none"))
436
f7fbdd4a 437; condition codes: this one is used by final_prescan_insn to speed up
438; conditionalizing instructions. It saves having to scan the rtl to see if
439; it uses or alters the condition codes.
215b30b3 440;
f7fbdd4a 441; USE means that the condition codes are used by the insn in the process of
215b30b3 442; outputting code, this means (at present) that we can't use the insn in
443; inlined branches
444;
f7fbdd4a 445; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 446; well defined manner.
447;
f7fbdd4a 448; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 449; they are altered at all
450;
ad6d3e2a 451; UNCONDITIONAL means the instruction can not be conditionally executed and
452; that the instruction does not use or alter the condition codes.
c52acdd2 453;
ad6d3e2a 454; NOCOND means that the instruction does not use or alter the condition
455; codes but can be converted into a conditionally exectuted instruction.
f7fbdd4a 456
b0694be0 457(define_attr "conds" "use,set,clob,unconditional,nocond"
747b7458 458 (if_then_else
459 (ior (eq_attr "is_thumb1" "yes")
460 (eq_attr "type" "call"))
c1a66faf 461 (const_string "clob")
c52acdd2 462 (if_then_else (eq_attr "neon_type" "none")
463 (const_string "nocond")
464 (const_string "unconditional"))))
f7fbdd4a 465
215b30b3 466; Predicable means that the insn can be conditionally executed based on
467; an automatically added predicate (additional patterns are generated by
468; gen...). We default to 'no' because no Thumb patterns match this rule
469; and not all ARM patterns do.
0d66636f 470(define_attr "predicable" "no,yes" (const_string "no"))
471
129a2fe4 472; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
473; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 474; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 475; affect the schedule).
74a71f7d 476(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 477
215b30b3 478; WRITE_CONFLICT implies that a read following an unrelated write is likely
479; to stall the processor. Used with model_wbuf above.
9c08d1fa 480(define_attr "write_conflict" "no,yes"
481 (if_then_else (eq_attr "type"
013b9671 482 "block,float_em,f_fpa_load,f_fpa_store,f_mem_r,r_mem_f,call,load1")
9c08d1fa 483 (const_string "yes")
484 (const_string "no")))
485
215b30b3 486; Classify the insns into those that take one cycle and those that take more
487; than one on the main cpu execution unit.
f7fbdd4a 488(define_attr "core_cycles" "single,multi"
489 (if_then_else (eq_attr "type"
a2cd141b 490 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
f7fbdd4a 491 (const_string "single")
492 (const_string "multi")))
493
cffb2a26 494;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 495;; distant label. Only applicable to Thumb code.
cffb2a26 496(define_attr "far_jump" "yes,no" (const_string "no"))
497
d51f92df 498
25f905c2 499;; The number of machine instructions this pattern expands to.
500;; Used for Thumb-2 conditional execution.
501(define_attr "ce_count" "" (const_int 1))
502
d51f92df 503;;---------------------------------------------------------------------------
fd781bb2 504;; Mode iterators
d51f92df 505
3de0dec6 506(include "iterators.md")
03770691 507
d51f92df 508;;---------------------------------------------------------------------------
509;; Predicates
510
9c9db025 511(include "predicates.md")
234f6557 512(include "constraints.md")
9c9db025 513
a2cd141b 514;;---------------------------------------------------------------------------
515;; Pipeline descriptions
215b30b3 516
e3879fd0 517(define_attr "tune_cortexr4" "yes,no"
518 (const (if_then_else
7d3cda8c 519 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
e3879fd0 520 (const_string "yes")
521 (const_string "no"))))
522
a2cd141b 523;; True if the generic scheduling description should be used.
524
525(define_attr "generic_sched" "yes,no"
2546d93a 526 (const (if_then_else
65f2f758 527 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa5,cortexa8,cortexa9,cortexa15,cortexm4")
2546d93a 528 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 529 (const_string "no")
530 (const_string "yes"))))
531
c0e1af52 532(define_attr "generic_vfp" "yes,no"
533 (const (if_then_else
534 (and (eq_attr "fpu" "vfp")
2546d93a 535 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa8,cortexa9,cortexm4")
e3879fd0 536 (eq_attr "tune_cortexr4" "no"))
c0e1af52 537 (const_string "yes")
538 (const_string "no"))))
539
a2cd141b 540(include "arm-generic.md")
541(include "arm926ejs.md")
c0e1af52 542(include "arm1020e.md")
a2cd141b 543(include "arm1026ejs.md")
544(include "arm1136jfs.md")
0e266d06 545(include "fa526.md")
546(include "fa606te.md")
547(include "fa626te.md")
548(include "fmp626.md")
549(include "fa726te.md")
3f1e069f 550(include "cortex-a5.md")
bcaec148 551(include "cortex-a8.md")
036068af 552(include "cortex-a9.md")
65f2f758 553(include "cortex-a15.md")
934a1e72 554(include "cortex-r4.md")
e3879fd0 555(include "cortex-r4f.md")
2546d93a 556(include "cortex-m4.md")
557(include "cortex-m4-fpu.md")
55e3ada8 558(include "vfp11.md")
3586df96 559
9c08d1fa 560\f
215b30b3 561;;---------------------------------------------------------------------------
e1159bbe 562;; Insn patterns
563;;
a0f94409 564;; Addition insns.
215b30b3 565
9c08d1fa 566;; Note: For DImode insns, there is normally no reason why operands should
567;; not be in the same register, what we don't want is for something being
568;; written to partially overlap something that is an input.
7d57ec45 569;; Cirrus 64bit additions should not be split because we have a native
570;; 64bit addition instructions.
9c08d1fa 571
cffb2a26 572(define_expand "adddi3"
573 [(parallel
215b30b3 574 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 575 (plus:DI (match_operand:DI 1 "s_register_operand" "")
576 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 577 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 578 "TARGET_EITHER"
579 "
a2cd141b 580 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
7d57ec45 581 {
582 if (!cirrus_fp_register (operands[0], DImode))
583 operands[0] = force_reg (DImode, operands[0]);
584 if (!cirrus_fp_register (operands[1], DImode))
585 operands[1] = force_reg (DImode, operands[1]);
586 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
587 DONE;
588 }
589
25f905c2 590 if (TARGET_THUMB1)
cffb2a26 591 {
592 if (GET_CODE (operands[1]) != REG)
bc5a93af 593 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 594 if (GET_CODE (operands[2]) != REG)
bc5a93af 595 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 596 }
597 "
598)
599
25f905c2 600(define_insn "*thumb1_adddi3"
cffb2a26 601 [(set (match_operand:DI 0 "register_operand" "=l")
602 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 603 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 604 (clobber (reg:CC CC_REGNUM))
cffb2a26 605 ]
25f905c2 606 "TARGET_THUMB1"
cffb2a26 607 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
608 [(set_attr "length" "4")]
609)
610
a0f94409 611(define_insn_and_split "*arm_adddi3"
cffb2a26 612 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
215b30b3 613 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
614 (match_operand:DI 2 "s_register_operand" "r, 0")))
bd5b4116 615 (clobber (reg:CC CC_REGNUM))]
94829feb 616 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK) && !TARGET_NEON"
33782ec7 617 "#"
94829feb 618 "TARGET_32BIT && reload_completed
619 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
a0f94409 620 [(parallel [(set (reg:CC_C CC_REGNUM)
621 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
622 (match_dup 1)))
623 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 624 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
625 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 626 "
627 {
628 operands[3] = gen_highpart (SImode, operands[0]);
629 operands[0] = gen_lowpart (SImode, operands[0]);
630 operands[4] = gen_highpart (SImode, operands[1]);
631 operands[1] = gen_lowpart (SImode, operands[1]);
632 operands[5] = gen_highpart (SImode, operands[2]);
633 operands[2] = gen_lowpart (SImode, operands[2]);
634 }"
cffb2a26 635 [(set_attr "conds" "clob")
636 (set_attr "length" "8")]
637)
9c08d1fa 638
a0f94409 639(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 640 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
641 (plus:DI (sign_extend:DI
97499065 642 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 643 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 644 (clobber (reg:CC CC_REGNUM))]
25f905c2 645 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 646 "#"
25f905c2 647 "TARGET_32BIT && reload_completed"
a0f94409 648 [(parallel [(set (reg:CC_C CC_REGNUM)
649 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
650 (match_dup 1)))
651 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 652 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 653 (const_int 31))
080c0b9a 654 (match_dup 4))
655 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 656 "
657 {
658 operands[3] = gen_highpart (SImode, operands[0]);
659 operands[0] = gen_lowpart (SImode, operands[0]);
660 operands[4] = gen_highpart (SImode, operands[1]);
661 operands[1] = gen_lowpart (SImode, operands[1]);
662 operands[2] = gen_lowpart (SImode, operands[2]);
663 }"
215b30b3 664 [(set_attr "conds" "clob")
665 (set_attr "length" "8")]
666)
9c08d1fa 667
a0f94409 668(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 669 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
670 (plus:DI (zero_extend:DI
97499065 671 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 672 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 673 (clobber (reg:CC CC_REGNUM))]
25f905c2 674 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 675 "#"
25f905c2 676 "TARGET_32BIT && reload_completed"
a0f94409 677 [(parallel [(set (reg:CC_C CC_REGNUM)
678 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
679 (match_dup 1)))
680 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 681 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
682 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 683 "
684 {
685 operands[3] = gen_highpart (SImode, operands[0]);
686 operands[0] = gen_lowpart (SImode, operands[0]);
687 operands[4] = gen_highpart (SImode, operands[1]);
688 operands[1] = gen_lowpart (SImode, operands[1]);
689 operands[2] = gen_lowpart (SImode, operands[2]);
690 }"
cffb2a26 691 [(set_attr "conds" "clob")
692 (set_attr "length" "8")]
693)
b11cae9e 694
87b22bf7 695(define_expand "addsi3"
cffb2a26 696 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 697 (plus:SI (match_operand:SI 1 "s_register_operand" "")
698 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 699 "TARGET_EITHER"
87b22bf7 700 "
25f905c2 701 if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
87b22bf7 702 {
96f57e36 703 arm_split_constant (PLUS, SImode, NULL_RTX,
704 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 705 optimize && can_create_pseudo_p ());
87b22bf7 706 DONE;
707 }
cffb2a26 708 "
709)
87b22bf7 710
5bd751ff 711; If there is a scratch available, this will be faster than synthesizing the
a0f94409 712; addition.
713(define_peephole2
714 [(match_scratch:SI 3 "r")
372575c7 715 (set (match_operand:SI 0 "arm_general_register_operand" "")
716 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 717 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 718 "TARGET_32BIT &&
a0f94409 719 !(const_ok_for_arm (INTVAL (operands[2]))
720 || const_ok_for_arm (-INTVAL (operands[2])))
721 && const_ok_for_arm (~INTVAL (operands[2]))"
722 [(set (match_dup 3) (match_dup 2))
723 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
724 ""
725)
87b22bf7 726
2f02c19f 727;; The r/r/k alternative is required when reloading the address
728;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
729;; put the duplicated register first, and not try the commutative version.
a0f94409 730(define_insn_and_split "*arm_addsi3"
d5cbae34 731 [(set (match_operand:SI 0 "s_register_operand" "=r, k,r,r, k, r, k,r, k, r")
732 (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,k,r,rk,k, rk,k,rk,k, rk")
733 (match_operand:SI 2 "reg_or_int_operand" "rI,rI,k,Pj,Pj,L, L,PJ,PJ,?n")))]
25f905c2 734 "TARGET_32BIT"
5565501b 735 "@
736 add%?\\t%0, %1, %2
aaa37ad6 737 add%?\\t%0, %1, %2
2f02c19f 738 add%?\\t%0, %2, %1
d5cbae34 739 addw%?\\t%0, %1, %2
740 addw%?\\t%0, %1, %2
aaa37ad6 741 sub%?\\t%0, %1, #%n2
87b22bf7 742 sub%?\\t%0, %1, #%n2
d5cbae34 743 subw%?\\t%0, %1, #%n2
744 subw%?\\t%0, %1, #%n2
87b22bf7 745 #"
a3ffc315 746 "TARGET_32BIT
747 && GET_CODE (operands[2]) == CONST_INT
d5cbae34 748 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
a3ffc315 749 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 750 [(clobber (const_int 0))]
751 "
96f57e36 752 arm_split_constant (PLUS, SImode, curr_insn,
753 INTVAL (operands[2]), operands[0],
a0f94409 754 operands[1], 0);
755 DONE;
756 "
d5cbae34 757 [(set_attr "length" "4,4,4,4,4,4,4,4,4,16")
758 (set_attr "predicable" "yes")
759 (set_attr "arch" "*,*,*,t2,t2,*,*,t2,t2,*")]
cffb2a26 760)
761
0bdb6455 762(define_insn_and_split "*thumb1_addsi3"
bf7bc2f6 763 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,k,l,l,l")
764 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,k,k,0,l,k")
765 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,M,O,Pa,Pb,Pc")))]
25f905c2 766 "TARGET_THUMB1"
cffb2a26 767 "*
0d66636f 768 static const char * const asms[] =
cffb2a26 769 {
770 \"add\\t%0, %0, %2\",
771 \"sub\\t%0, %0, #%n2\",
772 \"add\\t%0, %1, %2\",
773 \"add\\t%0, %0, %2\",
774 \"add\\t%0, %0, %2\",
775 \"add\\t%0, %1, %2\",
0bdb6455 776 \"add\\t%0, %1, %2\",
777 \"#\",
bf7bc2f6 778 \"#\",
0bdb6455 779 \"#\"
cffb2a26 780 };
781 if ((which_alternative == 2 || which_alternative == 6)
782 && GET_CODE (operands[2]) == CONST_INT
783 && INTVAL (operands[2]) < 0)
784 return \"sub\\t%0, %1, #%n2\";
785 return asms[which_alternative];
786 "
0bdb6455 787 "&& reload_completed && CONST_INT_P (operands[2])
bf7bc2f6 788 && ((operands[1] != stack_pointer_rtx
789 && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255))
790 || (operands[1] == stack_pointer_rtx
791 && INTVAL (operands[2]) > 1020))"
0bdb6455 792 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
793 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
794 {
795 HOST_WIDE_INT offset = INTVAL (operands[2]);
bf7bc2f6 796 if (operands[1] == stack_pointer_rtx)
797 offset -= 1020;
798 else
799 {
800 if (offset > 255)
801 offset = 255;
802 else if (offset < -255)
803 offset = -255;
804 }
0bdb6455 805 operands[3] = GEN_INT (offset);
806 operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
807 }
bf7bc2f6 808 [(set_attr "length" "2,2,2,2,2,2,2,4,4,4")]
cffb2a26 809)
810
811;; Reloading and elimination of the frame pointer can
812;; sometimes cause this optimization to be missed.
a0f94409 813(define_peephole2
372575c7 814 [(set (match_operand:SI 0 "arm_general_register_operand" "")
a058e94a 815 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 816 (set (match_dup 0)
372575c7 817 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
25f905c2 818 "TARGET_THUMB1
cffb2a26 819 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
820 && (INTVAL (operands[1]) & 3) == 0"
372575c7 821 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
a0f94409 822 ""
cffb2a26 823)
b11cae9e 824
90c2bcf0 825(define_insn "addsi3_compare0"
bd5b4116 826 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 827 (compare:CC_NOOV
215b30b3 828 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
829 (match_operand:SI 2 "arm_add_operand" "rI,L"))
5565501b 830 (const_int 0)))
831 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 832 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 833 "TARGET_ARM"
5565501b 834 "@
25f905c2 835 add%.\\t%0, %1, %2
836 sub%.\\t%0, %1, #%n2"
cffb2a26 837 [(set_attr "conds" "set")]
838)
9c08d1fa 839
aea4c774 840(define_insn "*addsi3_compare0_scratch"
bd5b4116 841 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 842 (compare:CC_NOOV
215b30b3 843 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
844 (match_operand:SI 1 "arm_add_operand" "rI,L"))
aea4c774 845 (const_int 0)))]
ec792a7b 846 "TARGET_ARM"
cffb2a26 847 "@
848 cmn%?\\t%0, %1
849 cmp%?\\t%0, #%n1"
596e5e8f 850 [(set_attr "conds" "set")
851 (set_attr "predicable" "yes")]
0d66636f 852)
cffb2a26 853
aed179ae 854(define_insn "*compare_negsi_si"
855 [(set (reg:CC_Z CC_REGNUM)
856 (compare:CC_Z
857 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
858 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 859 "TARGET_32BIT"
aed179ae 860 "cmn%?\\t%1, %0"
596e5e8f 861 [(set_attr "conds" "set")
862 (set_attr "predicable" "yes")]
0d66636f 863)
aea4c774 864
203c488f 865;; This is the canonicalization of addsi3_compare0_for_combiner when the
866;; addend is a constant.
867(define_insn "*cmpsi2_addneg"
868 [(set (reg:CC CC_REGNUM)
869 (compare:CC
870 (match_operand:SI 1 "s_register_operand" "r,r")
2a977b78 871 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 872 (set (match_operand:SI 0 "s_register_operand" "=r,r")
873 (plus:SI (match_dup 1)
2a977b78 874 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 875 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 876 "@
2a977b78 877 add%.\\t%0, %1, %3
878 sub%.\\t%0, %1, #%n3"
203c488f 879 [(set_attr "conds" "set")]
880)
881
882;; Convert the sequence
883;; sub rd, rn, #1
884;; cmn rd, #1 (equivalent to cmp rd, #-1)
885;; bne dest
886;; into
887;; subs rd, rn, #1
888;; bcs dest ((unsigned)rn >= 1)
889;; similarly for the beq variant using bcc.
890;; This is a common looping idiom (while (n--))
891(define_peephole2
372575c7 892 [(set (match_operand:SI 0 "arm_general_register_operand" "")
893 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 894 (const_int -1)))
895 (set (match_operand 2 "cc_register" "")
896 (compare (match_dup 0) (const_int -1)))
897 (set (pc)
898 (if_then_else (match_operator 3 "equality_operator"
899 [(match_dup 2) (const_int 0)])
900 (match_operand 4 "" "")
901 (match_operand 5 "" "")))]
25f905c2 902 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 903 [(parallel[
904 (set (match_dup 2)
905 (compare:CC
906 (match_dup 1) (const_int 1)))
907 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
908 (set (pc)
909 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
910 (match_dup 4)
911 (match_dup 5)))]
912 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
913 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
914 ? GEU : LTU),
915 VOIDmode,
916 operands[2], const0_rtx);"
917)
918
ebcc79bc 919;; The next four insns work because they compare the result with one of
920;; the operands, and we know that the use of the condition code is
921;; either GEU or LTU, so we can use the carry flag from the addition
922;; instead of doing the compare a second time.
923(define_insn "*addsi3_compare_op1"
bd5b4116 924 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 925 (compare:CC_C
926 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
927 (match_operand:SI 2 "arm_add_operand" "rI,L"))
928 (match_dup 1)))
929 (set (match_operand:SI 0 "s_register_operand" "=r,r")
930 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 931 "TARGET_32BIT"
ebcc79bc 932 "@
25f905c2 933 add%.\\t%0, %1, %2
934 sub%.\\t%0, %1, #%n2"
0d66636f 935 [(set_attr "conds" "set")]
936)
ebcc79bc 937
938(define_insn "*addsi3_compare_op2"
bd5b4116 939 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 940 (compare:CC_C
941 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
942 (match_operand:SI 2 "arm_add_operand" "rI,L"))
943 (match_dup 2)))
5565501b 944 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 945 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 946 "TARGET_32BIT"
5565501b 947 "@
25f905c2 948 add%.\\t%0, %1, %2
949 sub%.\\t%0, %1, #%n2"
0d66636f 950 [(set_attr "conds" "set")]
951)
9c08d1fa 952
ebcc79bc 953(define_insn "*compare_addsi2_op0"
bd5b4116 954 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 955 (compare:CC_C
956 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
957 (match_operand:SI 1 "arm_add_operand" "rI,L"))
958 (match_dup 0)))]
25f905c2 959 "TARGET_32BIT"
ebcc79bc 960 "@
961 cmn%?\\t%0, %1
962 cmp%?\\t%0, #%n1"
596e5e8f 963 [(set_attr "conds" "set")
964 (set_attr "predicable" "yes")]
0d66636f 965)
ebcc79bc 966
967(define_insn "*compare_addsi2_op1"
bd5b4116 968 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 969 (compare:CC_C
970 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
971 (match_operand:SI 1 "arm_add_operand" "rI,L"))
972 (match_dup 1)))]
25f905c2 973 "TARGET_32BIT"
ebcc79bc 974 "@
975 cmn%?\\t%0, %1
976 cmp%?\\t%0, #%n1"
596e5e8f 977 [(set_attr "conds" "set")
978 (set_attr "predicable" "yes")]
0d66636f 979)
ebcc79bc 980
080c0b9a 981(define_insn "*addsi3_carryin_<optab>"
ebcc79bc 982 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 983 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
ebcc79bc 984 (match_operand:SI 2 "arm_rhs_operand" "rI"))
080c0b9a 985 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 986 "TARGET_32BIT"
ebcc79bc 987 "adc%?\\t%0, %1, %2"
cffb2a26 988 [(set_attr "conds" "use")]
989)
ebcc79bc 990
080c0b9a 991(define_insn "*addsi3_carryin_alt2_<optab>"
ebcc79bc 992 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 993 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
994 (match_operand:SI 1 "s_register_operand" "%r"))
ebcc79bc 995 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 996 "TARGET_32BIT"
ebcc79bc 997 "adc%?\\t%0, %1, %2"
0d66636f 998 [(set_attr "conds" "use")]
999)
ebcc79bc 1000
080c0b9a 1001(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 1002 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 1003 (plus:SI (plus:SI
1004 (match_operator:SI 2 "shift_operator"
1005 [(match_operand:SI 3 "s_register_operand" "r")
1006 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1007 (match_operand:SI 1 "s_register_operand" "r"))
1008 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 1009 "TARGET_32BIT"
080c0b9a 1010 "adc%?\\t%0, %1, %3%S2"
1011 [(set_attr "conds" "use")
1012 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
1013 (const_string "alu_shift")
1014 (const_string "alu_shift_reg")))]
cffb2a26 1015)
ebcc79bc 1016
922b6913 1017(define_insn "*addsi3_carryin_clobercc_<optab>"
1018 [(set (match_operand:SI 0 "s_register_operand" "=r")
1019 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
1020 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1021 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
1022 (clobber (reg:CC CC_REGNUM))]
1023 "TARGET_32BIT"
1024 "adc%.\\t%0, %1, %2"
1025 [(set_attr "conds" "set")]
1026)
1027
25f905c2 1028(define_expand "incscc"
1029 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1030 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
1031 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
1032 (match_operand:SI 1 "s_register_operand" "0,?r")))]
1033 "TARGET_32BIT"
1034 ""
1035)
1036
1037(define_insn "*arm_incscc"
9c08d1fa 1038 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 1039 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1040 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
9c08d1fa 1041 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 1042 "TARGET_ARM"
5565501b 1043 "@
1044 add%d2\\t%0, %1, #1
1045 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
8fa3ba89 1046 [(set_attr "conds" "use")
215b30b3 1047 (set_attr "length" "4,8")]
1048)
9c08d1fa 1049
d795fb69 1050; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
1051(define_split
1052 [(set (match_operand:SI 0 "s_register_operand" "")
1053 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1054 (match_operand:SI 2 "s_register_operand" ""))
1055 (const_int -1)))
1056 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 1057 "TARGET_32BIT"
d795fb69 1058 [(set (match_dup 3) (match_dup 1))
1059 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1060 "
1061 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1062")
1063
604f3a0a 1064(define_expand "addsf3"
1065 [(set (match_operand:SF 0 "s_register_operand" "")
1066 (plus:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1067 (match_operand:SF 2 "arm_float_add_operand" "")))]
25f905c2 1068 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1069 "
a2cd141b 1070 if (TARGET_MAVERICK
604f3a0a 1071 && !cirrus_fp_register (operands[2], SFmode))
1072 operands[2] = force_reg (SFmode, operands[2]);
1073")
1074
604f3a0a 1075(define_expand "adddf3"
1076 [(set (match_operand:DF 0 "s_register_operand" "")
1077 (plus:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1078 (match_operand:DF 2 "arm_float_add_operand" "")))]
a50d7267 1079 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1080 "
a2cd141b 1081 if (TARGET_MAVERICK
604f3a0a 1082 && !cirrus_fp_register (operands[2], DFmode))
1083 operands[2] = force_reg (DFmode, operands[2]);
1084")
1085
cffb2a26 1086(define_expand "subdi3"
1087 [(parallel
1088 [(set (match_operand:DI 0 "s_register_operand" "")
1089 (minus:DI (match_operand:DI 1 "s_register_operand" "")
1090 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 1091 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 1092 "TARGET_EITHER"
1093 "
a2cd141b 1094 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
25f905c2 1095 && TARGET_32BIT
7d57ec45 1096 && cirrus_fp_register (operands[0], DImode)
1097 && cirrus_fp_register (operands[1], DImode))
1098 {
1099 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
1100 DONE;
1101 }
1102
25f905c2 1103 if (TARGET_THUMB1)
cffb2a26 1104 {
1105 if (GET_CODE (operands[1]) != REG)
5aa8c5f0 1106 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 1107 if (GET_CODE (operands[2]) != REG)
5aa8c5f0 1108 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 1109 }
1110 "
1111)
1112
1113(define_insn "*arm_subdi3"
1114 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 1115 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1116 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 1117 (clobber (reg:CC CC_REGNUM))]
94829feb 1118 "TARGET_32BIT && !TARGET_NEON"
97499065 1119 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
cffb2a26 1120 [(set_attr "conds" "clob")
1121 (set_attr "length" "8")]
1122)
1123
1124(define_insn "*thumb_subdi3"
1125 [(set (match_operand:DI 0 "register_operand" "=l")
1126 (minus:DI (match_operand:DI 1 "register_operand" "0")
1127 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 1128 (clobber (reg:CC CC_REGNUM))]
25f905c2 1129 "TARGET_THUMB1"
cffb2a26 1130 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
1131 [(set_attr "length" "4")]
1132)
9c08d1fa 1133
f7fbdd4a 1134(define_insn "*subdi_di_zesidi"
cffb2a26 1135 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1136 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1137 (zero_extend:DI
cffb2a26 1138 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1139 (clobber (reg:CC CC_REGNUM))]
25f905c2 1140 "TARGET_32BIT"
97499065 1141 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
cffb2a26 1142 [(set_attr "conds" "clob")
1143 (set_attr "length" "8")]
1144)
9c08d1fa 1145
f7fbdd4a 1146(define_insn "*subdi_di_sesidi"
cffb2a26 1147 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1148 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1149 (sign_extend:DI
cffb2a26 1150 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1151 (clobber (reg:CC CC_REGNUM))]
25f905c2 1152 "TARGET_32BIT"
97499065 1153 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
cffb2a26 1154 [(set_attr "conds" "clob")
1155 (set_attr "length" "8")]
1156)
9c08d1fa 1157
f7fbdd4a 1158(define_insn "*subdi_zesidi_di"
cffb2a26 1159 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1160 (minus:DI (zero_extend:DI
cffb2a26 1161 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1162 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1163 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1164 "TARGET_ARM"
97499065 1165 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
cffb2a26 1166 [(set_attr "conds" "clob")
1167 (set_attr "length" "8")]
1168)
9c08d1fa 1169
f7fbdd4a 1170(define_insn "*subdi_sesidi_di"
cffb2a26 1171 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1172 (minus:DI (sign_extend:DI
cffb2a26 1173 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1174 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1175 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1176 "TARGET_ARM"
97499065 1177 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
cffb2a26 1178 [(set_attr "conds" "clob")
1179 (set_attr "length" "8")]
1180)
9c08d1fa 1181
f7fbdd4a 1182(define_insn "*subdi_zesidi_zesidi"
cffb2a26 1183 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1184 (minus:DI (zero_extend:DI
cffb2a26 1185 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1186 (zero_extend:DI
cffb2a26 1187 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1188 (clobber (reg:CC CC_REGNUM))]
25f905c2 1189 "TARGET_32BIT"
1190 "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
cffb2a26 1191 [(set_attr "conds" "clob")
1192 (set_attr "length" "8")]
1193)
b11cae9e 1194
87b22bf7 1195(define_expand "subsi3"
cffb2a26 1196 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1197 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1198 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1199 "TARGET_EITHER"
87b22bf7 1200 "
1201 if (GET_CODE (operands[1]) == CONST_INT)
1202 {
25f905c2 1203 if (TARGET_32BIT)
cffb2a26 1204 {
96f57e36 1205 arm_split_constant (MINUS, SImode, NULL_RTX,
1206 INTVAL (operands[1]), operands[0],
e1ba4a27 1207 operands[2], optimize && can_create_pseudo_p ());
cffb2a26 1208 DONE;
1209 }
25f905c2 1210 else /* TARGET_THUMB1 */
cffb2a26 1211 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1212 }
cffb2a26 1213 "
1214)
87b22bf7 1215
747b7458 1216(define_insn "thumb1_subsi3_insn"
cffb2a26 1217 [(set (match_operand:SI 0 "register_operand" "=l")
1218 (minus:SI (match_operand:SI 1 "register_operand" "l")
747b7458 1219 (match_operand:SI 2 "reg_or_int_operand" "lPd")))]
25f905c2 1220 "TARGET_THUMB1"
cffb2a26 1221 "sub\\t%0, %1, %2"
747b7458 1222 [(set_attr "length" "2")
1223 (set_attr "conds" "set")])
cffb2a26 1224
25f905c2 1225; ??? Check Thumb-2 split length
a0f94409 1226(define_insn_and_split "*arm_subsi3_insn"
91a5e339 1227 [(set (match_operand:SI 0 "s_register_operand" "=r,r,rk,r")
1228 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,k,?n")
1229 (match_operand:SI 2 "reg_or_int_operand" "r,rI,r, r")))]
25f905c2 1230 "TARGET_32BIT"
e2348bcb 1231 "@
87b22bf7 1232 rsb%?\\t%0, %2, %1
aaa37ad6 1233 sub%?\\t%0, %1, %2
080c0b9a 1234 sub%?\\t%0, %1, %2
87b22bf7 1235 #"
91a5e339 1236 "&& (GET_CODE (operands[1]) == CONST_INT
1237 && !const_ok_for_arm (INTVAL (operands[1])))"
87b22bf7 1238 [(clobber (const_int 0))]
1239 "
96f57e36 1240 arm_split_constant (MINUS, SImode, curr_insn,
1241 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1242 DONE;
cffb2a26 1243 "
91a5e339 1244 [(set_attr "length" "4,4,4,16")
a0f94409 1245 (set_attr "predicable" "yes")]
1246)
1247
1248(define_peephole2
1249 [(match_scratch:SI 3 "r")
372575c7 1250 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1251 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1252 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1253 "TARGET_32BIT
a0f94409 1254 && !const_ok_for_arm (INTVAL (operands[1]))
1255 && const_ok_for_arm (~INTVAL (operands[1]))"
1256 [(set (match_dup 3) (match_dup 1))
1257 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1258 ""
cffb2a26 1259)
b11cae9e 1260
f7fbdd4a 1261(define_insn "*subsi3_compare0"
bd5b4116 1262 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1263 (compare:CC_NOOV
1264 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1265 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1266 (const_int 0)))
9c08d1fa 1267 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1268 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1269 "TARGET_32BIT"
e2348bcb 1270 "@
25f905c2 1271 sub%.\\t%0, %1, %2
1272 rsb%.\\t%0, %2, %1"
cffb2a26 1273 [(set_attr "conds" "set")]
1274)
9c08d1fa 1275
080c0b9a 1276(define_insn "*subsi3_compare"
1277 [(set (reg:CC CC_REGNUM)
1278 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,I")
1279 (match_operand:SI 2 "arm_rhs_operand" "rI,r")))
2df9477b 1280 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1281 (minus:SI (match_dup 1) (match_dup 2)))]
1282 "TARGET_32BIT"
1283 "@
1284 sub%.\\t%0, %1, %2
1285 rsb%.\\t%0, %2, %1"
1286 [(set_attr "conds" "set")]
1287)
1288
25f905c2 1289(define_expand "decscc"
1290 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1291 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1292 (match_operator:SI 2 "arm_comparison_operator"
1293 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1294 "TARGET_32BIT"
1295 ""
1296)
1297
1298(define_insn "*arm_decscc"
cffb2a26 1299 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1300 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 1301 (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1302 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1303 "TARGET_ARM"
e2348bcb 1304 "@
215b30b3 1305 sub%d2\\t%0, %1, #1
1306 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
cffb2a26 1307 [(set_attr "conds" "use")
1308 (set_attr "length" "*,8")]
1309)
9c08d1fa 1310
604f3a0a 1311(define_expand "subsf3"
1312 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1313 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1314 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1315 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1316 "
a2cd141b 1317 if (TARGET_MAVERICK)
604f3a0a 1318 {
1319 if (!cirrus_fp_register (operands[1], SFmode))
1320 operands[1] = force_reg (SFmode, operands[1]);
1321 if (!cirrus_fp_register (operands[2], SFmode))
1322 operands[2] = force_reg (SFmode, operands[2]);
1323 }
1324")
1325
604f3a0a 1326(define_expand "subdf3"
1327 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1328 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1329 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1330 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1331 "
a2cd141b 1332 if (TARGET_MAVERICK)
604f3a0a 1333 {
1334 if (!cirrus_fp_register (operands[1], DFmode))
1335 operands[1] = force_reg (DFmode, operands[1]);
1336 if (!cirrus_fp_register (operands[2], DFmode))
1337 operands[2] = force_reg (DFmode, operands[2]);
1338 }
1339")
1340
b11cae9e 1341\f
1342;; Multiplication insns
1343
cffb2a26 1344(define_expand "mulsi3"
1345 [(set (match_operand:SI 0 "s_register_operand" "")
1346 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1347 (match_operand:SI 1 "s_register_operand" "")))]
1348 "TARGET_EITHER"
1349 ""
1350)
1351
9c08d1fa 1352;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1353(define_insn "*arm_mulsi3"
1354 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1355 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1356 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1357 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1358 "mul%?\\t%0, %2, %1"
a2cd141b 1359 [(set_attr "insn" "mul")
0d66636f 1360 (set_attr "predicable" "yes")]
cffb2a26 1361)
1362
58d7d654 1363(define_insn "*arm_mulsi3_v6"
1364 [(set (match_operand:SI 0 "s_register_operand" "=r")
1365 (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1366 (match_operand:SI 2 "s_register_operand" "r")))]
1367 "TARGET_32BIT && arm_arch6"
1368 "mul%?\\t%0, %1, %2"
1369 [(set_attr "insn" "mul")
1370 (set_attr "predicable" "yes")]
1371)
1372
215b30b3 1373; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1374; 1 and 2; are the same, because reload will make operand 0 match
1375; operand 1 without realizing that this conflicts with operand 2. We fix
1376; this by adding another alternative to match this case, and then `reload'
1377; it ourselves. This alternative must come first.
cffb2a26 1378(define_insn "*thumb_mulsi3"
1379 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1380 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1381 (match_operand:SI 2 "register_operand" "l,l,l")))]
58d7d654 1382 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 1383 "*
1384 if (which_alternative < 2)
20c4e896 1385 return \"mov\\t%0, %1\;mul\\t%0, %2\";
cffb2a26 1386 else
20c4e896 1387 return \"mul\\t%0, %2\";
cffb2a26 1388 "
1389 [(set_attr "length" "4,4,2")
a2cd141b 1390 (set_attr "insn" "mul")]
cffb2a26 1391)
b11cae9e 1392
58d7d654 1393(define_insn "*thumb_mulsi3_v6"
1394 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
1395 (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1396 (match_operand:SI 2 "register_operand" "l,0,0")))]
1397 "TARGET_THUMB1 && arm_arch6"
1398 "@
1490694c 1399 mul\\t%0, %2
1400 mul\\t%0, %1
58d7d654 1401 mul\\t%0, %1"
1402 [(set_attr "length" "2")
1403 (set_attr "insn" "mul")]
1404)
1405
f7fbdd4a 1406(define_insn "*mulsi3_compare0"
bd5b4116 1407 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1408 (compare:CC_NOOV (mult:SI
1409 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1410 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1411 (const_int 0)))
1412 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1413 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1414 "TARGET_ARM && !arm_arch6"
1415 "mul%.\\t%0, %2, %1"
1416 [(set_attr "conds" "set")
1417 (set_attr "insn" "muls")]
1418)
1419
1420(define_insn "*mulsi3_compare0_v6"
1421 [(set (reg:CC_NOOV CC_REGNUM)
1422 (compare:CC_NOOV (mult:SI
1423 (match_operand:SI 2 "s_register_operand" "r")
1424 (match_operand:SI 1 "s_register_operand" "r"))
1425 (const_int 0)))
1426 (set (match_operand:SI 0 "s_register_operand" "=r")
1427 (mult:SI (match_dup 2) (match_dup 1)))]
1428 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1429 "mul%.\\t%0, %2, %1"
cffb2a26 1430 [(set_attr "conds" "set")
a2cd141b 1431 (set_attr "insn" "muls")]
cffb2a26 1432)
9c08d1fa 1433
f7fbdd4a 1434(define_insn "*mulsi_compare0_scratch"
bd5b4116 1435 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1436 (compare:CC_NOOV (mult:SI
1437 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1438 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1439 (const_int 0)))
1440 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1441 "TARGET_ARM && !arm_arch6"
1442 "mul%.\\t%0, %2, %1"
1443 [(set_attr "conds" "set")
1444 (set_attr "insn" "muls")]
1445)
1446
1447(define_insn "*mulsi_compare0_scratch_v6"
1448 [(set (reg:CC_NOOV CC_REGNUM)
1449 (compare:CC_NOOV (mult:SI
1450 (match_operand:SI 2 "s_register_operand" "r")
1451 (match_operand:SI 1 "s_register_operand" "r"))
1452 (const_int 0)))
1453 (clobber (match_scratch:SI 0 "=r"))]
1454 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1455 "mul%.\\t%0, %2, %1"
cffb2a26 1456 [(set_attr "conds" "set")
a2cd141b 1457 (set_attr "insn" "muls")]
cffb2a26 1458)
9c08d1fa 1459
b11cae9e 1460;; Unnamed templates to match MLA instruction.
1461
f7fbdd4a 1462(define_insn "*mulsi3addsi"
9c08d1fa 1463 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1464 (plus:SI
9c08d1fa 1465 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1466 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1467 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1468 "TARGET_32BIT && !arm_arch6"
1469 "mla%?\\t%0, %2, %1, %3"
1470 [(set_attr "insn" "mla")
1471 (set_attr "predicable" "yes")]
1472)
1473
1474(define_insn "*mulsi3addsi_v6"
1475 [(set (match_operand:SI 0 "s_register_operand" "=r")
1476 (plus:SI
1477 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1478 (match_operand:SI 1 "s_register_operand" "r"))
1479 (match_operand:SI 3 "s_register_operand" "r")))]
1480 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1481 "mla%?\\t%0, %2, %1, %3"
a2cd141b 1482 [(set_attr "insn" "mla")
0d66636f 1483 (set_attr "predicable" "yes")]
1484)
b11cae9e 1485
f7fbdd4a 1486(define_insn "*mulsi3addsi_compare0"
bd5b4116 1487 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1488 (compare:CC_NOOV
1489 (plus:SI (mult:SI
1490 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1491 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1492 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1493 (const_int 0)))
9c08d1fa 1494 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1495 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1496 (match_dup 3)))]
58d7d654 1497 "TARGET_ARM && arm_arch6"
1498 "mla%.\\t%0, %2, %1, %3"
1499 [(set_attr "conds" "set")
1500 (set_attr "insn" "mlas")]
1501)
1502
1503(define_insn "*mulsi3addsi_compare0_v6"
1504 [(set (reg:CC_NOOV CC_REGNUM)
1505 (compare:CC_NOOV
1506 (plus:SI (mult:SI
1507 (match_operand:SI 2 "s_register_operand" "r")
1508 (match_operand:SI 1 "s_register_operand" "r"))
1509 (match_operand:SI 3 "s_register_operand" "r"))
1510 (const_int 0)))
1511 (set (match_operand:SI 0 "s_register_operand" "=r")
1512 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1513 (match_dup 3)))]
1514 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1515 "mla%.\\t%0, %2, %1, %3"
0d66636f 1516 [(set_attr "conds" "set")
a2cd141b 1517 (set_attr "insn" "mlas")]
0d66636f 1518)
9c08d1fa 1519
f7fbdd4a 1520(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1521 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1522 (compare:CC_NOOV
1523 (plus:SI (mult:SI
1524 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1525 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1526 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1527 (const_int 0)))
9c08d1fa 1528 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1529 "TARGET_ARM && !arm_arch6"
1530 "mla%.\\t%0, %2, %1, %3"
1531 [(set_attr "conds" "set")
1532 (set_attr "insn" "mlas")]
1533)
1534
1535(define_insn "*mulsi3addsi_compare0_scratch_v6"
1536 [(set (reg:CC_NOOV CC_REGNUM)
1537 (compare:CC_NOOV
1538 (plus:SI (mult:SI
1539 (match_operand:SI 2 "s_register_operand" "r")
1540 (match_operand:SI 1 "s_register_operand" "r"))
1541 (match_operand:SI 3 "s_register_operand" "r"))
1542 (const_int 0)))
1543 (clobber (match_scratch:SI 0 "=r"))]
1544 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1545 "mla%.\\t%0, %2, %1, %3"
cffb2a26 1546 [(set_attr "conds" "set")
a2cd141b 1547 (set_attr "insn" "mlas")]
cffb2a26 1548)
f7fbdd4a 1549
89545238 1550(define_insn "*mulsi3subsi"
1551 [(set (match_operand:SI 0 "s_register_operand" "=r")
1552 (minus:SI
1553 (match_operand:SI 3 "s_register_operand" "r")
1554 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1555 (match_operand:SI 1 "s_register_operand" "r"))))]
1556 "TARGET_32BIT && arm_arch_thumb2"
1557 "mls%?\\t%0, %2, %1, %3"
1558 [(set_attr "insn" "mla")
1559 (set_attr "predicable" "yes")]
1560)
1561
5cdca009 1562(define_expand "maddsidi4"
1563 [(set (match_operand:DI 0 "s_register_operand" "")
1564 (plus:DI
1565 (mult:DI
1566 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1567 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1568 (match_operand:DI 3 "s_register_operand" "")))]
1569 "TARGET_32BIT && arm_arch3m"
1570 "")
82b85d08 1571
1572(define_insn "*mulsidi3adddi"
fe8dbf85 1573 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1574 (plus:DI
215b30b3 1575 (mult:DI
fe8dbf85 1576 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1577 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1578 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1579 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1580 "smlal%?\\t%Q0, %R0, %3, %2"
1581 [(set_attr "insn" "smlal")
1582 (set_attr "predicable" "yes")]
1583)
1584
1585(define_insn "*mulsidi3adddi_v6"
1586 [(set (match_operand:DI 0 "s_register_operand" "=r")
1587 (plus:DI
1588 (mult:DI
1589 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1590 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1591 (match_operand:DI 1 "s_register_operand" "0")))]
1592 "TARGET_32BIT && arm_arch6"
fe8dbf85 1593 "smlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1594 [(set_attr "insn" "smlal")
0d66636f 1595 (set_attr "predicable" "yes")]
1596)
82b85d08 1597
957788b0 1598;; 32x32->64 widening multiply.
1599;; As with mulsi3, the only difference between the v3-5 and v6+
1600;; versions of these patterns is the requirement that the output not
1601;; overlap the inputs, but that still means we have to have a named
1602;; expander and two different starred insns.
1603
1604(define_expand "mulsidi3"
1605 [(set (match_operand:DI 0 "s_register_operand" "")
1606 (mult:DI
1607 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1608 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1609 "TARGET_32BIT && arm_arch3m"
1610 ""
1611)
1612
1613(define_insn "*mulsidi3_nov6"
f7fbdd4a 1614 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1615 (mult:DI
1616 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1617 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1618 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1619 "smull%?\\t%Q0, %R0, %1, %2"
1620 [(set_attr "insn" "smull")
1621 (set_attr "predicable" "yes")]
1622)
1623
957788b0 1624(define_insn "*mulsidi3_v6"
58d7d654 1625 [(set (match_operand:DI 0 "s_register_operand" "=r")
1626 (mult:DI
1627 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1628 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1629 "TARGET_32BIT && arm_arch6"
97499065 1630 "smull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1631 [(set_attr "insn" "smull")
0d66636f 1632 (set_attr "predicable" "yes")]
1633)
f7fbdd4a 1634
957788b0 1635(define_expand "umulsidi3"
1636 [(set (match_operand:DI 0 "s_register_operand" "")
1637 (mult:DI
1638 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1639 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1640 "TARGET_32BIT && arm_arch3m"
1641 ""
1642)
1643
1644(define_insn "*umulsidi3_nov6"
f7fbdd4a 1645 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1646 (mult:DI
1647 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1648 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1649 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1650 "umull%?\\t%Q0, %R0, %1, %2"
1651 [(set_attr "insn" "umull")
1652 (set_attr "predicable" "yes")]
1653)
1654
957788b0 1655(define_insn "*umulsidi3_v6"
58d7d654 1656 [(set (match_operand:DI 0 "s_register_operand" "=r")
1657 (mult:DI
1658 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1659 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1660 "TARGET_32BIT && arm_arch6"
97499065 1661 "umull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1662 [(set_attr "insn" "umull")
0d66636f 1663 (set_attr "predicable" "yes")]
1664)
b11cae9e 1665
5cdca009 1666(define_expand "umaddsidi4"
1667 [(set (match_operand:DI 0 "s_register_operand" "")
1668 (plus:DI
1669 (mult:DI
1670 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1671 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1672 (match_operand:DI 3 "s_register_operand" "")))]
1673 "TARGET_32BIT && arm_arch3m"
1674 "")
82b85d08 1675
1676(define_insn "*umulsidi3adddi"
8ead09f9 1677 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1678 (plus:DI
215b30b3 1679 (mult:DI
fe8dbf85 1680 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1681 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1682 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1683 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1684 "umlal%?\\t%Q0, %R0, %3, %2"
1685 [(set_attr "insn" "umlal")
1686 (set_attr "predicable" "yes")]
1687)
1688
1689(define_insn "*umulsidi3adddi_v6"
1690 [(set (match_operand:DI 0 "s_register_operand" "=r")
1691 (plus:DI
1692 (mult:DI
1693 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1694 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1695 (match_operand:DI 1 "s_register_operand" "0")))]
1696 "TARGET_32BIT && arm_arch6"
fe8dbf85 1697 "umlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1698 [(set_attr "insn" "umlal")
0d66636f 1699 (set_attr "predicable" "yes")]
1700)
82b85d08 1701
957788b0 1702(define_expand "smulsi3_highpart"
1703 [(parallel
1704 [(set (match_operand:SI 0 "s_register_operand" "")
1705 (truncate:SI
1706 (lshiftrt:DI
1707 (mult:DI
1708 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1709 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1710 (const_int 32))))
1711 (clobber (match_scratch:SI 3 ""))])]
1712 "TARGET_32BIT && arm_arch3m"
1713 ""
1714)
1715
1716(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1717 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1718 (truncate:SI
1719 (lshiftrt:DI
215b30b3 1720 (mult:DI
e5fea38e 1721 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1722 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1723 (const_int 32))))
1724 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1725 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1726 "smull%?\\t%3, %0, %2, %1"
1727 [(set_attr "insn" "smull")
1728 (set_attr "predicable" "yes")]
1729)
1730
957788b0 1731(define_insn "*smulsi3_highpart_v6"
58d7d654 1732 [(set (match_operand:SI 0 "s_register_operand" "=r")
1733 (truncate:SI
1734 (lshiftrt:DI
1735 (mult:DI
1736 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1737 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1738 (const_int 32))))
1739 (clobber (match_scratch:SI 3 "=r"))]
1740 "TARGET_32BIT && arm_arch6"
f082f1c4 1741 "smull%?\\t%3, %0, %2, %1"
a2cd141b 1742 [(set_attr "insn" "smull")
0d66636f 1743 (set_attr "predicable" "yes")]
cffb2a26 1744)
f082f1c4 1745
957788b0 1746(define_expand "umulsi3_highpart"
1747 [(parallel
1748 [(set (match_operand:SI 0 "s_register_operand" "")
1749 (truncate:SI
1750 (lshiftrt:DI
1751 (mult:DI
1752 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1753 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1754 (const_int 32))))
1755 (clobber (match_scratch:SI 3 ""))])]
1756 "TARGET_32BIT && arm_arch3m"
1757 ""
1758)
1759
1760(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1761 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1762 (truncate:SI
1763 (lshiftrt:DI
215b30b3 1764 (mult:DI
e5fea38e 1765 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1766 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1767 (const_int 32))))
1768 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1769 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1770 "umull%?\\t%3, %0, %2, %1"
1771 [(set_attr "insn" "umull")
1772 (set_attr "predicable" "yes")]
1773)
1774
957788b0 1775(define_insn "*umulsi3_highpart_v6"
58d7d654 1776 [(set (match_operand:SI 0 "s_register_operand" "=r")
1777 (truncate:SI
1778 (lshiftrt:DI
1779 (mult:DI
1780 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1781 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1782 (const_int 32))))
1783 (clobber (match_scratch:SI 3 "=r"))]
1784 "TARGET_32BIT && arm_arch6"
f082f1c4 1785 "umull%?\\t%3, %0, %2, %1"
a2cd141b 1786 [(set_attr "insn" "umull")
0d66636f 1787 (set_attr "predicable" "yes")]
cffb2a26 1788)
f082f1c4 1789
331beb1a 1790(define_insn "mulhisi3"
1791 [(set (match_operand:SI 0 "s_register_operand" "=r")
1792 (mult:SI (sign_extend:SI
1793 (match_operand:HI 1 "s_register_operand" "%r"))
1794 (sign_extend:SI
1795 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1796 "TARGET_DSP_MULTIPLY"
61a2d04c 1797 "smulbb%?\\t%0, %1, %2"
a2cd141b 1798 [(set_attr "insn" "smulxy")
fec538d9 1799 (set_attr "predicable" "yes")]
1800)
1801
1802(define_insn "*mulhisi3tb"
1803 [(set (match_operand:SI 0 "s_register_operand" "=r")
1804 (mult:SI (ashiftrt:SI
1805 (match_operand:SI 1 "s_register_operand" "r")
1806 (const_int 16))
1807 (sign_extend:SI
1808 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1809 "TARGET_DSP_MULTIPLY"
fec538d9 1810 "smultb%?\\t%0, %1, %2"
a2cd141b 1811 [(set_attr "insn" "smulxy")
fec538d9 1812 (set_attr "predicable" "yes")]
1813)
1814
1815(define_insn "*mulhisi3bt"
1816 [(set (match_operand:SI 0 "s_register_operand" "=r")
1817 (mult:SI (sign_extend:SI
1818 (match_operand:HI 1 "s_register_operand" "r"))
1819 (ashiftrt:SI
1820 (match_operand:SI 2 "s_register_operand" "r")
1821 (const_int 16))))]
25f905c2 1822 "TARGET_DSP_MULTIPLY"
fec538d9 1823 "smulbt%?\\t%0, %1, %2"
a2cd141b 1824 [(set_attr "insn" "smulxy")
fec538d9 1825 (set_attr "predicable" "yes")]
1826)
1827
1828(define_insn "*mulhisi3tt"
1829 [(set (match_operand:SI 0 "s_register_operand" "=r")
1830 (mult:SI (ashiftrt:SI
1831 (match_operand:SI 1 "s_register_operand" "r")
1832 (const_int 16))
1833 (ashiftrt:SI
1834 (match_operand:SI 2 "s_register_operand" "r")
1835 (const_int 16))))]
25f905c2 1836 "TARGET_DSP_MULTIPLY"
fec538d9 1837 "smultt%?\\t%0, %1, %2"
a2cd141b 1838 [(set_attr "insn" "smulxy")
fec538d9 1839 (set_attr "predicable" "yes")]
331beb1a 1840)
1841
5cdca009 1842(define_insn "maddhisi4"
331beb1a 1843 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 1844 (plus:SI (mult:SI (sign_extend:SI
1845 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1846 (sign_extend:SI
cfa6c608 1847 (match_operand:HI 2 "s_register_operand" "r")))
1848 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 1849 "TARGET_DSP_MULTIPLY"
5cdca009 1850 "smlabb%?\\t%0, %1, %2, %3"
a2cd141b 1851 [(set_attr "insn" "smlaxy")
fec538d9 1852 (set_attr "predicable" "yes")]
331beb1a 1853)
1854
9a92f368 1855;; Note: there is no maddhisi4ibt because this one is canonical form
1856(define_insn "*maddhisi4tb"
1857 [(set (match_operand:SI 0 "s_register_operand" "=r")
1858 (plus:SI (mult:SI (ashiftrt:SI
1859 (match_operand:SI 1 "s_register_operand" "r")
1860 (const_int 16))
1861 (sign_extend:SI
1862 (match_operand:HI 2 "s_register_operand" "r")))
1863 (match_operand:SI 3 "s_register_operand" "r")))]
1864 "TARGET_DSP_MULTIPLY"
1865 "smlatb%?\\t%0, %1, %2, %3"
1866 [(set_attr "insn" "smlaxy")
1867 (set_attr "predicable" "yes")]
1868)
1869
1870(define_insn "*maddhisi4tt"
1871 [(set (match_operand:SI 0 "s_register_operand" "=r")
1872 (plus:SI (mult:SI (ashiftrt:SI
1873 (match_operand:SI 1 "s_register_operand" "r")
1874 (const_int 16))
1875 (ashiftrt:SI
1876 (match_operand:SI 2 "s_register_operand" "r")
1877 (const_int 16)))
1878 (match_operand:SI 3 "s_register_operand" "r")))]
1879 "TARGET_DSP_MULTIPLY"
1880 "smlatt%?\\t%0, %1, %2, %3"
1881 [(set_attr "insn" "smlaxy")
1882 (set_attr "predicable" "yes")]
1883)
1884
aff5fb4d 1885(define_insn "maddhidi4"
331beb1a 1886 [(set (match_operand:DI 0 "s_register_operand" "=r")
1887 (plus:DI
331beb1a 1888 (mult:DI (sign_extend:DI
cfa6c608 1889 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1890 (sign_extend:DI
cfa6c608 1891 (match_operand:HI 2 "s_register_operand" "r")))
1892 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 1893 "TARGET_DSP_MULTIPLY"
5cdca009 1894 "smlalbb%?\\t%Q0, %R0, %1, %2"
a2cd141b 1895 [(set_attr "insn" "smlalxy")
fec538d9 1896 (set_attr "predicable" "yes")])
331beb1a 1897
9a92f368 1898;; Note: there is no maddhidi4ibt because this one is canonical form
1899(define_insn "*maddhidi4tb"
1900 [(set (match_operand:DI 0 "s_register_operand" "=r")
1901 (plus:DI
1902 (mult:DI (sign_extend:DI
1903 (ashiftrt:SI
1904 (match_operand:SI 1 "s_register_operand" "r")
1905 (const_int 16)))
1906 (sign_extend:DI
1907 (match_operand:HI 2 "s_register_operand" "r")))
1908 (match_operand:DI 3 "s_register_operand" "0")))]
1909 "TARGET_DSP_MULTIPLY"
1910 "smlaltb%?\\t%Q0, %R0, %1, %2"
1911 [(set_attr "insn" "smlalxy")
1912 (set_attr "predicable" "yes")])
1913
1914(define_insn "*maddhidi4tt"
1915 [(set (match_operand:DI 0 "s_register_operand" "=r")
1916 (plus:DI
1917 (mult:DI (sign_extend:DI
1918 (ashiftrt:SI
1919 (match_operand:SI 1 "s_register_operand" "r")
1920 (const_int 16)))
1921 (sign_extend:DI
1922 (ashiftrt:SI
1923 (match_operand:SI 2 "s_register_operand" "r")
1924 (const_int 16))))
1925 (match_operand:DI 3 "s_register_operand" "0")))]
1926 "TARGET_DSP_MULTIPLY"
1927 "smlaltt%?\\t%Q0, %R0, %1, %2"
1928 [(set_attr "insn" "smlalxy")
1929 (set_attr "predicable" "yes")])
1930
604f3a0a 1931(define_expand "mulsf3"
1932 [(set (match_operand:SF 0 "s_register_operand" "")
1933 (mult:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1934 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1935 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1936 "
a2cd141b 1937 if (TARGET_MAVERICK
604f3a0a 1938 && !cirrus_fp_register (operands[2], SFmode))
1939 operands[2] = force_reg (SFmode, operands[2]);
1940")
1941
604f3a0a 1942(define_expand "muldf3"
1943 [(set (match_operand:DF 0 "s_register_operand" "")
1944 (mult:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1945 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1946 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1947 "
a2cd141b 1948 if (TARGET_MAVERICK
604f3a0a 1949 && !cirrus_fp_register (operands[2], DFmode))
1950 operands[2] = force_reg (DFmode, operands[2]);
1951")
b11cae9e 1952\f
1953;; Division insns
1954
7db9af5d 1955(define_expand "divsf3"
1956 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1957 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1958 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1959 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1960 "")
9c08d1fa 1961
7db9af5d 1962(define_expand "divdf3"
1963 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1964 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1965 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1966 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7db9af5d 1967 "")
b11cae9e 1968\f
1969;; Modulo insns
1970
7db9af5d 1971(define_expand "modsf3"
1972 [(set (match_operand:SF 0 "s_register_operand" "")
1973 (mod:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1974 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1975 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1976 "")
9c08d1fa 1977
7db9af5d 1978(define_expand "moddf3"
1979 [(set (match_operand:DF 0 "s_register_operand" "")
1980 (mod:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1981 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1982 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1983 "")
b11cae9e 1984\f
1985;; Boolean and,ior,xor insns
1986
f6ebffac 1987;; Split up double word logical operations
1988
1989;; Split up simple DImode logical operations. Simply perform the logical
1990;; operation on the upper and lower halves of the registers.
1991(define_split
1992 [(set (match_operand:DI 0 "s_register_operand" "")
1993 (match_operator:DI 6 "logical_binary_operator"
1994 [(match_operand:DI 1 "s_register_operand" "")
1995 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 1996 "TARGET_32BIT && reload_completed
e2669ea7 1997 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 1998 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1999 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2000 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
2001 "
215b30b3 2002 {
2003 operands[3] = gen_highpart (SImode, operands[0]);
2004 operands[0] = gen_lowpart (SImode, operands[0]);
2005 operands[4] = gen_highpart (SImode, operands[1]);
2006 operands[1] = gen_lowpart (SImode, operands[1]);
2007 operands[5] = gen_highpart (SImode, operands[2]);
2008 operands[2] = gen_lowpart (SImode, operands[2]);
2009 }"
2010)
f6ebffac 2011
f6ebffac 2012(define_split
2013 [(set (match_operand:DI 0 "s_register_operand" "")
2014 (match_operator:DI 6 "logical_binary_operator"
2015 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2016 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 2017 "TARGET_32BIT && reload_completed"
f6ebffac 2018 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2019 (set (match_dup 3) (match_op_dup:SI 6
2020 [(ashiftrt:SI (match_dup 2) (const_int 31))
2021 (match_dup 4)]))]
2022 "
215b30b3 2023 {
2024 operands[3] = gen_highpart (SImode, operands[0]);
2025 operands[0] = gen_lowpart (SImode, operands[0]);
2026 operands[4] = gen_highpart (SImode, operands[1]);
2027 operands[1] = gen_lowpart (SImode, operands[1]);
2028 operands[5] = gen_highpart (SImode, operands[2]);
2029 operands[2] = gen_lowpart (SImode, operands[2]);
2030 }"
2031)
f6ebffac 2032
f6ebffac 2033;; The zero extend of operand 2 means we can just copy the high part of
2034;; operand1 into operand0.
2035(define_split
2036 [(set (match_operand:DI 0 "s_register_operand" "")
2037 (ior:DI
2038 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2039 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2040 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2041 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
2042 (set (match_dup 3) (match_dup 4))]
2043 "
215b30b3 2044 {
2045 operands[4] = gen_highpart (SImode, operands[1]);
2046 operands[3] = gen_highpart (SImode, operands[0]);
2047 operands[0] = gen_lowpart (SImode, operands[0]);
2048 operands[1] = gen_lowpart (SImode, operands[1]);
2049 }"
2050)
f6ebffac 2051
2052;; The zero extend of operand 2 means we can just copy the high part of
2053;; operand1 into operand0.
2054(define_split
2055 [(set (match_operand:DI 0 "s_register_operand" "")
2056 (xor:DI
2057 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2058 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2059 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2060 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
2061 (set (match_dup 3) (match_dup 4))]
2062 "
215b30b3 2063 {
2064 operands[4] = gen_highpart (SImode, operands[1]);
2065 operands[3] = gen_highpart (SImode, operands[0]);
2066 operands[0] = gen_lowpart (SImode, operands[0]);
2067 operands[1] = gen_lowpart (SImode, operands[1]);
2068 }"
2069)
f6ebffac 2070
e2669ea7 2071(define_expand "anddi3"
2072 [(set (match_operand:DI 0 "s_register_operand" "")
2073 (and:DI (match_operand:DI 1 "s_register_operand" "")
2074 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
2075 "TARGET_32BIT"
2076 ""
2077)
2078
2079(define_insn "*anddi3_insn"
cffb2a26 2080 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2081 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2082 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2083 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2084 "#"
215b30b3 2085 [(set_attr "length" "8")]
2086)
b11cae9e 2087
a0f94409 2088(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 2089 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2090 (and:DI (zero_extend:DI
2091 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2092 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2093 "TARGET_32BIT"
f6ebffac 2094 "#"
25f905c2 2095 "TARGET_32BIT && reload_completed"
a0f94409 2096 ; The zero extend of operand 2 clears the high word of the output
2097 ; operand.
2098 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2099 (set (match_dup 3) (const_int 0))]
2100 "
2101 {
2102 operands[3] = gen_highpart (SImode, operands[0]);
2103 operands[0] = gen_lowpart (SImode, operands[0]);
2104 operands[1] = gen_lowpart (SImode, operands[1]);
2105 }"
215b30b3 2106 [(set_attr "length" "8")]
2107)
b11cae9e 2108
f7fbdd4a 2109(define_insn "*anddi_sesdi_di"
cffb2a26 2110 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 2111 (and:DI (sign_extend:DI
2112 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2113 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2114 "TARGET_32BIT"
f6ebffac 2115 "#"
cffb2a26 2116 [(set_attr "length" "8")]
2117)
b11cae9e 2118
87b22bf7 2119(define_expand "andsi3"
cffb2a26 2120 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2121 (and:SI (match_operand:SI 1 "s_register_operand" "")
2122 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2123 "TARGET_EITHER"
87b22bf7 2124 "
25f905c2 2125 if (TARGET_32BIT)
87b22bf7 2126 {
cffb2a26 2127 if (GET_CODE (operands[2]) == CONST_INT)
2128 {
47b5b27b 2129 if (INTVAL (operands[2]) == 255 && arm_arch6)
2130 {
2131 operands[1] = convert_to_mode (QImode, operands[1], 1);
2132 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2133 operands[1]));
2134 }
2135 else
2136 arm_split_constant (AND, SImode, NULL_RTX,
2137 INTVAL (operands[2]), operands[0],
2138 operands[1],
2139 optimize && can_create_pseudo_p ());
615caa51 2140
cffb2a26 2141 DONE;
2142 }
87b22bf7 2143 }
25f905c2 2144 else /* TARGET_THUMB1 */
cffb2a26 2145 {
2146 if (GET_CODE (operands[2]) != CONST_INT)
923ffadb 2147 {
2148 rtx tmp = force_reg (SImode, operands[2]);
2149 if (rtx_equal_p (operands[0], operands[1]))
2150 operands[2] = tmp;
2151 else
2152 {
2153 operands[2] = operands[1];
2154 operands[1] = tmp;
2155 }
2156 }
cffb2a26 2157 else
2158 {
2159 int i;
2160
215b30b3 2161 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2162 {
215b30b3 2163 operands[2] = force_reg (SImode,
2164 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2165
747b7458 2166 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2167
2168 DONE;
2169 }
87b22bf7 2170
cffb2a26 2171 for (i = 9; i <= 31; i++)
2172 {
2173 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2174 {
2175 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2176 const0_rtx));
2177 DONE;
2178 }
215b30b3 2179 else if ((((HOST_WIDE_INT) 1) << i) - 1
2180 == ~INTVAL (operands[2]))
cffb2a26 2181 {
2182 rtx shift = GEN_INT (i);
2183 rtx reg = gen_reg_rtx (SImode);
2184
2185 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2186 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2187
2188 DONE;
2189 }
2190 }
2191
2192 operands[2] = force_reg (SImode, operands[2]);
2193 }
215b30b3 2194 }
2195 "
cffb2a26 2196)
2197
25f905c2 2198; ??? Check split length for Thumb-2
a0f94409 2199(define_insn_and_split "*arm_andsi3_insn"
cffb2a26 2200 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87b22bf7 2201 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2202 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
25f905c2 2203 "TARGET_32BIT"
5565501b 2204 "@
2205 and%?\\t%0, %1, %2
87b22bf7 2206 bic%?\\t%0, %1, #%B2
2207 #"
25f905c2 2208 "TARGET_32BIT
a0f94409 2209 && GET_CODE (operands[2]) == CONST_INT
2210 && !(const_ok_for_arm (INTVAL (operands[2]))
2211 || const_ok_for_arm (~INTVAL (operands[2])))"
2212 [(clobber (const_int 0))]
2213 "
96f57e36 2214 arm_split_constant (AND, SImode, curr_insn,
2215 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2216 DONE;
2217 "
0d66636f 2218 [(set_attr "length" "4,4,16")
2219 (set_attr "predicable" "yes")]
cffb2a26 2220)
2221
25f905c2 2222(define_insn "*thumb1_andsi3_insn"
cffb2a26 2223 [(set (match_operand:SI 0 "register_operand" "=l")
2224 (and:SI (match_operand:SI 1 "register_operand" "%0")
2225 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2226 "TARGET_THUMB1"
747b7458 2227 "and\\t%0, %2"
2228 [(set_attr "length" "2")
2229 (set_attr "conds" "set")])
87b22bf7 2230
f7fbdd4a 2231(define_insn "*andsi3_compare0"
bd5b4116 2232 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2233 (compare:CC_NOOV
2234 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
2235 (match_operand:SI 2 "arm_not_operand" "rI,K"))
2236 (const_int 0)))
cffb2a26 2237 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 2238 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2239 "TARGET_32BIT"
5565501b 2240 "@
25f905c2 2241 and%.\\t%0, %1, %2
2242 bic%.\\t%0, %1, #%B2"
cffb2a26 2243 [(set_attr "conds" "set")]
2244)
9c08d1fa 2245
f7fbdd4a 2246(define_insn "*andsi3_compare0_scratch"
bd5b4116 2247 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2248 (compare:CC_NOOV
2249 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
2250 (match_operand:SI 1 "arm_not_operand" "rI,K"))
2251 (const_int 0)))
dd193d7c 2252 (clobber (match_scratch:SI 2 "=X,r"))]
25f905c2 2253 "TARGET_32BIT"
5565501b 2254 "@
2255 tst%?\\t%0, %1
25f905c2 2256 bic%.\\t%2, %0, #%B1"
0d66636f 2257 [(set_attr "conds" "set")]
2258)
9c08d1fa 2259
f7fbdd4a 2260(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2261 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2262 (compare:CC_NOOV (zero_extract:SI
2263 (match_operand:SI 0 "s_register_operand" "r")
206ee9a2 2264 (match_operand 1 "const_int_operand" "n")
2265 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2266 (const_int 0)))]
25f905c2 2267 "TARGET_32BIT
cffb2a26 2268 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2269 && INTVAL (operands[1]) > 0
2270 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2271 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2272 "*
5c49a439 2273 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2274 << INTVAL (operands[2]));
40dbec34 2275 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2276 return \"\";
0d66636f 2277 "
596e5e8f 2278 [(set_attr "conds" "set")
2279 (set_attr "predicable" "yes")]
0d66636f 2280)
9c08d1fa 2281
f4462328 2282(define_insn_and_split "*ne_zeroextractsi"
c4034607 2283 [(set (match_operand:SI 0 "s_register_operand" "=r")
2284 (ne:SI (zero_extract:SI
2285 (match_operand:SI 1 "s_register_operand" "r")
2286 (match_operand:SI 2 "const_int_operand" "n")
2287 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2288 (const_int 0)))
2289 (clobber (reg:CC CC_REGNUM))]
25f905c2 2290 "TARGET_32BIT
cffb2a26 2291 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2292 && INTVAL (operands[2]) > 0
2293 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2294 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2295 "#"
25f905c2 2296 "TARGET_32BIT
f4462328 2297 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2298 && INTVAL (operands[2]) > 0
2299 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2300 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2301 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2302 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2303 (const_int 0)))
2304 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2305 (set (match_dup 0)
2306 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2307 (match_dup 0) (const_int 1)))]
2308 "
2309 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2310 << INTVAL (operands[3]));
2311 "
2312 [(set_attr "conds" "clob")
25f905c2 2313 (set (attr "length")
2314 (if_then_else (eq_attr "is_thumb" "yes")
2315 (const_int 12)
2316 (const_int 8)))]
f4462328 2317)
2318
2319(define_insn_and_split "*ne_zeroextractsi_shifted"
2320 [(set (match_operand:SI 0 "s_register_operand" "=r")
2321 (ne:SI (zero_extract:SI
2322 (match_operand:SI 1 "s_register_operand" "r")
2323 (match_operand:SI 2 "const_int_operand" "n")
2324 (const_int 0))
2325 (const_int 0)))
2326 (clobber (reg:CC CC_REGNUM))]
2327 "TARGET_ARM"
2328 "#"
2329 "TARGET_ARM"
2330 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2331 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2332 (const_int 0)))
2333 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2334 (set (match_dup 0)
2335 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2336 (match_dup 0) (const_int 1)))]
2337 "
2338 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2339 "
2340 [(set_attr "conds" "clob")
2341 (set_attr "length" "8")]
2342)
2343
2344(define_insn_and_split "*ite_ne_zeroextractsi"
2345 [(set (match_operand:SI 0 "s_register_operand" "=r")
2346 (if_then_else:SI (ne (zero_extract:SI
2347 (match_operand:SI 1 "s_register_operand" "r")
2348 (match_operand:SI 2 "const_int_operand" "n")
2349 (match_operand:SI 3 "const_int_operand" "n"))
2350 (const_int 0))
2351 (match_operand:SI 4 "arm_not_operand" "rIK")
2352 (const_int 0)))
2353 (clobber (reg:CC CC_REGNUM))]
2354 "TARGET_ARM
2355 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2356 && INTVAL (operands[2]) > 0
2357 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2358 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2359 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2360 "#"
2361 "TARGET_ARM
2362 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2363 && INTVAL (operands[2]) > 0
2364 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2365 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2366 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2367 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2368 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2369 (const_int 0)))
2370 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2371 (set (match_dup 0)
2372 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2373 (match_dup 0) (match_dup 4)))]
2374 "
c4034607 2375 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2376 << INTVAL (operands[3]));
2377 "
2378 [(set_attr "conds" "clob")
2379 (set_attr "length" "8")]
2380)
2381
2382(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2383 [(set (match_operand:SI 0 "s_register_operand" "=r")
2384 (if_then_else:SI (ne (zero_extract:SI
2385 (match_operand:SI 1 "s_register_operand" "r")
2386 (match_operand:SI 2 "const_int_operand" "n")
2387 (const_int 0))
2388 (const_int 0))
2389 (match_operand:SI 3 "arm_not_operand" "rIK")
2390 (const_int 0)))
2391 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2392 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2393 "#"
f8d7bf2f 2394 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2395 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2396 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2397 (const_int 0)))
2398 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2399 (set (match_dup 0)
2400 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2401 (match_dup 0) (match_dup 3)))]
2402 "
2403 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2404 "
2405 [(set_attr "conds" "clob")
215b30b3 2406 (set_attr "length" "8")]
2407)
9c08d1fa 2408
58d6528b 2409(define_split
2410 [(set (match_operand:SI 0 "s_register_operand" "")
2411 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2412 (match_operand:SI 2 "const_int_operand" "")
2413 (match_operand:SI 3 "const_int_operand" "")))
2414 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2415 "TARGET_THUMB1"
58d6528b 2416 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2417 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2418 "{
2419 HOST_WIDE_INT temp = INTVAL (operands[2]);
2420
2421 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2422 operands[3] = GEN_INT (32 - temp);
2423 }"
2424)
2425
25f905c2 2426;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2427(define_split
2428 [(set (match_operand:SI 0 "s_register_operand" "")
2429 (match_operator:SI 1 "shiftable_operator"
2430 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2431 (match_operand:SI 3 "const_int_operand" "")
2432 (match_operand:SI 4 "const_int_operand" ""))
2433 (match_operand:SI 5 "s_register_operand" "")]))
2434 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2435 "TARGET_ARM"
2436 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2437 (set (match_dup 0)
2438 (match_op_dup 1
2439 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2440 (match_dup 5)]))]
2441 "{
2442 HOST_WIDE_INT temp = INTVAL (operands[3]);
2443
2444 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2445 operands[4] = GEN_INT (32 - temp);
2446 }"
2447)
2448
58d6528b 2449(define_split
2450 [(set (match_operand:SI 0 "s_register_operand" "")
2451 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2452 (match_operand:SI 2 "const_int_operand" "")
2453 (match_operand:SI 3 "const_int_operand" "")))]
25f905c2 2454 "TARGET_THUMB1"
58d6528b 2455 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2456 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2457 "{
2458 HOST_WIDE_INT temp = INTVAL (operands[2]);
2459
2460 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2461 operands[3] = GEN_INT (32 - temp);
2462 }"
2463)
2464
d7863cfe 2465(define_split
2466 [(set (match_operand:SI 0 "s_register_operand" "")
2467 (match_operator:SI 1 "shiftable_operator"
2468 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2469 (match_operand:SI 3 "const_int_operand" "")
2470 (match_operand:SI 4 "const_int_operand" ""))
2471 (match_operand:SI 5 "s_register_operand" "")]))
2472 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2473 "TARGET_ARM"
2474 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2475 (set (match_dup 0)
2476 (match_op_dup 1
2477 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2478 (match_dup 5)]))]
2479 "{
2480 HOST_WIDE_INT temp = INTVAL (operands[3]);
2481
2482 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2483 operands[4] = GEN_INT (32 - temp);
2484 }"
2485)
2486
a42059fd 2487;;; ??? This pattern is bogus. If operand3 has bits outside the range
2488;;; represented by the bitfield, then this will produce incorrect results.
2489;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2490;;; which have a real bit-field insert instruction, the truncation happens
2491;;; in the bit-field insert instruction itself. Since arm does not have a
2492;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2493;;; the value before we insert. This loses some of the advantage of having
2494;;; this insv pattern, so this pattern needs to be reevalutated.
2495
8a18b90c 2496(define_expand "insv"
eb04cafb 2497 [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2498 (match_operand 1 "general_operand" "")
2499 (match_operand 2 "general_operand" ""))
2500 (match_operand 3 "reg_or_int_operand" ""))]
8b054d5a 2501 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2502 "
215b30b3 2503 {
2504 int start_bit = INTVAL (operands[2]);
2505 int width = INTVAL (operands[1]);
2506 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2507 rtx target, subtarget;
2508
8b054d5a 2509 if (arm_arch_thumb2)
2510 {
eb04cafb 2511 if (unaligned_access && MEM_P (operands[0])
2512 && s_register_operand (operands[3], GET_MODE (operands[3]))
2513 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
8b054d5a 2514 {
eb04cafb 2515 rtx base_addr;
2516
2517 if (BYTES_BIG_ENDIAN)
2518 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2519 - start_bit;
8b054d5a 2520
eb04cafb 2521 if (width == 32)
8b054d5a 2522 {
eb04cafb 2523 base_addr = adjust_address (operands[0], SImode,
2524 start_bit / BITS_PER_UNIT);
2525 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
8b054d5a 2526 }
eb04cafb 2527 else
2528 {
2529 rtx tmp = gen_reg_rtx (HImode);
8b054d5a 2530
eb04cafb 2531 base_addr = adjust_address (operands[0], HImode,
2532 start_bit / BITS_PER_UNIT);
2533 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2534 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2535 }
2536 DONE;
8b054d5a 2537 }
eb04cafb 2538 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
8b054d5a 2539 {
eb04cafb 2540 bool use_bfi = TRUE;
8b054d5a 2541
eb04cafb 2542 if (GET_CODE (operands[3]) == CONST_INT)
2543 {
2544 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2545
2546 if (val == 0)
2547 {
2548 emit_insn (gen_insv_zero (operands[0], operands[1],
2549 operands[2]));
2550 DONE;
2551 }
2552
2553 /* See if the set can be done with a single orr instruction. */
2554 if (val == mask && const_ok_for_arm (val << start_bit))
2555 use_bfi = FALSE;
2556 }
2557
2558 if (use_bfi)
2559 {
2560 if (GET_CODE (operands[3]) != REG)
2561 operands[3] = force_reg (SImode, operands[3]);
2562
2563 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2564 operands[3]));
2565 DONE;
2566 }
8b054d5a 2567 }
eb04cafb 2568 else
2569 FAIL;
8b054d5a 2570 }
2571
eb04cafb 2572 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2573 FAIL;
2574
3f8fde42 2575 target = copy_rtx (operands[0]);
215b30b3 2576 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2577 subreg as the final target. */
2578 if (GET_CODE (target) == SUBREG)
2579 {
2580 subtarget = gen_reg_rtx (SImode);
2581 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2582 < GET_MODE_SIZE (SImode))
2583 target = SUBREG_REG (target);
2584 }
2585 else
2586 subtarget = target;
8a18b90c 2587
215b30b3 2588 if (GET_CODE (operands[3]) == CONST_INT)
2589 {
2590 /* Since we are inserting a known constant, we may be able to
2591 reduce the number of bits that we have to clear so that
2592 the mask becomes simple. */
2593 /* ??? This code does not check to see if the new mask is actually
2594 simpler. It may not be. */
2595 rtx op1 = gen_reg_rtx (SImode);
2596 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2597 start of this pattern. */
2598 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2599 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2600
c5b3a71b 2601 emit_insn (gen_andsi3 (op1, operands[0],
2602 gen_int_mode (~mask2, SImode)));
215b30b3 2603 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2604 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2605 }
2606 else if (start_bit == 0
2607 && !(const_ok_for_arm (mask)
2608 || const_ok_for_arm (~mask)))
2609 {
2610 /* A Trick, since we are setting the bottom bits in the word,
2611 we can shift operand[3] up, operand[0] down, OR them together
2612 and rotate the result back again. This takes 3 insns, and
5910bb95 2613 the third might be mergeable into another op. */
215b30b3 2614 /* The shift up copes with the possibility that operand[3] is
2615 wider than the bitfield. */
2616 rtx op0 = gen_reg_rtx (SImode);
2617 rtx op1 = gen_reg_rtx (SImode);
2618
2619 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2620 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2621 emit_insn (gen_iorsi3 (op1, op1, op0));
2622 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2623 }
2624 else if ((width + start_bit == 32)
2625 && !(const_ok_for_arm (mask)
2626 || const_ok_for_arm (~mask)))
2627 {
2628 /* Similar trick, but slightly less efficient. */
8a18b90c 2629
215b30b3 2630 rtx op0 = gen_reg_rtx (SImode);
2631 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2632
215b30b3 2633 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2634 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2635 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2636 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2637 }
2638 else
2639 {
c5b3a71b 2640 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2641 rtx op1 = gen_reg_rtx (SImode);
2642 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2643
215b30b3 2644 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2645 {
2646 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2647
215b30b3 2648 emit_insn (gen_movsi (tmp, op0));
2649 op0 = tmp;
2650 }
8a18b90c 2651
215b30b3 2652 /* Mask out any bits in operand[3] that are not needed. */
2653 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2654
215b30b3 2655 if (GET_CODE (op0) == CONST_INT
2656 && (const_ok_for_arm (mask << start_bit)
2657 || const_ok_for_arm (~(mask << start_bit))))
2658 {
c5b3a71b 2659 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2660 emit_insn (gen_andsi3 (op2, operands[0], op0));
2661 }
2662 else
2663 {
2664 if (GET_CODE (op0) == CONST_INT)
2665 {
2666 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2667
215b30b3 2668 emit_insn (gen_movsi (tmp, op0));
2669 op0 = tmp;
2670 }
2671
2672 if (start_bit != 0)
2673 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2674
215b30b3 2675 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2676 }
8a18b90c 2677
215b30b3 2678 if (start_bit != 0)
2679 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2680
215b30b3 2681 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2682 }
f082f1c4 2683
215b30b3 2684 if (subtarget != target)
2685 {
2686 /* If TARGET is still a SUBREG, then it must be wider than a word,
2687 so we must be careful only to set the subword we were asked to. */
2688 if (GET_CODE (target) == SUBREG)
2689 emit_move_insn (target, subtarget);
2690 else
2691 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2692 }
8a18b90c 2693
215b30b3 2694 DONE;
2695 }"
2696)
8a18b90c 2697
8b054d5a 2698(define_insn "insv_zero"
2699 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2700 (match_operand:SI 1 "const_int_operand" "M")
2701 (match_operand:SI 2 "const_int_operand" "M"))
2702 (const_int 0))]
2703 "arm_arch_thumb2"
2704 "bfc%?\t%0, %2, %1"
2705 [(set_attr "length" "4")
2706 (set_attr "predicable" "yes")]
2707)
2708
2709(define_insn "insv_t2"
2710 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2711 (match_operand:SI 1 "const_int_operand" "M")
2712 (match_operand:SI 2 "const_int_operand" "M"))
2713 (match_operand:SI 3 "s_register_operand" "r"))]
2714 "arm_arch_thumb2"
2715 "bfi%?\t%0, %3, %2, %1"
2716 [(set_attr "length" "4")
2717 (set_attr "predicable" "yes")]
2718)
2719
215b30b3 2720; constants for op 2 will never be given to these patterns.
a0f94409 2721(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2722 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2723 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2724 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2725 "TARGET_32BIT"
f6ebffac 2726 "#"
e2669ea7 2727 "TARGET_32BIT && reload_completed
2728 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2729 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2730 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2731 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2732 "
2733 {
2734 operands[3] = gen_highpart (SImode, operands[0]);
2735 operands[0] = gen_lowpart (SImode, operands[0]);
2736 operands[4] = gen_highpart (SImode, operands[1]);
2737 operands[1] = gen_lowpart (SImode, operands[1]);
2738 operands[5] = gen_highpart (SImode, operands[2]);
2739 operands[2] = gen_lowpart (SImode, operands[2]);
2740 }"
0d66636f 2741 [(set_attr "length" "8")
2742 (set_attr "predicable" "yes")]
2743)
9c08d1fa 2744
a0f94409 2745(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2746 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2747 (and:DI (not:DI (zero_extend:DI
2748 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2749 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2750 "TARGET_32BIT"
e2348bcb 2751 "@
97499065 2752 bic%?\\t%Q0, %Q1, %2
f6ebffac 2753 #"
a0f94409 2754 ; (not (zero_extend ...)) allows us to just copy the high word from
2755 ; operand1 to operand0.
25f905c2 2756 "TARGET_32BIT
a0f94409 2757 && reload_completed
2758 && operands[0] != operands[1]"
5a097f7d 2759 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2760 (set (match_dup 3) (match_dup 4))]
2761 "
2762 {
2763 operands[3] = gen_highpart (SImode, operands[0]);
2764 operands[0] = gen_lowpart (SImode, operands[0]);
2765 operands[4] = gen_highpart (SImode, operands[1]);
2766 operands[1] = gen_lowpart (SImode, operands[1]);
2767 }"
0d66636f 2768 [(set_attr "length" "4,8")
2769 (set_attr "predicable" "yes")]
2770)
9c08d1fa 2771
a0f94409 2772(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2773 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2774 (and:DI (not:DI (sign_extend:DI
2775 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2776 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2777 "TARGET_32BIT"
f6ebffac 2778 "#"
25f905c2 2779 "TARGET_32BIT && reload_completed"
5a097f7d 2780 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2781 (set (match_dup 3) (and:SI (not:SI
2782 (ashiftrt:SI (match_dup 2) (const_int 31)))
2783 (match_dup 4)))]
2784 "
2785 {
2786 operands[3] = gen_highpart (SImode, operands[0]);
2787 operands[0] = gen_lowpart (SImode, operands[0]);
2788 operands[4] = gen_highpart (SImode, operands[1]);
2789 operands[1] = gen_lowpart (SImode, operands[1]);
2790 }"
0d66636f 2791 [(set_attr "length" "8")
2792 (set_attr "predicable" "yes")]
2793)
9c08d1fa 2794
8a18b90c 2795(define_insn "andsi_notsi_si"
9c08d1fa 2796 [(set (match_operand:SI 0 "s_register_operand" "=r")
2797 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2798 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2799 "TARGET_32BIT"
0d66636f 2800 "bic%?\\t%0, %1, %2"
2801 [(set_attr "predicable" "yes")]
2802)
b11cae9e 2803
747b7458 2804(define_insn "thumb1_bicsi3"
cffb2a26 2805 [(set (match_operand:SI 0 "register_operand" "=l")
2806 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2807 (match_operand:SI 2 "register_operand" "0")))]
25f905c2 2808 "TARGET_THUMB1"
747b7458 2809 "bic\\t%0, %1"
2810 [(set_attr "length" "2")
2811 (set_attr "conds" "set")])
cffb2a26 2812
8a18b90c 2813(define_insn "andsi_not_shiftsi_si"
a2cd141b 2814 [(set (match_operand:SI 0 "s_register_operand" "=r")
2815 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2816 [(match_operand:SI 2 "s_register_operand" "r")
2817 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2818 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2819 "TARGET_ARM"
6c4c2133 2820 "bic%?\\t%0, %1, %2%S4"
344495ea 2821 [(set_attr "predicable" "yes")
331beb1a 2822 (set_attr "shift" "2")
a2cd141b 2823 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2824 (const_string "alu_shift")
2825 (const_string "alu_shift_reg")))]
6c4c2133 2826)
8a18b90c 2827
f7fbdd4a 2828(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2829 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2830 (compare:CC_NOOV
2831 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2832 (match_operand:SI 1 "s_register_operand" "r"))
2833 (const_int 0)))
9c08d1fa 2834 (set (match_operand:SI 0 "s_register_operand" "=r")
2835 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2836 "TARGET_32BIT"
2837 "bic%.\\t%0, %1, %2"
0d66636f 2838 [(set_attr "conds" "set")]
2839)
9c08d1fa 2840
f7fbdd4a 2841(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2842 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2843 (compare:CC_NOOV
2844 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2845 (match_operand:SI 1 "s_register_operand" "r"))
2846 (const_int 0)))
9c08d1fa 2847 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2848 "TARGET_32BIT"
2849 "bic%.\\t%0, %1, %2"
0d66636f 2850 [(set_attr "conds" "set")]
2851)
9c08d1fa 2852
e2669ea7 2853(define_expand "iordi3"
2854 [(set (match_operand:DI 0 "s_register_operand" "")
2855 (ior:DI (match_operand:DI 1 "s_register_operand" "")
2856 (match_operand:DI 2 "neon_logic_op2" "")))]
2857 "TARGET_32BIT"
2858 ""
2859)
2860
2861(define_insn "*iordi3_insn"
cffb2a26 2862 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2863 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2864 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2865 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2866 "#"
0d66636f 2867 [(set_attr "length" "8")
2868 (set_attr "predicable" "yes")]
cffb2a26 2869)
9c08d1fa 2870
f7fbdd4a 2871(define_insn "*iordi_zesidi_di"
9c08d1fa 2872 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2873 (ior:DI (zero_extend:DI
2874 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2875 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2876 "TARGET_32BIT"
e2348bcb 2877 "@
97499065 2878 orr%?\\t%Q0, %Q1, %2
f6ebffac 2879 #"
0d66636f 2880 [(set_attr "length" "4,8")
2881 (set_attr "predicable" "yes")]
cffb2a26 2882)
9c08d1fa 2883
f7fbdd4a 2884(define_insn "*iordi_sesidi_di"
9c08d1fa 2885 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2886 (ior:DI (sign_extend:DI
2887 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2888 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2889 "TARGET_32BIT"
f6ebffac 2890 "#"
0d66636f 2891 [(set_attr "length" "8")
2892 (set_attr "predicable" "yes")]
cffb2a26 2893)
9c08d1fa 2894
87b22bf7 2895(define_expand "iorsi3"
cffb2a26 2896 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2897 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2898 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2899 "TARGET_EITHER"
87b22bf7 2900 "
2901 if (GET_CODE (operands[2]) == CONST_INT)
2902 {
25f905c2 2903 if (TARGET_32BIT)
cffb2a26 2904 {
96f57e36 2905 arm_split_constant (IOR, SImode, NULL_RTX,
2906 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 2907 optimize && can_create_pseudo_p ());
cffb2a26 2908 DONE;
2909 }
25f905c2 2910 else /* TARGET_THUMB1 */
923ffadb 2911 {
2912 rtx tmp = force_reg (SImode, operands[2]);
2913 if (rtx_equal_p (operands[0], operands[1]))
2914 operands[2] = tmp;
2915 else
2916 {
2917 operands[2] = operands[1];
2918 operands[1] = tmp;
2919 }
2920 }
87b22bf7 2921 }
cffb2a26 2922 "
2923)
87b22bf7 2924
d5d4dc8d 2925(define_insn_and_split "*iorsi3_insn"
2926 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2927 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
2928 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
2929 "TARGET_32BIT"
87b22bf7 2930 "@
2931 orr%?\\t%0, %1, %2
d5d4dc8d 2932 orn%?\\t%0, %1, #%B2
87b22bf7 2933 #"
d5d4dc8d 2934 "TARGET_32BIT
a0f94409 2935 && GET_CODE (operands[2]) == CONST_INT
d5d4dc8d 2936 && !(const_ok_for_arm (INTVAL (operands[2]))
2937 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 2938 [(clobber (const_int 0))]
d5d4dc8d 2939{
96f57e36 2940 arm_split_constant (IOR, SImode, curr_insn,
2941 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2942 DONE;
d5d4dc8d 2943}
2944 [(set_attr "length" "4,4,16")
2945 (set_attr "arch" "32,t2,32")
2946 (set_attr "predicable" "yes")])
cffb2a26 2947
747b7458 2948(define_insn "*thumb1_iorsi3_insn"
cffb2a26 2949 [(set (match_operand:SI 0 "register_operand" "=l")
2950 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2951 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2952 "TARGET_THUMB1"
747b7458 2953 "orr\\t%0, %2"
2954 [(set_attr "length" "2")
2955 (set_attr "conds" "set")])
9c08d1fa 2956
a0f94409 2957(define_peephole2
2958 [(match_scratch:SI 3 "r")
372575c7 2959 (set (match_operand:SI 0 "arm_general_register_operand" "")
2960 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2961 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 2962 "TARGET_ARM
a0f94409 2963 && !const_ok_for_arm (INTVAL (operands[2]))
2964 && const_ok_for_arm (~INTVAL (operands[2]))"
2965 [(set (match_dup 3) (match_dup 2))
2966 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2967 ""
215b30b3 2968)
a0f94409 2969
f7fbdd4a 2970(define_insn "*iorsi3_compare0"
bd5b4116 2971 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2972 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2973 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2974 (const_int 0)))
2975 (set (match_operand:SI 0 "s_register_operand" "=r")
2976 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 2977 "TARGET_32BIT"
2978 "orr%.\\t%0, %1, %2"
cffb2a26 2979 [(set_attr "conds" "set")]
2980)
9c08d1fa 2981
f7fbdd4a 2982(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2983 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2984 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2985 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2986 (const_int 0)))
2987 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2988 "TARGET_32BIT"
2989 "orr%.\\t%0, %1, %2"
0d66636f 2990 [(set_attr "conds" "set")]
2991)
9c08d1fa 2992
e2669ea7 2993(define_expand "xordi3"
2994 [(set (match_operand:DI 0 "s_register_operand" "")
2995 (xor:DI (match_operand:DI 1 "s_register_operand" "")
2996 (match_operand:DI 2 "s_register_operand" "")))]
2997 "TARGET_32BIT"
2998 ""
2999)
3000
3001(define_insn "*xordi3_insn"
cffb2a26 3002 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3003 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
3004 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 3005 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 3006 "#"
0d66636f 3007 [(set_attr "length" "8")
3008 (set_attr "predicable" "yes")]
cffb2a26 3009)
9c08d1fa 3010
f7fbdd4a 3011(define_insn "*xordi_zesidi_di"
9c08d1fa 3012 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3013 (xor:DI (zero_extend:DI
3014 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3015 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3016 "TARGET_32BIT"
e2348bcb 3017 "@
97499065 3018 eor%?\\t%Q0, %Q1, %2
f6ebffac 3019 #"
0d66636f 3020 [(set_attr "length" "4,8")
3021 (set_attr "predicable" "yes")]
cffb2a26 3022)
9c08d1fa 3023
f7fbdd4a 3024(define_insn "*xordi_sesidi_di"
9c08d1fa 3025 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3026 (xor:DI (sign_extend:DI
3027 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3028 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3029 "TARGET_32BIT"
f6ebffac 3030 "#"
0d66636f 3031 [(set_attr "length" "8")
3032 (set_attr "predicable" "yes")]
cffb2a26 3033)
9c08d1fa 3034
cffb2a26 3035(define_expand "xorsi3"
3036 [(set (match_operand:SI 0 "s_register_operand" "")
3037 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 3038 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3039 "TARGET_EITHER"
923ffadb 3040 "if (GET_CODE (operands[2]) == CONST_INT)
3041 {
3042 if (TARGET_32BIT)
3043 {
3044 arm_split_constant (XOR, SImode, NULL_RTX,
3045 INTVAL (operands[2]), operands[0], operands[1],
3046 optimize && can_create_pseudo_p ());
3047 DONE;
3048 }
3049 else /* TARGET_THUMB1 */
3050 {
3051 rtx tmp = force_reg (SImode, operands[2]);
3052 if (rtx_equal_p (operands[0], operands[1]))
3053 operands[2] = tmp;
3054 else
3055 {
3056 operands[2] = operands[1];
3057 operands[1] = tmp;
3058 }
3059 }
3060 }"
cffb2a26 3061)
3062
5dcb35d9 3063(define_insn_and_split "*arm_xorsi3"
3064 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3065 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3066 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
25f905c2 3067 "TARGET_32BIT"
5dcb35d9 3068 "@
3069 eor%?\\t%0, %1, %2
3070 #"
3071 "TARGET_32BIT
3072 && GET_CODE (operands[2]) == CONST_INT
3073 && !const_ok_for_arm (INTVAL (operands[2]))"
3074 [(clobber (const_int 0))]
3075{
3076 arm_split_constant (XOR, SImode, curr_insn,
3077 INTVAL (operands[2]), operands[0], operands[1], 0);
3078 DONE;
3079}
3080 [(set_attr "length" "4,16")
3081 (set_attr "predicable" "yes")]
cffb2a26 3082)
3083
747b7458 3084(define_insn "*thumb1_xorsi3_insn"
cffb2a26 3085 [(set (match_operand:SI 0 "register_operand" "=l")
3086 (xor:SI (match_operand:SI 1 "register_operand" "%0")
3087 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3088 "TARGET_THUMB1"
747b7458 3089 "eor\\t%0, %2"
3090 [(set_attr "length" "2")
3091 (set_attr "conds" "set")])
9c08d1fa 3092
f7fbdd4a 3093(define_insn "*xorsi3_compare0"
bd5b4116 3094 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3095 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
3096 (match_operand:SI 2 "arm_rhs_operand" "rI"))
3097 (const_int 0)))
3098 (set (match_operand:SI 0 "s_register_operand" "=r")
3099 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 3100 "TARGET_32BIT"
3101 "eor%.\\t%0, %1, %2"
0d66636f 3102 [(set_attr "conds" "set")]
3103)
9c08d1fa 3104
f7fbdd4a 3105(define_insn "*xorsi3_compare0_scratch"
bd5b4116 3106 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3107 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
3108 (match_operand:SI 1 "arm_rhs_operand" "rI"))
3109 (const_int 0)))]
25f905c2 3110 "TARGET_32BIT"
40dbec34 3111 "teq%?\\t%0, %1"
cffb2a26 3112 [(set_attr "conds" "set")]
3113)
9c08d1fa 3114
215b30b3 3115; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3116; (NOT D) we can sometimes merge the final NOT into one of the following
3117; insns.
9c08d1fa 3118
3119(define_split
a058e94a 3120 [(set (match_operand:SI 0 "s_register_operand" "")
3121 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3122 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3123 (match_operand:SI 3 "arm_rhs_operand" "")))
3124 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 3125 "TARGET_32BIT"
9c08d1fa 3126 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3127 (not:SI (match_dup 3))))
3128 (set (match_dup 0) (not:SI (match_dup 4)))]
3129 ""
3130)
3131
f7fbdd4a 3132(define_insn "*andsi_iorsi3_notsi"
9c08d1fa 3133 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 3134 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 3135 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3136 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 3137 "TARGET_32BIT"
40dbec34 3138 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
0d66636f 3139 [(set_attr "length" "8")
25f905c2 3140 (set_attr "ce_count" "2")
0d66636f 3141 (set_attr "predicable" "yes")]
cffb2a26 3142)
9c08d1fa 3143
25f905c2 3144; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3145; insns are available?
d7863cfe 3146(define_split
3147 [(set (match_operand:SI 0 "s_register_operand" "")
3148 (match_operator:SI 1 "logical_binary_operator"
3149 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3150 (match_operand:SI 3 "const_int_operand" "")
3151 (match_operand:SI 4 "const_int_operand" ""))
3152 (match_operator:SI 9 "logical_binary_operator"
3153 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3154 (match_operand:SI 6 "const_int_operand" ""))
3155 (match_operand:SI 7 "s_register_operand" "")])]))
3156 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3157 "TARGET_32BIT
d7863cfe 3158 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3159 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3160 [(set (match_dup 8)
3161 (match_op_dup 1
3162 [(ashift:SI (match_dup 2) (match_dup 4))
3163 (match_dup 5)]))
3164 (set (match_dup 0)
3165 (match_op_dup 1
3166 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3167 (match_dup 7)]))]
3168 "
3169 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3170")
3171
3172(define_split
3173 [(set (match_operand:SI 0 "s_register_operand" "")
3174 (match_operator:SI 1 "logical_binary_operator"
3175 [(match_operator:SI 9 "logical_binary_operator"
3176 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3177 (match_operand:SI 6 "const_int_operand" ""))
3178 (match_operand:SI 7 "s_register_operand" "")])
3179 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3180 (match_operand:SI 3 "const_int_operand" "")
3181 (match_operand:SI 4 "const_int_operand" ""))]))
3182 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3183 "TARGET_32BIT
d7863cfe 3184 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3185 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3186 [(set (match_dup 8)
3187 (match_op_dup 1
3188 [(ashift:SI (match_dup 2) (match_dup 4))
3189 (match_dup 5)]))
3190 (set (match_dup 0)
3191 (match_op_dup 1
3192 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3193 (match_dup 7)]))]
3194 "
3195 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3196")
3197
3198(define_split
3199 [(set (match_operand:SI 0 "s_register_operand" "")
3200 (match_operator:SI 1 "logical_binary_operator"
3201 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3202 (match_operand:SI 3 "const_int_operand" "")
3203 (match_operand:SI 4 "const_int_operand" ""))
3204 (match_operator:SI 9 "logical_binary_operator"
3205 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3206 (match_operand:SI 6 "const_int_operand" ""))
3207 (match_operand:SI 7 "s_register_operand" "")])]))
3208 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3209 "TARGET_32BIT
d7863cfe 3210 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3211 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3212 [(set (match_dup 8)
3213 (match_op_dup 1
3214 [(ashift:SI (match_dup 2) (match_dup 4))
3215 (match_dup 5)]))
3216 (set (match_dup 0)
3217 (match_op_dup 1
3218 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3219 (match_dup 7)]))]
3220 "
3221 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3222")
3223
3224(define_split
3225 [(set (match_operand:SI 0 "s_register_operand" "")
3226 (match_operator:SI 1 "logical_binary_operator"
3227 [(match_operator:SI 9 "logical_binary_operator"
3228 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3229 (match_operand:SI 6 "const_int_operand" ""))
3230 (match_operand:SI 7 "s_register_operand" "")])
3231 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3232 (match_operand:SI 3 "const_int_operand" "")
3233 (match_operand:SI 4 "const_int_operand" ""))]))
3234 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3235 "TARGET_32BIT
d7863cfe 3236 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3237 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3238 [(set (match_dup 8)
3239 (match_op_dup 1
3240 [(ashift:SI (match_dup 2) (match_dup 4))
3241 (match_dup 5)]))
3242 (set (match_dup 0)
3243 (match_op_dup 1
3244 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3245 (match_dup 7)]))]
3246 "
3247 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3248")
9c08d1fa 3249\f
3250
3251;; Minimum and maximum insns
3252
8b9dc177 3253(define_expand "smaxsi3"
3254 [(parallel [
3255 (set (match_operand:SI 0 "s_register_operand" "")
3256 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3257 (match_operand:SI 2 "arm_rhs_operand" "")))
3258 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3259 "TARGET_32BIT"
8b9dc177 3260 "
8774928b 3261 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3262 {
3263 /* No need for a clobber of the condition code register here. */
3264 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3265 gen_rtx_SMAX (SImode, operands[1],
3266 operands[2])));
3267 DONE;
3268 }
3269")
3270
3271(define_insn "*smax_0"
3272 [(set (match_operand:SI 0 "s_register_operand" "=r")
3273 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3274 (const_int 0)))]
25f905c2 3275 "TARGET_32BIT"
8b9dc177 3276 "bic%?\\t%0, %1, %1, asr #31"
3277 [(set_attr "predicable" "yes")]
3278)
3279
8774928b 3280(define_insn "*smax_m1"
3281 [(set (match_operand:SI 0 "s_register_operand" "=r")
3282 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3283 (const_int -1)))]
25f905c2 3284 "TARGET_32BIT"
8774928b 3285 "orr%?\\t%0, %1, %1, asr #31"
3286 [(set_attr "predicable" "yes")]
3287)
3288
25f905c2 3289(define_insn "*arm_smax_insn"
8b9dc177 3290 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3291 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3292 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3293 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3294 "TARGET_ARM"
e2348bcb 3295 "@
3296 cmp\\t%1, %2\;movlt\\t%0, %2
e2348bcb 3297 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
cffb2a26 3298 [(set_attr "conds" "clob")
8b9dc177 3299 (set_attr "length" "8,12")]
cffb2a26 3300)
9c08d1fa 3301
8b9dc177 3302(define_expand "sminsi3"
3303 [(parallel [
3304 (set (match_operand:SI 0 "s_register_operand" "")
3305 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3306 (match_operand:SI 2 "arm_rhs_operand" "")))
3307 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3308 "TARGET_32BIT"
8b9dc177 3309 "
3310 if (operands[2] == const0_rtx)
3311 {
3312 /* No need for a clobber of the condition code register here. */
3313 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3314 gen_rtx_SMIN (SImode, operands[1],
3315 operands[2])));
3316 DONE;
3317 }
3318")
3319
3320(define_insn "*smin_0"
3321 [(set (match_operand:SI 0 "s_register_operand" "=r")
3322 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3323 (const_int 0)))]
25f905c2 3324 "TARGET_32BIT"
8b9dc177 3325 "and%?\\t%0, %1, %1, asr #31"
3326 [(set_attr "predicable" "yes")]
3327)
3328
25f905c2 3329(define_insn "*arm_smin_insn"
8b9dc177 3330 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3331 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3332 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3333 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3334 "TARGET_ARM"
e2348bcb 3335 "@
3336 cmp\\t%1, %2\;movge\\t%0, %2
e2348bcb 3337 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
0d66636f 3338 [(set_attr "conds" "clob")
8b9dc177 3339 (set_attr "length" "8,12")]
0d66636f 3340)
9c08d1fa 3341
25f905c2 3342(define_expand "umaxsi3"
3343 [(parallel [
3344 (set (match_operand:SI 0 "s_register_operand" "")
3345 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3346 (match_operand:SI 2 "arm_rhs_operand" "")))
3347 (clobber (reg:CC CC_REGNUM))])]
3348 "TARGET_32BIT"
3349 ""
3350)
3351
3352(define_insn "*arm_umaxsi3"
9c08d1fa 3353 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3354 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3355 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3356 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3357 "TARGET_ARM"
e2348bcb 3358 "@
3359 cmp\\t%1, %2\;movcc\\t%0, %2
3360 cmp\\t%1, %2\;movcs\\t%0, %1
3361 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
0d66636f 3362 [(set_attr "conds" "clob")
3363 (set_attr "length" "8,8,12")]
3364)
9c08d1fa 3365
25f905c2 3366(define_expand "uminsi3"
3367 [(parallel [
3368 (set (match_operand:SI 0 "s_register_operand" "")
3369 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3370 (match_operand:SI 2 "arm_rhs_operand" "")))
3371 (clobber (reg:CC CC_REGNUM))])]
3372 "TARGET_32BIT"
3373 ""
3374)
3375
3376(define_insn "*arm_uminsi3"
9c08d1fa 3377 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3378 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3379 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3380 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3381 "TARGET_ARM"
e2348bcb 3382 "@
3383 cmp\\t%1, %2\;movcs\\t%0, %2
3384 cmp\\t%1, %2\;movcc\\t%0, %1
3385 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
0d66636f 3386 [(set_attr "conds" "clob")
3387 (set_attr "length" "8,8,12")]
3388)
9c08d1fa 3389
8a18b90c 3390(define_insn "*store_minmaxsi"
9c08d1fa 3391 [(set (match_operand:SI 0 "memory_operand" "=m")
3392 (match_operator:SI 3 "minmax_operator"
3393 [(match_operand:SI 1 "s_register_operand" "r")
3394 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3395 (clobber (reg:CC CC_REGNUM))]
25f905c2 3396 "TARGET_32BIT"
9c08d1fa 3397 "*
dc55b8a9 3398 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3399 operands[1], operands[2]);
e2348bcb 3400 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3401 if (TARGET_THUMB2)
3402 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3403 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3404 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3405 return \"\";
0d66636f 3406 "
3407 [(set_attr "conds" "clob")
25f905c2 3408 (set (attr "length")
3409 (if_then_else (eq_attr "is_thumb" "yes")
3410 (const_int 14)
3411 (const_int 12)))
0d66636f 3412 (set_attr "type" "store1")]
3413)
9c08d1fa 3414
8a18b90c 3415; Reject the frame pointer in operand[1], since reloading this after
3416; it has been eliminated can cause carnage.
f7fbdd4a 3417(define_insn "*minmax_arithsi"
9c08d1fa 3418 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3419 (match_operator:SI 4 "shiftable_operator"
3420 [(match_operator:SI 5 "minmax_operator"
3421 [(match_operand:SI 2 "s_register_operand" "r,r")
3422 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3423 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3424 (clobber (reg:CC CC_REGNUM))]
25f905c2 3425 "TARGET_32BIT && !arm_eliminable_register (operands[1])"
9c08d1fa 3426 "*
0d66636f 3427 {
3428 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3429 bool need_else;
3430
3431 if (which_alternative != 0 || operands[3] != const0_rtx
ca0fc5a2 3432 || (code != PLUS && code != IOR && code != XOR))
25f905c2 3433 need_else = true;
3434 else
3435 need_else = false;
0d66636f 3436
dc55b8a9 3437 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3438 operands[2], operands[3]);
0d66636f 3439 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3440 if (TARGET_THUMB2)
3441 {
3442 if (need_else)
3443 output_asm_insn (\"ite\\t%d5\", operands);
3444 else
3445 output_asm_insn (\"it\\t%d5\", operands);
3446 }
0d66636f 3447 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3448 if (need_else)
0d66636f 3449 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3450 return \"\";
215b30b3 3451 }"
0d66636f 3452 [(set_attr "conds" "clob")
25f905c2 3453 (set (attr "length")
3454 (if_then_else (eq_attr "is_thumb" "yes")
3455 (const_int 14)
3456 (const_int 12)))]
0d66636f 3457)
9c08d1fa 3458
b49e3742 3459(define_code_iterator SAT [smin smax])
3460(define_code_iterator SATrev [smin smax])
3461(define_code_attr SATlo [(smin "1") (smax "2")])
3462(define_code_attr SAThi [(smin "2") (smax "1")])
3463
3464(define_insn "*satsi_<SAT:code>"
3465 [(set (match_operand:SI 0 "s_register_operand" "=r")
3466 (SAT:SI (SATrev:SI (match_operand:SI 3 "s_register_operand" "r")
3467 (match_operand:SI 1 "const_int_operand" "i"))
3468 (match_operand:SI 2 "const_int_operand" "i")))]
3469 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3470 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3471{
3472 int mask;
3473 bool signed_sat;
3474 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3475 &mask, &signed_sat))
3476 gcc_unreachable ();
3477
3478 operands[1] = GEN_INT (mask);
3479 if (signed_sat)
3480 return "ssat%?\t%0, %1, %3";
3481 else
3482 return "usat%?\t%0, %1, %3";
3483}
3484 [(set_attr "predicable" "yes")
3485 (set_attr "insn" "sat")])
3486
3487(define_insn "*satsi_<SAT:code>_shift"
3488 [(set (match_operand:SI 0 "s_register_operand" "=r")
3489 (SAT:SI (SATrev:SI (match_operator:SI 3 "sat_shift_operator"
3490 [(match_operand:SI 4 "s_register_operand" "r")
3491 (match_operand:SI 5 "const_int_operand" "i")])
3492 (match_operand:SI 1 "const_int_operand" "i"))
3493 (match_operand:SI 2 "const_int_operand" "i")))]
3494 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3495 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3496{
3497 int mask;
3498 bool signed_sat;
3499 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3500 &mask, &signed_sat))
3501 gcc_unreachable ();
3502
3503 operands[1] = GEN_INT (mask);
3504 if (signed_sat)
3505 return "ssat%?\t%0, %1, %4%S3";
3506 else
3507 return "usat%?\t%0, %1, %4%S3";
3508}
3509 [(set_attr "predicable" "yes")
3510 (set_attr "insn" "sat")
3511 (set_attr "shift" "3")
3512 (set_attr "type" "alu_shift")])
b11cae9e 3513\f
3514;; Shift and rotation insns
3515
a2cd141b 3516(define_expand "ashldi3"
3517 [(set (match_operand:DI 0 "s_register_operand" "")
3518 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
3519 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3520 "TARGET_32BIT"
a2cd141b 3521 "
3522 if (GET_CODE (operands[2]) == CONST_INT)
3523 {
3524 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3525 {
3526 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3527 DONE;
3528 }
3529 /* Ideally we shouldn't fail here if we could know that operands[1]
3530 ends up already living in an iwmmxt register. Otherwise it's
3531 cheaper to have the alternate code being generated than moving
1d60d981 3532 values to iwmmxt regs and back. */
a2cd141b 3533 FAIL;
3534 }
3535 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
3536 FAIL;
3537 "
3538)
3539
3540(define_insn "arm_ashldi3_1bit"
50ad1bf9 3541 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3542 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3543 (const_int 1)))
3544 (clobber (reg:CC CC_REGNUM))]
25f905c2 3545 "TARGET_32BIT"
a2cd141b 3546 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3547 [(set_attr "conds" "clob")
3548 (set_attr "length" "8")]
3549)
3550
87b22bf7 3551(define_expand "ashlsi3"
cffb2a26 3552 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3553 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3554 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3555 "TARGET_EITHER"
87b22bf7 3556 "
3557 if (GET_CODE (operands[2]) == CONST_INT
3558 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3559 {
3560 emit_insn (gen_movsi (operands[0], const0_rtx));
3561 DONE;
3562 }
cffb2a26 3563 "
3564)
3565
25f905c2 3566(define_insn "*thumb1_ashlsi3"
cffb2a26 3567 [(set (match_operand:SI 0 "register_operand" "=l,l")
3568 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3569 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3570 "TARGET_THUMB1"
cffb2a26 3571 "lsl\\t%0, %1, %2"
747b7458 3572 [(set_attr "length" "2")
3573 (set_attr "conds" "set")])
b11cae9e 3574
a2cd141b 3575(define_expand "ashrdi3"
3576 [(set (match_operand:DI 0 "s_register_operand" "")
3577 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3578 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3579 "TARGET_32BIT"
a2cd141b 3580 "
3581 if (GET_CODE (operands[2]) == CONST_INT)
3582 {
3583 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3584 {
3585 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3586 DONE;
3587 }
3588 /* Ideally we shouldn't fail here if we could know that operands[1]
3589 ends up already living in an iwmmxt register. Otherwise it's
3590 cheaper to have the alternate code being generated than moving
1d60d981 3591 values to iwmmxt regs and back. */
a2cd141b 3592 FAIL;
3593 }
3594 else if (!TARGET_REALLY_IWMMXT)
3595 FAIL;
3596 "
3597)
3598
3599(define_insn "arm_ashrdi3_1bit"
50ad1bf9 3600 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3601 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3602 (const_int 1)))
3603 (clobber (reg:CC CC_REGNUM))]
25f905c2 3604 "TARGET_32BIT"
a2cd141b 3605 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3606 [(set_attr "conds" "clob")
d2a518d1 3607 (set_attr "insn" "mov")
a2cd141b 3608 (set_attr "length" "8")]
3609)
3610
87b22bf7 3611(define_expand "ashrsi3"
cffb2a26 3612 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3613 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3614 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3615 "TARGET_EITHER"
87b22bf7 3616 "
3617 if (GET_CODE (operands[2]) == CONST_INT
3618 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3619 operands[2] = GEN_INT (31);
cffb2a26 3620 "
3621)
3622
25f905c2 3623(define_insn "*thumb1_ashrsi3"
cffb2a26 3624 [(set (match_operand:SI 0 "register_operand" "=l,l")
3625 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3626 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3627 "TARGET_THUMB1"
cffb2a26 3628 "asr\\t%0, %1, %2"
747b7458 3629 [(set_attr "length" "2")
3630 (set_attr "conds" "set")])
b11cae9e 3631
a2cd141b 3632(define_expand "lshrdi3"
3633 [(set (match_operand:DI 0 "s_register_operand" "")
3634 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3635 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3636 "TARGET_32BIT"
a2cd141b 3637 "
3638 if (GET_CODE (operands[2]) == CONST_INT)
3639 {
3640 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3641 {
3642 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3643 DONE;
3644 }
3645 /* Ideally we shouldn't fail here if we could know that operands[1]
3646 ends up already living in an iwmmxt register. Otherwise it's
3647 cheaper to have the alternate code being generated than moving
1d60d981 3648 values to iwmmxt regs and back. */
a2cd141b 3649 FAIL;
3650 }
3651 else if (!TARGET_REALLY_IWMMXT)
3652 FAIL;
3653 "
3654)
3655
3656(define_insn "arm_lshrdi3_1bit"
50ad1bf9 3657 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3658 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3659 (const_int 1)))
3660 (clobber (reg:CC CC_REGNUM))]
25f905c2 3661 "TARGET_32BIT"
a2cd141b 3662 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3663 [(set_attr "conds" "clob")
d2a518d1 3664 (set_attr "insn" "mov")
a2cd141b 3665 (set_attr "length" "8")]
3666)
3667
87b22bf7 3668(define_expand "lshrsi3"
cffb2a26 3669 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3670 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3671 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3672 "TARGET_EITHER"
87b22bf7 3673 "
3674 if (GET_CODE (operands[2]) == CONST_INT
3675 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3676 {
3677 emit_insn (gen_movsi (operands[0], const0_rtx));
3678 DONE;
3679 }
cffb2a26 3680 "
3681)
3682
25f905c2 3683(define_insn "*thumb1_lshrsi3"
cffb2a26 3684 [(set (match_operand:SI 0 "register_operand" "=l,l")
3685 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3686 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3687 "TARGET_THUMB1"
cffb2a26 3688 "lsr\\t%0, %1, %2"
747b7458 3689 [(set_attr "length" "2")
3690 (set_attr "conds" "set")])
b11cae9e 3691
87b22bf7 3692(define_expand "rotlsi3"
cffb2a26 3693 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3694 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3695 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3696 "TARGET_32BIT"
87b22bf7 3697 "
3698 if (GET_CODE (operands[2]) == CONST_INT)
3699 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3700 else
b11cae9e 3701 {
87b22bf7 3702 rtx reg = gen_reg_rtx (SImode);
3703 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3704 operands[2] = reg;
b11cae9e 3705 }
cffb2a26 3706 "
3707)
9c08d1fa 3708
87b22bf7 3709(define_expand "rotrsi3"
cffb2a26 3710 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3711 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3712 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3713 "TARGET_EITHER"
87b22bf7 3714 "
25f905c2 3715 if (TARGET_32BIT)
cffb2a26 3716 {
3717 if (GET_CODE (operands[2]) == CONST_INT
3718 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3719 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3720 }
25f905c2 3721 else /* TARGET_THUMB1 */
cffb2a26 3722 {
3723 if (GET_CODE (operands [2]) == CONST_INT)
3724 operands [2] = force_reg (SImode, operands[2]);
3725 }
3726 "
3727)
87b22bf7 3728
25f905c2 3729(define_insn "*thumb1_rotrsi3"
cffb2a26 3730 [(set (match_operand:SI 0 "register_operand" "=l")
3731 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3732 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3733 "TARGET_THUMB1"
cffb2a26 3734 "ror\\t%0, %0, %2"
3735 [(set_attr "length" "2")]
3736)
3737
3738(define_insn "*arm_shiftsi3"
3739 [(set (match_operand:SI 0 "s_register_operand" "=r")
3740 (match_operator:SI 3 "shift_operator"
3741 [(match_operand:SI 1 "s_register_operand" "r")
87b22bf7 3742 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
25f905c2 3743 "TARGET_32BIT"
3744 "* return arm_output_shift(operands, 0);"
344495ea 3745 [(set_attr "predicable" "yes")
331beb1a 3746 (set_attr "shift" "1")
a2cd141b 3747 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3748 (const_string "alu_shift")
3749 (const_string "alu_shift_reg")))]
6c4c2133 3750)
87b22bf7 3751
f7fbdd4a 3752(define_insn "*shiftsi3_compare0"
bd5b4116 3753 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3754 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3755 [(match_operand:SI 1 "s_register_operand" "r")
3756 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3757 (const_int 0)))
3758 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3759 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3760 "TARGET_32BIT"
3761 "* return arm_output_shift(operands, 1);"
344495ea 3762 [(set_attr "conds" "set")
331beb1a 3763 (set_attr "shift" "1")
a2cd141b 3764 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3765 (const_string "alu_shift")
3766 (const_string "alu_shift_reg")))]
0d66636f 3767)
9c08d1fa 3768
f7fbdd4a 3769(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3770 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3771 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3772 [(match_operand:SI 1 "s_register_operand" "r")
3773 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3774 (const_int 0)))
3775 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3776 "TARGET_32BIT"
3777 "* return arm_output_shift(operands, 1);"
344495ea 3778 [(set_attr "conds" "set")
a2cd141b 3779 (set_attr "shift" "1")]
0d66636f 3780)
9c08d1fa 3781
d5d4dc8d 3782(define_insn "*not_shiftsi"
3783 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3784 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 3785 [(match_operand:SI 1 "s_register_operand" "r,r")
3786 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3787 "TARGET_32BIT"
6c4c2133 3788 "mvn%?\\t%0, %1%S3"
344495ea 3789 [(set_attr "predicable" "yes")
331beb1a 3790 (set_attr "shift" "1")
d2a518d1 3791 (set_attr "insn" "mvn")
d5d4dc8d 3792 (set_attr "arch" "32,a")
3793 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3794
d5d4dc8d 3795(define_insn "*not_shiftsi_compare0"
bd5b4116 3796 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3797 (compare:CC_NOOV
3798 (not:SI (match_operator:SI 3 "shift_operator"
3799 [(match_operand:SI 1 "s_register_operand" "r,r")
3800 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3801 (const_int 0)))
3802 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3803 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 3804 "TARGET_32BIT"
25f905c2 3805 "mvn%.\\t%0, %1%S3"
344495ea 3806 [(set_attr "conds" "set")
331beb1a 3807 (set_attr "shift" "1")
d2a518d1 3808 (set_attr "insn" "mvn")
d5d4dc8d 3809 (set_attr "arch" "32,a")
3810 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3811
d5d4dc8d 3812(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 3813 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3814 (compare:CC_NOOV
3815 (not:SI (match_operator:SI 3 "shift_operator"
3816 [(match_operand:SI 1 "s_register_operand" "r,r")
3817 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3818 (const_int 0)))
3819 (clobber (match_scratch:SI 0 "=r,r"))]
3820 "TARGET_32BIT"
25f905c2 3821 "mvn%.\\t%0, %1%S3"
344495ea 3822 [(set_attr "conds" "set")
331beb1a 3823 (set_attr "shift" "1")
d2a518d1 3824 (set_attr "insn" "mvn")
d5d4dc8d 3825 (set_attr "arch" "32,a")
3826 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3827
cffb2a26 3828;; We don't really have extzv, but defining this using shifts helps
3829;; to reduce register pressure later on.
3830
3831(define_expand "extzv"
eb04cafb 3832 [(set (match_operand 0 "s_register_operand" "")
3833 (zero_extract (match_operand 1 "nonimmediate_operand" "")
3834 (match_operand 2 "const_int_operand" "")
3835 (match_operand 3 "const_int_operand" "")))]
8b054d5a 3836 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 3837 "
3838 {
3839 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3840 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3841
8b054d5a 3842 if (arm_arch_thumb2)
3843 {
eb04cafb 3844 HOST_WIDE_INT width = INTVAL (operands[2]);
3845 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
3846
3847 if (unaligned_access && MEM_P (operands[1])
3848 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
3849 {
3850 rtx base_addr;
3851
3852 if (BYTES_BIG_ENDIAN)
3853 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
3854 - bitpos;
3855
3856 if (width == 32)
3857 {
3858 base_addr = adjust_address (operands[1], SImode,
3859 bitpos / BITS_PER_UNIT);
3860 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
3861 }
3862 else
3863 {
3864 rtx dest = operands[0];
3865 rtx tmp = gen_reg_rtx (SImode);
3866
3867 /* We may get a paradoxical subreg here. Strip it off. */
3868 if (GET_CODE (dest) == SUBREG
3869 && GET_MODE (dest) == SImode
3870 && GET_MODE (SUBREG_REG (dest)) == HImode)
3871 dest = SUBREG_REG (dest);
3872
3873 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
3874 FAIL;
3875
3876 base_addr = adjust_address (operands[1], HImode,
3877 bitpos / BITS_PER_UNIT);
3878 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
3879 emit_move_insn (gen_lowpart (SImode, dest), tmp);
3880 }
3881 DONE;
3882 }
3883 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
3884 {
3885 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3886 operands[3]));
3887 DONE;
3888 }
3889 else
3890 FAIL;
8b054d5a 3891 }
eb04cafb 3892
3893 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
3894 FAIL;
8b054d5a 3895
cffb2a26 3896 operands[3] = GEN_INT (rshift);
3897
3898 if (lshift == 0)
3899 {
3900 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3901 DONE;
3902 }
3903
eb04cafb 3904 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
3905 operands[3], gen_reg_rtx (SImode)));
3906 DONE;
215b30b3 3907 }"
cffb2a26 3908)
3909
eb04cafb 3910;; Helper for extzv, for the Thumb-1 register-shifts case.
3911
3912(define_expand "extzv_t1"
3913 [(set (match_operand:SI 4 "s_register_operand" "")
3914 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
3915 (match_operand:SI 2 "const_int_operand" "")))
3916 (set (match_operand:SI 0 "s_register_operand" "")
3917 (lshiftrt:SI (match_dup 4)
3918 (match_operand:SI 3 "const_int_operand" "")))]
3919 "TARGET_THUMB1"
3920 "")
3921
3922(define_expand "extv"
3923 [(set (match_operand 0 "s_register_operand" "")
3924 (sign_extract (match_operand 1 "nonimmediate_operand" "")
3925 (match_operand 2 "const_int_operand" "")
3926 (match_operand 3 "const_int_operand" "")))]
3927 "arm_arch_thumb2"
3928{
3929 HOST_WIDE_INT width = INTVAL (operands[2]);
3930 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
3931
3932 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
3933 && (bitpos % BITS_PER_UNIT) == 0)
3934 {
3935 rtx base_addr;
3936
3937 if (BYTES_BIG_ENDIAN)
3938 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
3939
3940 if (width == 32)
3941 {
3942 base_addr = adjust_address (operands[1], SImode,
3943 bitpos / BITS_PER_UNIT);
3944 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
3945 }
3946 else
3947 {
3948 rtx dest = operands[0];
3949 rtx tmp = gen_reg_rtx (SImode);
3950
3951 /* We may get a paradoxical subreg here. Strip it off. */
3952 if (GET_CODE (dest) == SUBREG
3953 && GET_MODE (dest) == SImode
3954 && GET_MODE (SUBREG_REG (dest)) == HImode)
3955 dest = SUBREG_REG (dest);
3956
3957 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
3958 FAIL;
3959
3960 base_addr = adjust_address (operands[1], HImode,
3961 bitpos / BITS_PER_UNIT);
3962 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
3963 emit_move_insn (gen_lowpart (SImode, dest), tmp);
3964 }
3965
3966 DONE;
3967 }
3968 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
3969 FAIL;
3970 else if (GET_MODE (operands[0]) == SImode
3971 && GET_MODE (operands[1]) == SImode)
3972 {
3973 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
3974 operands[3]));
3975 DONE;
3976 }
3977
3978 FAIL;
3979})
3980
3981; Helper to expand register forms of extv with the proper modes.
3982
3983(define_expand "extv_regsi"
3984 [(set (match_operand:SI 0 "s_register_operand" "")
3985 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
3986 (match_operand 2 "const_int_operand" "")
3987 (match_operand 3 "const_int_operand" "")))]
3988 ""
3989{
3990})
3991
3992; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
3993
3994(define_insn "unaligned_loadsi"
3995 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
3996 (unspec:SI [(match_operand:SI 1 "memory_operand" "Uw,m")]
3997 UNSPEC_UNALIGNED_LOAD))]
3998 "unaligned_access && TARGET_32BIT"
3999 "ldr%?\t%0, %1\t@ unaligned"
4000 [(set_attr "arch" "t2,any")
4001 (set_attr "length" "2,4")
4002 (set_attr "predicable" "yes")
4003 (set_attr "type" "load1")])
4004
4005(define_insn "unaligned_loadhis"
4006 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4007 (sign_extend:SI
4008 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4009 UNSPEC_UNALIGNED_LOAD)))]
4010 "unaligned_access && TARGET_32BIT"
4011 "ldr%(sh%)\t%0, %1\t@ unaligned"
4012 [(set_attr "arch" "t2,any")
4013 (set_attr "length" "2,4")
4014 (set_attr "predicable" "yes")
4015 (set_attr "type" "load_byte")])
4016
4017(define_insn "unaligned_loadhiu"
4018 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4019 (zero_extend:SI
4020 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4021 UNSPEC_UNALIGNED_LOAD)))]
4022 "unaligned_access && TARGET_32BIT"
4023 "ldr%(h%)\t%0, %1\t@ unaligned"
4024 [(set_attr "arch" "t2,any")
4025 (set_attr "length" "2,4")
4026 (set_attr "predicable" "yes")
4027 (set_attr "type" "load_byte")])
4028
4029(define_insn "unaligned_storesi"
4030 [(set (match_operand:SI 0 "memory_operand" "=Uw,m")
4031 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,r")]
4032 UNSPEC_UNALIGNED_STORE))]
4033 "unaligned_access && TARGET_32BIT"
4034 "str%?\t%1, %0\t@ unaligned"
4035 [(set_attr "arch" "t2,any")
4036 (set_attr "length" "2,4")
4037 (set_attr "predicable" "yes")
4038 (set_attr "type" "store1")])
4039
4040(define_insn "unaligned_storehi"
4041 [(set (match_operand:HI 0 "memory_operand" "=Uw,m")
4042 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
4043 UNSPEC_UNALIGNED_STORE))]
4044 "unaligned_access && TARGET_32BIT"
4045 "str%(h%)\t%1, %0\t@ unaligned"
4046 [(set_attr "arch" "t2,any")
4047 (set_attr "length" "2,4")
4048 (set_attr "predicable" "yes")
4049 (set_attr "type" "store1")])
4050
4051(define_insn "*extv_reg"
8b054d5a 4052 [(set (match_operand:SI 0 "s_register_operand" "=r")
4053 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
4054 (match_operand:SI 2 "const_int_operand" "M")
4055 (match_operand:SI 3 "const_int_operand" "M")))]
4056 "arm_arch_thumb2"
4057 "sbfx%?\t%0, %1, %3, %2"
4058 [(set_attr "length" "4")
4059 (set_attr "predicable" "yes")]
4060)
4061
4062(define_insn "extzv_t2"
4063 [(set (match_operand:SI 0 "s_register_operand" "=r")
4064 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
4065 (match_operand:SI 2 "const_int_operand" "M")
4066 (match_operand:SI 3 "const_int_operand" "M")))]
4067 "arm_arch_thumb2"
4068 "ubfx%?\t%0, %1, %3, %2"
4069 [(set_attr "length" "4")
4070 (set_attr "predicable" "yes")]
4071)
4072
7d3cda8c 4073
4074;; Division instructions
4075(define_insn "divsi3"
4076 [(set (match_operand:SI 0 "s_register_operand" "=r")
4077 (div:SI (match_operand:SI 1 "s_register_operand" "r")
4078 (match_operand:SI 2 "s_register_operand" "r")))]
4079 "TARGET_IDIV"
4080 "sdiv%?\t%0, %1, %2"
4081 [(set_attr "predicable" "yes")
4082 (set_attr "insn" "sdiv")]
4083)
4084
4085(define_insn "udivsi3"
4086 [(set (match_operand:SI 0 "s_register_operand" "=r")
4087 (udiv:SI (match_operand:SI 1 "s_register_operand" "r")
4088 (match_operand:SI 2 "s_register_operand" "r")))]
4089 "TARGET_IDIV"
4090 "udiv%?\t%0, %1, %2"
4091 [(set_attr "predicable" "yes")
4092 (set_attr "insn" "udiv")]
4093)
4094
b11cae9e 4095\f
4096;; Unary arithmetic insns
4097
cffb2a26 4098(define_expand "negdi2"
4099 [(parallel
8135a42b 4100 [(set (match_operand:DI 0 "s_register_operand" "")
4101 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 4102 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 4103 "TARGET_EITHER"
774d2fbb 4104 {
4105 if (TARGET_NEON)
4106 {
4107 emit_insn (gen_negdi2_neon (operands[0], operands[1]));
4108 DONE;
4109 }
4110 }
cffb2a26 4111)
4112
4113;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 4114;; The first alternative allows the common case of a *full* overlap.
cffb2a26 4115(define_insn "*arm_negdi2"
458a8706 4116 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4117 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 4118 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4119 "TARGET_ARM"
97499065 4120 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
cffb2a26 4121 [(set_attr "conds" "clob")
4122 (set_attr "length" "8")]
4123)
b11cae9e 4124
25f905c2 4125(define_insn "*thumb1_negdi2"
8135a42b 4126 [(set (match_operand:DI 0 "register_operand" "=&l")
4127 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 4128 (clobber (reg:CC CC_REGNUM))]
25f905c2 4129 "TARGET_THUMB1"
cffb2a26 4130 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
4131 [(set_attr "length" "6")]
4132)
4133
4134(define_expand "negsi2"
4135 [(set (match_operand:SI 0 "s_register_operand" "")
4136 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
4137 "TARGET_EITHER"
b11cae9e 4138 ""
cffb2a26 4139)
4140
4141(define_insn "*arm_negsi2"
4142 [(set (match_operand:SI 0 "s_register_operand" "=r")
4143 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 4144 "TARGET_32BIT"
cffb2a26 4145 "rsb%?\\t%0, %1, #0"
0d66636f 4146 [(set_attr "predicable" "yes")]
cffb2a26 4147)
4148
25f905c2 4149(define_insn "*thumb1_negsi2"
cffb2a26 4150 [(set (match_operand:SI 0 "register_operand" "=l")
4151 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 4152 "TARGET_THUMB1"
cffb2a26 4153 "neg\\t%0, %1"
4154 [(set_attr "length" "2")]
4155)
b11cae9e 4156
604f3a0a 4157(define_expand "negsf2"
4158 [(set (match_operand:SF 0 "s_register_operand" "")
4159 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 4160 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 4161 ""
4162)
4163
4164(define_expand "negdf2"
4165 [(set (match_operand:DF 0 "s_register_operand" "")
4166 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4167 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
604f3a0a 4168 "")
4169
9c08d1fa 4170;; abssi2 doesn't really clobber the condition codes if a different register
4171;; is being set. To keep things simple, assume during rtl manipulations that
4172;; it does, but tell the final scan operator the truth. Similarly for
4173;; (neg (abs...))
4174
604f3a0a 4175(define_expand "abssi2"
4176 [(parallel
4177 [(set (match_operand:SI 0 "s_register_operand" "")
4178 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 4179 (clobber (match_dup 2))])]
4180 "TARGET_EITHER"
4181 "
25f905c2 4182 if (TARGET_THUMB1)
ba156559 4183 operands[2] = gen_rtx_SCRATCH (SImode);
4184 else
4185 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4186")
604f3a0a 4187
7d57ec45 4188(define_insn "*arm_abssi2"
ba156559 4189 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 4190 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 4191 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4192 "TARGET_ARM"
e2348bcb 4193 "@
4194 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
40dbec34 4195 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
cffb2a26 4196 [(set_attr "conds" "clob,*")
331beb1a 4197 (set_attr "shift" "1")
0d66636f 4198 ;; predicable can't be set based on the variant, so left as no
cffb2a26 4199 (set_attr "length" "8")]
4200)
9c08d1fa 4201
25f905c2 4202(define_insn_and_split "*thumb1_abssi2"
ba156559 4203 [(set (match_operand:SI 0 "s_register_operand" "=l")
4204 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
4205 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 4206 "TARGET_THUMB1"
ba156559 4207 "#"
25f905c2 4208 "TARGET_THUMB1 && reload_completed"
ba156559 4209 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
4210 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
4211 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
4212 ""
4213 [(set_attr "length" "6")]
4214)
4215
4216(define_insn "*arm_neg_abssi2"
9c08d1fa 4217 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4218 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 4219 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4220 "TARGET_ARM"
e2348bcb 4221 "@
4222 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
40dbec34 4223 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
cffb2a26 4224 [(set_attr "conds" "clob,*")
331beb1a 4225 (set_attr "shift" "1")
0d66636f 4226 ;; predicable can't be set based on the variant, so left as no
cffb2a26 4227 (set_attr "length" "8")]
4228)
b11cae9e 4229
25f905c2 4230(define_insn_and_split "*thumb1_neg_abssi2"
ba156559 4231 [(set (match_operand:SI 0 "s_register_operand" "=l")
4232 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
4233 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 4234 "TARGET_THUMB1"
ba156559 4235 "#"
25f905c2 4236 "TARGET_THUMB1 && reload_completed"
ba156559 4237 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
4238 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
4239 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
4240 ""
4241 [(set_attr "length" "6")]
4242)
4243
604f3a0a 4244(define_expand "abssf2"
4245 [(set (match_operand:SF 0 "s_register_operand" "")
4246 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 4247 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4248 "")
4249
604f3a0a 4250(define_expand "absdf2"
4251 [(set (match_operand:DF 0 "s_register_operand" "")
4252 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4253 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4254 "")
4255
7db9af5d 4256(define_expand "sqrtsf2"
4257 [(set (match_operand:SF 0 "s_register_operand" "")
4258 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 4259 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 4260 "")
9c08d1fa 4261
7db9af5d 4262(define_expand "sqrtdf2"
4263 [(set (match_operand:DF 0 "s_register_operand" "")
4264 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4265 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7db9af5d 4266 "")
9c08d1fa 4267
a0f94409 4268(define_insn_and_split "one_cmpldi2"
10efb95f 4269 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,?w")
4270 (not:DI (match_operand:DI 1 "s_register_operand" " w, 0, r, w")))]
25f905c2 4271 "TARGET_32BIT"
10efb95f 4272 "@
4273 vmvn\t%P0, %P1
4274 #
4275 #
4276 vmvn\t%P0, %P1"
4277 "TARGET_32BIT && reload_completed
4278 && arm_general_register_operand (operands[0], DImode)"
a0f94409 4279 [(set (match_dup 0) (not:SI (match_dup 1)))
4280 (set (match_dup 2) (not:SI (match_dup 3)))]
4281 "
4282 {
4283 operands[2] = gen_highpart (SImode, operands[0]);
4284 operands[0] = gen_lowpart (SImode, operands[0]);
4285 operands[3] = gen_highpart (SImode, operands[1]);
4286 operands[1] = gen_lowpart (SImode, operands[1]);
4287 }"
10efb95f 4288 [(set_attr "length" "*,8,8,*")
4289 (set_attr "predicable" "no,yes,yes,no")
4290 (set_attr "neon_type" "neon_int_1,*,*,neon_int_1")
4291 (set_attr "arch" "neon_nota8,*,*,neon_onlya8")]
cffb2a26 4292)
b11cae9e 4293
cffb2a26 4294(define_expand "one_cmplsi2"
4295 [(set (match_operand:SI 0 "s_register_operand" "")
4296 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
4297 "TARGET_EITHER"
b11cae9e 4298 ""
cffb2a26 4299)
4300
4301(define_insn "*arm_one_cmplsi2"
4302 [(set (match_operand:SI 0 "s_register_operand" "=r")
4303 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 4304 "TARGET_32BIT"
cffb2a26 4305 "mvn%?\\t%0, %1"
d2a518d1 4306 [(set_attr "predicable" "yes")
4307 (set_attr "insn" "mvn")]
cffb2a26 4308)
4309
25f905c2 4310(define_insn "*thumb1_one_cmplsi2"
cffb2a26 4311 [(set (match_operand:SI 0 "register_operand" "=l")
4312 (not:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 4313 "TARGET_THUMB1"
cffb2a26 4314 "mvn\\t%0, %1"
d2a518d1 4315 [(set_attr "length" "2")
4316 (set_attr "insn" "mvn")]
cffb2a26 4317)
9c08d1fa 4318
f7fbdd4a 4319(define_insn "*notsi_compare0"
bd5b4116 4320 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4321 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4322 (const_int 0)))
4323 (set (match_operand:SI 0 "s_register_operand" "=r")
4324 (not:SI (match_dup 1)))]
25f905c2 4325 "TARGET_32BIT"
4326 "mvn%.\\t%0, %1"
d2a518d1 4327 [(set_attr "conds" "set")
4328 (set_attr "insn" "mvn")]
cffb2a26 4329)
9c08d1fa 4330
f7fbdd4a 4331(define_insn "*notsi_compare0_scratch"
bd5b4116 4332 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4333 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4334 (const_int 0)))
4335 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 4336 "TARGET_32BIT"
4337 "mvn%.\\t%0, %1"
d2a518d1 4338 [(set_attr "conds" "set")
4339 (set_attr "insn" "mvn")]
cffb2a26 4340)
b11cae9e 4341\f
4342;; Fixed <--> Floating conversion insns
4343
9b8516be 4344(define_expand "floatsihf2"
4345 [(set (match_operand:HF 0 "general_operand" "")
4346 (float:HF (match_operand:SI 1 "general_operand" "")))]
4347 "TARGET_EITHER"
4348 "
4349 {
4350 rtx op1 = gen_reg_rtx (SFmode);
4351 expand_float (op1, operands[1], 0);
4352 op1 = convert_to_mode (HFmode, op1, 0);
4353 emit_move_insn (operands[0], op1);
4354 DONE;
4355 }"
4356)
4357
4358(define_expand "floatdihf2"
4359 [(set (match_operand:HF 0 "general_operand" "")
4360 (float:HF (match_operand:DI 1 "general_operand" "")))]
4361 "TARGET_EITHER"
4362 "
4363 {
4364 rtx op1 = gen_reg_rtx (SFmode);
4365 expand_float (op1, operands[1], 0);
4366 op1 = convert_to_mode (HFmode, op1, 0);
4367 emit_move_insn (operands[0], op1);
4368 DONE;
4369 }"
4370)
4371
604f3a0a 4372(define_expand "floatsisf2"
4373 [(set (match_operand:SF 0 "s_register_operand" "")
4374 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 4375 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4376 "
a2cd141b 4377 if (TARGET_MAVERICK)
604f3a0a 4378 {
4379 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
4380 DONE;
4381 }
4382")
4383
604f3a0a 4384(define_expand "floatsidf2"
4385 [(set (match_operand:DF 0 "s_register_operand" "")
4386 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 4387 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4388 "
a2cd141b 4389 if (TARGET_MAVERICK)
604f3a0a 4390 {
4391 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
4392 DONE;
4393 }
4394")
4395
9b8516be 4396(define_expand "fix_trunchfsi2"
4397 [(set (match_operand:SI 0 "general_operand" "")
4398 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4399 "TARGET_EITHER"
4400 "
4401 {
4402 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4403 expand_fix (operands[0], op1, 0);
4404 DONE;
4405 }"
4406)
4407
4408(define_expand "fix_trunchfdi2"
4409 [(set (match_operand:DI 0 "general_operand" "")
4410 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4411 "TARGET_EITHER"
4412 "
4413 {
4414 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4415 expand_fix (operands[0], op1, 0);
4416 DONE;
4417 }"
4418)
4419
604f3a0a 4420(define_expand "fix_truncsfsi2"
4421 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4422 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 4423 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4424 "
a2cd141b 4425 if (TARGET_MAVERICK)
604f3a0a 4426 {
4427 if (!cirrus_fp_register (operands[0], SImode))
4428 operands[0] = force_reg (SImode, operands[0]);
4429 if (!cirrus_fp_register (operands[1], SFmode))
4430 operands[1] = force_reg (SFmode, operands[0]);
4431 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
4432 DONE;
4433 }
4434")
4435
604f3a0a 4436(define_expand "fix_truncdfsi2"
4437 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4438 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 4439 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4440 "
a2cd141b 4441 if (TARGET_MAVERICK)
604f3a0a 4442 {
4443 if (!cirrus_fp_register (operands[1], DFmode))
4444 operands[1] = force_reg (DFmode, operands[0]);
4445 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
4446 DONE;
4447 }
4448")
4449
f544c6d2 4450;; Truncation insns
b11cae9e 4451
604f3a0a 4452(define_expand "truncdfsf2"
4453 [(set (match_operand:SF 0 "s_register_operand" "")
4454 (float_truncate:SF
4455 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4456 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4457 ""
4458)
9b8516be 4459
4460/* DFmode -> HFmode conversions have to go through SFmode. */
4461(define_expand "truncdfhf2"
4462 [(set (match_operand:HF 0 "general_operand" "")
4463 (float_truncate:HF
4464 (match_operand:DF 1 "general_operand" "")))]
4465 "TARGET_EITHER"
4466 "
4467 {
4468 rtx op1;
4469 op1 = convert_to_mode (SFmode, operands[1], 0);
4470 op1 = convert_to_mode (HFmode, op1, 0);
4471 emit_move_insn (operands[0], op1);
4472 DONE;
4473 }"
4474)
b11cae9e 4475\f
9c08d1fa 4476;; Zero and sign extension instructions.
b11cae9e 4477
848e66ac 4478(define_insn "zero_extend<mode>di2"
4479 [(set (match_operand:DI 0 "s_register_operand" "=r")
6d97728e 4480 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
4481 "<qhs_zextenddi_cstr>")))]
848e66ac 4482 "TARGET_32BIT <qhs_zextenddi_cond>"
4483 "#"
4484 [(set_attr "length" "8")
4485 (set_attr "ce_count" "2")
4486 (set_attr "predicable" "yes")]
25f905c2 4487)
4488
848e66ac 4489(define_insn "extend<mode>di2"
9c08d1fa 4490 [(set (match_operand:DI 0 "s_register_operand" "=r")
63d204a8 4491 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4492 "<qhs_extenddi_cstr>")))]
848e66ac 4493 "TARGET_32BIT <qhs_sextenddi_cond>"
4494 "#"
0d66636f 4495 [(set_attr "length" "8")
848e66ac 4496 (set_attr "ce_count" "2")
4497 (set_attr "shift" "1")
0d66636f 4498 (set_attr "predicable" "yes")]
4499)
9c08d1fa 4500
848e66ac 4501;; Splits for all extensions to DImode
4502(define_split
4503 [(set (match_operand:DI 0 "s_register_operand" "")
4504 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
25f905c2 4505 "TARGET_32BIT"
848e66ac 4506 [(set (match_dup 0) (match_dup 1))]
4507{
848e66ac 4508 rtx lo_part = gen_lowpart (SImode, operands[0]);
4509 enum machine_mode src_mode = GET_MODE (operands[1]);
4510
4511 if (REG_P (operands[0])
4512 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4513 emit_clobber (operands[0]);
4514 if (!REG_P (lo_part) || src_mode != SImode
4515 || !rtx_equal_p (lo_part, operands[1]))
4516 {
4517 if (src_mode == SImode)
4518 emit_move_insn (lo_part, operands[1]);
4519 else
4520 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4521 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4522 operands[1] = lo_part;
4523 }
4524 operands[0] = gen_highpart (SImode, operands[0]);
4525 operands[1] = const0_rtx;
4526})
9c08d1fa 4527
848e66ac 4528(define_split
25f905c2 4529 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 4530 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
25f905c2 4531 "TARGET_32BIT"
848e66ac 4532 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4533{
4534 rtx lo_part = gen_lowpart (SImode, operands[0]);
4535 enum machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 4536
848e66ac 4537 if (REG_P (operands[0])
4538 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4539 emit_clobber (operands[0]);
4540
4541 if (!REG_P (lo_part) || src_mode != SImode
4542 || !rtx_equal_p (lo_part, operands[1]))
4543 {
4544 if (src_mode == SImode)
4545 emit_move_insn (lo_part, operands[1]);
4546 else
4547 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4548 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4549 operands[1] = lo_part;
4550 }
4551 operands[0] = gen_highpart (SImode, operands[0]);
4552})
9c08d1fa 4553
4554(define_expand "zero_extendhisi2"
ef51b8e1 4555 [(set (match_operand:SI 0 "s_register_operand" "")
4556 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4557 "TARGET_EITHER"
ef51b8e1 4558{
4559 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 4560 {
ef51b8e1 4561 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4562 DONE;
25f7a26e 4563 }
ef51b8e1 4564 if (!arm_arch6 && !MEM_P (operands[1]))
4565 {
4566 rtx t = gen_lowpart (SImode, operands[1]);
4567 rtx tmp = gen_reg_rtx (SImode);
4568 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4569 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4570 DONE;
4571 }
4572})
9c08d1fa 4573
ef51b8e1 4574(define_split
b146458f 4575 [(set (match_operand:SI 0 "s_register_operand" "")
4576 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 4577 "!TARGET_THUMB2 && !arm_arch6"
4578 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4579 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4580{
4581 operands[2] = gen_lowpart (SImode, operands[1]);
4582})
4583
4584(define_insn "*thumb1_zero_extendhisi2"
a2cd141b 4585 [(set (match_operand:SI 0 "register_operand" "=l,l")
4586 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
ef51b8e1 4587 "TARGET_THUMB1"
848e66ac 4588{
a2cd141b 4589 rtx mem;
4590
ef51b8e1 4591 if (which_alternative == 0 && arm_arch6)
848e66ac 4592 return "uxth\t%0, %1";
ef51b8e1 4593 if (which_alternative == 0)
848e66ac 4594 return "#";
a2cd141b 4595
4596 mem = XEXP (operands[1], 0);
4597
4598 if (GET_CODE (mem) == CONST)
4599 mem = XEXP (mem, 0);
4600
a2cd141b 4601 if (GET_CODE (mem) == PLUS)
4602 {
4603 rtx a = XEXP (mem, 0);
a2cd141b 4604
4605 /* This can happen due to bugs in reload. */
4606 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4607 {
4608 rtx ops[2];
4609 ops[0] = operands[0];
4610 ops[1] = a;
4611
848e66ac 4612 output_asm_insn ("mov\t%0, %1", ops);
a2cd141b 4613
4614 XEXP (mem, 0) = operands[0];
4615 }
a2cd141b 4616 }
4617
848e66ac 4618 return "ldrh\t%0, %1";
4619}
ef51b8e1 4620 [(set_attr_alternative "length"
4621 [(if_then_else (eq_attr "is_arch6" "yes")
4622 (const_int 2) (const_int 4))
4623 (const_int 4)])
848e66ac 4624 (set_attr "type" "alu_shift,load_byte")]
a2cd141b 4625)
4626
cffb2a26 4627(define_insn "*arm_zero_extendhisi2"
ef51b8e1 4628 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4629 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4630 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4631 "@
4632 #
4633 ldr%(h%)\\t%0, %1"
4634 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4635 (set_attr "predicable" "yes")]
cffb2a26 4636)
f7fbdd4a 4637
a2cd141b 4638(define_insn "*arm_zero_extendhisi2_v6"
4639 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4640 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4641 "TARGET_ARM && arm_arch6"
4642 "@
4643 uxth%?\\t%0, %1
25f905c2 4644 ldr%(h%)\\t%0, %1"
a2cd141b 4645 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4646 (set_attr "predicable" "yes")]
a2cd141b 4647)
4648
4649(define_insn "*arm_zero_extendhisi2addsi"
4650 [(set (match_operand:SI 0 "s_register_operand" "=r")
4651 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4652 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4653 "TARGET_INT_SIMD"
a2cd141b 4654 "uxtah%?\\t%0, %2, %1"
4655 [(set_attr "type" "alu_shift")
4656 (set_attr "predicable" "yes")]
4657)
4658
87b22bf7 4659(define_expand "zero_extendqisi2"
cffb2a26 4660 [(set (match_operand:SI 0 "s_register_operand" "")
4661 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4662 "TARGET_EITHER"
ef51b8e1 4663{
4664 if (TARGET_ARM && !arm_arch6 && GET_CODE (operands[1]) != MEM)
87b22bf7 4665 {
ef51b8e1 4666 emit_insn (gen_andsi3 (operands[0],
4667 gen_lowpart (SImode, operands[1]),
4668 GEN_INT (255)));
4669 DONE;
4670 }
4671 if (!arm_arch6 && !MEM_P (operands[1]))
4672 {
4673 rtx t = gen_lowpart (SImode, operands[1]);
4674 rtx tmp = gen_reg_rtx (SImode);
4675 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4676 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
4677 DONE;
4678 }
4679})
cffb2a26 4680
ef51b8e1 4681(define_split
b146458f 4682 [(set (match_operand:SI 0 "s_register_operand" "")
4683 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 4684 "!arm_arch6"
4685 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4686 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
4687{
4688 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4689 if (TARGET_ARM)
4690 {
4691 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 4692 DONE;
4693 }
ef51b8e1 4694})
9c08d1fa 4695
25f905c2 4696(define_insn "*thumb1_zero_extendqisi2"
ef51b8e1 4697 [(set (match_operand:SI 0 "register_operand" "=l,l")
4698 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4699 "TARGET_THUMB1 && !arm_arch6"
ef51b8e1 4700 "@
4701 #
4702 ldrb\\t%0, %1"
4703 [(set_attr "length" "4,2")
4704 (set_attr "type" "alu_shift,load_byte")
4705 (set_attr "pool_range" "*,32")]
cffb2a26 4706)
4707
25f905c2 4708(define_insn "*thumb1_zero_extendqisi2_v6"
a2cd141b 4709 [(set (match_operand:SI 0 "register_operand" "=l,l")
4710 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4711 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4712 "@
4713 uxtb\\t%0, %1
4714 ldrb\\t%0, %1"
848e66ac 4715 [(set_attr "length" "2")
4716 (set_attr "type" "alu_shift,load_byte")]
a2cd141b 4717)
4718
cffb2a26 4719(define_insn "*arm_zero_extendqisi2"
ef51b8e1 4720 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4721 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4722 "TARGET_ARM && !arm_arch6"
ef51b8e1 4723 "@
4724 #
4725 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4726 [(set_attr "length" "8,4")
4727 (set_attr "type" "alu_shift,load_byte")
848e66ac 4728 (set_attr "predicable" "yes")]
cffb2a26 4729)
87b22bf7 4730
a2cd141b 4731(define_insn "*arm_zero_extendqisi2_v6"
4732 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4733 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4734 "TARGET_ARM && arm_arch6"
4735 "@
25f905c2 4736 uxtb%(%)\\t%0, %1
4737 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 4738 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4739 (set_attr "predicable" "yes")]
a2cd141b 4740)
4741
4742(define_insn "*arm_zero_extendqisi2addsi"
4743 [(set (match_operand:SI 0 "s_register_operand" "=r")
4744 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4745 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4746 "TARGET_INT_SIMD"
a2cd141b 4747 "uxtab%?\\t%0, %2, %1"
4748 [(set_attr "predicable" "yes")
bcaec148 4749 (set_attr "insn" "xtab")
a2cd141b 4750 (set_attr "type" "alu_shift")]
4751)
4752
87b22bf7 4753(define_split
4754 [(set (match_operand:SI 0 "s_register_operand" "")
4755 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4756 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4757 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
87b22bf7 4758 [(set (match_dup 2) (match_dup 1))
4759 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 4760 ""
4761)
9c08d1fa 4762
8a4d25d6 4763(define_split
4764 [(set (match_operand:SI 0 "s_register_operand" "")
4765 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4766 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4767 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
8a4d25d6 4768 [(set (match_dup 2) (match_dup 1))
4769 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4770 ""
4771)
4772
1c274529 4773
4774(define_split
4775 [(set (match_operand:SI 0 "s_register_operand" "")
4776 (ior_xor:SI (and:SI (ashift:SI
4777 (match_operand:SI 1 "s_register_operand" "")
4778 (match_operand:SI 2 "const_int_operand" ""))
4779 (match_operand:SI 3 "const_int_operand" ""))
4780 (zero_extend:SI
4781 (match_operator 5 "subreg_lowpart_operator"
4782 [(match_operand:SI 4 "s_register_operand" "")]))))]
4783 "TARGET_32BIT
63787642 4784 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
1c274529 4785 == (GET_MODE_MASK (GET_MODE (operands[5]))
4786 & (GET_MODE_MASK (GET_MODE (operands[5]))
4787 << (INTVAL (operands[2])))))"
4788 [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
4789 (match_dup 4)))
4790 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4791 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4792)
4793
f7fbdd4a 4794(define_insn "*compareqi_eq0"
bd5b4116 4795 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 4796 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 4797 (const_int 0)))]
25f905c2 4798 "TARGET_32BIT"
596e5e8f 4799 "tst%?\\t%0, #255"
4800 [(set_attr "conds" "set")
4801 (set_attr "predicable" "yes")]
cffb2a26 4802)
b11cae9e 4803
b11cae9e 4804(define_expand "extendhisi2"
ef51b8e1 4805 [(set (match_operand:SI 0 "s_register_operand" "")
4806 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4807 "TARGET_EITHER"
ef51b8e1 4808{
4809 if (TARGET_THUMB1)
4810 {
4811 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4812 DONE;
4813 }
4814 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
4815 {
4816 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4817 DONE;
4818 }
ed29c566 4819
ef51b8e1 4820 if (!arm_arch6 && !MEM_P (operands[1]))
4821 {
4822 rtx t = gen_lowpart (SImode, operands[1]);
4823 rtx tmp = gen_reg_rtx (SImode);
4824 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4825 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
4826 DONE;
4827 }
4828})
cffb2a26 4829
ef51b8e1 4830(define_split
4831 [(parallel
4832 [(set (match_operand:SI 0 "register_operand" "")
4833 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
4834 (clobber (match_scratch:SI 2 ""))])]
4835 "!arm_arch6"
4836 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4837 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4838{
4839 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4840})
25f7a26e 4841
a2cd141b 4842;; We used to have an early-clobber on the scratch register here.
4843;; However, there's a bug somewhere in reload which means that this
4844;; can be partially ignored during spill allocation if the memory
ed29c566 4845;; address also needs reloading; this causes us to die later on when
a2cd141b 4846;; we try to verify the operands. Fortunately, we don't really need
4847;; the early-clobber: we can always use operand 0 if operand 2
4848;; overlaps the address.
ef51b8e1 4849(define_insn "thumb1_extendhisi2"
a2cd141b 4850 [(set (match_operand:SI 0 "register_operand" "=l,l")
4851 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4852 (clobber (match_scratch:SI 2 "=X,l"))]
ef51b8e1 4853 "TARGET_THUMB1"
a2cd141b 4854 "*
4855 {
4856 rtx ops[4];
4857 rtx mem;
4858
ef51b8e1 4859 if (which_alternative == 0 && !arm_arch6)
4860 return \"#\";
a2cd141b 4861 if (which_alternative == 0)
4862 return \"sxth\\t%0, %1\";
4863
4864 mem = XEXP (operands[1], 0);
4865
4866 /* This code used to try to use 'V', and fix the address only if it was
4867 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4868 range of QImode offsets, and offsettable_address_p does a QImode
4869 address check. */
4870
4871 if (GET_CODE (mem) == CONST)
4872 mem = XEXP (mem, 0);
4873
4874 if (GET_CODE (mem) == LABEL_REF)
4875 return \"ldr\\t%0, %1\";
4876
4877 if (GET_CODE (mem) == PLUS)
4878 {
4879 rtx a = XEXP (mem, 0);
4880 rtx b = XEXP (mem, 1);
4881
4882 if (GET_CODE (a) == LABEL_REF
4883 && GET_CODE (b) == CONST_INT)
4884 return \"ldr\\t%0, %1\";
4885
4886 if (GET_CODE (b) == REG)
4887 return \"ldrsh\\t%0, %1\";
4888
4889 ops[1] = a;
4890 ops[2] = b;
4891 }
4892 else
4893 {
4894 ops[1] = mem;
4895 ops[2] = const0_rtx;
4896 }
4897
ed29c566 4898 gcc_assert (GET_CODE (ops[1]) == REG);
a2cd141b 4899
4900 ops[0] = operands[0];
4901 if (reg_mentioned_p (operands[2], ops[1]))
4902 ops[3] = ops[0];
4903 else
4904 ops[3] = operands[2];
4905 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4906 return \"\";
4907 }"
ef51b8e1 4908 [(set_attr_alternative "length"
4909 [(if_then_else (eq_attr "is_arch6" "yes")
4910 (const_int 2) (const_int 4))
4911 (const_int 4)])
a2cd141b 4912 (set_attr "type" "alu_shift,load_byte")
4913 (set_attr "pool_range" "*,1020")]
4914)
4915
25f905c2 4916;; This pattern will only be used when ldsh is not available
25f7a26e 4917(define_expand "extendhisi2_mem"
eab14235 4918 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4919 (set (match_dup 3)
eab14235 4920 (zero_extend:SI (match_dup 7)))
25f7a26e 4921 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4922 (set (match_operand:SI 0 "" "")
4923 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 4924 "TARGET_ARM"
25f7a26e 4925 "
215b30b3 4926 {
4927 rtx mem1, mem2;
4928 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4929
788fcce0 4930 mem1 = change_address (operands[1], QImode, addr);
4931 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 4932 operands[0] = gen_lowpart (SImode, operands[0]);
4933 operands[1] = mem1;
4934 operands[2] = gen_reg_rtx (SImode);
4935 operands[3] = gen_reg_rtx (SImode);
4936 operands[6] = gen_reg_rtx (SImode);
4937 operands[7] = mem2;
25f7a26e 4938
215b30b3 4939 if (BYTES_BIG_ENDIAN)
4940 {
4941 operands[4] = operands[2];
4942 operands[5] = operands[3];
4943 }
4944 else
4945 {
4946 operands[4] = operands[3];
4947 operands[5] = operands[2];
4948 }
4949 }"
4950)
b11cae9e 4951
ef51b8e1 4952(define_split
4953 [(set (match_operand:SI 0 "register_operand" "")
4954 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
4955 "!arm_arch6"
4956 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4957 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4958{
4959 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4960})
4961
a2cd141b 4962(define_insn "*arm_extendhisi2"
ef51b8e1 4963 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4964 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4965 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4966 "@
4967 #
4968 ldr%(sh%)\\t%0, %1"
4969 [(set_attr "length" "8,4")
4970 (set_attr "type" "alu_shift,load_byte")
0d66636f 4971 (set_attr "predicable" "yes")
ef51b8e1 4972 (set_attr "pool_range" "*,256")
4973 (set_attr "neg_pool_range" "*,244")]
cffb2a26 4974)
f7fbdd4a 4975
25f905c2 4976;; ??? Check Thumb-2 pool range
a2cd141b 4977(define_insn "*arm_extendhisi2_v6"
4978 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4979 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
25f905c2 4980 "TARGET_32BIT && arm_arch6"
a2cd141b 4981 "@
4982 sxth%?\\t%0, %1
25f905c2 4983 ldr%(sh%)\\t%0, %1"
a2cd141b 4984 [(set_attr "type" "alu_shift,load_byte")
4985 (set_attr "predicable" "yes")
4986 (set_attr "pool_range" "*,256")
4987 (set_attr "neg_pool_range" "*,244")]
4988)
4989
4990(define_insn "*arm_extendhisi2addsi"
4991 [(set (match_operand:SI 0 "s_register_operand" "=r")
4992 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4993 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4994 "TARGET_INT_SIMD"
a2cd141b 4995 "sxtah%?\\t%0, %2, %1"
4996)
4997
c8f69309 4998(define_expand "extendqihi2"
4999 [(set (match_dup 2)
bed7d9a5 5000 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 5001 (const_int 24)))
9c08d1fa 5002 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 5003 (ashiftrt:SI (match_dup 2)
5004 (const_int 24)))]
cffb2a26 5005 "TARGET_ARM"
c8f69309 5006 "
215b30b3 5007 {
5008 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
5009 {
5010 emit_insn (gen_rtx_SET (VOIDmode,
5011 operands[0],
5012 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
5013 DONE;
5014 }
5015 if (!s_register_operand (operands[1], QImode))
5016 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5017 operands[0] = gen_lowpart (SImode, operands[0]);
5018 operands[1] = gen_lowpart (SImode, operands[1]);
5019 operands[2] = gen_reg_rtx (SImode);
5020 }"
5021)
f7fbdd4a 5022
25f905c2 5023(define_insn "*arm_extendqihi_insn"
b4e8a300 5024 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 5025 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 5026 "TARGET_ARM && arm_arch4"
25f905c2 5027 "ldr%(sb%)\\t%0, %1"
a2cd141b 5028 [(set_attr "type" "load_byte")
0d66636f 5029 (set_attr "predicable" "yes")
cffb2a26 5030 (set_attr "pool_range" "256")
5031 (set_attr "neg_pool_range" "244")]
5032)
3fc2009e 5033
b11cae9e 5034(define_expand "extendqisi2"
ef51b8e1 5035 [(set (match_operand:SI 0 "s_register_operand" "")
5036 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 5037 "TARGET_EITHER"
ef51b8e1 5038{
5039 if (!arm_arch4 && MEM_P (operands[1]))
5040 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 5041
ef51b8e1 5042 if (!arm_arch6 && !MEM_P (operands[1]))
5043 {
5044 rtx t = gen_lowpart (SImode, operands[1]);
5045 rtx tmp = gen_reg_rtx (SImode);
5046 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5047 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
5048 DONE;
5049 }
5050})
a2cd141b 5051
ef51b8e1 5052(define_split
5053 [(set (match_operand:SI 0 "register_operand" "")
5054 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5055 "!arm_arch6"
5056 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5057 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5058{
5059 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5060})
f7fbdd4a 5061
a2cd141b 5062(define_insn "*arm_extendqisi"
ef51b8e1 5063 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5064 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5065 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 5066 "@
5067 #
5068 ldr%(sb%)\\t%0, %1"
5069 [(set_attr "length" "8,4")
5070 (set_attr "type" "alu_shift,load_byte")
0d66636f 5071 (set_attr "predicable" "yes")
ef51b8e1 5072 (set_attr "pool_range" "*,256")
5073 (set_attr "neg_pool_range" "*,244")]
cffb2a26 5074)
3fc2009e 5075
a2cd141b 5076(define_insn "*arm_extendqisi_v6"
5077 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 5078 (sign_extend:SI
5079 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 5080 "TARGET_ARM && arm_arch6"
b4e8a300 5081 "@
5082 sxtb%?\\t%0, %1
25f905c2 5083 ldr%(sb%)\\t%0, %1"
a2cd141b 5084 [(set_attr "type" "alu_shift,load_byte")
5085 (set_attr "predicable" "yes")
a2cd141b 5086 (set_attr "pool_range" "*,256")
5087 (set_attr "neg_pool_range" "*,244")]
5088)
5089
5090(define_insn "*arm_extendqisi2addsi"
5091 [(set (match_operand:SI 0 "s_register_operand" "=r")
5092 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5093 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5094 "TARGET_INT_SIMD"
a2cd141b 5095 "sxtab%?\\t%0, %2, %1"
5096 [(set_attr "type" "alu_shift")
bcaec148 5097 (set_attr "insn" "xtab")
a2cd141b 5098 (set_attr "predicable" "yes")]
5099)
5100
ef51b8e1 5101(define_split
5102 [(set (match_operand:SI 0 "register_operand" "")
5103 (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))]
5104 "TARGET_THUMB1 && reload_completed"
5105 [(set (match_dup 0) (match_dup 2))
5106 (set (match_dup 0) (sign_extend:SI (match_dup 3)))]
5107{
5108 rtx addr = XEXP (operands[1], 0);
cffb2a26 5109
ef51b8e1 5110 if (GET_CODE (addr) == CONST)
5111 addr = XEXP (addr, 0);
cffb2a26 5112
ef51b8e1 5113 if (GET_CODE (addr) == PLUS
5114 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
5115 /* No split necessary. */
5116 FAIL;
5117
5118 if (GET_CODE (addr) == PLUS
5119 && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1)))
5120 FAIL;
5121
5122 if (reg_overlap_mentioned_p (operands[0], addr))
5123 {
5124 rtx t = gen_lowpart (QImode, operands[0]);
5125 emit_move_insn (t, operands[1]);
5126 emit_insn (gen_thumb1_extendqisi2 (operands[0], t));
5127 DONE;
5128 }
5129
5130 if (REG_P (addr))
5131 {
5132 addr = gen_rtx_PLUS (Pmode, addr, operands[0]);
5133 operands[2] = const0_rtx;
5134 }
5135 else if (GET_CODE (addr) != PLUS)
5136 FAIL;
5137 else if (REG_P (XEXP (addr, 0)))
5138 {
5139 operands[2] = XEXP (addr, 1);
5140 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]);
5141 }
5142 else
5143 {
5144 operands[2] = XEXP (addr, 0);
5145 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]);
5146 }
cffb2a26 5147
ef51b8e1 5148 operands[3] = change_address (operands[1], QImode, addr);
5149})
5150
8a3b73a1 5151(define_peephole2
5152 [(set (match_operand:SI 0 "register_operand" "")
5153 (plus:SI (match_dup 0) (match_operand 1 "const_int_operand")))
5154 (set (match_operand:SI 2 "register_operand" "") (const_int 0))
5155 (set (match_operand:SI 3 "register_operand" "")
5156 (sign_extend:SI (match_operand:QI 4 "memory_operand" "")))]
5157 "TARGET_THUMB1
5158 && GET_CODE (XEXP (operands[4], 0)) == PLUS
5159 && rtx_equal_p (operands[0], XEXP (XEXP (operands[4], 0), 0))
5160 && rtx_equal_p (operands[2], XEXP (XEXP (operands[4], 0), 1))
5161 && (peep2_reg_dead_p (3, operands[0])
5162 || rtx_equal_p (operands[0], operands[3]))
5163 && (peep2_reg_dead_p (3, operands[2])
5164 || rtx_equal_p (operands[2], operands[3]))"
5165 [(set (match_dup 2) (match_dup 1))
5166 (set (match_dup 3) (sign_extend:SI (match_dup 4)))]
5167{
5168 rtx addr = gen_rtx_PLUS (Pmode, operands[0], operands[2]);
5169 operands[4] = change_address (operands[4], QImode, addr);
5170})
5171
ef51b8e1 5172(define_insn "thumb1_extendqisi2"
a2cd141b 5173 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
5174 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
ef51b8e1 5175 "TARGET_THUMB1"
5176{
5177 rtx addr;
a2cd141b 5178
ef51b8e1 5179 if (which_alternative == 0 && arm_arch6)
5180 return "sxtb\\t%0, %1";
5181 if (which_alternative == 0)
5182 return "#";
a2cd141b 5183
ef51b8e1 5184 addr = XEXP (operands[1], 0);
5185 if (GET_CODE (addr) == PLUS
5186 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
5187 return "ldrsb\\t%0, %1";
a2cd141b 5188
ef51b8e1 5189 return "#";
5190}
5191 [(set_attr_alternative "length"
5192 [(if_then_else (eq_attr "is_arch6" "yes")
5193 (const_int 2) (const_int 4))
5194 (const_int 2)
5195 (if_then_else (eq_attr "is_arch6" "yes")
5196 (const_int 4) (const_int 6))])
5197 (set_attr "type" "alu_shift,load_byte,load_byte")]
a2cd141b 5198)
5199
caedf871 5200(define_expand "extendsfdf2"
5201 [(set (match_operand:DF 0 "s_register_operand" "")
5202 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 5203 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 5204 ""
5205)
9b8516be 5206
5207/* HFmode -> DFmode conversions have to go through SFmode. */
5208(define_expand "extendhfdf2"
5209 [(set (match_operand:DF 0 "general_operand" "")
5210 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
5211 "TARGET_EITHER"
5212 "
5213 {
5214 rtx op1;
5215 op1 = convert_to_mode (SFmode, operands[1], 0);
5216 op1 = convert_to_mode (DFmode, op1, 0);
5217 emit_insn (gen_movdf (operands[0], op1));
5218 DONE;
5219 }"
5220)
b11cae9e 5221\f
5222;; Move insns (including loads and stores)
5223
5224;; XXX Just some ideas about movti.
9c08d1fa 5225;; I don't think these are a good idea on the arm, there just aren't enough
5226;; registers
b11cae9e 5227;;(define_expand "loadti"
9c08d1fa 5228;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 5229;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
5230;; "" "")
5231
5232;;(define_expand "storeti"
5233;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 5234;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 5235;; "" "")
5236
5237;;(define_expand "movti"
5238;; [(set (match_operand:TI 0 "general_operand" "")
5239;; (match_operand:TI 1 "general_operand" ""))]
5240;; ""
5241;; "
5242;;{
5243;; rtx insn;
5244;;
5245;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
5246;; operands[1] = copy_to_reg (operands[1]);
5247;; if (GET_CODE (operands[0]) == MEM)
5248;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
5249;; else if (GET_CODE (operands[1]) == MEM)
5250;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5251;; else
5252;; FAIL;
5253;;
5254;; emit_insn (insn);
5255;; DONE;
5256;;}")
5257
a2f10574 5258;; Recognize garbage generated above.
b11cae9e 5259
5260;;(define_insn ""
5261;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5262;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5263;; ""
5264;; "*
5265;; {
5266;; register mem = (which_alternative < 3);
0d66636f 5267;; register const char *template;
b11cae9e 5268;;
5269;; operands[mem] = XEXP (operands[mem], 0);
5270;; switch (which_alternative)
5271;; {
5272;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5273;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5274;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5275;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5276;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5277;; case 5: template = \"stmia\\t%0, %M1\"; break;
5278;; }
e2348bcb 5279;; output_asm_insn (template, operands);
5280;; return \"\";
b11cae9e 5281;; }")
5282
cffb2a26 5283(define_expand "movdi"
5284 [(set (match_operand:DI 0 "general_operand" "")
5285 (match_operand:DI 1 "general_operand" ""))]
5286 "TARGET_EITHER"
5287 "
e1ba4a27 5288 if (can_create_pseudo_p ())
cffb2a26 5289 {
b2778788 5290 if (GET_CODE (operands[0]) != REG)
5291 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 5292 }
5293 "
5294)
b11cae9e 5295
cffb2a26 5296(define_insn "*arm_movdi"
d51f92df 5297 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
5298 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
cde1623a 5299 "TARGET_32BIT
b2778788 5300 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
5301 && !TARGET_IWMMXT
5302 && ( register_operand (operands[0], DImode)
5303 || register_operand (operands[1], DImode))"
b11cae9e 5304 "*
d51f92df 5305 switch (which_alternative)
5306 {
5307 case 0:
5308 case 1:
5309 case 2:
5310 return \"#\";
5311 default:
26ff80c0 5312 return output_move_double (operands, true, NULL);
d51f92df 5313 }
cffb2a26 5314 "
359a6e9f 5315 [(set_attr "length" "8,12,16,8,8")
5316 (set_attr "type" "*,*,*,load2,store2")
cde1623a 5317 (set_attr "arm_pool_range" "*,*,*,1020,*")
8848d797 5318 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 5319 (set_attr "thumb2_pool_range" "*,*,*,4096,*")
5320 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 5321)
5322
d51f92df 5323(define_split
5324 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5325 (match_operand:ANY64 1 "const_double_operand" ""))]
25f905c2 5326 "TARGET_32BIT
d51f92df 5327 && reload_completed
5328 && (arm_const_double_inline_cost (operands[1])
5329 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
5330 [(const_int 0)]
5331 "
5332 arm_split_constant (SET, SImode, curr_insn,
5333 INTVAL (gen_lowpart (SImode, operands[1])),
5334 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5335 arm_split_constant (SET, SImode, curr_insn,
5336 INTVAL (gen_highpart_mode (SImode,
5337 GET_MODE (operands[0]),
5338 operands[1])),
5339 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5340 DONE;
5341 "
5342)
5343
e5ba9289 5344; If optimizing for size, or if we have load delay slots, then
5345; we want to split the constant into two separate operations.
5346; In both cases this may split a trivial part into a single data op
5347; leaving a single complex constant to load. We can also get longer
5348; offsets in a LDR which means we get better chances of sharing the pool
5349; entries. Finally, we can normally do a better job of scheduling
5350; LDR instructions than we can with LDM.
5351; This pattern will only match if the one above did not.
5352(define_split
5353 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5354 (match_operand:ANY64 1 "const_double_operand" ""))]
5355 "TARGET_ARM && reload_completed
5356 && arm_const_double_by_parts (operands[1])"
5357 [(set (match_dup 0) (match_dup 1))
5358 (set (match_dup 2) (match_dup 3))]
5359 "
5360 operands[2] = gen_highpart (SImode, operands[0]);
5361 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5362 operands[1]);
5363 operands[0] = gen_lowpart (SImode, operands[0]);
5364 operands[1] = gen_lowpart (SImode, operands[1]);
5365 "
5366)
5367
d51f92df 5368(define_split
5369 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5370 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5371 "TARGET_EITHER && reload_completed"
5372 [(set (match_dup 0) (match_dup 1))
5373 (set (match_dup 2) (match_dup 3))]
5374 "
5375 operands[2] = gen_highpart (SImode, operands[0]);
5376 operands[3] = gen_highpart (SImode, operands[1]);
5377 operands[0] = gen_lowpart (SImode, operands[0]);
5378 operands[1] = gen_lowpart (SImode, operands[1]);
5379
5380 /* Handle a partial overlap. */
5381 if (rtx_equal_p (operands[0], operands[3]))
5382 {
5383 rtx tmp0 = operands[0];
5384 rtx tmp1 = operands[1];
5385
5386 operands[0] = operands[2];
5387 operands[1] = operands[3];
5388 operands[2] = tmp0;
5389 operands[3] = tmp1;
5390 }
5391 "
5392)
5393
a8a3b539 5394;; We can't actually do base+index doubleword loads if the index and
5395;; destination overlap. Split here so that we at least have chance to
5396;; schedule.
5397(define_split
5398 [(set (match_operand:DI 0 "s_register_operand" "")
5399 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5400 (match_operand:SI 2 "s_register_operand" ""))))]
5401 "TARGET_LDRD
5402 && reg_overlap_mentioned_p (operands[0], operands[1])
5403 && reg_overlap_mentioned_p (operands[0], operands[2])"
5404 [(set (match_dup 4)
5405 (plus:SI (match_dup 1)
5406 (match_dup 2)))
5407 (set (match_dup 0)
5408 (mem:DI (match_dup 4)))]
5409 "
5410 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5411 "
5412)
5413
cffb2a26 5414;;; ??? This should have alternatives for constants.
5415;;; ??? This was originally identical to the movdf_insn pattern.
5416;;; ??? The 'i' constraint looks funny, but it should always be replaced by
5417;;; thumb_reorg with a memory reference.
25f905c2 5418(define_insn "*thumb1_movdi_insn"
215b30b3 5419 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
5420 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
25f905c2 5421 "TARGET_THUMB1
a2cd141b 5422 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
cffb2a26 5423 && ( register_operand (operands[0], DImode)
5424 || register_operand (operands[1], DImode))"
5425 "*
5426 {
5427 switch (which_alternative)
5428 {
5429 default:
5430 case 0:
5431 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5432 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5433 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5434 case 1:
5435 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
5436 case 2:
5437 operands[1] = GEN_INT (- INTVAL (operands[1]));
5438 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
5439 case 3:
5440 return \"ldmia\\t%1, {%0, %H0}\";
5441 case 4:
5442 return \"stmia\\t%0, {%1, %H1}\";
5443 case 5:
5444 return thumb_load_double_from_address (operands);
5445 case 6:
1a83b3ff 5446 operands[2] = gen_rtx_MEM (SImode,
215b30b3 5447 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 5448 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5449 return \"\";
5450 case 7:
5451 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5452 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5453 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5454 }
5455 }"
5456 [(set_attr "length" "4,4,6,2,2,6,4,4")
a2cd141b 5457 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
d2a518d1 5458 (set_attr "insn" "*,mov,*,*,*,*,*,mov")
cffb2a26 5459 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
5460)
b11cae9e 5461
9c08d1fa 5462(define_expand "movsi"
5463 [(set (match_operand:SI 0 "general_operand" "")
5464 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5465 "TARGET_EITHER"
9c08d1fa 5466 "
befb0bac 5467 {
e348ff3e 5468 rtx base, offset, tmp;
5469
25f905c2 5470 if (TARGET_32BIT)
9c08d1fa 5471 {
674a8f0b 5472 /* Everything except mem = const or mem = mem can be done easily. */
cffb2a26 5473 if (GET_CODE (operands[0]) == MEM)
5474 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5475 if (arm_general_register_operand (operands[0], SImode)
5476 && GET_CODE (operands[1]) == CONST_INT
cffb2a26 5477 && !(const_ok_for_arm (INTVAL (operands[1]))
5478 || const_ok_for_arm (~INTVAL (operands[1]))))
5479 {
96f57e36 5480 arm_split_constant (SET, SImode, NULL_RTX,
5481 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 5482 optimize && can_create_pseudo_p ());
cffb2a26 5483 DONE;
5484 }
d0e6a121 5485
5486 if (TARGET_USE_MOVT && !target_word_relocations
5487 && GET_CODE (operands[1]) == SYMBOL_REF
5488 && !flag_pic && !arm_tls_referenced_p (operands[1]))
5489 {
5490 arm_emit_movpair (operands[0], operands[1]);
5491 DONE;
5492 }
cffb2a26 5493 }
25f905c2 5494 else /* TARGET_THUMB1... */
cffb2a26 5495 {
e1ba4a27 5496 if (can_create_pseudo_p ())
cffb2a26 5497 {
5498 if (GET_CODE (operands[0]) != REG)
5499 operands[1] = force_reg (SImode, operands[1]);
5500 }
9c08d1fa 5501 }
f655717d 5502
e348ff3e 5503 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5504 {
5505 split_const (operands[1], &base, &offset);
5506 if (GET_CODE (base) == SYMBOL_REF
5507 && !offset_within_block_p (base, INTVAL (offset)))
5508 {
b308ddcf 5509 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 5510 emit_move_insn (tmp, base);
5511 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5512 DONE;
5513 }
5514 }
5515
f655717d 5516 /* Recognize the case where operand[1] is a reference to thread-local
5517 data and load its address to a register. */
5518 if (arm_tls_referenced_p (operands[1]))
5519 {
5520 rtx tmp = operands[1];
5521 rtx addend = NULL;
5522
5523 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5524 {
5525 addend = XEXP (XEXP (tmp, 0), 1);
5526 tmp = XEXP (XEXP (tmp, 0), 0);
5527 }
5528
5529 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5530 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5531
e1ba4a27 5532 tmp = legitimize_tls_address (tmp,
5533 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 5534 if (addend)
5535 {
5536 tmp = gen_rtx_PLUS (SImode, tmp, addend);
5537 tmp = force_operand (tmp, operands[0]);
5538 }
5539 operands[1] = tmp;
5540 }
5541 else if (flag_pic
5542 && (CONSTANT_P (operands[1])
5543 || symbol_mentioned_p (operands[1])
5544 || label_mentioned_p (operands[1])))
5545 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 5546 (!can_create_pseudo_p ()
5547 ? operands[0]
5548 : 0));
befb0bac 5549 }
215b30b3 5550 "
5551)
9c08d1fa 5552
d0e6a121 5553;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5554;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5555;; so this does not matter.
5556(define_insn "*arm_movt"
5557 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5558 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5559 (match_operand:SI 2 "general_operand" "i")))]
c9b2ce40 5560 "arm_arch_thumb2"
d0e6a121 5561 "movt%?\t%0, #:upper16:%c2"
5562 [(set_attr "predicable" "yes")
5563 (set_attr "length" "4")]
5564)
5565
cffb2a26 5566(define_insn "*arm_movsi_insn"
aaa37ad6 5567 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5568 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
755eb2b4 5569 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 5570 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 5571 && ( register_operand (operands[0], SImode)
5572 || register_operand (operands[1], SImode))"
f7fbdd4a 5573 "@
aaa37ad6 5574 mov%?\\t%0, %1
f7fbdd4a 5575 mov%?\\t%0, %1
5576 mvn%?\\t%0, #%B1
25f905c2 5577 movw%?\\t%0, %1
f7fbdd4a 5578 ldr%?\\t%0, %1
5579 str%?\\t%1, %0"
aaa37ad6 5580 [(set_attr "type" "*,*,*,*,load1,store1")
d2a518d1 5581 (set_attr "insn" "mov,mov,mvn,mov,*,*")
0d66636f 5582 (set_attr "predicable" "yes")
aaa37ad6 5583 (set_attr "pool_range" "*,*,*,*,4096,*")
5584 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5585)
87b22bf7 5586
5587(define_split
a2cd141b 5588 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5589 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5590 "TARGET_32BIT
215b30b3 5591 && (!(const_ok_for_arm (INTVAL (operands[1]))
5592 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5593 [(clobber (const_int 0))]
5594 "
96f57e36 5595 arm_split_constant (SET, SImode, NULL_RTX,
5596 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5597 DONE;
215b30b3 5598 "
5599)
9c08d1fa 5600
25f905c2 5601(define_insn "*thumb1_movsi_insn"
55a0d64c 5602 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*l*h*k")
5603 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*l*h*k"))]
25f905c2 5604 "TARGET_THUMB1
cffb2a26 5605 && ( register_operand (operands[0], SImode)
5606 || register_operand (operands[1], SImode))"
5607 "@
5608 mov %0, %1
5609 mov %0, %1
5610 #
5611 #
5612 ldmia\\t%1, {%0}
5613 stmia\\t%0, {%1}
5614 ldr\\t%0, %1
5615 str\\t%1, %0
5616 mov\\t%0, %1"
5617 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 5618 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
747b7458 5619 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")
5620 (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")])
cffb2a26 5621
5622(define_split
5623 [(set (match_operand:SI 0 "register_operand" "")
5624 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5625 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
1276f1b8 5626 [(set (match_dup 2) (match_dup 1))
5627 (set (match_dup 0) (neg:SI (match_dup 2)))]
5628 "
5629 {
5630 operands[1] = GEN_INT (- INTVAL (operands[1]));
5631 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5632 }"
cffb2a26 5633)
5634
5635(define_split
5636 [(set (match_operand:SI 0 "register_operand" "")
5637 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5638 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
1276f1b8 5639 [(set (match_dup 2) (match_dup 1))
5640 (set (match_dup 0) (ashift:SI (match_dup 2) (match_dup 3)))]
cffb2a26 5641 "
5642 {
e4aeee53 5643 unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
cffb2a26 5644 unsigned HOST_WIDE_INT mask = 0xff;
5645 int i;
5646
5647 for (i = 0; i < 25; i++)
5648 if ((val & (mask << i)) == val)
5649 break;
5650
1276f1b8 5651 /* Don't split if the shift is zero. */
cffb2a26 5652 if (i == 0)
5653 FAIL;
5654
5655 operands[1] = GEN_INT (val >> i);
1276f1b8 5656 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5657 operands[3] = GEN_INT (i);
cffb2a26 5658 }"
5659)
5660
c5b75283 5661;; For thumb1 split imm move [256-510] into mov [1-255] and add #255
5662(define_split
5663 [(set (match_operand:SI 0 "register_operand" "")
5664 (match_operand:SI 1 "const_int_operand" ""))]
5665 "TARGET_THUMB1 && satisfies_constraint_Pe (operands[1])"
5666 [(set (match_dup 2) (match_dup 1))
5667 (set (match_dup 0) (plus:SI (match_dup 2) (match_dup 3)))]
5668 "
5669 {
5670 operands[1] = GEN_INT (INTVAL (operands[1]) - 255);
5671 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5672 operands[3] = GEN_INT (255);
5673 }"
5674)
5675
67336bcf 5676;; When generating pic, we need to load the symbol offset into a register.
5677;; So that the optimizer does not confuse this with a normal symbol load
5678;; we use an unspec. The offset will be loaded from a constant pool entry,
5679;; since that is the only type of relocation we can use.
5680
94f8caca 5681;; Wrap calculation of the whole PIC address in a single pattern for the
5682;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5683;; a PIC address involves two loads from memory, so we want to CSE it
5684;; as often as possible.
5685;; This pattern will be split into one of the pic_load_addr_* patterns
5686;; and a move after GCSE optimizations.
5687;;
5688;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5689(define_expand "calculate_pic_address"
5690 [(set (match_operand:SI 0 "register_operand" "")
5691 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5692 (unspec:SI [(match_operand:SI 2 "" "")]
5693 UNSPEC_PIC_SYM))))]
5694 "flag_pic"
5695)
5696
5697;; Split calculate_pic_address into pic_load_addr_* and a move.
5698(define_split
5699 [(set (match_operand:SI 0 "register_operand" "")
5700 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5701 (unspec:SI [(match_operand:SI 2 "" "")]
5702 UNSPEC_PIC_SYM))))]
5703 "flag_pic"
5704 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5705 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5706 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5707)
5708
350ccca5 5709;; operand1 is the memory address to go into
5710;; pic_load_addr_32bit.
5711;; operand2 is the PIC label to be emitted
5712;; from pic_add_dot_plus_eight.
5713;; We do this to allow hoisting of the entire insn.
5714(define_insn_and_split "pic_load_addr_unified"
5715 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
5716 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
5717 (match_operand:SI 2 "" "")]
5718 UNSPEC_PIC_UNIFIED))]
5719 "flag_pic"
5720 "#"
5721 "&& reload_completed"
5722 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
5723 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
5724 (match_dup 2)] UNSPEC_PIC_BASE))]
5725 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
5726 [(set_attr "type" "load1,load1,load1")
5727 (set_attr "pool_range" "4096,4096,1024")
5728 (set_attr "neg_pool_range" "4084,0,0")
5729 (set_attr "arch" "a,t2,t1")
5730 (set_attr "length" "8,6,4")]
5731)
5732
67336bcf 5733;; The rather odd constraints on the following are to force reload to leave
5734;; the insn alone, and to force the minipool generation pass to then move
5735;; the GOT symbol to memory.
849170fd 5736
b3cd5f55 5737(define_insn "pic_load_addr_32bit"
849170fd 5738 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5739 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 5740 "TARGET_32BIT && flag_pic"
67336bcf 5741 "ldr%?\\t%0, %1"
a2cd141b 5742 [(set_attr "type" "load1")
b3cd5f55 5743 (set_attr "pool_range" "4096")
5744 (set (attr "neg_pool_range")
5745 (if_then_else (eq_attr "is_thumb" "no")
5746 (const_int 4084)
5747 (const_int 0)))]
8c4d8060 5748)
5749
25f905c2 5750(define_insn "pic_load_addr_thumb1"
8c4d8060 5751 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5752 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5753 "TARGET_THUMB1 && flag_pic"
8c4d8060 5754 "ldr\\t%0, %1"
a2cd141b 5755 [(set_attr "type" "load1")
8c4d8060 5756 (set (attr "pool_range") (const_int 1024))]
cffb2a26 5757)
849170fd 5758
cffb2a26 5759(define_insn "pic_add_dot_plus_four"
15d5d060 5760 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5761 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5762 (const_int 4)
beef0fb5 5763 (match_operand 2 "" "")]
5764 UNSPEC_PIC_BASE))]
b3cd5f55 5765 "TARGET_THUMB"
cffb2a26 5766 "*
6cdcb15c 5767 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5768 INTVAL (operands[2]));
cffb2a26 5769 return \"add\\t%0, %|pc\";
5770 "
5771 [(set_attr "length" "2")]
5772)
849170fd 5773
5774(define_insn "pic_add_dot_plus_eight"
15d5d060 5775 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5776 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5777 (const_int 8)
beef0fb5 5778 (match_operand 2 "" "")]
5779 UNSPEC_PIC_BASE))]
f655717d 5780 "TARGET_ARM"
c4034607 5781 "*
6cdcb15c 5782 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5783 INTVAL (operands[2]));
15d5d060 5784 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5785 "
0d66636f 5786 [(set_attr "predicable" "yes")]
cffb2a26 5787)
849170fd 5788
f655717d 5789(define_insn "tls_load_dot_plus_eight"
cc071db6 5790 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5791 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5792 (const_int 8)
beef0fb5 5793 (match_operand 2 "" "")]
5794 UNSPEC_PIC_BASE)))]
f655717d 5795 "TARGET_ARM"
5796 "*
6cdcb15c 5797 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5798 INTVAL (operands[2]));
f655717d 5799 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5800 "
5801 [(set_attr "predicable" "yes")]
5802)
5803
5804;; PIC references to local variables can generate pic_add_dot_plus_eight
5805;; followed by a load. These sequences can be crunched down to
5806;; tls_load_dot_plus_eight by a peephole.
5807
5808(define_peephole2
c0c1fba5 5809 [(set (match_operand:SI 0 "register_operand" "")
5810 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5811 (const_int 8)
5812 (match_operand 1 "" "")]
5813 UNSPEC_PIC_BASE))
2d05dfad 5814 (set (match_operand:SI 2 "arm_general_register_operand" "")
5815 (mem:SI (match_dup 0)))]
f655717d 5816 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5817 [(set (match_dup 2)
5818 (mem:SI (unspec:SI [(match_dup 3)
5819 (const_int 8)
5820 (match_dup 1)]
5821 UNSPEC_PIC_BASE)))]
f655717d 5822 ""
5823)
5824
bac7fc85 5825(define_insn "pic_offset_arm"
5826 [(set (match_operand:SI 0 "register_operand" "=r")
5827 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5828 (unspec:SI [(match_operand:SI 2 "" "X")]
5829 UNSPEC_PIC_OFFSET))))]
5830 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5831 "ldr%?\\t%0, [%1,%2]"
5832 [(set_attr "type" "load1")]
5833)
5834
95373f08 5835(define_expand "builtin_setjmp_receiver"
5836 [(label_ref (match_operand 0 "" ""))]
5837 "flag_pic"
5838 "
5839{
b935b306 5840 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5841 register. */
2cb7d577 5842 if (arm_pic_register != INVALID_REGNUM)
5843 arm_load_pic_register (1UL << 3);
95373f08 5844 DONE;
5845}")
5846
9c08d1fa 5847;; If copying one reg to another we can set the condition codes according to
5848;; its value. Such a move is common after a return from subroutine and the
5849;; result is being tested against zero.
5850
f7fbdd4a 5851(define_insn "*movsi_compare0"
bd5b4116 5852 [(set (reg:CC CC_REGNUM)
cffb2a26 5853 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5854 (const_int 0)))
5855 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5856 (match_dup 1))]
25f905c2 5857 "TARGET_32BIT"
e2348bcb 5858 "@
40dbec34 5859 cmp%?\\t%0, #0
25f905c2 5860 sub%.\\t%0, %1, #0"
cffb2a26 5861 [(set_attr "conds" "set")]
5862)
b11cae9e 5863
b11cae9e 5864;; Subroutine to store a half word from a register into memory.
5865;; Operand 0 is the source register (HImode)
c8f69309 5866;; Operand 1 is the destination address in a register (SImode)
b11cae9e 5867
9c08d1fa 5868;; In both this routine and the next, we must be careful not to spill
01cc3b75 5869;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 5870;; can generate unrecognizable rtl.
5871
b11cae9e 5872(define_expand "storehi"
c8f69309 5873 [;; store the low byte
f082f1c4 5874 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 5875 ;; extract the high byte
c8f69309 5876 (set (match_dup 2)
5877 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 5878 ;; store the high byte
787f8210 5879 (set (match_dup 4) (match_dup 5))]
cffb2a26 5880 "TARGET_ARM"
b11cae9e 5881 "
215b30b3 5882 {
537ffcfc 5883 rtx op1 = operands[1];
5884 rtx addr = XEXP (op1, 0);
215b30b3 5885 enum rtx_code code = GET_CODE (addr);
5886
5887 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5888 || code == MINUS)
537ffcfc 5889 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5890
537ffcfc 5891 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5892 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5893 operands[3] = gen_lowpart (QImode, operands[0]);
5894 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5895 operands[2] = gen_reg_rtx (SImode);
5896 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5897 }"
5898)
b11cae9e 5899
c7597b5d 5900(define_expand "storehi_bigend"
f082f1c4 5901 [(set (match_dup 4) (match_dup 3))
c7597b5d 5902 (set (match_dup 2)
5903 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5904 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5905 "TARGET_ARM"
b11cae9e 5906 "
215b30b3 5907 {
537ffcfc 5908 rtx op1 = operands[1];
5909 rtx addr = XEXP (op1, 0);
215b30b3 5910 enum rtx_code code = GET_CODE (addr);
5911
5912 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5913 || code == MINUS)
537ffcfc 5914 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5915
537ffcfc 5916 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5917 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5918 operands[3] = gen_lowpart (QImode, operands[0]);
5919 operands[0] = gen_lowpart (SImode, operands[0]);
5920 operands[2] = gen_reg_rtx (SImode);
787f8210 5921 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5922 }"
5923)
c7597b5d 5924
5925;; Subroutine to store a half word integer constant into memory.
5926(define_expand "storeinthi"
f082f1c4 5927 [(set (match_operand 0 "" "")
787f8210 5928 (match_operand 1 "" ""))
9e8503e6 5929 (set (match_dup 3) (match_dup 2))]
cffb2a26 5930 "TARGET_ARM"
c7597b5d 5931 "
215b30b3 5932 {
5933 HOST_WIDE_INT value = INTVAL (operands[1]);
5934 rtx addr = XEXP (operands[0], 0);
537ffcfc 5935 rtx op0 = operands[0];
215b30b3 5936 enum rtx_code code = GET_CODE (addr);
c7597b5d 5937
215b30b3 5938 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5939 || code == MINUS)
537ffcfc 5940 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 5941
215b30b3 5942 operands[1] = gen_reg_rtx (SImode);
5943 if (BYTES_BIG_ENDIAN)
5944 {
5945 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5946 if ((value & 255) == ((value >> 8) & 255))
5947 operands[2] = operands[1];
5948 else
5949 {
5950 operands[2] = gen_reg_rtx (SImode);
5951 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5952 }
5953 }
5954 else
5955 {
5956 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5957 if ((value & 255) == ((value >> 8) & 255))
5958 operands[2] = operands[1];
5959 else
5960 {
5961 operands[2] = gen_reg_rtx (SImode);
5962 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5963 }
5964 }
c7597b5d 5965
537ffcfc 5966 operands[3] = adjust_address (op0, QImode, 1);
e513d163 5967 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 5968 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 5969 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 5970 }"
5971)
b11cae9e 5972
f7fbdd4a 5973(define_expand "storehi_single_op"
5974 [(set (match_operand:HI 0 "memory_operand" "")
5975 (match_operand:HI 1 "general_operand" ""))]
25f905c2 5976 "TARGET_32BIT && arm_arch4"
f7fbdd4a 5977 "
215b30b3 5978 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 5979 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 5980 "
5981)
f7fbdd4a 5982
b11cae9e 5983(define_expand "movhi"
5984 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 5985 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 5986 "TARGET_EITHER"
b11cae9e 5987 "
cffb2a26 5988 if (TARGET_ARM)
b11cae9e 5989 {
e1ba4a27 5990 if (can_create_pseudo_p ())
cffb2a26 5991 {
5992 if (GET_CODE (operands[0]) == MEM)
b11cae9e 5993 {
cffb2a26 5994 if (arm_arch4)
5995 {
5996 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5997 DONE;
5998 }
5999 if (GET_CODE (operands[1]) == CONST_INT)
6000 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 6001 else
cffb2a26 6002 {
6003 if (GET_CODE (operands[1]) == MEM)
6004 operands[1] = force_reg (HImode, operands[1]);
6005 if (BYTES_BIG_ENDIAN)
6006 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
6007 else
6008 emit_insn (gen_storehi (operands[1], operands[0]));
6009 }
6010 DONE;
b11cae9e 6011 }
cffb2a26 6012 /* Sign extend a constant, and keep it in an SImode reg. */
6013 else if (GET_CODE (operands[1]) == CONST_INT)
9c08d1fa 6014 {
cffb2a26 6015 rtx reg = gen_reg_rtx (SImode);
6016 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6017
6018 /* If the constant is already valid, leave it alone. */
215b30b3 6019 if (!const_ok_for_arm (val))
cffb2a26 6020 {
6021 /* If setting all the top bits will make the constant
6022 loadable in a single instruction, then set them.
6023 Otherwise, sign extend the number. */
6024
215b30b3 6025 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 6026 val |= ~0xffff;
6027 else if (val & 0x8000)
6028 val |= ~0xffff;
6029 }
6030
6031 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 6032 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 6033 }
e1ba4a27 6034 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0045890a 6035 && GET_CODE (operands[1]) == MEM)
6036 {
6037 rtx reg = gen_reg_rtx (SImode);
6038
6039 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6040 operands[1] = gen_lowpart (HImode, reg);
6041 }
215b30b3 6042 else if (!arm_arch4)
f7fbdd4a 6043 {
cffb2a26 6044 if (GET_CODE (operands[1]) == MEM)
6045 {
c1a66faf 6046 rtx base;
6047 rtx offset = const0_rtx;
6048 rtx reg = gen_reg_rtx (SImode);
6049
6050 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
6051 || (GET_CODE (base) == PLUS
6052 && (GET_CODE (offset = XEXP (base, 1))
6053 == CONST_INT)
6054 && ((INTVAL(offset) & 1) != 1)
6055 && GET_CODE (base = XEXP (base, 0)) == REG))
6056 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 6057 {
8deb3959 6058 rtx new_rtx;
c1a66faf 6059
8deb3959 6060 new_rtx = widen_memory_access (operands[1], SImode,
6061 ((INTVAL (offset) & ~3)
6062 - INTVAL (offset)));
6063 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 6064 if (((INTVAL (offset) & 2) != 0)
6065 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
6066 {
6067 rtx reg2 = gen_reg_rtx (SImode);
6068
6069 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
6070 reg = reg2;
6071 }
206ee9a2 6072 }
c1a66faf 6073 else
6074 emit_insn (gen_movhi_bytes (reg, operands[1]));
6075
6076 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 6077 }
6078 }
6079 }
674a8f0b 6080 /* Handle loading a large integer during reload. */
cffb2a26 6081 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 6082 && !const_ok_for_arm (INTVAL (operands[1]))
6083 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 6084 {
6085 /* Writing a constant to memory needs a scratch, which should
6086 be handled with SECONDARY_RELOADs. */
ed29c566 6087 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 6088
6089 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6090 emit_insn (gen_movsi (operands[0], operands[1]));
6091 DONE;
6092 }
6093 }
25f905c2 6094 else if (TARGET_THUMB2)
6095 {
6096 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 6097 if (can_create_pseudo_p ())
25f905c2 6098 {
6099 if (GET_CODE (operands[0]) != REG)
6100 operands[1] = force_reg (HImode, operands[1]);
6101 /* Zero extend a constant, and keep it in an SImode reg. */
6102 else if (GET_CODE (operands[1]) == CONST_INT)
6103 {
6104 rtx reg = gen_reg_rtx (SImode);
6105 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6106
6107 emit_insn (gen_movsi (reg, GEN_INT (val)));
6108 operands[1] = gen_lowpart (HImode, reg);
6109 }
6110 }
6111 }
6112 else /* TARGET_THUMB1 */
cffb2a26 6113 {
e1ba4a27 6114 if (can_create_pseudo_p ())
cffb2a26 6115 {
6cffc037 6116 if (GET_CODE (operands[1]) == CONST_INT)
6117 {
6118 rtx reg = gen_reg_rtx (SImode);
6119
6120 emit_insn (gen_movsi (reg, operands[1]));
6121 operands[1] = gen_lowpart (HImode, reg);
6122 }
cffb2a26 6123
6124 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6125 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6126 virtual register (also rejected as illegitimate for HImode/QImode)
6127 relative address. */
cffb2a26 6128 /* ??? This should perhaps be fixed elsewhere, for instance, in
6129 fixup_stack_1, by checking for other kinds of invalid addresses,
6130 e.g. a bare reference to a virtual register. This may confuse the
6131 alpha though, which must handle this case differently. */
6132 if (GET_CODE (operands[0]) == MEM
215b30b3 6133 && !memory_address_p (GET_MODE (operands[0]),
6134 XEXP (operands[0], 0)))
537ffcfc 6135 operands[0]
6136 = replace_equiv_address (operands[0],
6137 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 6138
6139 if (GET_CODE (operands[1]) == MEM
215b30b3 6140 && !memory_address_p (GET_MODE (operands[1]),
6141 XEXP (operands[1], 0)))
537ffcfc 6142 operands[1]
6143 = replace_equiv_address (operands[1],
6144 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6145
6146 if (GET_CODE (operands[1]) == MEM && optimize > 0)
6147 {
6148 rtx reg = gen_reg_rtx (SImode);
6149
6150 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6151 operands[1] = gen_lowpart (HImode, reg);
6152 }
6153
6154 if (GET_CODE (operands[0]) == MEM)
6155 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 6156 }
cffb2a26 6157 else if (GET_CODE (operands[1]) == CONST_INT
234f6557 6158 && !satisfies_constraint_I (operands[1]))
cffb2a26 6159 {
6cffc037 6160 /* Handle loading a large integer during reload. */
6161
cffb2a26 6162 /* Writing a constant to memory needs a scratch, which should
6163 be handled with SECONDARY_RELOADs. */
ed29c566 6164 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 6165
1a83b3ff 6166 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 6167 emit_insn (gen_movsi (operands[0], operands[1]));
6168 DONE;
6169 }
b11cae9e 6170 }
cffb2a26 6171 "
6172)
6173
25f905c2 6174(define_insn "*thumb1_movhi_insn"
a941568e 6175 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
6176 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
25f905c2 6177 "TARGET_THUMB1
cffb2a26 6178 && ( register_operand (operands[0], HImode)
6179 || register_operand (operands[1], HImode))"
6180 "*
6181 switch (which_alternative)
d79300ac 6182 {
cffb2a26 6183 case 0: return \"add %0, %1, #0\";
6184 case 2: return \"strh %1, %0\";
6185 case 3: return \"mov %0, %1\";
6186 case 4: return \"mov %0, %1\";
6187 case 5: return \"mov %0, %1\";
ed29c566 6188 default: gcc_unreachable ();
cffb2a26 6189 case 1:
6190 /* The stack pointer can end up being taken as an index register.
6191 Catch this case here and deal with it. */
6192 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
6193 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
6194 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
6195 {
6196 rtx ops[2];
6197 ops[0] = operands[0];
6198 ops[1] = XEXP (XEXP (operands[1], 0), 0);
6199
6200 output_asm_insn (\"mov %0, %1\", ops);
6201
6202 XEXP (XEXP (operands[1], 0), 0) = operands[0];
6203
6204 }
6205 return \"ldrh %0, %1\";
6206 }"
6207 [(set_attr "length" "2,4,2,2,2,2")
747b7458 6208 (set_attr "type" "*,load1,store1,*,*,*")
6209 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
d79300ac 6210
b11cae9e 6211
25f7a26e 6212(define_expand "movhi_bytes"
eab14235 6213 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 6214 (set (match_dup 3)
eab14235 6215 (zero_extend:SI (match_dup 6)))
25f7a26e 6216 (set (match_operand:SI 0 "" "")
6217 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 6218 "TARGET_ARM"
25f7a26e 6219 "
215b30b3 6220 {
6221 rtx mem1, mem2;
6222 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6223
788fcce0 6224 mem1 = change_address (operands[1], QImode, addr);
6225 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 6226 operands[0] = gen_lowpart (SImode, operands[0]);
6227 operands[1] = mem1;
6228 operands[2] = gen_reg_rtx (SImode);
6229 operands[3] = gen_reg_rtx (SImode);
6230 operands[6] = mem2;
25f7a26e 6231
215b30b3 6232 if (BYTES_BIG_ENDIAN)
6233 {
6234 operands[4] = operands[2];
6235 operands[5] = operands[3];
6236 }
6237 else
6238 {
6239 operands[4] = operands[3];
6240 operands[5] = operands[2];
6241 }
6242 }"
6243)
25f7a26e 6244
c7597b5d 6245(define_expand "movhi_bigend"
6246 [(set (match_dup 2)
6247 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
6248 (const_int 16)))
6249 (set (match_dup 3)
6250 (ashiftrt:SI (match_dup 2) (const_int 16)))
6251 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 6252 (match_dup 4))]
cffb2a26 6253 "TARGET_ARM"
c7597b5d 6254 "
6255 operands[2] = gen_reg_rtx (SImode);
6256 operands[3] = gen_reg_rtx (SImode);
787f8210 6257 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 6258 "
6259)
b11cae9e 6260
a2f10574 6261;; Pattern to recognize insn generated default case above
f7fbdd4a 6262(define_insn "*movhi_insn_arch4"
cde1623a 6263 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
85e02ccb 6264 (match_operand:HI 1 "general_operand" "rI,K,r,mi"))]
cffb2a26 6265 "TARGET_ARM
6266 && arm_arch4
85e02ccb 6267 && (register_operand (operands[0], HImode)
6268 || register_operand (operands[1], HImode))"
f7fbdd4a 6269 "@
6270 mov%?\\t%0, %1\\t%@ movhi
6271 mvn%?\\t%0, #%B1\\t%@ movhi
25f905c2 6272 str%(h%)\\t%1, %0\\t%@ movhi
6273 ldr%(h%)\\t%0, %1\\t%@ movhi"
a2cd141b 6274 [(set_attr "type" "*,*,store1,load1")
0d66636f 6275 (set_attr "predicable" "yes")
d2a518d1 6276 (set_attr "insn" "mov,mvn,*,*")
cffb2a26 6277 (set_attr "pool_range" "*,*,*,256")
6278 (set_attr "neg_pool_range" "*,*,*,244")]
6279)
f7fbdd4a 6280
f7fbdd4a 6281(define_insn "*movhi_bytes"
25f7a26e 6282 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
6283 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
c1a66faf 6284 "TARGET_ARM"
25f7a26e 6285 "@
6286 mov%?\\t%0, %1\\t%@ movhi
0d66636f 6287 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 6288 [(set_attr "predicable" "yes")
6289 (set_attr "insn" "mov,mvn")]
0d66636f 6290)
25f7a26e 6291
f90b51f1 6292(define_expand "thumb_movhi_clobber"
6293 [(set (match_operand:HI 0 "memory_operand" "")
6294 (match_operand:HI 1 "register_operand" ""))
6295 (clobber (match_operand:DI 2 "register_operand" ""))]
25f905c2 6296 "TARGET_THUMB1"
f90b51f1 6297 "
6298 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
6299 && REGNO (operands[1]) <= LAST_LO_REGNUM)
6300 {
6301 emit_insn (gen_movhi (operands[0], operands[1]));
6302 DONE;
6303 }
6304 /* XXX Fixme, need to handle other cases here as well. */
6305 gcc_unreachable ();
6306 "
cffb2a26 6307)
6308
bc5c7e08 6309;; We use a DImode scratch because we may occasionally need an additional
6310;; temporary if the address isn't offsettable -- push_reload doesn't seem
6311;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 6312(define_expand "reload_outhi"
cffb2a26 6313 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 6314 (match_operand:HI 1 "s_register_operand" "r")
6315 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 6316 "TARGET_EITHER"
6317 "if (TARGET_ARM)
6318 arm_reload_out_hi (operands);
6319 else
6320 thumb_reload_out_hi (operands);
d3373b54 6321 DONE;
cffb2a26 6322 "
6323)
d3373b54 6324
25f7a26e 6325(define_expand "reload_inhi"
6326 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 6327 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 6328 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 6329 "TARGET_EITHER"
25f7a26e 6330 "
cffb2a26 6331 if (TARGET_ARM)
6332 arm_reload_in_hi (operands);
6333 else
6334 thumb_reload_out_hi (operands);
25f7a26e 6335 DONE;
6336")
6337
9c08d1fa 6338(define_expand "movqi"
6339 [(set (match_operand:QI 0 "general_operand" "")
6340 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 6341 "TARGET_EITHER"
9c08d1fa 6342 "
6cffc037 6343 /* Everything except mem = const or mem = mem can be done easily */
0045890a 6344
e1ba4a27 6345 if (can_create_pseudo_p ())
cffb2a26 6346 {
6cffc037 6347 if (GET_CODE (operands[1]) == CONST_INT)
6348 {
6349 rtx reg = gen_reg_rtx (SImode);
6350
03770691 6351 /* For thumb we want an unsigned immediate, then we are more likely
6352 to be able to use a movs insn. */
6353 if (TARGET_THUMB)
6354 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6355
6cffc037 6356 emit_insn (gen_movsi (reg, operands[1]));
6357 operands[1] = gen_lowpart (QImode, reg);
6358 }
cffb2a26 6359
6cffc037 6360 if (TARGET_THUMB)
6361 {
cffb2a26 6362 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6363 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6364 virtual register (also rejected as illegitimate for HImode/QImode)
6365 relative address. */
cffb2a26 6366 /* ??? This should perhaps be fixed elsewhere, for instance, in
6367 fixup_stack_1, by checking for other kinds of invalid addresses,
6368 e.g. a bare reference to a virtual register. This may confuse the
6369 alpha though, which must handle this case differently. */
6370 if (GET_CODE (operands[0]) == MEM
215b30b3 6371 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 6372 XEXP (operands[0], 0)))
537ffcfc 6373 operands[0]
6374 = replace_equiv_address (operands[0],
6375 copy_to_reg (XEXP (operands[0], 0)));
215b30b3 6376 if (GET_CODE (operands[1]) == MEM
6377 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 6378 XEXP (operands[1], 0)))
537ffcfc 6379 operands[1]
6380 = replace_equiv_address (operands[1],
6381 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6382 }
6383
6384 if (GET_CODE (operands[1]) == MEM && optimize > 0)
6385 {
6386 rtx reg = gen_reg_rtx (SImode);
6387
6388 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6389 operands[1] = gen_lowpart (QImode, reg);
6390 }
6391
6392 if (GET_CODE (operands[0]) == MEM)
6393 operands[1] = force_reg (QImode, operands[1]);
6394 }
6395 else if (TARGET_THUMB
6396 && GET_CODE (operands[1]) == CONST_INT
234f6557 6397 && !satisfies_constraint_I (operands[1]))
6cffc037 6398 {
674a8f0b 6399 /* Handle loading a large integer during reload. */
cffb2a26 6400
6cffc037 6401 /* Writing a constant to memory needs a scratch, which should
6402 be handled with SECONDARY_RELOADs. */
6403 gcc_assert (GET_CODE (operands[0]) == REG);
6404
6405 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6406 emit_insn (gen_movsi (operands[0], operands[1]));
6407 DONE;
cffb2a26 6408 }
6409 "
6410)
b11cae9e 6411
9c08d1fa 6412
cffb2a26 6413(define_insn "*arm_movqi_insn"
a54e3e7b 6414 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,l,Uu,r,m")
6415 (match_operand:QI 1 "general_operand" "rI,K,Uu,l,m,r"))]
25f905c2 6416 "TARGET_32BIT
cffb2a26 6417 && ( register_operand (operands[0], QImode)
6418 || register_operand (operands[1], QImode))"
5565501b 6419 "@
6420 mov%?\\t%0, %1
6421 mvn%?\\t%0, #%B1
25f905c2 6422 ldr%(b%)\\t%0, %1
a54e3e7b 6423 str%(b%)\\t%1, %0
6424 ldr%(b%)\\t%0, %1
25f905c2 6425 str%(b%)\\t%1, %0"
a54e3e7b 6426 [(set_attr "type" "*,*,load1,store1,load1,store1")
6427 (set_attr "insn" "mov,mvn,*,*,*,*")
6428 (set_attr "predicable" "yes")
6429 (set_attr "arch" "any,any,t2,t2,any,any")
6430 (set_attr "length" "4,4,2,2,4,4")]
cffb2a26 6431)
6432
25f905c2 6433(define_insn "*thumb1_movqi_insn"
cffb2a26 6434 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 6435 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
25f905c2 6436 "TARGET_THUMB1
cffb2a26 6437 && ( register_operand (operands[0], QImode)
6438 || register_operand (operands[1], QImode))"
6439 "@
6440 add\\t%0, %1, #0
6441 ldrb\\t%0, %1
6442 strb\\t%1, %0
6443 mov\\t%0, %1
6444 mov\\t%0, %1
6445 mov\\t%0, %1"
6446 [(set_attr "length" "2")
a2cd141b 6447 (set_attr "type" "*,load1,store1,*,*,*")
d2a518d1 6448 (set_attr "insn" "*,*,*,mov,mov,mov")
747b7458 6449 (set_attr "pool_range" "*,32,*,*,*,*")
6450 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
b11cae9e 6451
9b8516be 6452;; HFmode moves
6453(define_expand "movhf"
6454 [(set (match_operand:HF 0 "general_operand" "")
6455 (match_operand:HF 1 "general_operand" ""))]
6456 "TARGET_EITHER"
6457 "
6458 if (TARGET_32BIT)
6459 {
6460 if (GET_CODE (operands[0]) == MEM)
6461 operands[1] = force_reg (HFmode, operands[1]);
6462 }
6463 else /* TARGET_THUMB1 */
6464 {
6465 if (can_create_pseudo_p ())
6466 {
6467 if (GET_CODE (operands[0]) != REG)
6468 operands[1] = force_reg (HFmode, operands[1]);
6469 }
6470 }
6471 "
6472)
6473
6474(define_insn "*arm32_movhf"
6475 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6476 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
a50d7267 6477 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
9b8516be 6478 && ( s_register_operand (operands[0], HFmode)
6479 || s_register_operand (operands[1], HFmode))"
6480 "*
6481 switch (which_alternative)
6482 {
6483 case 0: /* ARM register from memory */
6484 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
6485 case 1: /* memory from ARM register */
6486 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
6487 case 2: /* ARM register from ARM register */
6488 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6489 case 3: /* ARM register from constant */
6490 {
6491 REAL_VALUE_TYPE r;
6492 long bits;
6493 rtx ops[4];
6494
6495 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
6496 bits = real_to_target (NULL, &r, HFmode);
6497 ops[0] = operands[0];
6498 ops[1] = GEN_INT (bits);
6499 ops[2] = GEN_INT (bits & 0xff00);
6500 ops[3] = GEN_INT (bits & 0x00ff);
6501
6502 if (arm_arch_thumb2)
6503 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6504 else
6505 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6506 return \"\";
6507 }
6508 default:
6509 gcc_unreachable ();
6510 }
6511 "
6512 [(set_attr "conds" "unconditional")
6513 (set_attr "type" "load1,store1,*,*")
d2a518d1 6514 (set_attr "insn" "*,*,mov,mov")
9b8516be 6515 (set_attr "length" "4,4,4,8")
d2a518d1 6516 (set_attr "predicable" "yes")]
9b8516be 6517)
6518
6519(define_insn "*thumb1_movhf"
6520 [(set (match_operand:HF 0 "nonimmediate_operand" "=l,l,m,*r,*h")
6521 (match_operand:HF 1 "general_operand" "l,mF,l,*h,*r"))]
6522 "TARGET_THUMB1
6523 && ( s_register_operand (operands[0], HFmode)
6524 || s_register_operand (operands[1], HFmode))"
6525 "*
6526 switch (which_alternative)
6527 {
6528 case 1:
6529 {
6530 rtx addr;
6531 gcc_assert (GET_CODE(operands[1]) == MEM);
6532 addr = XEXP (operands[1], 0);
6533 if (GET_CODE (addr) == LABEL_REF
6534 || (GET_CODE (addr) == CONST
6535 && GET_CODE (XEXP (addr, 0)) == PLUS
6536 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
6537 && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT))
6538 {
6539 /* Constant pool entry. */
6540 return \"ldr\\t%0, %1\";
6541 }
6542 return \"ldrh\\t%0, %1\";
6543 }
6544 case 2: return \"strh\\t%1, %0\";
6545 default: return \"mov\\t%0, %1\";
6546 }
6547 "
6548 [(set_attr "length" "2")
6549 (set_attr "type" "*,load1,store1,*,*")
d2a518d1 6550 (set_attr "insn" "mov,*,*,mov,mov")
747b7458 6551 (set_attr "pool_range" "*,1020,*,*,*")
6552 (set_attr "conds" "clob,nocond,nocond,nocond,nocond")])
9b8516be 6553
87b22bf7 6554(define_expand "movsf"
6555 [(set (match_operand:SF 0 "general_operand" "")
6556 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6557 "TARGET_EITHER"
87b22bf7 6558 "
25f905c2 6559 if (TARGET_32BIT)
cffb2a26 6560 {
6561 if (GET_CODE (operands[0]) == MEM)
6562 operands[1] = force_reg (SFmode, operands[1]);
6563 }
25f905c2 6564 else /* TARGET_THUMB1 */
cffb2a26 6565 {
e1ba4a27 6566 if (can_create_pseudo_p ())
cffb2a26 6567 {
6568 if (GET_CODE (operands[0]) != REG)
6569 operands[1] = force_reg (SFmode, operands[1]);
6570 }
6571 }
6572 "
6573)
6574
03d440a6 6575;; Transform a floating-point move of a constant into a core register into
6576;; an SImode operation.
cffb2a26 6577(define_split
03d440a6 6578 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6579 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6580 "TARGET_EITHER
cffb2a26 6581 && reload_completed
6582 && GET_CODE (operands[1]) == CONST_DOUBLE"
6583 [(set (match_dup 2) (match_dup 3))]
6584 "
6585 operands[2] = gen_lowpart (SImode, operands[0]);
6586 operands[3] = gen_lowpart (SImode, operands[1]);
6587 if (operands[2] == 0 || operands[3] == 0)
6588 FAIL;
215b30b3 6589 "
6590)
87b22bf7 6591
cffb2a26 6592(define_insn "*arm_movsf_soft_insn"
6593 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6594 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 6595 "TARGET_32BIT
cffb2a26 6596 && TARGET_SOFT_FLOAT
215b30b3 6597 && (GET_CODE (operands[0]) != MEM
6598 || register_operand (operands[1], SFmode))"
9a1112d7 6599 "@
6600 mov%?\\t%0, %1
6601 ldr%?\\t%0, %1\\t%@ float
6602 str%?\\t%1, %0\\t%@ float"
cde1623a 6603 [(set_attr "predicable" "yes")
a2cd141b 6604 (set_attr "type" "*,load1,store1")
d2a518d1 6605 (set_attr "insn" "mov,*,*")
cffb2a26 6606 (set_attr "pool_range" "*,4096,*")
cde1623a 6607 (set_attr "arm_neg_pool_range" "*,4084,*")
6608 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 6609)
6610
6611;;; ??? This should have alternatives for constants.
25f905c2 6612(define_insn "*thumb1_movsf_insn"
215b30b3 6613 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
6614 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
25f905c2 6615 "TARGET_THUMB1
cffb2a26 6616 && ( register_operand (operands[0], SFmode)
6617 || register_operand (operands[1], SFmode))"
6618 "@
6619 add\\t%0, %1, #0
6620 ldmia\\t%1, {%0}
6621 stmia\\t%0, {%1}
6622 ldr\\t%0, %1
6623 str\\t%1, %0
6624 mov\\t%0, %1
6625 mov\\t%0, %1"
6626 [(set_attr "length" "2")
a2cd141b 6627 (set_attr "type" "*,load1,store1,load1,store1,*,*")
747b7458 6628 (set_attr "pool_range" "*,*,*,1020,*,*,*")
d2a518d1 6629 (set_attr "insn" "*,*,*,*,*,mov,mov")
747b7458 6630 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,nocond,nocond")]
cffb2a26 6631)
9a1112d7 6632
9c08d1fa 6633(define_expand "movdf"
87b22bf7 6634 [(set (match_operand:DF 0 "general_operand" "")
6635 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 6636 "TARGET_EITHER"
9c08d1fa 6637 "
25f905c2 6638 if (TARGET_32BIT)
cffb2a26 6639 {
6640 if (GET_CODE (operands[0]) == MEM)
6641 operands[1] = force_reg (DFmode, operands[1]);
6642 }
6643 else /* TARGET_THUMB */
6644 {
e1ba4a27 6645 if (can_create_pseudo_p ())
cffb2a26 6646 {
6647 if (GET_CODE (operands[0]) != REG)
6648 operands[1] = force_reg (DFmode, operands[1]);
6649 }
6650 }
6651 "
6652)
b11cae9e 6653
9c08d1fa 6654;; Reloading a df mode value stored in integer regs to memory can require a
6655;; scratch reg.
6656(define_expand "reload_outdf"
cffb2a26 6657 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6658 (match_operand:DF 1 "s_register_operand" "r")
6659 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 6660 "TARGET_THUMB2"
87b22bf7 6661 "
215b30b3 6662 {
6663 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6664
215b30b3 6665 if (code == REG)
6666 operands[2] = XEXP (operands[0], 0);
6667 else if (code == POST_INC || code == PRE_DEC)
6668 {
6669 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6670 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6671 emit_insn (gen_movdi (operands[0], operands[1]));
6672 DONE;
6673 }
6674 else if (code == PRE_INC)
6675 {
6676 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6677
215b30b3 6678 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6679 operands[2] = reg;
6680 }
6681 else if (code == POST_DEC)
6682 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6683 else
6684 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6685 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6686
788fcce0 6687 emit_insn (gen_rtx_SET (VOIDmode,
6688 replace_equiv_address (operands[0], operands[2]),
215b30b3 6689 operands[1]));
f7fbdd4a 6690
215b30b3 6691 if (code == POST_DEC)
6692 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6693
6694 DONE;
6695 }"
6696)
9c08d1fa 6697
9a1112d7 6698(define_insn "*movdf_soft_insn"
359a6e9f 6699 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6700 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
cde1623a 6701 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 6702 && ( register_operand (operands[0], DFmode)
6703 || register_operand (operands[1], DFmode))"
d51f92df 6704 "*
6705 switch (which_alternative)
6706 {
6707 case 0:
6708 case 1:
6709 case 2:
6710 return \"#\";
6711 default:
26ff80c0 6712 return output_move_double (operands, true, NULL);
d51f92df 6713 }
6714 "
359a6e9f 6715 [(set_attr "length" "8,12,16,8,8")
6716 (set_attr "type" "*,*,*,load2,store2")
cde1623a 6717 (set_attr "pool_range" "*,*,*,1020,*")
8848d797 6718 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 6719 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 6720)
6721
6722;;; ??? This should have alternatives for constants.
6723;;; ??? This was originally identical to the movdi_insn pattern.
6724;;; ??? The 'F' constraint looks funny, but it should always be replaced by
6725;;; thumb_reorg with a memory reference.
6726(define_insn "*thumb_movdf_insn"
215b30b3 6727 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
6728 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
25f905c2 6729 "TARGET_THUMB1
cffb2a26 6730 && ( register_operand (operands[0], DFmode)
6731 || register_operand (operands[1], DFmode))"
6732 "*
6733 switch (which_alternative)
6734 {
6735 default:
6736 case 0:
6737 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6738 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6739 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6740 case 1:
6741 return \"ldmia\\t%1, {%0, %H0}\";
6742 case 2:
6743 return \"stmia\\t%0, {%1, %H1}\";
6744 case 3:
6745 return thumb_load_double_from_address (operands);
6746 case 4:
1a83b3ff 6747 operands[2] = gen_rtx_MEM (SImode,
6748 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 6749 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6750 return \"\";
6751 case 5:
6752 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6753 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6754 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6755 }
6756 "
6757 [(set_attr "length" "4,2,2,6,4,4")
a2cd141b 6758 (set_attr "type" "*,load2,store2,load2,store2,*")
d2a518d1 6759 (set_attr "insn" "*,*,*,*,*,mov")
cffb2a26 6760 (set_attr "pool_range" "*,*,*,1020,*,*")]
6761)
755eb2b4 6762
ccd90aaa 6763(define_expand "movxf"
6764 [(set (match_operand:XF 0 "general_operand" "")
6765 (match_operand:XF 1 "general_operand" ""))]
25f905c2 6766 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
ccd90aaa 6767 "
6768 if (GET_CODE (operands[0]) == MEM)
6769 operands[1] = force_reg (XFmode, operands[1]);
6770 "
6771)
6772
b11cae9e 6773\f
b11cae9e 6774
9c08d1fa 6775;; load- and store-multiple insns
6776;; The arm can load/store any set of registers, provided that they are in
320ea44d 6777;; ascending order, but these expanders assume a contiguous set.
b11cae9e 6778
9c08d1fa 6779(define_expand "load_multiple"
6780 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6781 (match_operand:SI 1 "" ""))
6782 (use (match_operand:SI 2 "" ""))])]
25f905c2 6783 "TARGET_32BIT"
9580c25f 6784{
6785 HOST_WIDE_INT offset = 0;
6786
bd5b4116 6787 /* Support only fixed point registers. */
9c08d1fa 6788 if (GET_CODE (operands[2]) != CONST_INT
6789 || INTVAL (operands[2]) > 14
6790 || INTVAL (operands[2]) < 2
6791 || GET_CODE (operands[1]) != MEM
6792 || GET_CODE (operands[0]) != REG
bd5b4116 6793 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6794 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6795 FAIL;
6796
6797 operands[3]
320ea44d 6798 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6799 INTVAL (operands[2]),
f082f1c4 6800 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 6801 FALSE, operands[1], &offset);
9580c25f 6802})
b11cae9e 6803
9c08d1fa 6804(define_expand "store_multiple"
6805 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6806 (match_operand:SI 1 "" ""))
6807 (use (match_operand:SI 2 "" ""))])]
25f905c2 6808 "TARGET_32BIT"
9580c25f 6809{
6810 HOST_WIDE_INT offset = 0;
6811
674a8f0b 6812 /* Support only fixed point registers. */
9c08d1fa 6813 if (GET_CODE (operands[2]) != CONST_INT
6814 || INTVAL (operands[2]) > 14
6815 || INTVAL (operands[2]) < 2
6816 || GET_CODE (operands[1]) != REG
6817 || GET_CODE (operands[0]) != MEM
bd5b4116 6818 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6819 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6820 FAIL;
6821
6822 operands[3]
320ea44d 6823 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6824 INTVAL (operands[2]),
f082f1c4 6825 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 6826 FALSE, operands[0], &offset);
9580c25f 6827})
b11cae9e 6828
9c08d1fa 6829
6830;; Move a block of memory if it is word aligned and MORE than 2 words long.
6831;; We could let this apply for blocks of less than this, but it clobbers so
6832;; many registers that there is then probably a better way.
6833
008c057d 6834(define_expand "movmemqi"
34191dd1 6835 [(match_operand:BLK 0 "general_operand" "")
6836 (match_operand:BLK 1 "general_operand" "")
6837 (match_operand:SI 2 "const_int_operand" "")
6838 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 6839 "TARGET_EITHER"
9c08d1fa 6840 "
25f905c2 6841 if (TARGET_32BIT)
cffb2a26 6842 {
008c057d 6843 if (arm_gen_movmemqi (operands))
cffb2a26 6844 DONE;
6845 FAIL;
6846 }
25f905c2 6847 else /* TARGET_THUMB1 */
cffb2a26 6848 {
6849 if ( INTVAL (operands[3]) != 4
6850 || INTVAL (operands[2]) > 48)
6851 FAIL;
6852
008c057d 6853 thumb_expand_movmemqi (operands);
cffb2a26 6854 DONE;
6855 }
6856 "
6857)
6858
2162064c 6859;; Thumb block-move insns
cffb2a26 6860
6861(define_insn "movmem12b"
960f3acf 6862 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6863 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6864 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6865 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6866 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6867 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6868 (set (match_operand:SI 0 "register_operand" "=l")
6869 (plus:SI (match_dup 2) (const_int 12)))
6870 (set (match_operand:SI 1 "register_operand" "=l")
6871 (plus:SI (match_dup 3) (const_int 12)))
6872 (clobber (match_scratch:SI 4 "=&l"))
6873 (clobber (match_scratch:SI 5 "=&l"))
6874 (clobber (match_scratch:SI 6 "=&l"))]
25f905c2 6875 "TARGET_THUMB1"
cffb2a26 6876 "* return thumb_output_move_mem_multiple (3, operands);"
6877 [(set_attr "length" "4")
215b30b3 6878 ; This isn't entirely accurate... It loads as well, but in terms of
6879 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6880 (set_attr "type" "store3")]
6881)
6882
6883(define_insn "movmem8b"
960f3acf 6884 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6885 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6886 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6887 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6888 (set (match_operand:SI 0 "register_operand" "=l")
6889 (plus:SI (match_dup 2) (const_int 8)))
6890 (set (match_operand:SI 1 "register_operand" "=l")
6891 (plus:SI (match_dup 3) (const_int 8)))
6892 (clobber (match_scratch:SI 4 "=&l"))
6893 (clobber (match_scratch:SI 5 "=&l"))]
25f905c2 6894 "TARGET_THUMB1"
cffb2a26 6895 "* return thumb_output_move_mem_multiple (2, operands);"
6896 [(set_attr "length" "4")
215b30b3 6897 ; This isn't entirely accurate... It loads as well, but in terms of
6898 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6899 (set_attr "type" "store2")]
6900)
6901
9c08d1fa 6902\f
b11cae9e 6903
341940e8 6904;; Compare & branch insns
8d232dc7 6905;; The range calculations are based as follows:
341940e8 6906;; For forward branches, the address calculation returns the address of
6907;; the next instruction. This is 2 beyond the branch instruction.
6908;; For backward branches, the address calculation returns the address of
6909;; the first instruction in this pattern (cmp). This is 2 before the branch
6910;; instruction for the shortest sequence, and 4 before the branch instruction
6911;; if we have to jump around an unconditional branch.
6912;; To the basic branch range the PC offset must be added (this is +4).
6913;; So for forward branches we have
6914;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6915;; And for backward branches we have
6916;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6917;;
6918;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6919;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6920
aeac46d4 6921(define_expand "cbranchsi4"
6922 [(set (pc) (if_then_else
aa06947a 6923 (match_operator 0 "expandable_comparison_operator"
aeac46d4 6924 [(match_operand:SI 1 "s_register_operand" "")
6925 (match_operand:SI 2 "nonmemory_operand" "")])
6926 (label_ref (match_operand 3 "" ""))
6927 (pc)))]
74f4459c 6928 "TARGET_THUMB1 || TARGET_32BIT"
aeac46d4 6929 "
74f4459c 6930 if (!TARGET_THUMB1)
6931 {
6932 if (!arm_add_operand (operands[2], SImode))
6933 operands[2] = force_reg (SImode, operands[2]);
6934 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6935 operands[3]));
6936 DONE;
6937 }
25f905c2 6938 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6939 {
6940 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6941 operands[3], operands[0]));
6942 DONE;
6943 }
25f905c2 6944 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6945 operands[2] = force_reg (SImode, operands[2]);
6946 ")
6947
a8e6c15d 6948;; A pattern to recognize a special situation and optimize for it.
6949;; On the thumb, zero-extension from memory is preferrable to sign-extension
6950;; due to the available addressing modes. Hence, convert a signed comparison
6951;; with zero into an unsigned comparison with 127 if possible.
6952(define_expand "cbranchqi4"
6953 [(set (pc) (if_then_else
6954 (match_operator 0 "lt_ge_comparison_operator"
6955 [(match_operand:QI 1 "memory_operand" "")
6956 (match_operand:QI 2 "const0_operand" "")])
6957 (label_ref (match_operand 3 "" ""))
6958 (pc)))]
6959 "TARGET_THUMB1"
6960{
d0f6c30d 6961 rtx xops[4];
a8e6c15d 6962 xops[1] = gen_reg_rtx (SImode);
6963 emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
6964 xops[2] = GEN_INT (127);
6965 xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
6966 VOIDmode, xops[1], xops[2]);
6967 xops[3] = operands[3];
6968 emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
6969 DONE;
6970})
6971
74f4459c 6972(define_expand "cbranchsf4"
6973 [(set (pc) (if_then_else
aa06947a 6974 (match_operator 0 "expandable_comparison_operator"
74f4459c 6975 [(match_operand:SF 1 "s_register_operand" "")
6976 (match_operand:SF 2 "arm_float_compare_operand" "")])
6977 (label_ref (match_operand 3 "" ""))
6978 (pc)))]
6979 "TARGET_32BIT && TARGET_HARD_FLOAT"
6980 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6981 operands[3])); DONE;"
6982)
6983
6984(define_expand "cbranchdf4"
6985 [(set (pc) (if_then_else
aa06947a 6986 (match_operator 0 "expandable_comparison_operator"
74f4459c 6987 [(match_operand:DF 1 "s_register_operand" "")
6988 (match_operand:DF 2 "arm_float_compare_operand" "")])
6989 (label_ref (match_operand 3 "" ""))
6990 (pc)))]
a50d7267 6991 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 6992 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6993 operands[3])); DONE;"
6994)
6995
74f4459c 6996(define_expand "cbranchdi4"
6997 [(set (pc) (if_then_else
aa06947a 6998 (match_operator 0 "expandable_comparison_operator"
a8045a4f 6999 [(match_operand:DI 1 "cmpdi_operand" "")
7000 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 7001 (label_ref (match_operand 3 "" ""))
7002 (pc)))]
a8045a4f 7003 "TARGET_32BIT"
7004 "{
7005 rtx swap = NULL_RTX;
7006 enum rtx_code code = GET_CODE (operands[0]);
7007
7008 /* We should not have two constants. */
7009 gcc_assert (GET_MODE (operands[1]) == DImode
7010 || GET_MODE (operands[2]) == DImode);
7011
7012 /* Flip unimplemented DImode comparisons to a form that
7013 arm_gen_compare_reg can handle. */
7014 switch (code)
7015 {
7016 case GT:
7017 swap = gen_rtx_LT (VOIDmode, operands[2], operands[1]); break;
7018 case LE:
7019 swap = gen_rtx_GE (VOIDmode, operands[2], operands[1]); break;
7020 case GTU:
7021 swap = gen_rtx_LTU (VOIDmode, operands[2], operands[1]); break;
7022 case LEU:
7023 swap = gen_rtx_GEU (VOIDmode, operands[2], operands[1]); break;
7024 default:
7025 break;
7026 }
7027 if (swap)
7028 emit_jump_insn (gen_cbranch_cc (swap, operands[2], operands[1],
7029 operands[3]));
7030 else
7031 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7032 operands[3]));
7033 DONE;
7034 }"
74f4459c 7035)
7036
d60047aa 7037(define_insn "cbranchsi4_insn"
aeac46d4 7038 [(set (pc) (if_then_else
7039 (match_operator 0 "arm_comparison_operator"
747b7458 7040 [(match_operand:SI 1 "s_register_operand" "l,l*h")
25f905c2 7041 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
aeac46d4 7042 (label_ref (match_operand 3 "" ""))
7043 (pc)))]
25f905c2 7044 "TARGET_THUMB1"
747b7458 7045{
7046 rtx t = cfun->machine->thumb1_cc_insn;
7047 if (t != NULL_RTX)
d60047aa 7048 {
747b7458 7049 if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
7050 || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2]))
7051 t = NULL_RTX;
7052 if (cfun->machine->thumb1_cc_mode == CC_NOOVmode)
7053 {
7054 if (!noov_comparison_operator (operands[0], VOIDmode))
7055 t = NULL_RTX;
7056 }
7057 else if (cfun->machine->thumb1_cc_mode != CCmode)
d60047aa 7058 t = NULL_RTX;
7059 }
d60047aa 7060 if (t == NULL_RTX)
747b7458 7061 {
7062 output_asm_insn ("cmp\t%1, %2", operands);
7063 cfun->machine->thumb1_cc_insn = insn;
7064 cfun->machine->thumb1_cc_op0 = operands[1];
7065 cfun->machine->thumb1_cc_op1 = operands[2];
7066 cfun->machine->thumb1_cc_mode = CCmode;
7067 }
7068 else
7069 /* Ensure we emit the right type of condition code on the jump. */
7070 XEXP (operands[0], 0) = gen_rtx_REG (cfun->machine->thumb1_cc_mode,
7071 CC_REGNUM);
aeac46d4 7072
cffb2a26 7073 switch (get_attr_length (insn))
7074 {
7075 case 4: return \"b%d0\\t%l3\";
7076 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7077 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7078 }
747b7458 7079}
cffb2a26 7080 [(set (attr "far_jump")
7081 (if_then_else
7082 (eq_attr "length" "8")
7083 (const_string "yes")
7084 (const_string "no")))
7085 (set (attr "length")
7086 (if_then_else
7087 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7088 (le (minus (match_dup 3) (pc)) (const_int 256)))
7089 (const_int 4)
7090 (if_then_else
7091 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 7092 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 7093 (const_int 6)
7094 (const_int 8))))]
7095)
7096
aeac46d4 7097(define_insn "cbranchsi4_scratch"
7098 [(set (pc) (if_then_else
7099 (match_operator 4 "arm_comparison_operator"
7100 [(match_operand:SI 1 "s_register_operand" "l,0")
25f905c2 7101 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
aeac46d4 7102 (label_ref (match_operand 3 "" ""))
7103 (pc)))
7104 (clobber (match_scratch:SI 0 "=l,l"))]
25f905c2 7105 "TARGET_THUMB1"
aeac46d4 7106 "*
7107 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
7108
7109 switch (get_attr_length (insn))
7110 {
7111 case 4: return \"b%d4\\t%l3\";
7112 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7113 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7114 }
7115 "
7116 [(set (attr "far_jump")
7117 (if_then_else
7118 (eq_attr "length" "8")
7119 (const_string "yes")
7120 (const_string "no")))
7121 (set (attr "length")
7122 (if_then_else
7123 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7124 (le (minus (match_dup 3) (pc)) (const_int 256)))
7125 (const_int 4)
7126 (if_then_else
7127 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7128 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7129 (const_int 6)
7130 (const_int 8))))]
7131)
446a1e96 7132
747b7458 7133;; Two peepholes to generate subtract of 0 instead of a move if the
7134;; condition codes will be useful.
446a1e96 7135(define_peephole2
7136 [(set (match_operand:SI 0 "low_register_operand" "")
7137 (match_operand:SI 1 "low_register_operand" ""))
7138 (set (pc)
7139 (if_then_else (match_operator 2 "arm_comparison_operator"
7140 [(match_dup 1) (const_int 0)])
7141 (label_ref (match_operand 3 "" ""))
7142 (pc)))]
7143 "TARGET_THUMB1"
747b7458 7144 [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
7145 (set (pc)
7146 (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
446a1e96 7147 (label_ref (match_dup 3))
747b7458 7148 (pc)))]
7149 "")
446a1e96 7150
7151;; Sigh! This variant shouldn't be needed, but combine often fails to
7152;; merge cases like this because the op1 is a hard register in
07d32235 7153;; arm_class_likely_spilled_p.
446a1e96 7154(define_peephole2
7155 [(set (match_operand:SI 0 "low_register_operand" "")
7156 (match_operand:SI 1 "low_register_operand" ""))
7157 (set (pc)
7158 (if_then_else (match_operator 2 "arm_comparison_operator"
7159 [(match_dup 0) (const_int 0)])
7160 (label_ref (match_operand 3 "" ""))
7161 (pc)))]
7162 "TARGET_THUMB1"
747b7458 7163 [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
7164 (set (pc)
7165 (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
446a1e96 7166 (label_ref (match_dup 3))
747b7458 7167 (pc)))]
7168 "")
446a1e96 7169
cffb2a26 7170(define_insn "*negated_cbranchsi4"
7171 [(set (pc)
7172 (if_then_else
aed179ae 7173 (match_operator 0 "equality_operator"
aeac46d4 7174 [(match_operand:SI 1 "s_register_operand" "l")
7175 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
7176 (label_ref (match_operand 3 "" ""))
215b30b3 7177 (pc)))]
25f905c2 7178 "TARGET_THUMB1"
cffb2a26 7179 "*
7180 output_asm_insn (\"cmn\\t%1, %2\", operands);
7181 switch (get_attr_length (insn))
7182 {
7183 case 4: return \"b%d0\\t%l3\";
7184 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7185 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7186 }
7187 "
7188 [(set (attr "far_jump")
7189 (if_then_else
7190 (eq_attr "length" "8")
7191 (const_string "yes")
7192 (const_string "no")))
7193 (set (attr "length")
7194 (if_then_else
7195 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 7196 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 7197 (const_int 4)
7198 (if_then_else
341940e8 7199 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7200 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 7201 (const_int 6)
7202 (const_int 8))))]
7203)
7204
58d6528b 7205(define_insn "*tbit_cbranch"
7206 [(set (pc)
7207 (if_then_else
7208 (match_operator 0 "equality_operator"
7209 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
7210 (const_int 1)
7211 (match_operand:SI 2 "const_int_operand" "i"))
7212 (const_int 0)])
7213 (label_ref (match_operand 3 "" ""))
7214 (pc)))
7215 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 7216 "TARGET_THUMB1"
58d6528b 7217 "*
7218 {
7219 rtx op[3];
7220 op[0] = operands[4];
7221 op[1] = operands[1];
7222 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
7223
86efa74d 7224 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
7225 switch (get_attr_length (insn))
7226 {
7227 case 4: return \"b%d0\\t%l3\";
7228 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7229 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7230 }
7231 }"
7232 [(set (attr "far_jump")
7233 (if_then_else
7234 (eq_attr "length" "8")
7235 (const_string "yes")
7236 (const_string "no")))
7237 (set (attr "length")
7238 (if_then_else
7239 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7240 (le (minus (match_dup 3) (pc)) (const_int 256)))
7241 (const_int 4)
7242 (if_then_else
7243 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7244 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7245 (const_int 6)
7246 (const_int 8))))]
7247)
7248
7249(define_insn "*tlobits_cbranch"
7250 [(set (pc)
7251 (if_then_else
7252 (match_operator 0 "equality_operator"
7253 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
7254 (match_operand:SI 2 "const_int_operand" "i")
7255 (const_int 0))
7256 (const_int 0)])
7257 (label_ref (match_operand 3 "" ""))
7258 (pc)))
7259 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 7260 "TARGET_THUMB1"
86efa74d 7261 "*
7262 {
7263 rtx op[3];
7264 op[0] = operands[4];
7265 op[1] = operands[1];
7266 op[2] = GEN_INT (32 - INTVAL (operands[2]));
7267
58d6528b 7268 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
7269 switch (get_attr_length (insn))
7270 {
7271 case 4: return \"b%d0\\t%l3\";
7272 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7273 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7274 }
7275 }"
7276 [(set (attr "far_jump")
7277 (if_then_else
7278 (eq_attr "length" "8")
7279 (const_string "yes")
7280 (const_string "no")))
7281 (set (attr "length")
7282 (if_then_else
7283 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7284 (le (minus (match_dup 3) (pc)) (const_int 256)))
7285 (const_int 4)
7286 (if_then_else
7287 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7288 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7289 (const_int 6)
7290 (const_int 8))))]
7291)
747b7458 7292
aeac46d4 7293(define_insn "*tstsi3_cbranch"
58d6528b 7294 [(set (pc)
7295 (if_then_else
aeac46d4 7296 (match_operator 3 "equality_operator"
7297 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
7298 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 7299 (const_int 0)])
aeac46d4 7300 (label_ref (match_operand 2 "" ""))
7301 (pc)))]
25f905c2 7302 "TARGET_THUMB1"
58d6528b 7303 "*
7304 {
aeac46d4 7305 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 7306 switch (get_attr_length (insn))
7307 {
aeac46d4 7308 case 4: return \"b%d3\\t%l2\";
7309 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
7310 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 7311 }
7312 }"
7313 [(set (attr "far_jump")
7314 (if_then_else
7315 (eq_attr "length" "8")
7316 (const_string "yes")
7317 (const_string "no")))
7318 (set (attr "length")
7319 (if_then_else
aeac46d4 7320 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
7321 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 7322 (const_int 4)
7323 (if_then_else
aeac46d4 7324 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
7325 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 7326 (const_int 6)
7327 (const_int 8))))]
7328)
7329
203c488f 7330(define_insn "*cbranchne_decr1"
7331 [(set (pc)
7332 (if_then_else (match_operator 3 "equality_operator"
7333 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
7334 (const_int 0)])
7335 (label_ref (match_operand 4 "" ""))
7336 (pc)))
aeac46d4 7337 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 7338 (plus:SI (match_dup 2) (const_int -1)))
7339 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7340 "TARGET_THUMB1"
203c488f 7341 "*
7342 {
7343 rtx cond[2];
7344 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
7345 ? GEU : LTU),
58d6528b 7346 VOIDmode, operands[2], const1_rtx);
203c488f 7347 cond[1] = operands[4];
7348
7349 if (which_alternative == 0)
7350 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
7351 else if (which_alternative == 1)
7352 {
7353 /* We must provide an alternative for a hi reg because reload
7354 cannot handle output reloads on a jump instruction, but we
7355 can't subtract into that. Fortunately a mov from lo to hi
7356 does not clobber the condition codes. */
7357 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7358 output_asm_insn (\"mov\\t%0, %1\", operands);
7359 }
7360 else
7361 {
7362 /* Similarly, but the target is memory. */
7363 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7364 output_asm_insn (\"str\\t%1, %0\", operands);
7365 }
7366
7367 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7368 {
7369 case 4:
8aea555f 7370 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 7371 return \"\";
7372 case 6:
8aea555f 7373 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 7374 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
7375 default:
8aea555f 7376 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 7377 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7378 }
7379 }
7380 "
7381 [(set (attr "far_jump")
7382 (if_then_else
7383 (ior (and (eq (symbol_ref ("which_alternative"))
7384 (const_int 0))
7385 (eq_attr "length" "8"))
7386 (eq_attr "length" "10"))
7387 (const_string "yes")
7388 (const_string "no")))
7389 (set_attr_alternative "length"
7390 [
7391 ;; Alternative 0
7392 (if_then_else
7393 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7394 (le (minus (match_dup 4) (pc)) (const_int 256)))
7395 (const_int 4)
7396 (if_then_else
7397 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7398 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7399 (const_int 6)
7400 (const_int 8)))
7401 ;; Alternative 1
7402 (if_then_else
7403 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7404 (le (minus (match_dup 4) (pc)) (const_int 256)))
7405 (const_int 6)
7406 (if_then_else
7407 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7408 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7409 (const_int 8)
7410 (const_int 10)))
7411 ;; Alternative 2
7412 (if_then_else
7413 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7414 (le (minus (match_dup 4) (pc)) (const_int 256)))
7415 (const_int 6)
7416 (if_then_else
7417 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7418 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7419 (const_int 8)
7420 (const_int 10)))
7421 ;; Alternative 3
7422 (if_then_else
7423 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7424 (le (minus (match_dup 4) (pc)) (const_int 256)))
7425 (const_int 6)
7426 (if_then_else
7427 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7428 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7429 (const_int 8)
7430 (const_int 10)))])]
7431)
cffb2a26 7432
58d6528b 7433(define_insn "*addsi3_cbranch"
7434 [(set (pc)
7435 (if_then_else
b0694be0 7436 (match_operator 4 "arm_comparison_operator"
58d6528b 7437 [(plus:SI
e54011cb 7438 (match_operand:SI 2 "s_register_operand" "%0,l,*l,1,1,1")
7439 (match_operand:SI 3 "reg_or_int_operand" "IJ,lL,*l,lIJ,lIJ,lIJ"))
58d6528b 7440 (const_int 0)])
7441 (label_ref (match_operand 5 "" ""))
7442 (pc)))
aeac46d4 7443 (set
7444 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
7445 (plus:SI (match_dup 2) (match_dup 3)))
956a6170 7446 (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
25f905c2 7447 "TARGET_THUMB1
58d6528b 7448 && (GET_CODE (operands[4]) == EQ
7449 || GET_CODE (operands[4]) == NE
7450 || GET_CODE (operands[4]) == GE
7451 || GET_CODE (operands[4]) == LT)"
7452 "*
7453 {
7454 rtx cond[3];
7455
956a6170 7456 cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
58d6528b 7457 cond[1] = operands[2];
7458 cond[2] = operands[3];
7459
7460 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
7461 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
7462 else
7463 output_asm_insn (\"add\\t%0, %1, %2\", cond);
7464
956a6170 7465 if (which_alternative >= 2
58d6528b 7466 && which_alternative < 4)
7467 output_asm_insn (\"mov\\t%0, %1\", operands);
7468 else if (which_alternative >= 4)
7469 output_asm_insn (\"str\\t%1, %0\", operands);
7470
d0f6c30d 7471 switch (get_attr_length (insn) - ((which_alternative >= 2) ? 2 : 0))
58d6528b 7472 {
7473 case 4:
7474 return \"b%d4\\t%l5\";
7475 case 6:
7476 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7477 default:
7478 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7479 }
7480 }
7481 "
7482 [(set (attr "far_jump")
7483 (if_then_else
7484 (ior (and (lt (symbol_ref ("which_alternative"))
d0f6c30d 7485 (const_int 2))
58d6528b 7486 (eq_attr "length" "8"))
7487 (eq_attr "length" "10"))
7488 (const_string "yes")
7489 (const_string "no")))
7490 (set (attr "length")
7491 (if_then_else
7492 (lt (symbol_ref ("which_alternative"))
d0f6c30d 7493 (const_int 2))
58d6528b 7494 (if_then_else
7495 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7496 (le (minus (match_dup 5) (pc)) (const_int 256)))
7497 (const_int 4)
7498 (if_then_else
7499 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7500 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7501 (const_int 6)
7502 (const_int 8)))
7503 (if_then_else
7504 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7505 (le (minus (match_dup 5) (pc)) (const_int 256)))
7506 (const_int 6)
7507 (if_then_else
7508 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7509 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7510 (const_int 8)
7511 (const_int 10)))))]
7512)
7513
7514(define_insn "*addsi3_cbranch_scratch"
7515 [(set (pc)
7516 (if_then_else
b0694be0 7517 (match_operator 3 "arm_comparison_operator"
58d6528b 7518 [(plus:SI
7519 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 7520 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 7521 (const_int 0)])
7522 (label_ref (match_operand 4 "" ""))
7523 (pc)))
7524 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
25f905c2 7525 "TARGET_THUMB1
58d6528b 7526 && (GET_CODE (operands[3]) == EQ
7527 || GET_CODE (operands[3]) == NE
7528 || GET_CODE (operands[3]) == GE
7529 || GET_CODE (operands[3]) == LT)"
7530 "*
7531 {
7532 switch (which_alternative)
7533 {
7534 case 0:
7535 output_asm_insn (\"cmp\t%1, #%n2\", operands);
7536 break;
7537 case 1:
7538 output_asm_insn (\"cmn\t%1, %2\", operands);
7539 break;
0f5e9701 7540 case 2:
3a445a04 7541 if (INTVAL (operands[2]) < 0)
7542 output_asm_insn (\"sub\t%0, %1, %2\", operands);
7543 else
7544 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 7545 break;
0f5e9701 7546 case 3:
3a445a04 7547 if (INTVAL (operands[2]) < 0)
7548 output_asm_insn (\"sub\t%0, %0, %2\", operands);
7549 else
7550 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 7551 break;
7552 }
7553
7554 switch (get_attr_length (insn))
7555 {
7556 case 4:
7557 return \"b%d3\\t%l4\";
7558 case 6:
7559 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7560 default:
7561 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7562 }
7563 }
7564 "
7565 [(set (attr "far_jump")
7566 (if_then_else
7567 (eq_attr "length" "8")
7568 (const_string "yes")
7569 (const_string "no")))
7570 (set (attr "length")
7571 (if_then_else
7572 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7573 (le (minus (match_dup 4) (pc)) (const_int 256)))
7574 (const_int 4)
7575 (if_then_else
7576 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7577 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7578 (const_int 6)
7579 (const_int 8))))]
7580)
7581
58d6528b 7582
9c08d1fa 7583;; Comparison and test insns
7584
cffb2a26 7585(define_insn "*arm_cmpsi_insn"
bd5b4116 7586 [(set (reg:CC CC_REGNUM)
a6864a24 7587 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r")
7588 (match_operand:SI 1 "arm_add_operand" "Py,r,rI,L")))]
25f905c2 7589 "TARGET_32BIT"
5565501b 7590 "@
a6864a24 7591 cmp%?\\t%0, %1
7592 cmp%?\\t%0, %1
aea4c774 7593 cmp%?\\t%0, %1
7594 cmn%?\\t%0, #%n1"
a6864a24 7595 [(set_attr "conds" "set")
7596 (set_attr "arch" "t2,t2,any,any")
596e5e8f 7597 (set_attr "length" "2,2,4,4")
7598 (set_attr "predicable" "yes")]
cffb2a26 7599)
b11cae9e 7600
d5d4dc8d 7601(define_insn "*cmpsi_shiftsi"
bd5b4116 7602 [(set (reg:CC CC_REGNUM)
d5d4dc8d 7603 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 7604 (match_operator:SI 3 "shift_operator"
d5d4dc8d 7605 [(match_operand:SI 1 "s_register_operand" "r,r")
7606 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
7607 "TARGET_32BIT"
aea4c774 7608 "cmp%?\\t%0, %1%S3"
344495ea 7609 [(set_attr "conds" "set")
331beb1a 7610 (set_attr "shift" "1")
d5d4dc8d 7611 (set_attr "arch" "32,a")
7612 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7613
d5d4dc8d 7614(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 7615 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7616 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d5d4dc8d 7617 [(match_operand:SI 1 "s_register_operand" "r,r")
7618 (match_operand:SI 2 "shift_amount_operand" "M,rM")])
7619 (match_operand:SI 0 "s_register_operand" "r,r")))]
7620 "TARGET_32BIT"
aea4c774 7621 "cmp%?\\t%0, %1%S3"
344495ea 7622 [(set_attr "conds" "set")
331beb1a 7623 (set_attr "shift" "1")
d5d4dc8d 7624 (set_attr "arch" "32,a")
7625 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7626
25f905c2 7627(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7628 [(set (reg:CC_Z CC_REGNUM)
7629 (compare:CC_Z
7630 (neg:SI (match_operator:SI 1 "shift_operator"
7631 [(match_operand:SI 2 "s_register_operand" "r")
7632 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7633 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7634 "TARGET_ARM"
aed179ae 7635 "cmn%?\\t%0, %2%S1"
344495ea 7636 [(set_attr "conds" "set")
aed179ae 7637 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7638 (const_string "alu_shift")
596e5e8f 7639 (const_string "alu_shift_reg")))
7640 (set_attr "predicable" "yes")]
0d66636f 7641)
b11cae9e 7642
a8045a4f 7643;; DImode comparisons. The generic code generates branches that
7644;; if-conversion can not reduce to a conditional compare, so we do
7645;; that directly.
7646
7647(define_insn "*arm_cmpdi_insn"
7648 [(set (reg:CC_NCV CC_REGNUM)
7649 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7650 (match_operand:DI 1 "arm_di_operand" "rDi")))
7651 (clobber (match_scratch:SI 2 "=r"))]
7652 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
7653 "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7654 [(set_attr "conds" "set")
7655 (set_attr "length" "8")]
7656)
7657
7658(define_insn "*arm_cmpdi_unsigned"
7659 [(set (reg:CC_CZ CC_REGNUM)
7660 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "r")
7661 (match_operand:DI 1 "arm_di_operand" "rDi")))]
48a98053 7662 "TARGET_32BIT"
7663 "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
a8045a4f 7664 [(set_attr "conds" "set")
7665 (set_attr "length" "8")]
7666)
7667
7668(define_insn "*arm_cmpdi_zero"
7669 [(set (reg:CC_Z CC_REGNUM)
7670 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7671 (const_int 0)))
7672 (clobber (match_scratch:SI 1 "=r"))]
7673 "TARGET_32BIT"
7674 "orr%.\\t%1, %Q0, %R0"
7675 [(set_attr "conds" "set")]
7676)
7677
7678(define_insn "*thumb_cmpdi_zero"
7679 [(set (reg:CC_Z CC_REGNUM)
7680 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
7681 (const_int 0)))
7682 (clobber (match_scratch:SI 1 "=l"))]
7683 "TARGET_THUMB1"
7684 "orr\\t%1, %Q0, %R0"
7685 [(set_attr "conds" "set")
7686 (set_attr "length" "2")]
7687)
7688
7d57ec45 7689;; Cirrus SF compare instruction
7690(define_insn "*cirrus_cmpsf"
7691 [(set (reg:CCFP CC_REGNUM)
7692 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7693 (match_operand:SF 1 "cirrus_fp_register" "v")))]
a2cd141b 7694 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7695 "cfcmps%?\\tr15, %V0, %V1"
2c6c7d8b 7696 [(set_attr "type" "mav_farith")
7d57ec45 7697 (set_attr "cirrus" "compare")]
7698)
7699
7700;; Cirrus DF compare instruction
7701(define_insn "*cirrus_cmpdf"
7702 [(set (reg:CCFP CC_REGNUM)
7703 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7704 (match_operand:DF 1 "cirrus_fp_register" "v")))]
a2cd141b 7705 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7706 "cfcmpd%?\\tr15, %V0, %V1"
2c6c7d8b 7707 [(set_attr "type" "mav_farith")
7d57ec45 7708 (set_attr "cirrus" "compare")]
7709)
7710
7d57ec45 7711(define_insn "*cirrus_cmpdi"
7712 [(set (reg:CC CC_REGNUM)
7713 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7714 (match_operand:DI 1 "cirrus_fp_register" "v")))]
a2cd141b 7715 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7716 "cfcmp64%?\\tr15, %V0, %V1"
2c6c7d8b 7717 [(set_attr "type" "mav_farith")
7d57ec45 7718 (set_attr "cirrus" "compare")]
7719)
7720
9c08d1fa 7721; This insn allows redundant compares to be removed by cse, nothing should
7722; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7723; is deleted later on. The match_dup will match the mode here, so that
7724; mode changes of the condition codes aren't lost by this even though we don't
7725; specify what they are.
7726
8a18b90c 7727(define_insn "*deleted_compare"
9c08d1fa 7728 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7729 "TARGET_32BIT"
40dbec34 7730 "\\t%@ deleted compare"
cffb2a26 7731 [(set_attr "conds" "set")
7732 (set_attr "length" "0")]
7733)
9c08d1fa 7734
7735\f
7736;; Conditional branch insns
7737
74f4459c 7738(define_expand "cbranch_cc"
9c08d1fa 7739 [(set (pc)
74f4459c 7740 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7741 (match_operand 2 "" "")])
7742 (label_ref (match_operand 3 "" ""))
9c08d1fa 7743 (pc)))]
25f905c2 7744 "TARGET_32BIT"
74f4459c 7745 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
e1b93706 7746 operands[1], operands[2], NULL_RTX);
74f4459c 7747 operands[2] = const0_rtx;"
8fa3ba89 7748)
7749
7750;;
7751;; Patterns to match conditional branch insns.
7752;;
7753
cffb2a26 7754(define_insn "*arm_cond_branch"
9c08d1fa 7755 [(set (pc)
8fa3ba89 7756 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7757 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7758 (label_ref (match_operand 0 "" ""))
7759 (pc)))]
25f905c2 7760 "TARGET_32BIT"
d75350ce 7761 "*
9c08d1fa 7762 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7763 {
7764 arm_ccfsm_state += 2;
7765 return \"\";
7766 }
e2348bcb 7767 return \"b%d1\\t%l0\";
cffb2a26 7768 "
a2cd141b 7769 [(set_attr "conds" "use")
a6864a24 7770 (set_attr "type" "branch")
7771 (set (attr "length")
7772 (if_then_else
0bf497f5 7773 (and (match_test "TARGET_THUMB2")
a6864a24 7774 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7775 (le (minus (match_dup 0) (pc)) (const_int 256))))
7776 (const_int 2)
7777 (const_int 4)))]
cffb2a26 7778)
d75350ce 7779
cffb2a26 7780(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7781 [(set (pc)
8fa3ba89 7782 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7783 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7784 (pc)
7785 (label_ref (match_operand 0 "" ""))))]
25f905c2 7786 "TARGET_32BIT"
d75350ce 7787 "*
9c08d1fa 7788 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7789 {
7790 arm_ccfsm_state += 2;
7791 return \"\";
7792 }
e2348bcb 7793 return \"b%D1\\t%l0\";
cffb2a26 7794 "
a2cd141b 7795 [(set_attr "conds" "use")
a6864a24 7796 (set_attr "type" "branch")
7797 (set (attr "length")
7798 (if_then_else
0bf497f5 7799 (and (match_test "TARGET_THUMB2")
a6864a24 7800 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7801 (le (minus (match_dup 0) (pc)) (const_int 256))))
7802 (const_int 2)
7803 (const_int 4)))]
cffb2a26 7804)
7805
b11cae9e 7806\f
9c08d1fa 7807
7808; scc insns
7809
74f4459c 7810(define_expand "cstore_cc"
7db9af5d 7811 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7812 (match_operator:SI 1 "" [(match_operand 2 "" "")
7813 (match_operand 3 "" "")]))]
25f905c2 7814 "TARGET_32BIT"
74f4459c 7815 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
e1b93706 7816 operands[2], operands[3], NULL_RTX);
74f4459c 7817 operands[3] = const0_rtx;"
8fa3ba89 7818)
7819
f7fbdd4a 7820(define_insn "*mov_scc"
9c08d1fa 7821 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7822 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7823 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7824 "TARGET_ARM"
4d61e570 7825 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 7826 [(set_attr "conds" "use")
d2a518d1 7827 (set_attr "insn" "mov")
cffb2a26 7828 (set_attr "length" "8")]
7829)
9c08d1fa 7830
f7fbdd4a 7831(define_insn "*mov_negscc"
9c08d1fa 7832 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7833 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7834 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7835 "TARGET_ARM"
4d61e570 7836 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 7837 [(set_attr "conds" "use")
d2a518d1 7838 (set_attr "insn" "mov")
cffb2a26 7839 (set_attr "length" "8")]
7840)
9c08d1fa 7841
f7fbdd4a 7842(define_insn "*mov_notscc"
9c08d1fa 7843 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7844 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7845 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7846 "TARGET_ARM"
7d0a3bab 7847 "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 7848 [(set_attr "conds" "use")
d2a518d1 7849 (set_attr "insn" "mov")
cffb2a26 7850 (set_attr "length" "8")]
7851)
9c08d1fa 7852
595d88b5 7853(define_expand "cstoresi4"
7854 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7855 (match_operator:SI 1 "expandable_comparison_operator"
595d88b5 7856 [(match_operand:SI 2 "s_register_operand" "")
7857 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7858 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7859 "{
7860 rtx op3, scratch, scratch2;
7861
74f4459c 7862 if (!TARGET_THUMB1)
7863 {
7864 if (!arm_add_operand (operands[3], SImode))
7865 operands[3] = force_reg (SImode, operands[3]);
7866 emit_insn (gen_cstore_cc (operands[0], operands[1],
7867 operands[2], operands[3]));
7868 DONE;
7869 }
7870
595d88b5 7871 if (operands[3] == const0_rtx)
7872 {
7873 switch (GET_CODE (operands[1]))
7874 {
7875 case EQ:
25f905c2 7876 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7877 break;
7878
7879 case NE:
25f905c2 7880 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7881 break;
7882
7883 case LE:
7884 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7885 NULL_RTX, 0, OPTAB_WIDEN);
7886 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7887 NULL_RTX, 0, OPTAB_WIDEN);
7888 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7889 operands[0], 1, OPTAB_WIDEN);
7890 break;
7891
7892 case GE:
7893 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7894 NULL_RTX, 1);
7895 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7896 NULL_RTX, 1, OPTAB_WIDEN);
7897 break;
7898
7899 case GT:
7900 scratch = expand_binop (SImode, ashr_optab, operands[2],
7901 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7902 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7903 NULL_RTX, 0, OPTAB_WIDEN);
7904 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7905 0, OPTAB_WIDEN);
7906 break;
7907
7908 /* LT is handled by generic code. No need for unsigned with 0. */
7909 default:
7910 FAIL;
7911 }
7912 DONE;
7913 }
7914
7915 switch (GET_CODE (operands[1]))
7916 {
7917 case EQ:
7918 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7919 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7920 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7921 break;
7922
7923 case NE:
7924 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7925 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7926 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7927 break;
7928
7929 case LE:
7930 op3 = force_reg (SImode, operands[3]);
7931
7932 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7933 NULL_RTX, 1, OPTAB_WIDEN);
7934 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7935 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7936 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7937 op3, operands[2]));
7938 break;
7939
7940 case GE:
7941 op3 = operands[3];
25f905c2 7942 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7943 op3 = force_reg (SImode, op3);
7944 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7945 NULL_RTX, 0, OPTAB_WIDEN);
7946 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7947 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7948 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7949 operands[2], op3));
7950 break;
7951
7952 case LEU:
7953 op3 = force_reg (SImode, operands[3]);
7954 scratch = force_reg (SImode, const0_rtx);
25f905c2 7955 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7956 op3, operands[2]));
7957 break;
7958
7959 case GEU:
7960 op3 = operands[3];
25f905c2 7961 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7962 op3 = force_reg (SImode, op3);
7963 scratch = force_reg (SImode, const0_rtx);
25f905c2 7964 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7965 operands[2], op3));
7966 break;
7967
7968 case LTU:
7969 op3 = operands[3];
25f905c2 7970 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7971 op3 = force_reg (SImode, op3);
7972 scratch = gen_reg_rtx (SImode);
408b7ae5 7973 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7974 break;
7975
7976 case GTU:
7977 op3 = force_reg (SImode, operands[3]);
7978 scratch = gen_reg_rtx (SImode);
408b7ae5 7979 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7980 break;
7981
7982 /* No good sequences for GT, LT. */
7983 default:
7984 FAIL;
7985 }
7986 DONE;
7987}")
7988
74f4459c 7989(define_expand "cstoresf4"
7990 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7991 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7992 [(match_operand:SF 2 "s_register_operand" "")
7993 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
7994 "TARGET_32BIT && TARGET_HARD_FLOAT"
7995 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7996 operands[2], operands[3])); DONE;"
7997)
7998
7999(define_expand "cstoredf4"
8000 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 8001 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 8002 [(match_operand:DF 2 "s_register_operand" "")
8003 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
d63ed457 8004 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 8005 "emit_insn (gen_cstore_cc (operands[0], operands[1],
8006 operands[2], operands[3])); DONE;"
8007)
8008
74f4459c 8009(define_expand "cstoredi4"
8010 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 8011 (match_operator:SI 1 "expandable_comparison_operator"
a8045a4f 8012 [(match_operand:DI 2 "cmpdi_operand" "")
8013 (match_operand:DI 3 "cmpdi_operand" "")]))]
8014 "TARGET_32BIT"
8015 "{
8016 rtx swap = NULL_RTX;
8017 enum rtx_code code = GET_CODE (operands[1]);
8018
8019 /* We should not have two constants. */
8020 gcc_assert (GET_MODE (operands[2]) == DImode
8021 || GET_MODE (operands[3]) == DImode);
8022
8023 /* Flip unimplemented DImode comparisons to a form that
8024 arm_gen_compare_reg can handle. */
8025 switch (code)
8026 {
8027 case GT:
8028 swap = gen_rtx_LT (VOIDmode, operands[3], operands[2]); break;
8029 case LE:
8030 swap = gen_rtx_GE (VOIDmode, operands[3], operands[2]); break;
8031 case GTU:
8032 swap = gen_rtx_LTU (VOIDmode, operands[3], operands[2]); break;
8033 case LEU:
8034 swap = gen_rtx_GEU (VOIDmode, operands[3], operands[2]); break;
8035 default:
8036 break;
8037 }
8038 if (swap)
8039 emit_insn (gen_cstore_cc (operands[0], swap, operands[3],
8040 operands[2]));
8041 else
8042 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
8043 operands[3]));
8044 DONE;
8045 }"
74f4459c 8046)
8047
25f905c2 8048(define_expand "cstoresi_eq0_thumb1"
595d88b5 8049 [(parallel
8050 [(set (match_operand:SI 0 "s_register_operand" "")
8051 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8052 (const_int 0)))
8053 (clobber (match_dup:SI 2))])]
25f905c2 8054 "TARGET_THUMB1"
595d88b5 8055 "operands[2] = gen_reg_rtx (SImode);"
8056)
8057
25f905c2 8058(define_expand "cstoresi_ne0_thumb1"
595d88b5 8059 [(parallel
8060 [(set (match_operand:SI 0 "s_register_operand" "")
8061 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8062 (const_int 0)))
8063 (clobber (match_dup:SI 2))])]
25f905c2 8064 "TARGET_THUMB1"
595d88b5 8065 "operands[2] = gen_reg_rtx (SImode);"
8066)
8067
25f905c2 8068(define_insn "*cstoresi_eq0_thumb1_insn"
595d88b5 8069 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
8070 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
8071 (const_int 0)))
8072 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
25f905c2 8073 "TARGET_THUMB1"
595d88b5 8074 "@
8075 neg\\t%0, %1\;adc\\t%0, %0, %1
8076 neg\\t%2, %1\;adc\\t%0, %1, %2"
8077 [(set_attr "length" "4")]
8078)
8079
25f905c2 8080(define_insn "*cstoresi_ne0_thumb1_insn"
595d88b5 8081 [(set (match_operand:SI 0 "s_register_operand" "=l")
8082 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
8083 (const_int 0)))
8084 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
25f905c2 8085 "TARGET_THUMB1"
595d88b5 8086 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
8087 [(set_attr "length" "4")]
8088)
8089
408b7ae5 8090;; Used as part of the expansion of thumb ltu and gtu sequences
25f905c2 8091(define_insn "cstoresi_nltu_thumb1"
595d88b5 8092 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
a277ddf3 8093 (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 8094 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
8095 "TARGET_THUMB1"
595d88b5 8096 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
8097 [(set_attr "length" "4")]
8098)
8099
408b7ae5 8100(define_insn_and_split "cstoresi_ltu_thumb1"
8101 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
8102 (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
8103 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
8104 "TARGET_THUMB1"
8105 "#"
8106 "TARGET_THUMB1"
8107 [(set (match_dup 3)
8108 (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
8109 (set (match_dup 0) (neg:SI (match_dup 3)))]
8110 "operands[3] = gen_reg_rtx (SImode);"
8111 [(set_attr "length" "4")]
8112)
8113
595d88b5 8114;; Used as part of the expansion of thumb les sequence.
25f905c2 8115(define_insn "thumb1_addsi3_addgeu"
595d88b5 8116 [(set (match_operand:SI 0 "s_register_operand" "=l")
8117 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8118 (match_operand:SI 2 "s_register_operand" "l"))
8119 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
25f905c2 8120 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
8121 "TARGET_THUMB1"
595d88b5 8122 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
8123 [(set_attr "length" "4")]
8124)
8125
9c08d1fa 8126\f
39b5e676 8127;; Conditional move insns
8128
8129(define_expand "movsicc"
8a18b90c 8130 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 8131 (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
aea4c774 8132 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 8133 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 8134 "TARGET_32BIT"
39b5e676 8135 "
215b30b3 8136 {
8137 enum rtx_code code = GET_CODE (operands[1]);
278b301d 8138 rtx ccreg;
8139
8140 if (code == UNEQ || code == LTGT)
8141 FAIL;
39b5e676 8142
74f4459c 8143 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 8144 XEXP (operands[1], 1), NULL_RTX);
29bb088d 8145 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8146 }"
8147)
39b5e676 8148
8149(define_expand "movsfcc"
8a18b90c 8150 [(set (match_operand:SF 0 "s_register_operand" "")
aa06947a 8151 (if_then_else:SF (match_operand 1 "expandable_comparison_operator" "")
8a18b90c 8152 (match_operand:SF 2 "s_register_operand" "")
8153 (match_operand:SF 3 "nonmemory_operand" "")))]
19f6bf8d 8154 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 8155 "
215b30b3 8156 {
8157 enum rtx_code code = GET_CODE (operands[1]);
8158 rtx ccreg;
f082f1c4 8159
278b301d 8160 if (code == UNEQ || code == LTGT)
8161 FAIL;
8162
215b30b3 8163 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
a2cd141b 8164 Otherwise, ensure it is a valid FP add operand */
8165 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
8166 || (!arm_float_add_operand (operands[3], SFmode)))
215b30b3 8167 operands[3] = force_reg (SFmode, operands[3]);
39b5e676 8168
74f4459c 8169 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 8170 XEXP (operands[1], 1), NULL_RTX);
29bb088d 8171 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8172 }"
8173)
39b5e676 8174
8175(define_expand "movdfcc"
8a18b90c 8176 [(set (match_operand:DF 0 "s_register_operand" "")
aa06947a 8177 (if_then_else:DF (match_operand 1 "expandable_comparison_operator" "")
8a18b90c 8178 (match_operand:DF 2 "s_register_operand" "")
a2cd141b 8179 (match_operand:DF 3 "arm_float_add_operand" "")))]
a50d7267 8180 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
39b5e676 8181 "
215b30b3 8182 {
8183 enum rtx_code code = GET_CODE (operands[1]);
278b301d 8184 rtx ccreg;
39b5e676 8185
278b301d 8186 if (code == UNEQ || code == LTGT)
8187 FAIL;
8188
74f4459c 8189 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
e1b93706 8190 XEXP (operands[1], 1), NULL_RTX);
29bb088d 8191 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8192 }"
8193)
39b5e676 8194
8195(define_insn "*movsicc_insn"
f082f1c4 8196 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 8197 (if_then_else:SI
8fa3ba89 8198 (match_operator 3 "arm_comparison_operator"
8a18b90c 8199 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8200 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8201 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 8202 "TARGET_ARM"
39b5e676 8203 "@
8a18b90c 8204 mov%D3\\t%0, %2
8205 mvn%D3\\t%0, #%B2
f082f1c4 8206 mov%d3\\t%0, %1
8207 mvn%d3\\t%0, #%B1
8a18b90c 8208 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8209 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8210 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8211 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 8212 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 8213 (set_attr "conds" "use")
8214 (set_attr "insn" "mov,mvn,mov,mvn,mov,mov,mvn,mvn")]
215b30b3 8215)
39b5e676 8216
39b5e676 8217(define_insn "*movsfcc_soft_insn"
f082f1c4 8218 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 8219 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 8220 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8221 (match_operand:SF 1 "s_register_operand" "0,r")
8222 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 8223 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 8224 "@
8225 mov%D3\\t%0, %2
8226 mov%d3\\t%0, %1"
d2a518d1 8227 [(set_attr "conds" "use")
8228 (set_attr "insn" "mov")]
8fa3ba89 8229)
39b5e676 8230
39b5e676 8231\f
9c08d1fa 8232;; Jump and linkage insns
8233
cffb2a26 8234(define_expand "jump"
9c08d1fa 8235 [(set (pc)
8236 (label_ref (match_operand 0 "" "")))]
cffb2a26 8237 "TARGET_EITHER"
9c08d1fa 8238 ""
cffb2a26 8239)
8240
8241(define_insn "*arm_jump"
8242 [(set (pc)
8243 (label_ref (match_operand 0 "" "")))]
25f905c2 8244 "TARGET_32BIT"
9c08d1fa 8245 "*
0d66636f 8246 {
8247 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8248 {
8249 arm_ccfsm_state += 2;
8250 return \"\";
8251 }
8252 return \"b%?\\t%l0\";
8253 }
8254 "
a6864a24 8255 [(set_attr "predicable" "yes")
8256 (set (attr "length")
8257 (if_then_else
0bf497f5 8258 (and (match_test "TARGET_THUMB2")
a6864a24 8259 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8260 (le (minus (match_dup 0) (pc)) (const_int 2048))))
8261 (const_int 2)
8262 (const_int 4)))]
0d66636f 8263)
9c08d1fa 8264
cffb2a26 8265(define_insn "*thumb_jump"
8266 [(set (pc)
8267 (label_ref (match_operand 0 "" "")))]
25f905c2 8268 "TARGET_THUMB1"
cffb2a26 8269 "*
8270 if (get_attr_length (insn) == 2)
8271 return \"b\\t%l0\";
8272 return \"bl\\t%l0\\t%@ far jump\";
8273 "
8274 [(set (attr "far_jump")
8275 (if_then_else
8276 (eq_attr "length" "4")
8277 (const_string "yes")
8278 (const_string "no")))
8279 (set (attr "length")
8280 (if_then_else
911ed8af 8281 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8282 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 8283 (const_int 2)
8284 (const_int 4)))]
8285)
8286
d3373b54 8287(define_expand "call"
8288 [(parallel [(call (match_operand 0 "memory_operand" "")
8289 (match_operand 1 "general_operand" ""))
cffb2a26 8290 (use (match_operand 2 "" ""))
bd5b4116 8291 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8292 "TARGET_EITHER"
6c4c2133 8293 "
8294 {
bac7fc85 8295 rtx callee, pat;
bbe777ea 8296
bbe777ea 8297 /* In an untyped call, we can get NULL for operand 2. */
8298 if (operands[2] == NULL_RTX)
8299 operands[2] = const0_rtx;
8300
de55252a 8301 /* Decide if we should generate indirect calls by loading the
85c36fd1 8302 32-bit address of the callee into a register before performing the
de55252a 8303 branch and link. */
8304 callee = XEXP (operands[0], 0);
8305 if (GET_CODE (callee) == SYMBOL_REF
8306 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8307 : !REG_P (callee))
bbe777ea 8308 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 8309
8310 pat = gen_call_internal (operands[0], operands[1], operands[2]);
8311 arm_emit_call_insn (pat, XEXP (operands[0], 0));
8312 DONE;
6c4c2133 8313 }"
8314)
d3373b54 8315
bac7fc85 8316(define_expand "call_internal"
8317 [(parallel [(call (match_operand 0 "memory_operand" "")
8318 (match_operand 1 "general_operand" ""))
8319 (use (match_operand 2 "" ""))
8320 (clobber (reg:SI LR_REGNUM))])])
8321
f1039640 8322(define_insn "*call_reg_armv5"
d3373b54 8323 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 8324 (match_operand 1 "" ""))
8325 (use (match_operand 2 "" ""))
bd5b4116 8326 (clobber (reg:SI LR_REGNUM))]
f1039640 8327 "TARGET_ARM && arm_arch5"
8328 "blx%?\\t%0"
8329 [(set_attr "type" "call")]
8330)
8331
8332(define_insn "*call_reg_arm"
8333 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8334 (match_operand 1 "" ""))
8335 (use (match_operand 2 "" ""))
8336 (clobber (reg:SI LR_REGNUM))]
8337 "TARGET_ARM && !arm_arch5"
9c08d1fa 8338 "*
5565501b 8339 return output_call (operands);
cffb2a26 8340 "
8341 ;; length is worst case, normally it is only two
8342 [(set_attr "length" "12")
8343 (set_attr "type" "call")]
8344)
9c08d1fa 8345
89504fc1 8346
8347;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
8348;; considered a function call by the branch predictor of some cores (PR40887).
8349;; Falls back to blx rN (*call_reg_armv5).
8350
f7fbdd4a 8351(define_insn "*call_mem"
a3c63a9d 8352 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 8353 (match_operand 1 "" ""))
8354 (use (match_operand 2 "" ""))
bd5b4116 8355 (clobber (reg:SI LR_REGNUM))]
89504fc1 8356 "TARGET_ARM && !arm_arch5"
9c08d1fa 8357 "*
5565501b 8358 return output_call_mem (operands);
cffb2a26 8359 "
8360 [(set_attr "length" "12")
8361 (set_attr "type" "call")]
8362)
8363
25f905c2 8364(define_insn "*call_reg_thumb1_v5"
cffb2a26 8365 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8366 (match_operand 1 "" ""))
8367 (use (match_operand 2 "" ""))
bd5b4116 8368 (clobber (reg:SI LR_REGNUM))]
25f905c2 8369 "TARGET_THUMB1 && arm_arch5"
f1039640 8370 "blx\\t%0"
8371 [(set_attr "length" "2")
8372 (set_attr "type" "call")]
cffb2a26 8373)
8374
25f905c2 8375(define_insn "*call_reg_thumb1"
f1039640 8376 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8377 (match_operand 1 "" ""))
8378 (use (match_operand 2 "" ""))
bd5b4116 8379 (clobber (reg:SI LR_REGNUM))]
25f905c2 8380 "TARGET_THUMB1 && !arm_arch5"
cffb2a26 8381 "*
8382 {
150502c9 8383 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8384 return thumb_call_via_reg (operands[0]);
150502c9 8385 else if (operands[1] == const0_rtx)
f1039640 8386 return \"bl\\t%__interwork_call_via_%0\";
150502c9 8387 else if (frame_pointer_needed)
8388 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 8389 else
150502c9 8390 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 8391 }"
8392 [(set_attr "type" "call")]
8393)
9c08d1fa 8394
d3373b54 8395(define_expand "call_value"
e0698af7 8396 [(parallel [(set (match_operand 0 "" "")
8397 (call (match_operand 1 "memory_operand" "")
8398 (match_operand 2 "general_operand" "")))
cffb2a26 8399 (use (match_operand 3 "" ""))
bd5b4116 8400 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8401 "TARGET_EITHER"
6c4c2133 8402 "
8403 {
bac7fc85 8404 rtx pat, callee;
bbe777ea 8405
8406 /* In an untyped call, we can get NULL for operand 2. */
8407 if (operands[3] == 0)
8408 operands[3] = const0_rtx;
8409
de55252a 8410 /* Decide if we should generate indirect calls by loading the
8411 32-bit address of the callee into a register before performing the
8412 branch and link. */
8413 callee = XEXP (operands[1], 0);
8414 if (GET_CODE (callee) == SYMBOL_REF
8415 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8416 : !REG_P (callee))
78fe751b 8417 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 8418
8419 pat = gen_call_value_internal (operands[0], operands[1],
8420 operands[2], operands[3]);
8421 arm_emit_call_insn (pat, XEXP (operands[1], 0));
8422 DONE;
6c4c2133 8423 }"
8424)
d3373b54 8425
bac7fc85 8426(define_expand "call_value_internal"
8427 [(parallel [(set (match_operand 0 "" "")
8428 (call (match_operand 1 "memory_operand" "")
8429 (match_operand 2 "general_operand" "")))
8430 (use (match_operand 3 "" ""))
8431 (clobber (reg:SI LR_REGNUM))])])
8432
f1039640 8433(define_insn "*call_value_reg_armv5"
27ed6835 8434 [(set (match_operand 0 "" "")
755eb2b4 8435 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 8436 (match_operand 2 "" "")))
bbe777ea 8437 (use (match_operand 3 "" ""))
bd5b4116 8438 (clobber (reg:SI LR_REGNUM))]
f1039640 8439 "TARGET_ARM && arm_arch5"
8440 "blx%?\\t%1"
8441 [(set_attr "type" "call")]
8442)
8443
8444(define_insn "*call_value_reg_arm"
8445 [(set (match_operand 0 "" "")
8446 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8447 (match_operand 2 "" "")))
8448 (use (match_operand 3 "" ""))
8449 (clobber (reg:SI LR_REGNUM))]
8450 "TARGET_ARM && !arm_arch5"
9c08d1fa 8451 "*
215b30b3 8452 return output_call (&operands[1]);
cffb2a26 8453 "
8454 [(set_attr "length" "12")
8455 (set_attr "type" "call")]
8456)
9c08d1fa 8457
89504fc1 8458;; Note: see *call_mem
8459
f7fbdd4a 8460(define_insn "*call_value_mem"
27ed6835 8461 [(set (match_operand 0 "" "")
a3c63a9d 8462 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 8463 (match_operand 2 "" "")))
bbe777ea 8464 (use (match_operand 3 "" ""))
bd5b4116 8465 (clobber (reg:SI LR_REGNUM))]
89504fc1 8466 "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 8467 "*
215b30b3 8468 return output_call_mem (&operands[1]);
cffb2a26 8469 "
8470 [(set_attr "length" "12")
8471 (set_attr "type" "call")]
8472)
9c08d1fa 8473
25f905c2 8474(define_insn "*call_value_reg_thumb1_v5"
f1039640 8475 [(set (match_operand 0 "" "")
8476 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8477 (match_operand 2 "" "")))
8478 (use (match_operand 3 "" ""))
8479 (clobber (reg:SI LR_REGNUM))]
25f905c2 8480 "TARGET_THUMB1 && arm_arch5"
f1039640 8481 "blx\\t%1"
8482 [(set_attr "length" "2")
8483 (set_attr "type" "call")]
8484)
8485
25f905c2 8486(define_insn "*call_value_reg_thumb1"
f1039640 8487 [(set (match_operand 0 "" "")
8488 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8489 (match_operand 2 "" "")))
8490 (use (match_operand 3 "" ""))
8491 (clobber (reg:SI LR_REGNUM))]
25f905c2 8492 "TARGET_THUMB1 && !arm_arch5"
f1039640 8493 "*
8494 {
150502c9 8495 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8496 return thumb_call_via_reg (operands[1]);
150502c9 8497 else if (operands[2] == const0_rtx)
f1039640 8498 return \"bl\\t%__interwork_call_via_%1\";
150502c9 8499 else if (frame_pointer_needed)
8500 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 8501 else
150502c9 8502 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 8503 }"
8504 [(set_attr "type" "call")]
8505)
8506
9c08d1fa 8507;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8508;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8509
f7fbdd4a 8510(define_insn "*call_symbol"
27ed6835 8511 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8512 (match_operand 1 "" ""))
bbe777ea 8513 (use (match_operand 2 "" ""))
bd5b4116 8514 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8515 "TARGET_32BIT
cffb2a26 8516 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8517 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8518 "*
8519 {
55c1e470 8520 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8521 }"
cffb2a26 8522 [(set_attr "type" "call")]
8523)
9c08d1fa 8524
f7fbdd4a 8525(define_insn "*call_value_symbol"
ccd90aaa 8526 [(set (match_operand 0 "" "")
27ed6835 8527 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8528 (match_operand:SI 2 "" "")))
bbe777ea 8529 (use (match_operand 3 "" ""))
bd5b4116 8530 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8531 "TARGET_32BIT
cffb2a26 8532 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8533 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8534 "*
8535 {
55c1e470 8536 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8537 }"
cffb2a26 8538 [(set_attr "type" "call")]
8539)
8540
8541(define_insn "*call_insn"
27ed6835 8542 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8543 (match_operand:SI 1 "" ""))
8544 (use (match_operand 2 "" ""))
bd5b4116 8545 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8546 "TARGET_THUMB1
1675c6e9 8547 && GET_CODE (operands[0]) == SYMBOL_REF
de55252a 8548 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
cffb2a26 8549 "bl\\t%a0"
8550 [(set_attr "length" "4")
8551 (set_attr "type" "call")]
8552)
8553
8554(define_insn "*call_value_insn"
ccd90aaa 8555 [(set (match_operand 0 "" "")
27ed6835 8556 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 8557 (match_operand 2 "" "")))
8558 (use (match_operand 3 "" ""))
bd5b4116 8559 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8560 "TARGET_THUMB1
1675c6e9 8561 && GET_CODE (operands[1]) == SYMBOL_REF
de55252a 8562 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
cffb2a26 8563 "bl\\t%a1"
8564 [(set_attr "length" "4")
8565 (set_attr "type" "call")]
8566)
9c08d1fa 8567
1c494086 8568;; We may also be able to do sibcalls for Thumb, but it's much harder...
8569(define_expand "sibcall"
8570 [(parallel [(call (match_operand 0 "memory_operand" "")
8571 (match_operand 1 "general_operand" ""))
2ba80634 8572 (return)
8573 (use (match_operand 2 "" ""))])]
d68c2c10 8574 "TARGET_32BIT"
1c494086 8575 "
8576 {
8577 if (operands[2] == NULL_RTX)
8578 operands[2] = const0_rtx;
1c494086 8579 }"
8580)
8581
8582(define_expand "sibcall_value"
ccd90aaa 8583 [(parallel [(set (match_operand 0 "" "")
1c494086 8584 (call (match_operand 1 "memory_operand" "")
8585 (match_operand 2 "general_operand" "")))
2ba80634 8586 (return)
8587 (use (match_operand 3 "" ""))])]
d68c2c10 8588 "TARGET_32BIT"
1c494086 8589 "
8590 {
8591 if (operands[3] == NULL_RTX)
8592 operands[3] = const0_rtx;
1c494086 8593 }"
8594)
8595
8596(define_insn "*sibcall_insn"
8597 [(call (mem:SI (match_operand:SI 0 "" "X"))
8598 (match_operand 1 "" ""))
2ba80634 8599 (return)
8600 (use (match_operand 2 "" ""))]
d68c2c10 8601 "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF"
1c494086 8602 "*
8603 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8604 "
8605 [(set_attr "type" "call")]
8606)
8607
8608(define_insn "*sibcall_value_insn"
ccd90aaa 8609 [(set (match_operand 0 "" "")
755eb2b4 8610 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 8611 (match_operand 2 "" "")))
2ba80634 8612 (return)
8613 (use (match_operand 3 "" ""))]
d68c2c10 8614 "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF"
1c494086 8615 "*
8616 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8617 "
8618 [(set_attr "type" "call")]
8619)
8620
d68c2c10 8621(define_expand "return"
8622 [(return)]
8623 "TARGET_32BIT && USE_RETURN_INSN (FALSE)"
8624 "")
8625
9c08d1fa 8626;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 8627(define_insn "*arm_return"
9c08d1fa 8628 [(return)]
cffb2a26 8629 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8630 "*
9c08d1fa 8631 {
cffb2a26 8632 if (arm_ccfsm_state == 2)
8633 {
8634 arm_ccfsm_state += 2;
8635 return \"\";
8636 }
5db468b7 8637 return output_return_instruction (const_true_rtx, TRUE, FALSE);
cffb2a26 8638 }"
a2cd141b 8639 [(set_attr "type" "load1")
755eb2b4 8640 (set_attr "length" "12")
0d66636f 8641 (set_attr "predicable" "yes")]
cffb2a26 8642)
9c08d1fa 8643
f7fbdd4a 8644(define_insn "*cond_return"
9c08d1fa 8645 [(set (pc)
8fa3ba89 8646 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8647 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8648 (return)
8649 (pc)))]
cffb2a26 8650 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8651 "*
8fa3ba89 8652 {
8653 if (arm_ccfsm_state == 2)
8654 {
8655 arm_ccfsm_state += 2;
8656 return \"\";
8657 }
8658 return output_return_instruction (operands[0], TRUE, FALSE);
8659 }"
8660 [(set_attr "conds" "use")
755eb2b4 8661 (set_attr "length" "12")
a2cd141b 8662 (set_attr "type" "load1")]
8fa3ba89 8663)
9c08d1fa 8664
f7fbdd4a 8665(define_insn "*cond_return_inverted"
9c08d1fa 8666 [(set (pc)
8fa3ba89 8667 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8668 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8669 (pc)
8670 (return)))]
cffb2a26 8671 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8672 "*
8fa3ba89 8673 {
8674 if (arm_ccfsm_state == 2)
8675 {
8676 arm_ccfsm_state += 2;
8677 return \"\";
8678 }
8679 return output_return_instruction (operands[0], TRUE, TRUE);
8680 }"
8681 [(set_attr "conds" "use")
37a1317b 8682 (set_attr "length" "12")
a2cd141b 8683 (set_attr "type" "load1")]
8fa3ba89 8684)
9c08d1fa 8685
68121397 8686;; Generate a sequence of instructions to determine if the processor is
8687;; in 26-bit or 32-bit mode, and return the appropriate return address
8688;; mask.
8689
8690(define_expand "return_addr_mask"
8691 [(set (match_dup 1)
8692 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8693 (const_int 0)))
8694 (set (match_operand:SI 0 "s_register_operand" "")
8695 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8696 (const_int -1)
8697 (const_int 67108860)))] ; 0x03fffffc
8698 "TARGET_ARM"
8699 "
62eddbd4 8700 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8701 ")
8702
8703(define_insn "*check_arch2"
8704 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8705 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8706 (const_int 0)))]
8707 "TARGET_ARM"
8708 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8709 [(set_attr "length" "8")
8710 (set_attr "conds" "set")]
8711)
8712
9c08d1fa 8713;; Call subroutine returning any type.
8714
8715(define_expand "untyped_call"
8716 [(parallel [(call (match_operand 0 "" "")
8717 (const_int 0))
8718 (match_operand 1 "" "")
8719 (match_operand 2 "" "")])]
ccd90aaa 8720 "TARGET_EITHER"
9c08d1fa 8721 "
215b30b3 8722 {
8723 int i;
ccd90aaa 8724 rtx par = gen_rtx_PARALLEL (VOIDmode,
8725 rtvec_alloc (XVECLEN (operands[2], 0)));
8726 rtx addr = gen_reg_rtx (Pmode);
8727 rtx mem;
8728 int size = 0;
9c08d1fa 8729
ccd90aaa 8730 emit_move_insn (addr, XEXP (operands[1], 0));
8731 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8732
215b30b3 8733 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8734 {
ccd90aaa 8735 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8736
ccd90aaa 8737 /* Default code only uses r0 as a return value, but we could
8738 be using anything up to 4 registers. */
8739 if (REGNO (src) == R0_REGNUM)
8740 src = gen_rtx_REG (TImode, R0_REGNUM);
8741
8742 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8743 GEN_INT (size));
8744 size += GET_MODE_SIZE (GET_MODE (src));
8745 }
8746
8747 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8748 const0_rtx));
8749
8750 size = 0;
8751
8752 for (i = 0; i < XVECLEN (par, 0); i++)
8753 {
8754 HOST_WIDE_INT offset = 0;
8755 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8756
8757 if (size != 0)
8758 emit_move_insn (addr, plus_constant (addr, size));
8759
8760 mem = change_address (mem, GET_MODE (reg), NULL);
8761 if (REGNO (reg) == R0_REGNUM)
8762 {
8763 /* On thumb we have to use a write-back instruction. */
320ea44d 8764 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8765 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8766 size = TARGET_ARM ? 16 : 0;
8767 }
8768 else
8769 {
8770 emit_move_insn (mem, reg);
8771 size = GET_MODE_SIZE (GET_MODE (reg));
8772 }
215b30b3 8773 }
9c08d1fa 8774
215b30b3 8775 /* The optimizer does not know that the call sets the function value
8776 registers we stored in the result block. We avoid problems by
8777 claiming that all hard registers are used and clobbered at this
8778 point. */
8779 emit_insn (gen_blockage ());
8780
8781 DONE;
8782 }"
8783)
9c08d1fa 8784
ccd90aaa 8785(define_expand "untyped_return"
8786 [(match_operand:BLK 0 "memory_operand" "")
8787 (match_operand 1 "" "")]
8788 "TARGET_EITHER"
8789 "
8790 {
8791 int i;
8792 rtx addr = gen_reg_rtx (Pmode);
8793 rtx mem;
8794 int size = 0;
8795
8796 emit_move_insn (addr, XEXP (operands[0], 0));
8797 mem = change_address (operands[0], BLKmode, addr);
8798
8799 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8800 {
8801 HOST_WIDE_INT offset = 0;
8802 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8803
8804 if (size != 0)
8805 emit_move_insn (addr, plus_constant (addr, size));
8806
8807 mem = change_address (mem, GET_MODE (reg), NULL);
8808 if (REGNO (reg) == R0_REGNUM)
8809 {
8810 /* On thumb we have to use a write-back instruction. */
320ea44d 8811 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8812 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8813 size = TARGET_ARM ? 16 : 0;
8814 }
8815 else
8816 {
8817 emit_move_insn (reg, mem);
8818 size = GET_MODE_SIZE (GET_MODE (reg));
8819 }
8820 }
8821
8822 /* Emit USE insns before the return. */
8823 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8824 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8825
8826 /* Construct the return. */
8827 expand_naked_return ();
8828
8829 DONE;
8830 }"
8831)
8832
9c08d1fa 8833;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8834;; all of memory. This blocks insns from being moved across this point.
8835
8836(define_insn "blockage"
e1159bbe 8837 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8838 "TARGET_EITHER"
9c08d1fa 8839 ""
cffb2a26 8840 [(set_attr "length" "0")
8841 (set_attr "type" "block")]
8842)
9c08d1fa 8843
f7fbdd4a 8844(define_expand "casesi"
8845 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8846 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8847 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8848 (match_operand:SI 3 "" "") ; table label
8849 (match_operand:SI 4 "" "")] ; Out of range label
e6ac8414 8850 "TARGET_32BIT || optimize_size || flag_pic"
f7fbdd4a 8851 "
215b30b3 8852 {
e6ac8414 8853 enum insn_code code;
215b30b3 8854 if (operands[1] != const0_rtx)
8855 {
e6ac8414 8856 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8857
215b30b3 8858 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8859 gen_int_mode (-INTVAL (operands[1]),
8860 SImode)));
215b30b3 8861 operands[0] = reg;
8862 }
9c08d1fa 8863
25f905c2 8864 if (TARGET_ARM)
e6ac8414 8865 code = CODE_FOR_arm_casesi_internal;
3db2019b 8866 else if (TARGET_THUMB1)
e6ac8414 8867 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8868 else if (flag_pic)
e6ac8414 8869 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8870 else
e6ac8414 8871 code = CODE_FOR_thumb2_casesi_internal;
8872
8873 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8874 operands[2] = force_reg (SImode, operands[2]);
8875
8876 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8877 operands[3], operands[4]));
215b30b3 8878 DONE;
8879 }"
8880)
f7fbdd4a 8881
f082f1c4 8882;; The USE in this pattern is needed to tell flow analysis that this is
8883;; a CASESI insn. It has no other purpose.
25f905c2 8884(define_insn "arm_casesi_internal"
f082f1c4 8885 [(parallel [(set (pc)
8886 (if_then_else
8887 (leu (match_operand:SI 0 "s_register_operand" "r")
8888 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8889 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8890 (label_ref (match_operand 2 "" ""))))
8891 (label_ref (match_operand 3 "" ""))))
bd5b4116 8892 (clobber (reg:CC CC_REGNUM))
f082f1c4 8893 (use (label_ref (match_dup 2)))])]
cffb2a26 8894 "TARGET_ARM"
f7fbdd4a 8895 "*
0d66636f 8896 if (flag_pic)
8897 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8898 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8899 "
8900 [(set_attr "conds" "clob")
8901 (set_attr "length" "12")]
8902)
9c08d1fa 8903
e6ac8414 8904(define_expand "thumb1_casesi_internal_pic"
8905 [(match_operand:SI 0 "s_register_operand" "")
8906 (match_operand:SI 1 "thumb1_cmp_operand" "")
8907 (match_operand 2 "" "")
8908 (match_operand 3 "" "")]
3db2019b 8909 "TARGET_THUMB1"
e6ac8414 8910 {
8911 rtx reg0;
8912 rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
8913 emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
8914 operands[3]));
8915 reg0 = gen_rtx_REG (SImode, 0);
8916 emit_move_insn (reg0, operands[0]);
8917 emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
8918 DONE;
8919 }
8920)
8921
8922(define_insn "thumb1_casesi_dispatch"
8923 [(parallel [(set (pc) (unspec [(reg:SI 0)
8924 (label_ref (match_operand 0 "" ""))
8925;; (label_ref (match_operand 1 "" ""))
8926]
8927 UNSPEC_THUMB1_CASESI))
8928 (clobber (reg:SI IP_REGNUM))
8929 (clobber (reg:SI LR_REGNUM))])]
3db2019b 8930 "TARGET_THUMB1"
e6ac8414 8931 "* return thumb1_output_casesi(operands);"
8932 [(set_attr "length" "4")]
8933)
8934
cffb2a26 8935(define_expand "indirect_jump"
9c08d1fa 8936 [(set (pc)
cffb2a26 8937 (match_operand:SI 0 "s_register_operand" ""))]
8938 "TARGET_EITHER"
25f905c2 8939 "
8940 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8941 address and use bx. */
8942 if (TARGET_THUMB2)
8943 {
8944 rtx tmp;
8945 tmp = gen_reg_rtx (SImode);
8946 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8947 operands[0] = tmp;
8948 }
8949 "
cffb2a26 8950)
8951
f1039640 8952;; NB Never uses BX.
cffb2a26 8953(define_insn "*arm_indirect_jump"
8954 [(set (pc)
8955 (match_operand:SI 0 "s_register_operand" "r"))]
8956 "TARGET_ARM"
8957 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 8958 [(set_attr "predicable" "yes")]
cffb2a26 8959)
9c08d1fa 8960
f7fbdd4a 8961(define_insn "*load_indirect_jump"
9c08d1fa 8962 [(set (pc)
8963 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8964 "TARGET_ARM"
8965 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8966 [(set_attr "type" "load1")
61a2d04c 8967 (set_attr "pool_range" "4096")
8968 (set_attr "neg_pool_range" "4084")
0d66636f 8969 (set_attr "predicable" "yes")]
cffb2a26 8970)
8971
f1039640 8972;; NB Never uses BX.
25f905c2 8973(define_insn "*thumb1_indirect_jump"
cffb2a26 8974 [(set (pc)
8975 (match_operand:SI 0 "register_operand" "l*r"))]
25f905c2 8976 "TARGET_THUMB1"
cffb2a26 8977 "mov\\tpc, %0"
8978 [(set_attr "conds" "clob")
8979 (set_attr "length" "2")]
8980)
8981
9c08d1fa 8982\f
8983;; Misc insns
8984
8985(define_insn "nop"
8986 [(const_int 0)]
cffb2a26 8987 "TARGET_EITHER"
8988 "*
25f905c2 8989 if (TARGET_UNIFIED_ASM)
8990 return \"nop\";
cffb2a26 8991 if (TARGET_ARM)
8992 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8993 return \"mov\\tr8, r8\";
8994 "
8995 [(set (attr "length")
8996 (if_then_else (eq_attr "is_thumb" "yes")
8997 (const_int 2)
8998 (const_int 4)))]
8999)
9000
9c08d1fa 9001\f
9002;; Patterns to allow combination of arithmetic, cond code and shifts
9003
f7fbdd4a 9004(define_insn "*arith_shiftsi"
7392680c 9005 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9c08d1fa 9006 (match_operator:SI 1 "shiftable_operator"
9007 [(match_operator:SI 3 "shift_operator"
7392680c 9008 [(match_operand:SI 4 "s_register_operand" "r,r,r,r")
9009 (match_operand:SI 5 "shift_amount_operand" "M,M,M,r")])
9010 (match_operand:SI 2 "s_register_operand" "rk,rk,r,rk")]))]
d5d4dc8d 9011 "TARGET_32BIT"
6c4c2133 9012 "%i1%?\\t%0, %2, %4%S3"
344495ea 9013 [(set_attr "predicable" "yes")
331beb1a 9014 (set_attr "shift" "4")
7392680c 9015 (set_attr "arch" "a,t2,t2,a")
9016 ;; Thumb2 doesn't allow the stack pointer to be used for
9017 ;; operand1 for all operations other than add and sub. In this case
9018 ;; the minus operation is a candidate for an rsub and hence needs
9019 ;; to be disabled.
9020 ;; We have to make sure to disable the fourth alternative if
d5d4dc8d 9021 ;; the shift_operator is MULT, since otherwise the insn will
9022 ;; also match a multiply_accumulate pattern and validate_change
9023 ;; will allow a replacement of the constant with a register
9024 ;; despite the checks done in shift_operator.
9025 (set_attr_alternative "insn_enabled"
9026 [(const_string "yes")
7392680c 9027 (if_then_else
9028 (match_operand:SI 1 "add_operator" "")
9029 (const_string "yes") (const_string "no"))
9030 (const_string "yes")
d5d4dc8d 9031 (if_then_else
9032 (match_operand:SI 3 "mult_operator" "")
9033 (const_string "no") (const_string "yes"))])
7392680c 9034 (set_attr "type" "alu_shift,alu_shift,alu_shift,alu_shift_reg")])
9c08d1fa 9035
d7863cfe 9036(define_split
9037 [(set (match_operand:SI 0 "s_register_operand" "")
9038 (match_operator:SI 1 "shiftable_operator"
9039 [(match_operator:SI 2 "shiftable_operator"
9040 [(match_operator:SI 3 "shift_operator"
9041 [(match_operand:SI 4 "s_register_operand" "")
9042 (match_operand:SI 5 "reg_or_int_operand" "")])
9043 (match_operand:SI 6 "s_register_operand" "")])
9044 (match_operand:SI 7 "arm_rhs_operand" "")]))
9045 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 9046 "TARGET_32BIT"
d7863cfe 9047 [(set (match_dup 8)
9048 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9049 (match_dup 6)]))
9050 (set (match_dup 0)
9051 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
9052 "")
9053
f7fbdd4a 9054(define_insn "*arith_shiftsi_compare0"
bd5b4116 9055 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 9056 (compare:CC_NOOV
9057 (match_operator:SI 1 "shiftable_operator"
9058 [(match_operator:SI 3 "shift_operator"
9059 [(match_operand:SI 4 "s_register_operand" "r,r")
9060 (match_operand:SI 5 "shift_amount_operand" "M,r")])
9061 (match_operand:SI 2 "s_register_operand" "r,r")])
9062 (const_int 0)))
9063 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 9064 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9065 (match_dup 2)]))]
d5d4dc8d 9066 "TARGET_32BIT"
25f905c2 9067 "%i1%.\\t%0, %2, %4%S3"
344495ea 9068 [(set_attr "conds" "set")
331beb1a 9069 (set_attr "shift" "4")
d5d4dc8d 9070 (set_attr "arch" "32,a")
9071 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 9072
f7fbdd4a 9073(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 9074 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 9075 (compare:CC_NOOV
9076 (match_operator:SI 1 "shiftable_operator"
9077 [(match_operator:SI 3 "shift_operator"
9078 [(match_operand:SI 4 "s_register_operand" "r,r")
9079 (match_operand:SI 5 "shift_amount_operand" "M,r")])
9080 (match_operand:SI 2 "s_register_operand" "r,r")])
9081 (const_int 0)))
9082 (clobber (match_scratch:SI 0 "=r,r"))]
9083 "TARGET_32BIT"
25f905c2 9084 "%i1%.\\t%0, %2, %4%S3"
344495ea 9085 [(set_attr "conds" "set")
331beb1a 9086 (set_attr "shift" "4")
d5d4dc8d 9087 (set_attr "arch" "32,a")
9088 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 9089
f7fbdd4a 9090(define_insn "*sub_shiftsi"
d5d4dc8d 9091 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9092 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 9093 (match_operator:SI 2 "shift_operator"
d5d4dc8d 9094 [(match_operand:SI 3 "s_register_operand" "r,r")
9095 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
9096 "TARGET_32BIT"
6c4c2133 9097 "sub%?\\t%0, %1, %3%S2"
344495ea 9098 [(set_attr "predicable" "yes")
331beb1a 9099 (set_attr "shift" "3")
d5d4dc8d 9100 (set_attr "arch" "32,a")
9101 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 9102
f7fbdd4a 9103(define_insn "*sub_shiftsi_compare0"
bd5b4116 9104 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 9105 (compare:CC_NOOV
d5d4dc8d 9106 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 9107 (match_operator:SI 2 "shift_operator"
d5d4dc8d 9108 [(match_operand:SI 3 "s_register_operand" "r,r")
9109 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 9110 (const_int 0)))
d5d4dc8d 9111 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9112 (minus:SI (match_dup 1)
9113 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
9114 "TARGET_32BIT"
25f905c2 9115 "sub%.\\t%0, %1, %3%S2"
344495ea 9116 [(set_attr "conds" "set")
a2cd141b 9117 (set_attr "shift" "3")
d5d4dc8d 9118 (set_attr "arch" "32,a")
9119 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 9120
f7fbdd4a 9121(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 9122 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 9123 (compare:CC_NOOV
d5d4dc8d 9124 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 9125 (match_operator:SI 2 "shift_operator"
d5d4dc8d 9126 [(match_operand:SI 3 "s_register_operand" "r,r")
9127 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 9128 (const_int 0)))
d5d4dc8d 9129 (clobber (match_scratch:SI 0 "=r,r"))]
9130 "TARGET_32BIT"
25f905c2 9131 "sub%.\\t%0, %1, %3%S2"
344495ea 9132 [(set_attr "conds" "set")
a2cd141b 9133 (set_attr "shift" "3")
d5d4dc8d 9134 (set_attr "arch" "32,a")
9135 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 9136\f
9137
f7fbdd4a 9138(define_insn "*and_scc"
9c08d1fa 9139 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9140 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 9141 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 9142 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 9143 "TARGET_ARM"
e2348bcb 9144 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 9145 [(set_attr "conds" "use")
d2a518d1 9146 (set_attr "insn" "mov")
8fa3ba89 9147 (set_attr "length" "8")]
9148)
9c08d1fa 9149
f7fbdd4a 9150(define_insn "*ior_scc"
9c08d1fa 9151 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9152 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 9153 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 9154 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 9155 "TARGET_ARM"
e2348bcb 9156 "@
899850b0 9157 orr%d2\\t%0, %1, #1
9158 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 9159 [(set_attr "conds" "use")
9160 (set_attr "length" "4,8")]
9161)
9c08d1fa 9162
2df9477b 9163; A series of splitters for the compare_scc pattern below. Note that
9164; order is important.
9165(define_split
9166 [(set (match_operand:SI 0 "s_register_operand" "")
9167 (lt:SI (match_operand:SI 1 "s_register_operand" "")
9168 (const_int 0)))
9169 (clobber (reg:CC CC_REGNUM))]
9170 "TARGET_32BIT && reload_completed"
9171 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
9172
9173(define_split
9174 [(set (match_operand:SI 0 "s_register_operand" "")
9175 (ge:SI (match_operand:SI 1 "s_register_operand" "")
9176 (const_int 0)))
9177 (clobber (reg:CC CC_REGNUM))]
9178 "TARGET_32BIT && reload_completed"
9179 [(set (match_dup 0) (not:SI (match_dup 1)))
9180 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
9181
9182(define_split
9183 [(set (match_operand:SI 0 "s_register_operand" "")
9184 (eq:SI (match_operand:SI 1 "s_register_operand" "")
9185 (const_int 0)))
9186 (clobber (reg:CC CC_REGNUM))]
9187 "TARGET_32BIT && reload_completed"
9188 [(parallel
080c0b9a 9189 [(set (reg:CC CC_REGNUM)
9190 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 9191 (set (match_dup 0)
9192 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 9193 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 9194 (set (match_dup 0) (const_int 0)))])
9195
9196(define_split
9197 [(set (match_operand:SI 0 "s_register_operand" "")
9198 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9199 (match_operand:SI 2 "const_int_operand" "")))
9200 (clobber (reg:CC CC_REGNUM))]
9201 "TARGET_32BIT && reload_completed"
9202 [(parallel
9203 [(set (reg:CC CC_REGNUM)
9204 (compare:CC (match_dup 1) (match_dup 2)))
9205 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
9206 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
9207 (set (match_dup 0) (const_int 1)))]
9208{
9209 operands[3] = GEN_INT (-INTVAL (operands[2]));
9210})
9211
9212(define_split
9213 [(set (match_operand:SI 0 "s_register_operand" "")
9214 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9215 (match_operand:SI 2 "arm_add_operand" "")))
9216 (clobber (reg:CC CC_REGNUM))]
9217 "TARGET_32BIT && reload_completed"
9218 [(parallel
9219 [(set (reg:CC_NOOV CC_REGNUM)
9220 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
9221 (const_int 0)))
9222 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
9223 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
9224 (set (match_dup 0) (const_int 1)))])
9225
9226(define_insn_and_split "*compare_scc"
5565501b 9227 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9228 (match_operator:SI 1 "arm_comparison_operator"
5565501b 9229 [(match_operand:SI 2 "s_register_operand" "r,r")
9230 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 9231 (clobber (reg:CC CC_REGNUM))]
2df9477b 9232 "TARGET_32BIT"
9233 "#"
9234 "&& reload_completed"
9235 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
9236 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
9237 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
9238{
9239 rtx tmp1;
9240 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9241 operands[2], operands[3]);
9242 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 9243
2df9477b 9244 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 9245
2df9477b 9246 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9247 if (mode == CCFPmode || mode == CCFPEmode)
9248 rc = reverse_condition_maybe_unordered (rc);
9249 else
9250 rc = reverse_condition (rc);
9251 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9252})
9c08d1fa 9253
080c0b9a 9254;; Attempt to improve the sequence generated by the compare_scc splitters
9255;; not to use conditional execution.
9256(define_peephole2
9257 [(set (reg:CC CC_REGNUM)
9258 (compare:CC (match_operand:SI 1 "register_operand" "")
9259 (match_operand:SI 2 "arm_rhs_operand" "")))
9260 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9261 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9262 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9263 (set (match_dup 0) (const_int 1)))
9264 (match_scratch:SI 3 "r")]
9265 "TARGET_32BIT"
922b6913 9266 [(parallel
9267 [(set (reg:CC CC_REGNUM)
9268 (compare:CC (match_dup 1) (match_dup 2)))
9269 (set (match_dup 3) (minus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 9270 (parallel
9271 [(set (reg:CC CC_REGNUM)
9272 (compare:CC (const_int 0) (match_dup 3)))
9273 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
922b6913 9274 (parallel
9275 [(set (match_dup 0)
9276 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
9277 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))
9278 (clobber (reg:CC CC_REGNUM))])])
080c0b9a 9279
f7fbdd4a 9280(define_insn "*cond_move"
9c08d1fa 9281 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 9282 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 9283 [(match_operator 4 "arm_comparison_operator"
8a18b90c 9284 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 9285 (const_int 0)])
9286 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9287 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 9288 "TARGET_ARM"
9c08d1fa 9289 "*
8fa3ba89 9290 if (GET_CODE (operands[3]) == NE)
9291 {
9292 if (which_alternative != 1)
9293 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9294 if (which_alternative != 0)
9295 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9296 return \"\";
9297 }
9298 if (which_alternative != 0)
9299 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9300 if (which_alternative != 1)
9301 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9302 return \"\";
9303 "
9304 [(set_attr "conds" "use")
d2a518d1 9305 (set_attr "insn" "mov")
8fa3ba89 9306 (set_attr "length" "4,4,8")]
9307)
9c08d1fa 9308
f7fbdd4a 9309(define_insn "*cond_arith"
9c08d1fa 9310 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9311 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 9312 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9313 [(match_operand:SI 2 "s_register_operand" "r,r")
9314 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9315 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 9316 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9317 "TARGET_ARM"
9c08d1fa 9318 "*
8fa3ba89 9319 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9320 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 9321
8fa3ba89 9322 output_asm_insn (\"cmp\\t%2, %3\", operands);
9323 if (GET_CODE (operands[5]) == AND)
9324 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9325 else if (GET_CODE (operands[5]) == MINUS)
9326 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9327 else if (which_alternative != 0)
9328 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9329 return \"%i5%d4\\t%0, %1, #1\";
9330 "
9331 [(set_attr "conds" "clob")
9332 (set_attr "length" "12")]
9333)
9c08d1fa 9334
f7fbdd4a 9335(define_insn "*cond_sub"
9c08d1fa 9336 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9337 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 9338 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9339 [(match_operand:SI 2 "s_register_operand" "r,r")
9340 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9341 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9342 "TARGET_ARM"
9c08d1fa 9343 "*
8fa3ba89 9344 output_asm_insn (\"cmp\\t%2, %3\", operands);
9345 if (which_alternative != 0)
9346 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9347 return \"sub%d4\\t%0, %1, #1\";
9348 "
9349 [(set_attr "conds" "clob")
9350 (set_attr "length" "8,12")]
9351)
9c08d1fa 9352
aea4c774 9353(define_insn "*cmp_ite0"
cffb2a26 9354 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9355 (compare
9356 (if_then_else:SI
8fa3ba89 9357 (match_operator 4 "arm_comparison_operator"
2ff91fec 9358 [(match_operand:SI 0 "s_register_operand"
9359 "l,l,l,r,r,r,r,r,r")
9360 (match_operand:SI 1 "arm_add_operand"
9361 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 9362 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9363 [(match_operand:SI 2 "s_register_operand"
9364 "l,r,r,l,l,r,r,r,r")
9365 (match_operand:SI 3 "arm_add_operand"
9366 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 9367 (const_int 0))
9368 (const_int 0)))]
2ff91fec 9369 "TARGET_32BIT"
9c08d1fa 9370 "*
aea4c774 9371 {
2ff91fec 9372 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9373 {
9374 {\"cmp%d5\\t%0, %1\",
9375 \"cmp%d4\\t%2, %3\"},
9376 {\"cmn%d5\\t%0, #%n1\",
9377 \"cmp%d4\\t%2, %3\"},
9378 {\"cmp%d5\\t%0, %1\",
9379 \"cmn%d4\\t%2, #%n3\"},
9380 {\"cmn%d5\\t%0, #%n1\",
9381 \"cmn%d4\\t%2, #%n3\"}
9382 };
9383 static const char * const cmp2[NUM_OF_COND_CMP][2] =
9384 {
9385 {\"cmp\\t%2, %3\",
9386 \"cmp\\t%0, %1\"},
9387 {\"cmp\\t%2, %3\",
9388 \"cmn\\t%0, #%n1\"},
9389 {\"cmn\\t%2, #%n3\",
9390 \"cmp\\t%0, %1\"},
9391 {\"cmn\\t%2, #%n3\",
9392 \"cmn\\t%0, #%n1\"}
9393 };
9394 static const char * const ite[2] =
8fa3ba89 9395 {
2ff91fec 9396 \"it\\t%d5\",
9397 \"it\\t%d4\"
8fa3ba89 9398 };
2ff91fec 9399 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9400 CMP_CMP, CMN_CMP, CMP_CMP,
9401 CMN_CMP, CMP_CMN, CMN_CMN};
8fa3ba89 9402 int swap =
9403 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9404
2ff91fec 9405 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9406 if (TARGET_THUMB2) {
9407 output_asm_insn (ite[swap], operands);
9408 }
9409 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9410 return \"\";
8fa3ba89 9411 }"
9412 [(set_attr "conds" "set")
2ff91fec 9413 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9414 (set_attr_alternative "length"
9415 [(const_int 6)
9416 (const_int 8)
9417 (const_int 8)
9418 (const_int 8)
9419 (const_int 8)
9420 (if_then_else (eq_attr "is_thumb" "no")
9421 (const_int 8)
9422 (const_int 10))
9423 (if_then_else (eq_attr "is_thumb" "no")
9424 (const_int 8)
9425 (const_int 10))
9426 (if_then_else (eq_attr "is_thumb" "no")
9427 (const_int 8)
9428 (const_int 10))
9429 (if_then_else (eq_attr "is_thumb" "no")
9430 (const_int 8)
9431 (const_int 10))])]
8fa3ba89 9432)
9c08d1fa 9433
aea4c774 9434(define_insn "*cmp_ite1"
cffb2a26 9435 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9436 (compare
9437 (if_then_else:SI
8fa3ba89 9438 (match_operator 4 "arm_comparison_operator"
2ff91fec 9439 [(match_operand:SI 0 "s_register_operand"
9440 "l,l,l,r,r,r,r,r,r")
9441 (match_operand:SI 1 "arm_add_operand"
9442 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 9443 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9444 [(match_operand:SI 2 "s_register_operand"
9445 "l,r,r,l,l,r,r,r,r")
9446 (match_operand:SI 3 "arm_add_operand"
9447 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 9448 (const_int 1))
9449 (const_int 0)))]
2ff91fec 9450 "TARGET_32BIT"
9c08d1fa 9451 "*
9c08d1fa 9452 {
2ff91fec 9453 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9454 {
9455 {\"cmp\\t%0, %1\",
9456 \"cmp\\t%2, %3\"},
9457 {\"cmn\\t%0, #%n1\",
9458 \"cmp\\t%2, %3\"},
9459 {\"cmp\\t%0, %1\",
9460 \"cmn\\t%2, #%n3\"},
9461 {\"cmn\\t%0, #%n1\",
9462 \"cmn\\t%2, #%n3\"}
9463 };
9464 static const char * const cmp2[NUM_OF_COND_CMP][2] =
215b30b3 9465 {
2ff91fec 9466 {\"cmp%d4\\t%2, %3\",
9467 \"cmp%D5\\t%0, %1\"},
9468 {\"cmp%d4\\t%2, %3\",
9469 \"cmn%D5\\t%0, #%n1\"},
9470 {\"cmn%d4\\t%2, #%n3\",
9471 \"cmp%D5\\t%0, %1\"},
9472 {\"cmn%d4\\t%2, #%n3\",
9473 \"cmn%D5\\t%0, #%n1\"}
215b30b3 9474 };
2ff91fec 9475 static const char * const ite[2] =
9476 {
9477 \"it\\t%d4\",
9478 \"it\\t%D5\"
9479 };
9480 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9481 CMP_CMP, CMN_CMP, CMP_CMP,
9482 CMN_CMP, CMP_CMN, CMN_CMN};
215b30b3 9483 int swap =
9484 comparison_dominates_p (GET_CODE (operands[5]),
9485 reverse_condition (GET_CODE (operands[4])));
9486
2ff91fec 9487 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9488 if (TARGET_THUMB2) {
9489 output_asm_insn (ite[swap], operands);
9490 }
9491 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9492 return \"\";
215b30b3 9493 }"
8fa3ba89 9494 [(set_attr "conds" "set")
2ff91fec 9495 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9496 (set_attr_alternative "length"
9497 [(const_int 6)
9498 (const_int 8)
9499 (const_int 8)
9500 (const_int 8)
9501 (const_int 8)
9502 (if_then_else (eq_attr "is_thumb" "no")
9503 (const_int 8)
9504 (const_int 10))
9505 (if_then_else (eq_attr "is_thumb" "no")
9506 (const_int 8)
9507 (const_int 10))
9508 (if_then_else (eq_attr "is_thumb" "no")
9509 (const_int 8)
9510 (const_int 10))
9511 (if_then_else (eq_attr "is_thumb" "no")
9512 (const_int 8)
9513 (const_int 10))])]
8fa3ba89 9514)
9c08d1fa 9515
f6c53574 9516(define_insn "*cmp_and"
9517 [(set (match_operand 6 "dominant_cc_register" "")
9518 (compare
9519 (and:SI
9520 (match_operator 4 "arm_comparison_operator"
2ff91fec 9521 [(match_operand:SI 0 "s_register_operand"
9522 "l,l,l,r,r,r,r,r,r")
9523 (match_operand:SI 1 "arm_add_operand"
9524 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9525 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9526 [(match_operand:SI 2 "s_register_operand"
9527 "l,r,r,l,l,r,r,r,r")
9528 (match_operand:SI 3 "arm_add_operand"
9529 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9530 (const_int 0)))]
2ff91fec 9531 "TARGET_32BIT"
f6c53574 9532 "*
9533 {
2ff91fec 9534 static const char *const cmp1[NUM_OF_COND_CMP][2] =
f6c53574 9535 {
2ff91fec 9536 {\"cmp%d5\\t%0, %1\",
9537 \"cmp%d4\\t%2, %3\"},
9538 {\"cmn%d5\\t%0, #%n1\",
9539 \"cmp%d4\\t%2, %3\"},
9540 {\"cmp%d5\\t%0, %1\",
9541 \"cmn%d4\\t%2, #%n3\"},
9542 {\"cmn%d5\\t%0, #%n1\",
9543 \"cmn%d4\\t%2, #%n3\"}
f6c53574 9544 };
2ff91fec 9545 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9546 {
9547 {\"cmp\\t%2, %3\",
9548 \"cmp\\t%0, %1\"},
9549 {\"cmp\\t%2, %3\",
9550 \"cmn\\t%0, #%n1\"},
9551 {\"cmn\\t%2, #%n3\",
9552 \"cmp\\t%0, %1\"},
9553 {\"cmn\\t%2, #%n3\",
9554 \"cmn\\t%0, #%n1\"}
9555 };
9556 static const char *const ite[2] =
9557 {
9558 \"it\\t%d5\",
9559 \"it\\t%d4\"
9560 };
9561 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9562 CMP_CMP, CMN_CMP, CMP_CMP,
9563 CMN_CMP, CMP_CMN, CMN_CMN};
f6c53574 9564 int swap =
9565 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9566
2ff91fec 9567 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9568 if (TARGET_THUMB2) {
9569 output_asm_insn (ite[swap], operands);
9570 }
9571 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9572 return \"\";
f6c53574 9573 }"
9574 [(set_attr "conds" "set")
9575 (set_attr "predicable" "no")
2ff91fec 9576 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9577 (set_attr_alternative "length"
9578 [(const_int 6)
9579 (const_int 8)
9580 (const_int 8)
9581 (const_int 8)
9582 (const_int 8)
9583 (if_then_else (eq_attr "is_thumb" "no")
9584 (const_int 8)
9585 (const_int 10))
9586 (if_then_else (eq_attr "is_thumb" "no")
9587 (const_int 8)
9588 (const_int 10))
9589 (if_then_else (eq_attr "is_thumb" "no")
9590 (const_int 8)
9591 (const_int 10))
9592 (if_then_else (eq_attr "is_thumb" "no")
9593 (const_int 8)
9594 (const_int 10))])]
f6c53574 9595)
9596
9597(define_insn "*cmp_ior"
9598 [(set (match_operand 6 "dominant_cc_register" "")
9599 (compare
9600 (ior:SI
9601 (match_operator 4 "arm_comparison_operator"
2ff91fec 9602 [(match_operand:SI 0 "s_register_operand"
9603 "l,l,l,r,r,r,r,r,r")
9604 (match_operand:SI 1 "arm_add_operand"
9605 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9606 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9607 [(match_operand:SI 2 "s_register_operand"
9608 "l,r,r,l,l,r,r,r,r")
9609 (match_operand:SI 3 "arm_add_operand"
9610 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9611 (const_int 0)))]
2ff91fec 9612 "TARGET_32BIT"
f6c53574 9613 "*
f6c53574 9614 {
2ff91fec 9615 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9616 {
9617 {\"cmp\\t%0, %1\",
9618 \"cmp\\t%2, %3\"},
9619 {\"cmn\\t%0, #%n1\",
9620 \"cmp\\t%2, %3\"},
9621 {\"cmp\\t%0, %1\",
9622 \"cmn\\t%2, #%n3\"},
9623 {\"cmn\\t%0, #%n1\",
9624 \"cmn\\t%2, #%n3\"}
9625 };
9626 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9627 {
9628 {\"cmp%D4\\t%2, %3\",
9629 \"cmp%D5\\t%0, %1\"},
9630 {\"cmp%D4\\t%2, %3\",
9631 \"cmn%D5\\t%0, #%n1\"},
9632 {\"cmn%D4\\t%2, #%n3\",
9633 \"cmp%D5\\t%0, %1\"},
9634 {\"cmn%D4\\t%2, #%n3\",
9635 \"cmn%D5\\t%0, #%n1\"}
9636 };
9637 static const char *const ite[2] =
9638 {
9639 \"it\\t%D4\",
9640 \"it\\t%D5\"
9641 };
9642 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9643 CMP_CMP, CMN_CMP, CMP_CMP,
9644 CMN_CMP, CMP_CMN, CMN_CMN};
9645 int swap =
9646 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9647
9648 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9649 if (TARGET_THUMB2) {
9650 output_asm_insn (ite[swap], operands);
9651 }
9652 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9653 return \"\";
9654 }
9655 "
f6c53574 9656 [(set_attr "conds" "set")
2ff91fec 9657 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9658 (set_attr_alternative "length"
9659 [(const_int 6)
9660 (const_int 8)
9661 (const_int 8)
9662 (const_int 8)
9663 (const_int 8)
9664 (if_then_else (eq_attr "is_thumb" "no")
9665 (const_int 8)
9666 (const_int 10))
9667 (if_then_else (eq_attr "is_thumb" "no")
9668 (const_int 8)
9669 (const_int 10))
9670 (if_then_else (eq_attr "is_thumb" "no")
9671 (const_int 8)
9672 (const_int 10))
9673 (if_then_else (eq_attr "is_thumb" "no")
9674 (const_int 8)
9675 (const_int 10))])]
f6c53574 9676)
9677
3c5afce6 9678(define_insn_and_split "*ior_scc_scc"
9679 [(set (match_operand:SI 0 "s_register_operand" "=r")
9680 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9681 [(match_operand:SI 1 "s_register_operand" "r")
9682 (match_operand:SI 2 "arm_add_operand" "rIL")])
9683 (match_operator:SI 6 "arm_comparison_operator"
9684 [(match_operand:SI 4 "s_register_operand" "r")
9685 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9686 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9687 "TARGET_32BIT
3c5afce6 9688 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9689 != CCmode)"
9690 "#"
2ff91fec 9691 "TARGET_32BIT && reload_completed"
3c5afce6 9692 [(set (match_dup 7)
9693 (compare
9694 (ior:SI
9695 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9696 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9697 (const_int 0)))
9698 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9699 "operands[7]
9700 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9701 DOM_CC_X_OR_Y),
601f584c 9702 CC_REGNUM);"
9703 [(set_attr "conds" "clob")
9704 (set_attr "length" "16")])
9705
9706; If the above pattern is followed by a CMP insn, then the compare is
9707; redundant, since we can rework the conditional instruction that follows.
9708(define_insn_and_split "*ior_scc_scc_cmp"
9709 [(set (match_operand 0 "dominant_cc_register" "")
9710 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9711 [(match_operand:SI 1 "s_register_operand" "r")
9712 (match_operand:SI 2 "arm_add_operand" "rIL")])
9713 (match_operator:SI 6 "arm_comparison_operator"
9714 [(match_operand:SI 4 "s_register_operand" "r")
9715 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9716 (const_int 0)))
9717 (set (match_operand:SI 7 "s_register_operand" "=r")
9718 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9719 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9720 "TARGET_32BIT"
601f584c 9721 "#"
2ff91fec 9722 "TARGET_32BIT && reload_completed"
601f584c 9723 [(set (match_dup 0)
9724 (compare
9725 (ior:SI
9726 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9727 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9728 (const_int 0)))
9729 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9730 ""
9731 [(set_attr "conds" "set")
9732 (set_attr "length" "16")])
3c5afce6 9733
9734(define_insn_and_split "*and_scc_scc"
9735 [(set (match_operand:SI 0 "s_register_operand" "=r")
9736 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9737 [(match_operand:SI 1 "s_register_operand" "r")
9738 (match_operand:SI 2 "arm_add_operand" "rIL")])
9739 (match_operator:SI 6 "arm_comparison_operator"
9740 [(match_operand:SI 4 "s_register_operand" "r")
9741 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9742 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9743 "TARGET_32BIT
3c5afce6 9744 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9745 != CCmode)"
9746 "#"
2ff91fec 9747 "TARGET_32BIT && reload_completed
601f584c 9748 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9749 != CCmode)"
3c5afce6 9750 [(set (match_dup 7)
9751 (compare
9752 (and:SI
9753 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9754 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9755 (const_int 0)))
9756 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9757 "operands[7]
9758 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9759 DOM_CC_X_AND_Y),
601f584c 9760 CC_REGNUM);"
9761 [(set_attr "conds" "clob")
9762 (set_attr "length" "16")])
9763
9764; If the above pattern is followed by a CMP insn, then the compare is
9765; redundant, since we can rework the conditional instruction that follows.
9766(define_insn_and_split "*and_scc_scc_cmp"
9767 [(set (match_operand 0 "dominant_cc_register" "")
9768 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9769 [(match_operand:SI 1 "s_register_operand" "r")
9770 (match_operand:SI 2 "arm_add_operand" "rIL")])
9771 (match_operator:SI 6 "arm_comparison_operator"
9772 [(match_operand:SI 4 "s_register_operand" "r")
9773 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9774 (const_int 0)))
9775 (set (match_operand:SI 7 "s_register_operand" "=r")
9776 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9777 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9778 "TARGET_32BIT"
601f584c 9779 "#"
2ff91fec 9780 "TARGET_32BIT && reload_completed"
601f584c 9781 [(set (match_dup 0)
9782 (compare
9783 (and:SI
9784 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9785 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9786 (const_int 0)))
9787 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9788 ""
9789 [(set_attr "conds" "set")
9790 (set_attr "length" "16")])
9791
9792;; If there is no dominance in the comparison, then we can still save an
9793;; instruction in the AND case, since we can know that the second compare
9794;; need only zero the value if false (if true, then the value is already
9795;; correct).
9796(define_insn_and_split "*and_scc_scc_nodom"
9797 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9798 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9799 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9800 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9801 (match_operator:SI 6 "arm_comparison_operator"
9802 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9803 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9804 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9805 "TARGET_32BIT
601f584c 9806 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9807 == CCmode)"
9808 "#"
2ff91fec 9809 "TARGET_32BIT && reload_completed"
601f584c 9810 [(parallel [(set (match_dup 0)
9811 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9812 (clobber (reg:CC CC_REGNUM))])
9813 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9814 (set (match_dup 0)
9815 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9816 (match_dup 0)
9817 (const_int 0)))]
9818 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9819 operands[4], operands[5]),
9820 CC_REGNUM);
9821 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9822 operands[5]);"
9823 [(set_attr "conds" "clob")
9824 (set_attr "length" "20")])
3c5afce6 9825
3a0bdee0 9826(define_split
9827 [(set (reg:CC_NOOV CC_REGNUM)
9828 (compare:CC_NOOV (ior:SI
9829 (and:SI (match_operand:SI 0 "s_register_operand" "")
9830 (const_int 1))
b0694be0 9831 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9832 [(match_operand:SI 2 "s_register_operand" "")
9833 (match_operand:SI 3 "arm_add_operand" "")]))
9834 (const_int 0)))
9835 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9836 "TARGET_ARM"
9837 [(set (match_dup 4)
9838 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9839 (match_dup 0)))
9840 (set (reg:CC_NOOV CC_REGNUM)
9841 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9842 (const_int 0)))]
9843 "")
9844
9845(define_split
9846 [(set (reg:CC_NOOV CC_REGNUM)
9847 (compare:CC_NOOV (ior:SI
b0694be0 9848 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9849 [(match_operand:SI 2 "s_register_operand" "")
9850 (match_operand:SI 3 "arm_add_operand" "")])
9851 (and:SI (match_operand:SI 0 "s_register_operand" "")
9852 (const_int 1)))
9853 (const_int 0)))
9854 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9855 "TARGET_ARM"
9856 [(set (match_dup 4)
9857 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9858 (match_dup 0)))
9859 (set (reg:CC_NOOV CC_REGNUM)
9860 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9861 (const_int 0)))]
9862 "")
25f905c2 9863;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9864
f7fbdd4a 9865(define_insn "*negscc"
9c08d1fa 9866 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9867 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9868 [(match_operand:SI 1 "s_register_operand" "r")
9869 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9870 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9871 "TARGET_ARM"
9c08d1fa 9872 "*
2ca2ec2e 9873 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
e2348bcb 9874 return \"mov\\t%0, %1, asr #31\";
9875
9c08d1fa 9876 if (GET_CODE (operands[3]) == NE)
e2348bcb 9877 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9878
e2348bcb 9879 output_asm_insn (\"cmp\\t%1, %2\", operands);
9880 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9881 return \"mvn%d3\\t%0, #0\";
215b30b3 9882 "
8fa3ba89 9883 [(set_attr "conds" "clob")
9884 (set_attr "length" "12")]
9885)
9c08d1fa 9886
9887(define_insn "movcond"
9888 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9889 (if_then_else:SI
8fa3ba89 9890 (match_operator 5 "arm_comparison_operator"
5565501b 9891 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9892 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9893 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9894 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9895 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9896 "TARGET_ARM"
9c08d1fa 9897 "*
9898 if (GET_CODE (operands[5]) == LT
9899 && (operands[4] == const0_rtx))
9900 {
5565501b 9901 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9c08d1fa 9902 {
9c08d1fa 9903 if (operands[2] == const0_rtx)
e2348bcb 9904 return \"and\\t%0, %1, %3, asr #31\";
9905 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9906 }
9907 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9908 {
9c08d1fa 9909 if (operands[1] == const0_rtx)
e2348bcb 9910 return \"bic\\t%0, %2, %3, asr #31\";
9911 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9912 }
9913 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9914 are constants. */
9c08d1fa 9915 }
e2348bcb 9916
9c08d1fa 9917 if (GET_CODE (operands[5]) == GE
9918 && (operands[4] == const0_rtx))
9919 {
9920 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9921 {
9c08d1fa 9922 if (operands[2] == const0_rtx)
e2348bcb 9923 return \"bic\\t%0, %1, %3, asr #31\";
9924 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9925 }
9926 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9927 {
9c08d1fa 9928 if (operands[1] == const0_rtx)
e2348bcb 9929 return \"and\\t%0, %2, %3, asr #31\";
9930 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9931 }
9932 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9933 are constants. */
9c08d1fa 9934 }
9935 if (GET_CODE (operands[4]) == CONST_INT
9936 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9937 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9938 else
e2348bcb 9939 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9940 if (which_alternative != 0)
e2348bcb 9941 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9942 if (which_alternative != 1)
e2348bcb 9943 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9944 return \"\";
215b30b3 9945 "
8fa3ba89 9946 [(set_attr "conds" "clob")
9947 (set_attr "length" "8,8,12")]
9948)
9c08d1fa 9949
25f905c2 9950;; ??? The patterns below need checking for Thumb-2 usefulness.
9951
8a18b90c 9952(define_insn "*ifcompare_plus_move"
9953 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9954 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9955 [(match_operand:SI 4 "s_register_operand" "r,r")
9956 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9957 (plus:SI
9958 (match_operand:SI 2 "s_register_operand" "r,r")
9959 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9960 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9961 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9962 "TARGET_ARM"
8a18b90c 9963 "#"
8fa3ba89 9964 [(set_attr "conds" "clob")
9965 (set_attr "length" "8,12")]
9966)
8a18b90c 9967
9968(define_insn "*if_plus_move"
129a2fe4 9969 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9970 (if_then_else:SI
8fa3ba89 9971 (match_operator 4 "arm_comparison_operator"
8a18b90c 9972 [(match_operand 5 "cc_register" "") (const_int 0)])
9973 (plus:SI
129a2fe4 9974 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9975 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9976 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9977 "TARGET_ARM"
8a18b90c 9978 "@
9979 add%d4\\t%0, %2, %3
9980 sub%d4\\t%0, %2, #%n3
9981 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9982 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9983 [(set_attr "conds" "use")
9984 (set_attr "length" "4,4,8,8")
9985 (set_attr "type" "*,*,*,*")]
9986)
8a18b90c 9987
9988(define_insn "*ifcompare_move_plus"
5565501b 9989 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9990 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9991 [(match_operand:SI 4 "s_register_operand" "r,r")
9992 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9993 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9994 (plus:SI
9995 (match_operand:SI 2 "s_register_operand" "r,r")
9996 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9997 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9998 "TARGET_ARM"
8a18b90c 9999 "#"
8fa3ba89 10000 [(set_attr "conds" "clob")
10001 (set_attr "length" "8,12")]
10002)
8a18b90c 10003
10004(define_insn "*if_move_plus"
129a2fe4 10005 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 10006 (if_then_else:SI
8fa3ba89 10007 (match_operator 4 "arm_comparison_operator"
8a18b90c 10008 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 10009 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 10010 (plus:SI
129a2fe4 10011 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
10012 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 10013 "TARGET_ARM"
8a18b90c 10014 "@
10015 add%D4\\t%0, %2, %3
10016 sub%D4\\t%0, %2, #%n3
10017 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 10018 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 10019 [(set_attr "conds" "use")
10020 (set_attr "length" "4,4,8,8")
10021 (set_attr "type" "*,*,*,*")]
10022)
8a18b90c 10023
10024(define_insn "*ifcompare_arith_arith"
10025 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10026 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 10027 [(match_operand:SI 5 "s_register_operand" "r")
10028 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 10029 (match_operator:SI 8 "shiftable_operator"
8a18b90c 10030 [(match_operand:SI 1 "s_register_operand" "r")
10031 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 10032 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10033 [(match_operand:SI 3 "s_register_operand" "r")
10034 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 10035 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10036 "TARGET_ARM"
8a18b90c 10037 "#"
8fa3ba89 10038 [(set_attr "conds" "clob")
10039 (set_attr "length" "12")]
10040)
9c08d1fa 10041
8a18b90c 10042(define_insn "*if_arith_arith"
10043 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 10044 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 10045 [(match_operand 8 "cc_register" "") (const_int 0)])
10046 (match_operator:SI 6 "shiftable_operator"
10047 [(match_operand:SI 1 "s_register_operand" "r")
10048 (match_operand:SI 2 "arm_rhs_operand" "rI")])
10049 (match_operator:SI 7 "shiftable_operator"
10050 [(match_operand:SI 3 "s_register_operand" "r")
10051 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 10052 "TARGET_ARM"
8a18b90c 10053 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 10054 [(set_attr "conds" "use")
10055 (set_attr "length" "8")]
10056)
8a18b90c 10057
f7fbdd4a 10058(define_insn "*ifcompare_arith_move"
9c08d1fa 10059 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10060 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 10061 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 10062 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 10063 (match_operator:SI 7 "shiftable_operator"
10064 [(match_operand:SI 4 "s_register_operand" "r,r")
10065 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 10066 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 10067 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10068 "TARGET_ARM"
9c08d1fa 10069 "*
9c08d1fa 10070 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 10071 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 10072 everything is in registers then we can do this in two instructions. */
9c08d1fa 10073 if (operands[3] == const0_rtx
10074 && GET_CODE (operands[7]) != AND
10075 && GET_CODE (operands[5]) == REG
10076 && GET_CODE (operands[1]) == REG
10077 && REGNO (operands[1]) == REGNO (operands[4])
10078 && REGNO (operands[4]) != REGNO (operands[0]))
10079 {
10080 if (GET_CODE (operands[6]) == LT)
40dbec34 10081 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 10082 else if (GET_CODE (operands[6]) == GE)
40dbec34 10083 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 10084 }
10085 if (GET_CODE (operands[3]) == CONST_INT
10086 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 10087 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 10088 else
e2348bcb 10089 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 10090 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 10091 if (which_alternative != 0)
129a2fe4 10092 return \"mov%D6\\t%0, %1\";
9c08d1fa 10093 return \"\";
215b30b3 10094 "
8fa3ba89 10095 [(set_attr "conds" "clob")
10096 (set_attr "length" "8,12")]
10097)
9c08d1fa 10098
8a18b90c 10099(define_insn "*if_arith_move"
129a2fe4 10100 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10101 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 10102 [(match_operand 6 "cc_register" "") (const_int 0)])
10103 (match_operator:SI 5 "shiftable_operator"
129a2fe4 10104 [(match_operand:SI 2 "s_register_operand" "r,r")
10105 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
10106 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 10107 "TARGET_ARM"
8a18b90c 10108 "@
10109 %I5%d4\\t%0, %2, %3
129a2fe4 10110 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 10111 [(set_attr "conds" "use")
10112 (set_attr "length" "4,8")
10113 (set_attr "type" "*,*")]
10114)
8a18b90c 10115
f7fbdd4a 10116(define_insn "*ifcompare_move_arith"
9c08d1fa 10117 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10118 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 10119 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 10120 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 10121 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 10122 (match_operator:SI 7 "shiftable_operator"
10123 [(match_operand:SI 2 "s_register_operand" "r,r")
10124 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 10125 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10126 "TARGET_ARM"
9c08d1fa 10127 "*
9c08d1fa 10128 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 10129 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 10130 everything is in registers then we can do this in two instructions */
10131 if (operands[5] == const0_rtx
10132 && GET_CODE (operands[7]) != AND
10133 && GET_CODE (operands[3]) == REG
10134 && GET_CODE (operands[1]) == REG
10135 && REGNO (operands[1]) == REGNO (operands[2])
10136 && REGNO (operands[2]) != REGNO (operands[0]))
10137 {
10138 if (GET_CODE (operands[6]) == GE)
40dbec34 10139 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10140 else if (GET_CODE (operands[6]) == LT)
40dbec34 10141 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10142 }
40dbec34 10143
9c08d1fa 10144 if (GET_CODE (operands[5]) == CONST_INT
10145 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 10146 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 10147 else
e2348bcb 10148 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 10149
9c08d1fa 10150 if (which_alternative != 0)
129a2fe4 10151 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 10152 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 10153 "
8fa3ba89 10154 [(set_attr "conds" "clob")
10155 (set_attr "length" "8,12")]
10156)
9c08d1fa 10157
8a18b90c 10158(define_insn "*if_move_arith"
129a2fe4 10159 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10160 (if_then_else:SI
8fa3ba89 10161 (match_operator 4 "arm_comparison_operator"
8a18b90c 10162 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 10163 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 10164 (match_operator:SI 5 "shiftable_operator"
129a2fe4 10165 [(match_operand:SI 2 "s_register_operand" "r,r")
10166 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 10167 "TARGET_ARM"
8a18b90c 10168 "@
10169 %I5%D4\\t%0, %2, %3
129a2fe4 10170 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 10171 [(set_attr "conds" "use")
10172 (set_attr "length" "4,8")
10173 (set_attr "type" "*,*")]
10174)
8a18b90c 10175
10176(define_insn "*ifcompare_move_not"
9c08d1fa 10177 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10178 (if_then_else:SI
8fa3ba89 10179 (match_operator 5 "arm_comparison_operator"
8a18b90c 10180 [(match_operand:SI 3 "s_register_operand" "r,r")
10181 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10182 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10183 (not:SI
10184 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10185 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10186 "TARGET_ARM"
8a18b90c 10187 "#"
8fa3ba89 10188 [(set_attr "conds" "clob")
10189 (set_attr "length" "8,12")]
10190)
9c08d1fa 10191
8a18b90c 10192(define_insn "*if_move_not"
10193 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10194 (if_then_else:SI
8fa3ba89 10195 (match_operator 4 "arm_comparison_operator"
8a18b90c 10196 [(match_operand 3 "cc_register" "") (const_int 0)])
10197 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10198 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10199 "TARGET_ARM"
8a18b90c 10200 "@
10201 mvn%D4\\t%0, %2
10202 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
10203 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 10204 [(set_attr "conds" "use")
d2a518d1 10205 (set_attr "insn" "mvn")
8fa3ba89 10206 (set_attr "length" "4,8,8")]
10207)
8a18b90c 10208
10209(define_insn "*ifcompare_not_move"
9c08d1fa 10210 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10211 (if_then_else:SI
8fa3ba89 10212 (match_operator 5 "arm_comparison_operator"
8a18b90c 10213 [(match_operand:SI 3 "s_register_operand" "r,r")
10214 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10215 (not:SI
10216 (match_operand:SI 2 "s_register_operand" "r,r"))
10217 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10218 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10219 "TARGET_ARM"
8a18b90c 10220 "#"
8fa3ba89 10221 [(set_attr "conds" "clob")
10222 (set_attr "length" "8,12")]
10223)
9c08d1fa 10224
8a18b90c 10225(define_insn "*if_not_move"
10226 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10227 (if_then_else:SI
8fa3ba89 10228 (match_operator 4 "arm_comparison_operator"
8a18b90c 10229 [(match_operand 3 "cc_register" "") (const_int 0)])
10230 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10231 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10232 "TARGET_ARM"
8a18b90c 10233 "@
10234 mvn%d4\\t%0, %2
10235 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
10236 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 10237 [(set_attr "conds" "use")
d2a518d1 10238 (set_attr "insn" "mvn")
8fa3ba89 10239 (set_attr "length" "4,8,8")]
10240)
8a18b90c 10241
10242(define_insn "*ifcompare_shift_move"
9c08d1fa 10243 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10244 (if_then_else:SI
8fa3ba89 10245 (match_operator 6 "arm_comparison_operator"
8a18b90c 10246 [(match_operand:SI 4 "s_register_operand" "r,r")
10247 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10248 (match_operator:SI 7 "shift_operator"
10249 [(match_operand:SI 2 "s_register_operand" "r,r")
10250 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
10251 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10252 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10253 "TARGET_ARM"
9c08d1fa 10254 "#"
8fa3ba89 10255 [(set_attr "conds" "clob")
10256 (set_attr "length" "8,12")]
10257)
9c08d1fa 10258
8a18b90c 10259(define_insn "*if_shift_move"
10260 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10261 (if_then_else:SI
8fa3ba89 10262 (match_operator 5 "arm_comparison_operator"
8a18b90c 10263 [(match_operand 6 "cc_register" "") (const_int 0)])
10264 (match_operator:SI 4 "shift_operator"
10265 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10266 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
10267 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10268 "TARGET_ARM"
5565501b 10269 "@
8a18b90c 10270 mov%d5\\t%0, %2%S4
10271 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
10272 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 10273 [(set_attr "conds" "use")
331beb1a 10274 (set_attr "shift" "2")
a2cd141b 10275 (set_attr "length" "4,8,8")
d2a518d1 10276 (set_attr "insn" "mov")
a2cd141b 10277 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10278 (const_string "alu_shift")
10279 (const_string "alu_shift_reg")))]
8fa3ba89 10280)
5565501b 10281
8a18b90c 10282(define_insn "*ifcompare_move_shift"
10283 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10284 (if_then_else:SI
8fa3ba89 10285 (match_operator 6 "arm_comparison_operator"
8a18b90c 10286 [(match_operand:SI 4 "s_register_operand" "r,r")
10287 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10288 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 10289 (match_operator:SI 7 "shift_operator"
8a18b90c 10290 [(match_operand:SI 2 "s_register_operand" "r,r")
10291 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 10292 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10293 "TARGET_ARM"
8a18b90c 10294 "#"
8fa3ba89 10295 [(set_attr "conds" "clob")
10296 (set_attr "length" "8,12")]
10297)
5565501b 10298
8a18b90c 10299(define_insn "*if_move_shift"
10300 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 10301 (if_then_else:SI
8fa3ba89 10302 (match_operator 5 "arm_comparison_operator"
8a18b90c 10303 [(match_operand 6 "cc_register" "") (const_int 0)])
10304 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10305 (match_operator:SI 4 "shift_operator"
10306 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10307 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 10308 "TARGET_ARM"
5565501b 10309 "@
8a18b90c 10310 mov%D5\\t%0, %2%S4
10311 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10312 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 10313 [(set_attr "conds" "use")
331beb1a 10314 (set_attr "shift" "2")
a2cd141b 10315 (set_attr "length" "4,8,8")
d2a518d1 10316 (set_attr "insn" "mov")
a2cd141b 10317 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10318 (const_string "alu_shift")
10319 (const_string "alu_shift_reg")))]
8fa3ba89 10320)
9c08d1fa 10321
f7fbdd4a 10322(define_insn "*ifcompare_shift_shift"
8a18b90c 10323 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10324 (if_then_else:SI
8fa3ba89 10325 (match_operator 7 "arm_comparison_operator"
8a18b90c 10326 [(match_operand:SI 5 "s_register_operand" "r")
10327 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 10328 (match_operator:SI 8 "shift_operator"
8a18b90c 10329 [(match_operand:SI 1 "s_register_operand" "r")
10330 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 10331 (match_operator:SI 9 "shift_operator"
8a18b90c 10332 [(match_operand:SI 3 "s_register_operand" "r")
10333 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 10334 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10335 "TARGET_ARM"
8a18b90c 10336 "#"
8fa3ba89 10337 [(set_attr "conds" "clob")
10338 (set_attr "length" "12")]
10339)
9c08d1fa 10340
8a18b90c 10341(define_insn "*if_shift_shift"
10342 [(set (match_operand:SI 0 "s_register_operand" "=r")
10343 (if_then_else:SI
8fa3ba89 10344 (match_operator 5 "arm_comparison_operator"
8a18b90c 10345 [(match_operand 8 "cc_register" "") (const_int 0)])
10346 (match_operator:SI 6 "shift_operator"
10347 [(match_operand:SI 1 "s_register_operand" "r")
10348 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10349 (match_operator:SI 7 "shift_operator"
10350 [(match_operand:SI 3 "s_register_operand" "r")
10351 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 10352 "TARGET_ARM"
8a18b90c 10353 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 10354 [(set_attr "conds" "use")
331beb1a 10355 (set_attr "shift" "1")
a2cd141b 10356 (set_attr "length" "8")
d2a518d1 10357 (set_attr "insn" "mov")
a2cd141b 10358 (set (attr "type") (if_then_else
10359 (and (match_operand 2 "const_int_operand" "")
10360 (match_operand 4 "const_int_operand" ""))
10361 (const_string "alu_shift")
10362 (const_string "alu_shift_reg")))]
8fa3ba89 10363)
8a18b90c 10364
f7fbdd4a 10365(define_insn "*ifcompare_not_arith"
8a18b90c 10366 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10367 (if_then_else:SI
8fa3ba89 10368 (match_operator 6 "arm_comparison_operator"
8a18b90c 10369 [(match_operand:SI 4 "s_register_operand" "r")
10370 (match_operand:SI 5 "arm_add_operand" "rIL")])
10371 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 10372 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10373 [(match_operand:SI 2 "s_register_operand" "r")
10374 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 10375 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10376 "TARGET_ARM"
8a18b90c 10377 "#"
8fa3ba89 10378 [(set_attr "conds" "clob")
10379 (set_attr "length" "12")]
10380)
9c08d1fa 10381
8a18b90c 10382(define_insn "*if_not_arith"
10383 [(set (match_operand:SI 0 "s_register_operand" "=r")
10384 (if_then_else:SI
8fa3ba89 10385 (match_operator 5 "arm_comparison_operator"
8a18b90c 10386 [(match_operand 4 "cc_register" "") (const_int 0)])
10387 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10388 (match_operator:SI 6 "shiftable_operator"
10389 [(match_operand:SI 2 "s_register_operand" "r")
10390 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 10391 "TARGET_ARM"
8a18b90c 10392 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 10393 [(set_attr "conds" "use")
d2a518d1 10394 (set_attr "insn" "mvn")
8fa3ba89 10395 (set_attr "length" "8")]
10396)
8a18b90c 10397
10398(define_insn "*ifcompare_arith_not"
10399 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10400 (if_then_else:SI
8fa3ba89 10401 (match_operator 6 "arm_comparison_operator"
8a18b90c 10402 [(match_operand:SI 4 "s_register_operand" "r")
10403 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 10404 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10405 [(match_operand:SI 2 "s_register_operand" "r")
10406 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10407 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 10408 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10409 "TARGET_ARM"
8a18b90c 10410 "#"
8fa3ba89 10411 [(set_attr "conds" "clob")
10412 (set_attr "length" "12")]
10413)
9c08d1fa 10414
8a18b90c 10415(define_insn "*if_arith_not"
10416 [(set (match_operand:SI 0 "s_register_operand" "=r")
10417 (if_then_else:SI
8fa3ba89 10418 (match_operator 5 "arm_comparison_operator"
8a18b90c 10419 [(match_operand 4 "cc_register" "") (const_int 0)])
10420 (match_operator:SI 6 "shiftable_operator"
10421 [(match_operand:SI 2 "s_register_operand" "r")
10422 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10423 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 10424 "TARGET_ARM"
8a18b90c 10425 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 10426 [(set_attr "conds" "use")
d2a518d1 10427 (set_attr "insn" "mvn")
8fa3ba89 10428 (set_attr "length" "8")]
10429)
8a18b90c 10430
f7fbdd4a 10431(define_insn "*ifcompare_neg_move"
8a18b90c 10432 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10433 (if_then_else:SI
8fa3ba89 10434 (match_operator 5 "arm_comparison_operator"
8a18b90c 10435 [(match_operand:SI 3 "s_register_operand" "r,r")
10436 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10437 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10438 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10439 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10440 "TARGET_ARM"
8a18b90c 10441 "#"
8fa3ba89 10442 [(set_attr "conds" "clob")
10443 (set_attr "length" "8,12")]
10444)
8a18b90c 10445
10446(define_insn "*if_neg_move"
10447 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10448 (if_then_else:SI
8fa3ba89 10449 (match_operator 4 "arm_comparison_operator"
8a18b90c 10450 [(match_operand 3 "cc_register" "") (const_int 0)])
10451 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10452 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10453 "TARGET_ARM"
8a18b90c 10454 "@
10455 rsb%d4\\t%0, %2, #0
10456 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
10457 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 10458 [(set_attr "conds" "use")
10459 (set_attr "length" "4,8,8")]
10460)
9c08d1fa 10461
f7fbdd4a 10462(define_insn "*ifcompare_move_neg"
8a18b90c 10463 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10464 (if_then_else:SI
8fa3ba89 10465 (match_operator 5 "arm_comparison_operator"
8a18b90c 10466 [(match_operand:SI 3 "s_register_operand" "r,r")
10467 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10468 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10469 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10470 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10471 "TARGET_ARM"
8a18b90c 10472 "#"
8fa3ba89 10473 [(set_attr "conds" "clob")
10474 (set_attr "length" "8,12")]
10475)
8a18b90c 10476
10477(define_insn "*if_move_neg"
10478 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10479 (if_then_else:SI
8fa3ba89 10480 (match_operator 4 "arm_comparison_operator"
8a18b90c 10481 [(match_operand 3 "cc_register" "") (const_int 0)])
10482 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10483 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10484 "TARGET_ARM"
8a18b90c 10485 "@
10486 rsb%D4\\t%0, %2, #0
10487 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
10488 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 10489 [(set_attr "conds" "use")
10490 (set_attr "length" "4,8,8")]
10491)
9c08d1fa 10492
f7fbdd4a 10493(define_insn "*arith_adjacentmem"
9c08d1fa 10494 [(set (match_operand:SI 0 "s_register_operand" "=r")
10495 (match_operator:SI 1 "shiftable_operator"
10496 [(match_operand:SI 2 "memory_operand" "m")
10497 (match_operand:SI 3 "memory_operand" "m")]))
10498 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 10499 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 10500 "*
215b30b3 10501 {
10502 rtx ldm[3];
10503 rtx arith[4];
94dee231 10504 rtx base_reg;
10505 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 10506
215b30b3 10507 if (REGNO (operands[0]) > REGNO (operands[4]))
10508 {
10509 ldm[1] = operands[4];
10510 ldm[2] = operands[0];
10511 }
10512 else
10513 {
10514 ldm[1] = operands[0];
10515 ldm[2] = operands[4];
10516 }
94dee231 10517
10518 base_reg = XEXP (operands[2], 0);
10519
10520 if (!REG_P (base_reg))
10521 {
10522 val1 = INTVAL (XEXP (base_reg, 1));
10523 base_reg = XEXP (base_reg, 0);
10524 }
10525
10526 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10527 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10528
215b30b3 10529 arith[0] = operands[0];
10530 arith[3] = operands[1];
94dee231 10531
215b30b3 10532 if (val1 < val2)
10533 {
10534 arith[1] = ldm[1];
10535 arith[2] = ldm[2];
10536 }
10537 else
10538 {
10539 arith[1] = ldm[2];
10540 arith[2] = ldm[1];
10541 }
94dee231 10542
10543 ldm[0] = base_reg;
10544 if (val1 !=0 && val2 != 0)
215b30b3 10545 {
cdb1295a 10546 rtx ops[3];
10547
94dee231 10548 if (val1 == 4 || val2 == 4)
10549 /* Other val must be 8, since we know they are adjacent and neither
10550 is zero. */
25f905c2 10551 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 10552 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10553 {
94dee231 10554 ldm[0] = ops[0] = operands[4];
10555 ops[1] = base_reg;
10556 ops[2] = GEN_INT (val1);
10557 output_add_immediate (ops);
10558 if (val1 < val2)
25f905c2 10559 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 10560 else
25f905c2 10561 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 10562 }
cdb1295a 10563 else
10564 {
10565 /* Offset is out of range for a single add, so use two ldr. */
10566 ops[0] = ldm[1];
10567 ops[1] = base_reg;
10568 ops[2] = GEN_INT (val1);
10569 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10570 ops[0] = ldm[2];
10571 ops[2] = GEN_INT (val2);
10572 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10573 }
215b30b3 10574 }
94dee231 10575 else if (val1 != 0)
215b30b3 10576 {
215b30b3 10577 if (val1 < val2)
25f905c2 10578 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10579 else
25f905c2 10580 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10581 }
10582 else
10583 {
215b30b3 10584 if (val1 < val2)
25f905c2 10585 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10586 else
25f905c2 10587 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10588 }
10589 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10590 return \"\";
10591 }"
10592 [(set_attr "length" "12")
10593 (set_attr "predicable" "yes")
a2cd141b 10594 (set_attr "type" "load1")]
215b30b3 10595)
9c08d1fa 10596
9c08d1fa 10597; This pattern is never tried by combine, so do it as a peephole
10598
a0f94409 10599(define_peephole2
372575c7 10600 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10601 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10602 (set (reg:CC CC_REGNUM)
aea4c774 10603 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10604 "TARGET_ARM"
a0f94409 10605 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10606 (set (match_dup 0) (match_dup 1))])]
10607 ""
0d66636f 10608)
9c08d1fa 10609
9c08d1fa 10610(define_split
10611 [(set (match_operand:SI 0 "s_register_operand" "")
10612 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10613 (const_int 0))
8fa3ba89 10614 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10615 [(match_operand:SI 3 "s_register_operand" "")
10616 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10617 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10618 "TARGET_ARM"
9c08d1fa 10619 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10620 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10621 (match_dup 5)))]
215b30b3 10622 ""
10623)
9c08d1fa 10624
aea4c774 10625;; This split can be used because CC_Z mode implies that the following
10626;; branch will be an equality, or an unsigned inequality, so the sign
10627;; extension is not needed.
9c08d1fa 10628
aea4c774 10629(define_split
bd5b4116 10630 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10631 (compare:CC_Z
10632 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10633 (const_int 24))
aea4c774 10634 (match_operand 1 "const_int_operand" "")))
10635 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10636 "TARGET_ARM
10637 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10638 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 10639 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10640 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10641 "
9c08d1fa 10642 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10643 "
10644)
25f905c2 10645;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10646
87b22bf7 10647(define_expand "prologue"
10648 [(clobber (const_int 0))]
cffb2a26 10649 "TARGET_EITHER"
25f905c2 10650 "if (TARGET_32BIT)
cffb2a26 10651 arm_expand_prologue ();
10652 else
25f905c2 10653 thumb1_expand_prologue ();
87b22bf7 10654 DONE;
cffb2a26 10655 "
10656)
87b22bf7 10657
56d27660 10658(define_expand "epilogue"
4c44712e 10659 [(clobber (const_int 0))]
cffb2a26 10660 "TARGET_EITHER"
56d27660 10661 "
18d50ae6 10662 if (crtl->calls_eh_return)
4c44712e 10663 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10664 if (TARGET_THUMB1)
10665 thumb1_expand_epilogue ();
cffb2a26 10666 else if (USE_RETURN_INSN (FALSE))
56d27660 10667 {
10668 emit_jump_insn (gen_return ());
10669 DONE;
10670 }
cffb2a26 10671 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
1a860023 10672 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
cffb2a26 10673 DONE;
10674 "
10675)
56d27660 10676
7571d3f7 10677(define_insn "prologue_thumb1_interwork"
10678 [(unspec_volatile [(const_int 0)] VUNSPEC_THUMB1_INTERWORK)]
10679 "TARGET_THUMB1"
10680 "* return thumb1_output_interwork ();"
10681 [(set_attr "length" "8")]
10682)
10683
ef5651d0 10684;; Note - although unspec_volatile's USE all hard registers,
10685;; USEs are ignored after relaod has completed. Thus we need
10686;; to add an unspec of the link register to ensure that flow
10687;; does not think that it is unused by the sibcall branch that
10688;; will replace the standard function epilogue.
1c494086 10689(define_insn "sibcall_epilogue"
ef5651d0 10690 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10691 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
25f905c2 10692 "TARGET_32BIT"
1c494086 10693 "*
ffc9d00c 10694 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
5db468b7 10695 return output_return_instruction (const_true_rtx, FALSE, FALSE);
ffc9d00c 10696 return arm_output_epilogue (next_nonnote_insn (insn));
1c494086 10697 "
10698;; Length is absolute worst case
10699 [(set_attr "length" "44")
defc47cf 10700 (set_attr "type" "block")
10701 ;; We don't clobber the conditions, but the potential length of this
10702 ;; operation is sufficient to make conditionalizing the sequence
10703 ;; unlikely to be profitable.
10704 (set_attr "conds" "clob")]
1c494086 10705)
10706
cffb2a26 10707(define_insn "*epilogue_insns"
e1159bbe 10708 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 10709 "TARGET_EITHER"
56d27660 10710 "*
25f905c2 10711 if (TARGET_32BIT)
ffc9d00c 10712 return arm_output_epilogue (NULL);
25f905c2 10713 else /* TARGET_THUMB1 */
cffb2a26 10714 return thumb_unexpanded_epilogue ();
10715 "
215b30b3 10716 ; Length is absolute worst case
cffb2a26 10717 [(set_attr "length" "44")
defc47cf 10718 (set_attr "type" "block")
10719 ;; We don't clobber the conditions, but the potential length of this
10720 ;; operation is sufficient to make conditionalizing the sequence
10721 ;; unlikely to be profitable.
10722 (set_attr "conds" "clob")]
cffb2a26 10723)
10724
10725(define_expand "eh_epilogue"
7db9af5d 10726 [(use (match_operand:SI 0 "register_operand" ""))
10727 (use (match_operand:SI 1 "register_operand" ""))
10728 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10729 "TARGET_EITHER"
10730 "
215b30b3 10731 {
10732 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10733 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10734 {
10735 rtx ra = gen_rtx_REG (Pmode, 2);
10736
10737 emit_move_insn (ra, operands[2]);
10738 operands[2] = ra;
10739 }
5cf3595a 10740 /* This is a hack -- we may have crystalized the function type too
10741 early. */
10742 cfun->machine->func_type = 0;
215b30b3 10743 }"
10744)
56d27660 10745
9c08d1fa 10746;; This split is only used during output to reduce the number of patterns
10747;; that need assembler instructions adding to them. We allowed the setting
10748;; of the conditions to be implicit during rtl generation so that
10749;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10750;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10751;; up again here.
10752
25f905c2 10753;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10754;; conditional execution sufficient?
10755
9c08d1fa 10756(define_split
10757 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10758 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10759 [(match_operand 2 "" "") (match_operand 3 "" "")])
10760 (match_dup 0)
10761 (match_operand 4 "" "")))
bd5b4116 10762 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10763 "TARGET_ARM && reload_completed"
8fa3ba89 10764 [(set (match_dup 5) (match_dup 6))
10765 (cond_exec (match_dup 7)
10766 (set (match_dup 0) (match_dup 4)))]
10767 "
10768 {
10769 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10770 operands[2], operands[3]);
10771 enum rtx_code rc = GET_CODE (operands[1]);
10772
bd5b4116 10773 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10774 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10775 if (mode == CCFPmode || mode == CCFPEmode)
10776 rc = reverse_condition_maybe_unordered (rc);
10777 else
10778 rc = reverse_condition (rc);
10779
10780 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10781 }"
10782)
10783
10784(define_split
10785 [(set (match_operand:SI 0 "s_register_operand" "")
10786 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10787 [(match_operand 2 "" "") (match_operand 3 "" "")])
10788 (match_operand 4 "" "")
10789 (match_dup 0)))
bd5b4116 10790 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10791 "TARGET_ARM && reload_completed"
8fa3ba89 10792 [(set (match_dup 5) (match_dup 6))
10793 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10794 (set (match_dup 0) (match_dup 4)))]
10795 "
10796 {
10797 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10798 operands[2], operands[3]);
10799
bd5b4116 10800 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10801 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10802 }"
10803)
10804
10805(define_split
10806 [(set (match_operand:SI 0 "s_register_operand" "")
10807 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10808 [(match_operand 2 "" "") (match_operand 3 "" "")])
10809 (match_operand 4 "" "")
10810 (match_operand 5 "" "")))
bd5b4116 10811 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10812 "TARGET_ARM && reload_completed"
8fa3ba89 10813 [(set (match_dup 6) (match_dup 7))
10814 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10815 (set (match_dup 0) (match_dup 4)))
10816 (cond_exec (match_dup 8)
10817 (set (match_dup 0) (match_dup 5)))]
10818 "
10819 {
10820 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10821 operands[2], operands[3]);
10822 enum rtx_code rc = GET_CODE (operands[1]);
10823
bd5b4116 10824 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10825 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10826 if (mode == CCFPmode || mode == CCFPEmode)
10827 rc = reverse_condition_maybe_unordered (rc);
10828 else
10829 rc = reverse_condition (rc);
10830
10831 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10832 }"
10833)
10834
cffb2a26 10835(define_split
10836 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10837 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10838 [(match_operand:SI 2 "s_register_operand" "")
10839 (match_operand:SI 3 "arm_add_operand" "")])
10840 (match_operand:SI 4 "arm_rhs_operand" "")
10841 (not:SI
10842 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10843 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10844 "TARGET_ARM && reload_completed"
cffb2a26 10845 [(set (match_dup 6) (match_dup 7))
f6c53574 10846 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10847 (set (match_dup 0) (match_dup 4)))
10848 (cond_exec (match_dup 8)
10849 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10850 "
215b30b3 10851 {
10852 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10853 operands[2], operands[3]);
f6c53574 10854 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10855
bd5b4116 10856 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10857 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10858 if (mode == CCFPmode || mode == CCFPEmode)
10859 rc = reverse_condition_maybe_unordered (rc);
10860 else
10861 rc = reverse_condition (rc);
10862
10863 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10864 }"
10865)
cffb2a26 10866
10867(define_insn "*cond_move_not"
10868 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10869 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10870 [(match_operand 3 "cc_register" "") (const_int 0)])
10871 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10872 (not:SI
10873 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10874 "TARGET_ARM"
10875 "@
10876 mvn%D4\\t%0, %2
10877 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10878 [(set_attr "conds" "use")
d2a518d1 10879 (set_attr "insn" "mvn")
0d66636f 10880 (set_attr "length" "4,8")]
10881)
cffb2a26 10882
9c08d1fa 10883;; The next two patterns occur when an AND operation is followed by a
10884;; scc insn sequence
10885
f7fbdd4a 10886(define_insn "*sign_extract_onebit"
9c08d1fa 10887 [(set (match_operand:SI 0 "s_register_operand" "=r")
10888 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10889 (const_int 1)
ed750274 10890 (match_operand:SI 2 "const_int_operand" "n")))
10891 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10892 "TARGET_ARM"
9c08d1fa 10893 "*
0d66636f 10894 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10895 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10896 return \"mvnne\\t%0, #0\";
10897 "
10898 [(set_attr "conds" "clob")
10899 (set_attr "length" "8")]
10900)
9c08d1fa 10901
f7fbdd4a 10902(define_insn "*not_signextract_onebit"
9c08d1fa 10903 [(set (match_operand:SI 0 "s_register_operand" "=r")
10904 (not:SI
10905 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10906 (const_int 1)
ed750274 10907 (match_operand:SI 2 "const_int_operand" "n"))))
10908 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10909 "TARGET_ARM"
9c08d1fa 10910 "*
0d66636f 10911 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10912 output_asm_insn (\"tst\\t%1, %2\", operands);
10913 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10914 return \"movne\\t%0, #0\";
10915 "
10916 [(set_attr "conds" "clob")
10917 (set_attr "length" "12")]
10918)
25f905c2 10919;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10920
0d66636f 10921;; Push multiple registers to the stack. Registers are in parallel (use ...)
10922;; expressions. For simplicity, the first register is also in the unspec
10923;; part.
08508cbf 10924;; To avoid the usage of GNU extension, the length attribute is computed
10925;; in a C function arm_attr_length_push_multi.
f7fbdd4a 10926(define_insn "*push_multi"
87b22bf7 10927 [(match_parallel 2 "multi_register_push"
7571d3f7 10928 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
3cc80a30 10929 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 10930 UNSPEC_PUSH_MULT))])]
7571d3f7 10931 ""
87b22bf7 10932 "*
215b30b3 10933 {
10934 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10935
215b30b3 10936 /* For the StrongARM at least it is faster to
25f905c2 10937 use STR to store only a single register.
542d5028 10938 In Thumb mode always use push, and the assembler will pick
10939 something appropriate. */
25f905c2 10940 if (num_saves == 1 && TARGET_ARM)
61309563 10941 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
215b30b3 10942 else
10943 {
10944 int i;
10945 char pattern[100];
ed593f11 10946
25f905c2 10947 if (TARGET_ARM)
61309563 10948 strcpy (pattern, \"stm%(fd%)\\t%m0!, {%1\");
10949 else if (TARGET_THUMB2)
10950 strcpy (pattern, \"push%?\\t{%1\");
25f905c2 10951 else
10952 strcpy (pattern, \"push\\t{%1\");
215b30b3 10953
6079f055 10954 for (i = 1; i < num_saves; i++)
215b30b3 10955 {
10956 strcat (pattern, \", %|\");
10957 strcat (pattern,
10958 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10959 }
10960
10961 strcat (pattern, \"}\");
10962 output_asm_insn (pattern, operands);
10963 }
10964
10965 return \"\";
10966 }"
a6864a24 10967 [(set_attr "type" "store4")
10968 (set (attr "length")
08508cbf 10969 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 10970)
f7fbdd4a 10971
4c58c898 10972(define_insn "stack_tie"
10973 [(set (mem:BLK (scratch))
aaa37ad6 10974 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10975 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10976 UNSPEC_PRLG_STK))]
10977 ""
10978 ""
10979 [(set_attr "length" "0")]
10980)
10981
3398e91d 10982;; Similarly for the floating point registers
7b1d2fc4 10983(define_insn "*push_fp_multi"
10984 [(match_parallel 2 "multi_register_push"
10985 [(set (match_operand:BLK 0 "memory_operand" "=m")
3cc80a30 10986 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "")]
e1159bbe 10987 UNSPEC_PUSH_MULT))])]
25f905c2 10988 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7b1d2fc4 10989 "*
215b30b3 10990 {
10991 char pattern[100];
7b1d2fc4 10992
877cdec9 10993 sprintf (pattern, \"sfm%%(fd%%)\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
215b30b3 10994 output_asm_insn (pattern, operands);
10995 return \"\";
10996 }"
013b9671 10997 [(set_attr "type" "f_fpa_store")]
215b30b3 10998)
7b1d2fc4 10999
f7fbdd4a 11000;; Special patterns for dealing with the constant pool
11001
cffb2a26 11002(define_insn "align_4"
e1159bbe 11003 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 11004 "TARGET_EITHER"
f7fbdd4a 11005 "*
cffb2a26 11006 assemble_align (32);
f7fbdd4a 11007 return \"\";
cffb2a26 11008 "
11009)
f7fbdd4a 11010
755eb2b4 11011(define_insn "align_8"
11012 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 11013 "TARGET_EITHER"
755eb2b4 11014 "*
11015 assemble_align (64);
11016 return \"\";
11017 "
11018)
11019
cffb2a26 11020(define_insn "consttable_end"
e1159bbe 11021 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 11022 "TARGET_EITHER"
f7fbdd4a 11023 "*
cffb2a26 11024 making_const_table = FALSE;
f7fbdd4a 11025 return \"\";
cffb2a26 11026 "
11027)
f7fbdd4a 11028
cffb2a26 11029(define_insn "consttable_1"
e1159bbe 11030 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
25f905c2 11031 "TARGET_THUMB1"
f7fbdd4a 11032 "*
cffb2a26 11033 making_const_table = TRUE;
09d688ff 11034 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 11035 assemble_zeros (3);
f7fbdd4a 11036 return \"\";
cffb2a26 11037 "
11038 [(set_attr "length" "4")]
11039)
f7fbdd4a 11040
cffb2a26 11041(define_insn "consttable_2"
e1159bbe 11042 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
25f905c2 11043 "TARGET_THUMB1"
f7fbdd4a 11044 "*
cffb2a26 11045 making_const_table = TRUE;
9b8516be 11046 gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
09d688ff 11047 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 11048 assemble_zeros (2);
f7fbdd4a 11049 return \"\";
cffb2a26 11050 "
11051 [(set_attr "length" "4")]
11052)
11053
11054(define_insn "consttable_4"
e1159bbe 11055 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 11056 "TARGET_EITHER"
11057 "*
11058 {
9b8516be 11059 rtx x = operands[0];
cffb2a26 11060 making_const_table = TRUE;
9b8516be 11061 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 11062 {
11063 case MODE_FLOAT:
9b8516be 11064 if (GET_MODE (x) == HFmode)
11065 arm_emit_fp16_const (x);
11066 else
11067 {
11068 REAL_VALUE_TYPE r;
11069 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
11070 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
11071 }
11072 break;
cffb2a26 11073 default:
7b04c5d5 11074 /* XXX: Sometimes gcc does something really dumb and ends up with
11075 a HIGH in a constant pool entry, usually because it's trying to
11076 load into a VFP register. We know this will always be used in
11077 combination with a LO_SUM which ignores the high bits, so just
11078 strip off the HIGH. */
11079 if (GET_CODE (x) == HIGH)
11080 x = XEXP (x, 0);
9b8516be 11081 assemble_integer (x, 4, BITS_PER_WORD, 1);
11082 mark_symbol_refs_as_used (x);
cffb2a26 11083 break;
11084 }
11085 return \"\";
11086 }"
11087 [(set_attr "length" "4")]
11088)
11089
11090(define_insn "consttable_8"
e1159bbe 11091 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 11092 "TARGET_EITHER"
11093 "*
11094 {
11095 making_const_table = TRUE;
11096 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11097 {
11098 case MODE_FLOAT:
11099 {
badfe841 11100 REAL_VALUE_TYPE r;
11101 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
11102 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 11103 break;
11104 }
11105 default:
09d688ff 11106 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 11107 break;
11108 }
11109 return \"\";
11110 }"
11111 [(set_attr "length" "8")]
11112)
11113
d98a3884 11114(define_insn "consttable_16"
11115 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
11116 "TARGET_EITHER"
11117 "*
11118 {
11119 making_const_table = TRUE;
11120 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11121 {
11122 case MODE_FLOAT:
11123 {
11124 REAL_VALUE_TYPE r;
11125 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
11126 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
11127 break;
11128 }
11129 default:
11130 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
11131 break;
11132 }
11133 return \"\";
11134 }"
11135 [(set_attr "length" "16")]
11136)
11137
cffb2a26 11138;; Miscellaneous Thumb patterns
11139
fd957ef3 11140(define_expand "tablejump"
7db9af5d 11141 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 11142 (use (label_ref (match_operand 1 "" "")))])]
25f905c2 11143 "TARGET_THUMB1"
fd957ef3 11144 "
11145 if (flag_pic)
11146 {
11147 /* Hopefully, CSE will eliminate this copy. */
11148 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
11149 rtx reg2 = gen_reg_rtx (SImode);
11150
11151 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
11152 operands[0] = reg2;
11153 }
11154 "
11155)
11156
f1039640 11157;; NB never uses BX.
25f905c2 11158(define_insn "*thumb1_tablejump"
cffb2a26 11159 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
11160 (use (label_ref (match_operand 1 "" "")))]
25f905c2 11161 "TARGET_THUMB1"
fd957ef3 11162 "mov\\t%|pc, %0"
cffb2a26 11163 [(set_attr "length" "2")]
11164)
0d66636f 11165
331beb1a 11166;; V5 Instructions,
11167
8f4be2be 11168(define_insn "clzsi2"
11169 [(set (match_operand:SI 0 "s_register_operand" "=r")
11170 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 11171 "TARGET_32BIT && arm_arch5"
ee7cbe0e 11172 "clz%?\\t%0, %1"
bcaec148 11173 [(set_attr "predicable" "yes")
11174 (set_attr "insn" "clz")])
331beb1a 11175
099ad98b 11176(define_insn "rbitsi2"
11177 [(set (match_operand:SI 0 "s_register_operand" "=r")
11178 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
11179 "TARGET_32BIT && arm_arch_thumb2"
11180 "rbit%?\\t%0, %1"
11181 [(set_attr "predicable" "yes")
11182 (set_attr "insn" "clz")])
11183
11184(define_expand "ctzsi2"
11185 [(set (match_operand:SI 0 "s_register_operand" "")
11186 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
11187 "TARGET_32BIT && arm_arch_thumb2"
11188 "
30191172 11189 {
11190 rtx tmp = gen_reg_rtx (SImode);
11191 emit_insn (gen_rbitsi2 (tmp, operands[1]));
11192 emit_insn (gen_clzsi2 (operands[0], tmp));
11193 }
099ad98b 11194 DONE;
11195 "
11196)
11197
e1159bbe 11198;; V5E instructions.
331beb1a 11199
11200(define_insn "prefetch"
f4e79814 11201 [(prefetch (match_operand:SI 0 "address_operand" "p")
11202 (match_operand:SI 1 "" "")
11203 (match_operand:SI 2 "" ""))]
25f905c2 11204 "TARGET_32BIT && arm_arch5e"
bcb7a8f6 11205 "pld\\t%a0")
331beb1a 11206
0d66636f 11207;; General predication pattern
11208
11209(define_cond_exec
11210 [(match_operator 0 "arm_comparison_operator"
11211 [(match_operand 1 "cc_register" "")
11212 (const_int 0)])]
25f905c2 11213 "TARGET_32BIT"
0d66636f 11214 ""
11215)
11216
063a05c7 11217(define_insn "prologue_use"
11218 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
11219 ""
11220 "%@ %0 needed for prologue"
02cfc9c9 11221 [(set_attr "length" "0")]
063a05c7 11222)
7db9af5d 11223
4c44712e 11224
11225;; Patterns for exception handling
11226
11227(define_expand "eh_return"
11228 [(use (match_operand 0 "general_operand" ""))]
11229 "TARGET_EITHER"
11230 "
11231 {
25f905c2 11232 if (TARGET_32BIT)
4c44712e 11233 emit_insn (gen_arm_eh_return (operands[0]));
11234 else
11235 emit_insn (gen_thumb_eh_return (operands[0]));
11236 DONE;
11237 }"
11238)
11239
11240;; We can't expand this before we know where the link register is stored.
11241(define_insn_and_split "arm_eh_return"
11242 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11243 VUNSPEC_EH_RETURN)
11244 (clobber (match_scratch:SI 1 "=&r"))]
11245 "TARGET_ARM"
11246 "#"
11247 "&& reload_completed"
11248 [(const_int 0)]
11249 "
11250 {
11251 arm_set_return_address (operands[0], operands[1]);
11252 DONE;
11253 }"
11254)
11255
11256(define_insn_and_split "thumb_eh_return"
11257 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
11258 VUNSPEC_EH_RETURN)
11259 (clobber (match_scratch:SI 1 "=&l"))]
25f905c2 11260 "TARGET_THUMB1"
4c44712e 11261 "#"
11262 "&& reload_completed"
11263 [(const_int 0)]
11264 "
11265 {
11266 thumb_set_return_address (operands[0], operands[1]);
11267 DONE;
11268 }"
11269)
11270
f655717d 11271\f
11272;; TLS support
11273
11274(define_insn "load_tp_hard"
11275 [(set (match_operand:SI 0 "register_operand" "=r")
11276 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11277 "TARGET_HARD_TP"
11278 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
11279 [(set_attr "predicable" "yes")]
11280)
11281
11282;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11283(define_insn "load_tp_soft"
11284 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11285 (clobber (reg:SI LR_REGNUM))
11286 (clobber (reg:SI IP_REGNUM))
11287 (clobber (reg:CC CC_REGNUM))]
11288 "TARGET_SOFT_TP"
11289 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
11290 [(set_attr "conds" "clob")]
11291)
11292
f41e4452 11293;; tls descriptor call
11294(define_insn "tlscall"
11295 [(set (reg:SI R0_REGNUM)
11296 (unspec:SI [(reg:SI R0_REGNUM)
11297 (match_operand:SI 0 "" "X")
11298 (match_operand 1 "" "")] UNSPEC_TLS))
11299 (clobber (reg:SI R1_REGNUM))
11300 (clobber (reg:SI LR_REGNUM))
11301 (clobber (reg:SI CC_REGNUM))]
11302 "TARGET_GNU2_TLS"
11303 {
11304 targetm.asm_out.internal_label (asm_out_file, "LPIC",
11305 INTVAL (operands[1]));
11306 return "bl\\t%c0(tlscall)";
11307 }
11308 [(set_attr "conds" "clob")
11309 (set_attr "length" "4")]
11310)
11311
11312;;
11313
aabe09ac 11314;; We only care about the lower 16 bits of the constant
11315;; being inserted into the upper 16 bits of the register.
eca5c984 11316(define_insn "*arm_movtas_ze"
11317 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
11318 (const_int 16)
11319 (const_int 16))
11320 (match_operand:SI 1 "const_int_operand" ""))]
181ab277 11321 "arm_arch_thumb2"
aabe09ac 11322 "movt%?\t%0, %L1"
eca5c984 11323 [(set_attr "predicable" "yes")
11324 (set_attr "length" "4")]
11325)
11326
c0fc3696 11327(define_insn "*arm_rev"
ff82f757 11328 [(set (match_operand:SI 0 "s_register_operand" "=r")
11329 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
c0fc3696 11330 "TARGET_32BIT && arm_arch6"
11331 "rev%?\t%0, %1"
11332 [(set_attr "predicable" "yes")
11333 (set_attr "length" "4")]
11334)
11335
11336(define_insn "*thumb1_rev"
11337 [(set (match_operand:SI 0 "s_register_operand" "=l")
11338 (bswap:SI (match_operand:SI 1 "s_register_operand" "l")))]
11339 "TARGET_THUMB1 && arm_arch6"
11340 "rev\t%0, %1"
11341 [(set_attr "length" "2")]
ff82f757 11342)
11343
11344(define_expand "arm_legacy_rev"
11345 [(set (match_operand:SI 2 "s_register_operand" "")
11346 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
11347 (const_int 16))
11348 (match_dup 1)))
11349 (set (match_dup 2)
11350 (lshiftrt:SI (match_dup 2)
11351 (const_int 8)))
11352 (set (match_operand:SI 3 "s_register_operand" "")
11353 (rotatert:SI (match_dup 1)
11354 (const_int 8)))
11355 (set (match_dup 2)
11356 (and:SI (match_dup 2)
11357 (const_int -65281)))
11358 (set (match_operand:SI 0 "s_register_operand" "")
11359 (xor:SI (match_dup 3)
11360 (match_dup 2)))]
11361 "TARGET_32BIT"
11362 ""
11363)
11364
11365;; Reuse temporaries to keep register pressure down.
11366(define_expand "thumb_legacy_rev"
11367 [(set (match_operand:SI 2 "s_register_operand" "")
11368 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
11369 (const_int 24)))
11370 (set (match_operand:SI 3 "s_register_operand" "")
11371 (lshiftrt:SI (match_dup 1)
11372 (const_int 24)))
11373 (set (match_dup 3)
11374 (ior:SI (match_dup 3)
11375 (match_dup 2)))
11376 (set (match_operand:SI 4 "s_register_operand" "")
11377 (const_int 16))
11378 (set (match_operand:SI 5 "s_register_operand" "")
11379 (rotatert:SI (match_dup 1)
11380 (match_dup 4)))
11381 (set (match_dup 2)
11382 (ashift:SI (match_dup 5)
11383 (const_int 24)))
11384 (set (match_dup 5)
11385 (lshiftrt:SI (match_dup 5)
11386 (const_int 24)))
11387 (set (match_dup 5)
11388 (ior:SI (match_dup 5)
11389 (match_dup 2)))
11390 (set (match_dup 5)
11391 (rotatert:SI (match_dup 5)
11392 (match_dup 4)))
11393 (set (match_operand:SI 0 "s_register_operand" "")
11394 (ior:SI (match_dup 5)
11395 (match_dup 3)))]
11396 "TARGET_THUMB"
11397 ""
11398)
11399
11400(define_expand "bswapsi2"
11401 [(set (match_operand:SI 0 "s_register_operand" "=r")
11402 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
8d1af482 11403"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 11404"
8d1af482 11405 if (!arm_arch6)
11406 {
11407 rtx op2 = gen_reg_rtx (SImode);
11408 rtx op3 = gen_reg_rtx (SImode);
ff82f757 11409
8d1af482 11410 if (TARGET_THUMB)
11411 {
11412 rtx op4 = gen_reg_rtx (SImode);
11413 rtx op5 = gen_reg_rtx (SImode);
ff82f757 11414
8d1af482 11415 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11416 op2, op3, op4, op5));
11417 }
11418 else
11419 {
11420 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11421 op2, op3));
11422 }
ff82f757 11423
8d1af482 11424 DONE;
11425 }
ff82f757 11426 "
11427)
11428
320ea44d 11429;; Load the load/store multiple patterns
11430(include "ldmstm.md")
7db9af5d 11431;; Load the FPA co-processor patterns
11432(include "fpa.md")
11433;; Load the Maverick co-processor patterns
11434(include "cirrus.md")
d98a3884 11435;; Vector bits common to IWMMXT and Neon
11436(include "vec-common.md")
755eb2b4 11437;; Load the Intel Wireless Multimedia Extension patterns
11438(include "iwmmxt.md")
a2cd141b 11439;; Load the VFP co-processor patterns
11440(include "vfp.md")
25f905c2 11441;; Thumb-2 patterns
11442(include "thumb2.md")
d98a3884 11443;; Neon patterns
11444(include "neon.md")
06df6b17 11445;; Synchronization Primitives
11446(include "sync.md")
bbbe4599 11447;; Fixed-point patterns
11448(include "arm-fixed.md")