]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
* init.c (expand_default_init): Unshare args in ctor delegation.
[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,
7cf0dbf3 3;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
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.
e7d6d136 119])
e1159bbe 120
215b30b3 121;; UNSPEC_VOLATILE Usage:
e1159bbe 122
e7d6d136 123(define_c_enum "unspecv" [
124 VUNSPEC_BLOCKAGE ; `blockage' insn to prevent scheduling across an
125 ; insn in the code.
126 VUNSPEC_EPILOGUE ; `epilogue' insn, used to represent any part of the
127 ; instruction epilogue sequence that isn't expanded
128 ; into normal RTL. Used for both normal and sibcall
129 ; epilogues.
7571d3f7 130 VUNSPEC_THUMB1_INTERWORK ; `prologue_thumb1_interwork' insn, used to swap
131 ; modes from arm to thumb.
e7d6d136 132 VUNSPEC_ALIGN ; `align' insn. Used at the head of a minipool table
133 ; for inlined constants.
134 VUNSPEC_POOL_END ; `end-of-table'. Used to mark the end of a minipool
135 ; table.
136 VUNSPEC_POOL_1 ; `pool-entry(1)'. An entry in the constant pool for
137 ; an 8-bit object.
138 VUNSPEC_POOL_2 ; `pool-entry(2)'. An entry in the constant pool for
139 ; a 16-bit object.
140 VUNSPEC_POOL_4 ; `pool-entry(4)'. An entry in the constant pool for
141 ; a 32-bit object.
142 VUNSPEC_POOL_8 ; `pool-entry(8)'. An entry in the constant pool for
143 ; a 64-bit object.
144 VUNSPEC_POOL_16 ; `pool-entry(16)'. An entry in the constant pool for
145 ; a 128-bit object.
146 VUNSPEC_TMRC ; Used by the iWMMXt TMRC instruction.
147 VUNSPEC_TMCR ; Used by the iWMMXt TMCR instruction.
148 VUNSPEC_ALIGN8 ; 8-byte alignment version of VUNSPEC_ALIGN
149 VUNSPEC_WCMP_EQ ; Used by the iWMMXt WCMPEQ instructions
150 VUNSPEC_WCMP_GTU ; Used by the iWMMXt WCMPGTU instructions
151 VUNSPEC_WCMP_GT ; Used by the iwMMXT WCMPGT instructions
152 VUNSPEC_EH_RETURN ; Use to override the return address for exception
153 ; handling.
154 VUNSPEC_SYNC_COMPARE_AND_SWAP ; Represent an atomic compare swap.
155 VUNSPEC_SYNC_LOCK ; Represent a sync_lock_test_and_set.
156 VUNSPEC_SYNC_OP ; Represent a sync_<op>
157 VUNSPEC_SYNC_NEW_OP ; Represent a sync_new_<op>
158 VUNSPEC_SYNC_OLD_OP ; Represent a sync_old_<op>
159])
b11cae9e 160\f
e1159bbe 161;;---------------------------------------------------------------------------
9c08d1fa 162;; Attributes
163
a651f34d 164;; Processor type. This is created automatically from arm-cores.def.
165(include "arm-tune.md")
166
215b30b3 167; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
168; generating ARM code. This is used to control the length of some insn
169; patterns that share the same RTL in both ARM and Thumb code.
1c494086 170(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
cffb2a26 171
ef51b8e1 172; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
173(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
174
747b7458 175; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
176(define_attr "is_thumb1" "no,yes" (const (symbol_ref "thumb1_code")))
177
331beb1a 178;; Operand number of an input operand that is shifted. Zero if the
179;; given instruction does not shift one of its input operands.
331beb1a 180(define_attr "shift" "" (const_int 0))
181
3d91c5d6 182; Floating Point Unit. If we only have floating point emulation, then there
183; is no point in scheduling the floating point insns. (Well, for best
184; performance we should try and group them together).
4fea7d65 185(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
c7f506fd 186 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 187
06df6b17 188(define_attr "sync_result" "none,0,1,2,3,4,5" (const_string "none"))
189(define_attr "sync_memory" "none,0,1,2,3,4,5" (const_string "none"))
190(define_attr "sync_required_value" "none,0,1,2,3,4,5" (const_string "none"))
191(define_attr "sync_new_value" "none,0,1,2,3,4,5" (const_string "none"))
192(define_attr "sync_t1" "none,0,1,2,3,4,5" (const_string "none"))
193(define_attr "sync_t2" "none,0,1,2,3,4,5" (const_string "none"))
194(define_attr "sync_release_barrier" "yes,no" (const_string "yes"))
195(define_attr "sync_op" "none,add,sub,ior,xor,and,nand"
196 (const_string "none"))
197
094e994f 198; LENGTH of an instruction (in bytes)
06df6b17 199(define_attr "length" ""
200 (cond [(not (eq_attr "sync_memory" "none"))
201 (symbol_ref "arm_sync_loop_insns (insn, operands) * 4")
202 ] (const_int 4)))
9c08d1fa 203
d5d4dc8d 204; The architecture which supports the instruction (or alternative).
205; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
206; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
207; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
208; arm_arch6. This attribute is used to compute attribute "enabled",
209; use type "any" to enable an alternative in all cases.
a651f34d 210(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,onlya8,nota8"
d5d4dc8d 211 (const_string "any"))
212
213(define_attr "arch_enabled" "no,yes"
214 (cond [(eq_attr "arch" "any")
215 (const_string "yes")
216
217 (and (eq_attr "arch" "a")
0bf497f5 218 (match_test "TARGET_ARM"))
d5d4dc8d 219 (const_string "yes")
220
221 (and (eq_attr "arch" "t")
0bf497f5 222 (match_test "TARGET_THUMB"))
d5d4dc8d 223 (const_string "yes")
224
225 (and (eq_attr "arch" "t1")
0bf497f5 226 (match_test "TARGET_THUMB1"))
d5d4dc8d 227 (const_string "yes")
228
229 (and (eq_attr "arch" "t2")
0bf497f5 230 (match_test "TARGET_THUMB2"))
d5d4dc8d 231 (const_string "yes")
232
233 (and (eq_attr "arch" "32")
0bf497f5 234 (match_test "TARGET_32BIT"))
d5d4dc8d 235 (const_string "yes")
236
237 (and (eq_attr "arch" "v6")
0bf497f5 238 (match_test "TARGET_32BIT && arm_arch6"))
d5d4dc8d 239 (const_string "yes")
240
241 (and (eq_attr "arch" "nov6")
0bf497f5 242 (match_test "TARGET_32BIT && !arm_arch6"))
a651f34d 243 (const_string "yes")
244
245 (and (eq_attr "arch" "onlya8")
246 (eq_attr "tune" "cortexa8"))
247 (const_string "yes")
248
249 (and (eq_attr "arch" "nota8")
250 (not (eq_attr "tune" "cortexa8")))
d5d4dc8d 251 (const_string "yes")]
252 (const_string "no")))
253
254; Allows an insn to disable certain alternatives for reasons other than
255; arch support.
256(define_attr "insn_enabled" "no,yes"
257 (const_string "yes"))
258
259; Enable all alternatives that are both arch_enabled and insn_enabled.
93b431d9 260 (define_attr "enabled" "no,yes"
261 (if_then_else (eq_attr "insn_enabled" "yes")
262 (if_then_else (eq_attr "arch_enabled" "yes")
263 (const_string "yes")
264 (const_string "no"))
265 (const_string "no")))
d5d4dc8d 266
56d27660 267; POOL_RANGE is how far away from a constant pool entry that this insn
268; can be placed. If the distance is zero, then this insn will never
269; reference the pool.
cffb2a26 270; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
8848d797 271; before its address. It is set to <max_range> - (8 + <data_size>).
cde1623a 272(define_attr "arm_pool_range" "" (const_int 0))
273(define_attr "thumb2_pool_range" "" (const_int 0))
274(define_attr "arm_neg_pool_range" "" (const_int 0))
275(define_attr "thumb2_neg_pool_range" "" (const_int 0))
276
277(define_attr "pool_range" ""
278 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
279 (attr "arm_pool_range")))
280(define_attr "neg_pool_range" ""
281 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
282 (attr "arm_neg_pool_range")))
56d27660 283
215b30b3 284; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 285; If such an insn references the pool, then we have no way of knowing how,
286; so use the most conservative value for pool_range.
9c08d1fa 287(define_asm_attributes
4d7a8451 288 [(set_attr "conds" "clob")
289 (set_attr "length" "4")
290 (set_attr "pool_range" "250")])
9c08d1fa 291
a2cd141b 292;; The instruction used to implement a particular pattern. This
293;; information is used by pipeline descriptions to provide accurate
294;; scheduling information.
295
296(define_attr "insn"
934a1e72 297 "mov,mvn,smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,smmla,umaal,smlald,smlsld,clz,mrs,msr,xtab,sdiv,udiv,other"
a2cd141b 298 (const_string "other"))
299
9c08d1fa 300; TYPE attribute is used to detect floating point instructions which, if
301; running on a co-processor can run in parallel with other, basic instructions
302; If write-buffer scheduling is enabled then it can also be used in the
303; scheduling of writes.
304
305; Classification of each insn
607978a1 306; Note: vfp.md has different meanings for some of these, and some further
307; types as well. See that file for details.
a2cd141b 308; alu any alu instruction that doesn't hit memory or fp
309; regs or have a shifted source operand
310; alu_shift any data instruction that doesn't hit memory or fp
311; regs, but has a source operand shifted by a constant
312; alu_shift_reg any data instruction that doesn't hit memory or fp
313; regs, but has a source operand shifted by a register value
f7fbdd4a 314; mult a multiply instruction
9c08d1fa 315; block blockage insn, this blocks all functional units
316; float a floating point arithmetic operation (subject to expansion)
3d91c5d6 317; fdivd DFmode floating point division
318; fdivs SFmode floating point division
319; fmul Floating point multiply
320; ffmul Fast floating point multiply
321; farith Floating point arithmetic (4 cycle)
322; ffarith Fast floating point arithmetic (2 cycle)
9c08d1fa 323; float_em a floating point arithmetic operation that is normally emulated
3d91c5d6 324; even on a machine with an fpa.
013b9671 325; f_fpa_load a floating point load from memory. Only for the FPA.
326; f_fpa_store a floating point store to memory. Only for the FPA.
327; f_load[sd] A single/double load from memory. Used for VFP unit.
328; f_store[sd] A single/double store to memory. Used for VFP unit.
c0e1af52 329; f_flag a transfer of co-processor flags to the CPSR
9c08d1fa 330; f_mem_r a transfer of a floating point register to a real reg via mem
331; r_mem_f the reverse of f_mem_r
332; f_2_r fast transfer float to arm (no memory needed)
333; r_2_f fast transfer arm to float
c0e1af52 334; f_cvt convert floating<->integral
a2cd141b 335; branch a branch
9c08d1fa 336; call a subroutine call
a2cd141b 337; load_byte load byte(s) from memory to arm registers
338; load1 load 1 word from memory to arm registers
339; load2 load 2 words from memory to arm registers
340; load3 load 3 words from memory to arm registers
341; load4 load 4 words from memory to arm registers
342; store store 1 word to memory from arm registers
9c08d1fa 343; store2 store 2 words
344; store3 store 3 words
a2cd141b 345; store4 store 4 (or more) words
2c6c7d8b 346; Additions for Cirrus Maverick co-processor:
347; mav_farith Floating point arithmetic (4 cycle)
348; mav_dmult Double multiplies (7 cycle)
9c08d1fa 349;
bcaec148 350
9c08d1fa 351(define_attr "type"
013b9671 352 "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,fmuls,fmuld,fmacs,fmacd,ffmul,farith,ffarith,f_flag,float_em,f_fpa_load,f_fpa_store,f_loads,f_loadd,f_stores,f_stored,f_mem_r,r_mem_f,f_2_r,r_2_f,f_cvt,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult,fconsts,fconstd,fadds,faddd,ffariths,ffarithd,fcmps,fcmpd,fcpys"
a2cd141b 353 (if_then_else
354 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
355 (const_string "mult")
356 (const_string "alu")))
9c08d1fa 357
65f2f758 358; Is this an (integer side) multiply with a 64-bit result?
359(define_attr "mul64" "no,yes"
360 (if_then_else
361 (eq_attr "insn" "smlalxy,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
362 (const_string "yes")
363 (const_string "no")))
364
9888ad6d 365; Load scheduling, set from the arm_ld_sched variable
4c834714 366; initialized by arm_option_override()
9888ad6d 367(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 368
c52acdd2 369;; Classification of NEON instructions for scheduling purposes.
370;; Do not set this attribute and the "type" attribute together in
371;; any one instruction pattern.
372(define_attr "neon_type"
373 "neon_int_1,\
374 neon_int_2,\
375 neon_int_3,\
376 neon_int_4,\
377 neon_int_5,\
378 neon_vqneg_vqabs,\
379 neon_vmov,\
380 neon_vaba,\
381 neon_vsma,\
382 neon_vaba_qqq,\
383 neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
384 neon_mul_qqq_8_16_32_ddd_32,\
385 neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
386 neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
387 neon_mla_qqq_8_16,\
388 neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
389 neon_mla_qqq_32_qqd_32_scalar,\
390 neon_mul_ddd_16_scalar_32_16_long_scalar,\
391 neon_mul_qqd_32_scalar,\
392 neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
393 neon_shift_1,\
394 neon_shift_2,\
395 neon_shift_3,\
396 neon_vshl_ddd,\
397 neon_vqshl_vrshl_vqrshl_qqq,\
398 neon_vsra_vrsra,\
399 neon_fp_vadd_ddd_vabs_dd,\
400 neon_fp_vadd_qqq_vabs_qq,\
401 neon_fp_vsum,\
402 neon_fp_vmul_ddd,\
403 neon_fp_vmul_qqd,\
404 neon_fp_vmla_ddd,\
405 neon_fp_vmla_qqq,\
406 neon_fp_vmla_ddd_scalar,\
407 neon_fp_vmla_qqq_scalar,\
408 neon_fp_vrecps_vrsqrts_ddd,\
409 neon_fp_vrecps_vrsqrts_qqq,\
410 neon_bp_simple,\
411 neon_bp_2cycle,\
412 neon_bp_3cycle,\
413 neon_ldr,\
414 neon_str,\
415 neon_vld1_1_2_regs,\
416 neon_vld1_3_4_regs,\
417 neon_vld2_2_regs_vld1_vld2_all_lanes,\
418 neon_vld2_4_regs,\
419 neon_vld3_vld4,\
420 neon_vst1_1_2_regs_vst2_2_regs,\
421 neon_vst1_3_4_regs,\
422 neon_vst2_4_regs_vst3_vst4,\
423 neon_vst3_vst4,\
424 neon_vld1_vld2_lane,\
425 neon_vld3_vld4_lane,\
426 neon_vst1_vst2_lane,\
427 neon_vst3_vst4_lane,\
428 neon_vld3_vld4_all_lanes,\
429 neon_mcr,\
430 neon_mcr_2_mcrr,\
431 neon_mrc,\
432 neon_mrrc,\
433 neon_ldm_2,\
434 neon_stm_2,\
435 none"
436 (const_string "none"))
437
f7fbdd4a 438; condition codes: this one is used by final_prescan_insn to speed up
439; conditionalizing instructions. It saves having to scan the rtl to see if
440; it uses or alters the condition codes.
215b30b3 441;
f7fbdd4a 442; USE means that the condition codes are used by the insn in the process of
215b30b3 443; outputting code, this means (at present) that we can't use the insn in
444; inlined branches
445;
f7fbdd4a 446; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 447; well defined manner.
448;
f7fbdd4a 449; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 450; they are altered at all
451;
ad6d3e2a 452; UNCONDITIONAL means the instruction can not be conditionally executed and
453; that the instruction does not use or alter the condition codes.
c52acdd2 454;
ad6d3e2a 455; NOCOND means that the instruction does not use or alter the condition
456; codes but can be converted into a conditionally exectuted instruction.
f7fbdd4a 457
b0694be0 458(define_attr "conds" "use,set,clob,unconditional,nocond"
747b7458 459 (if_then_else
460 (ior (eq_attr "is_thumb1" "yes")
461 (eq_attr "type" "call"))
c1a66faf 462 (const_string "clob")
c52acdd2 463 (if_then_else (eq_attr "neon_type" "none")
464 (const_string "nocond")
465 (const_string "unconditional"))))
f7fbdd4a 466
215b30b3 467; Predicable means that the insn can be conditionally executed based on
468; an automatically added predicate (additional patterns are generated by
469; gen...). We default to 'no' because no Thumb patterns match this rule
470; and not all ARM patterns do.
0d66636f 471(define_attr "predicable" "no,yes" (const_string "no"))
472
129a2fe4 473; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
474; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 475; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 476; affect the schedule).
74a71f7d 477(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 478
215b30b3 479; WRITE_CONFLICT implies that a read following an unrelated write is likely
480; to stall the processor. Used with model_wbuf above.
9c08d1fa 481(define_attr "write_conflict" "no,yes"
482 (if_then_else (eq_attr "type"
013b9671 483 "block,float_em,f_fpa_load,f_fpa_store,f_mem_r,r_mem_f,call,load1")
9c08d1fa 484 (const_string "yes")
485 (const_string "no")))
486
215b30b3 487; Classify the insns into those that take one cycle and those that take more
488; than one on the main cpu execution unit.
f7fbdd4a 489(define_attr "core_cycles" "single,multi"
490 (if_then_else (eq_attr "type"
a2cd141b 491 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
f7fbdd4a 492 (const_string "single")
493 (const_string "multi")))
494
cffb2a26 495;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 496;; distant label. Only applicable to Thumb code.
cffb2a26 497(define_attr "far_jump" "yes,no" (const_string "no"))
498
d51f92df 499
25f905c2 500;; The number of machine instructions this pattern expands to.
501;; Used for Thumb-2 conditional execution.
502(define_attr "ce_count" "" (const_int 1))
503
d51f92df 504;;---------------------------------------------------------------------------
fd781bb2 505;; Mode iterators
d51f92df 506
3de0dec6 507(include "iterators.md")
03770691 508
d51f92df 509;;---------------------------------------------------------------------------
510;; Predicates
511
9c9db025 512(include "predicates.md")
234f6557 513(include "constraints.md")
9c9db025 514
a2cd141b 515;;---------------------------------------------------------------------------
516;; Pipeline descriptions
215b30b3 517
e3879fd0 518(define_attr "tune_cortexr4" "yes,no"
519 (const (if_then_else
7d3cda8c 520 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
e3879fd0 521 (const_string "yes")
522 (const_string "no"))))
523
a2cd141b 524;; True if the generic scheduling description should be used.
525
526(define_attr "generic_sched" "yes,no"
2546d93a 527 (const (if_then_else
65f2f758 528 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa5,cortexa8,cortexa9,cortexa15,cortexm4")
2546d93a 529 (eq_attr "tune_cortexr4" "yes"))
4d5cb40d 530 (const_string "no")
531 (const_string "yes"))))
532
c0e1af52 533(define_attr "generic_vfp" "yes,no"
534 (const (if_then_else
535 (and (eq_attr "fpu" "vfp")
2546d93a 536 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa8,cortexa9,cortexm4")
e3879fd0 537 (eq_attr "tune_cortexr4" "no"))
c0e1af52 538 (const_string "yes")
539 (const_string "no"))))
540
a2cd141b 541(include "arm-generic.md")
542(include "arm926ejs.md")
c0e1af52 543(include "arm1020e.md")
a2cd141b 544(include "arm1026ejs.md")
545(include "arm1136jfs.md")
0e266d06 546(include "fa526.md")
547(include "fa606te.md")
548(include "fa626te.md")
549(include "fmp626.md")
550(include "fa726te.md")
3f1e069f 551(include "cortex-a5.md")
bcaec148 552(include "cortex-a8.md")
036068af 553(include "cortex-a9.md")
65f2f758 554(include "cortex-a15.md")
934a1e72 555(include "cortex-r4.md")
e3879fd0 556(include "cortex-r4f.md")
2546d93a 557(include "cortex-m4.md")
558(include "cortex-m4-fpu.md")
55e3ada8 559(include "vfp11.md")
3586df96 560
9c08d1fa 561\f
215b30b3 562;;---------------------------------------------------------------------------
e1159bbe 563;; Insn patterns
564;;
a0f94409 565;; Addition insns.
215b30b3 566
9c08d1fa 567;; Note: For DImode insns, there is normally no reason why operands should
568;; not be in the same register, what we don't want is for something being
569;; written to partially overlap something that is an input.
7d57ec45 570;; Cirrus 64bit additions should not be split because we have a native
571;; 64bit addition instructions.
9c08d1fa 572
cffb2a26 573(define_expand "adddi3"
574 [(parallel
215b30b3 575 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 576 (plus:DI (match_operand:DI 1 "s_register_operand" "")
577 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 578 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 579 "TARGET_EITHER"
580 "
a2cd141b 581 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
7d57ec45 582 {
583 if (!cirrus_fp_register (operands[0], DImode))
584 operands[0] = force_reg (DImode, operands[0]);
585 if (!cirrus_fp_register (operands[1], DImode))
586 operands[1] = force_reg (DImode, operands[1]);
587 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
588 DONE;
589 }
590
25f905c2 591 if (TARGET_THUMB1)
cffb2a26 592 {
593 if (GET_CODE (operands[1]) != REG)
bc5a93af 594 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 595 if (GET_CODE (operands[2]) != REG)
bc5a93af 596 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 597 }
598 "
599)
600
25f905c2 601(define_insn "*thumb1_adddi3"
cffb2a26 602 [(set (match_operand:DI 0 "register_operand" "=l")
603 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 604 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 605 (clobber (reg:CC CC_REGNUM))
cffb2a26 606 ]
25f905c2 607 "TARGET_THUMB1"
cffb2a26 608 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
609 [(set_attr "length" "4")]
610)
611
a0f94409 612(define_insn_and_split "*arm_adddi3"
cffb2a26 613 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
215b30b3 614 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
615 (match_operand:DI 2 "s_register_operand" "r, 0")))
bd5b4116 616 (clobber (reg:CC CC_REGNUM))]
94829feb 617 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK) && !TARGET_NEON"
33782ec7 618 "#"
94829feb 619 "TARGET_32BIT && reload_completed
620 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
a0f94409 621 [(parallel [(set (reg:CC_C CC_REGNUM)
622 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
623 (match_dup 1)))
624 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 625 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
626 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 627 "
628 {
629 operands[3] = gen_highpart (SImode, operands[0]);
630 operands[0] = gen_lowpart (SImode, operands[0]);
631 operands[4] = gen_highpart (SImode, operands[1]);
632 operands[1] = gen_lowpart (SImode, operands[1]);
633 operands[5] = gen_highpart (SImode, operands[2]);
634 operands[2] = gen_lowpart (SImode, operands[2]);
635 }"
cffb2a26 636 [(set_attr "conds" "clob")
637 (set_attr "length" "8")]
638)
9c08d1fa 639
a0f94409 640(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 641 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
642 (plus:DI (sign_extend:DI
97499065 643 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 644 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 645 (clobber (reg:CC CC_REGNUM))]
25f905c2 646 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 647 "#"
25f905c2 648 "TARGET_32BIT && reload_completed"
a0f94409 649 [(parallel [(set (reg:CC_C CC_REGNUM)
650 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
651 (match_dup 1)))
652 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 653 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
a0f94409 654 (const_int 31))
080c0b9a 655 (match_dup 4))
656 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 657 "
658 {
659 operands[3] = gen_highpart (SImode, operands[0]);
660 operands[0] = gen_lowpart (SImode, operands[0]);
661 operands[4] = gen_highpart (SImode, operands[1]);
662 operands[1] = gen_lowpart (SImode, operands[1]);
663 operands[2] = gen_lowpart (SImode, operands[2]);
664 }"
215b30b3 665 [(set_attr "conds" "clob")
666 (set_attr "length" "8")]
667)
9c08d1fa 668
a0f94409 669(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 670 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
671 (plus:DI (zero_extend:DI
97499065 672 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 673 (match_operand:DI 1 "s_register_operand" "0,r")))
a0f94409 674 (clobber (reg:CC CC_REGNUM))]
25f905c2 675 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 676 "#"
25f905c2 677 "TARGET_32BIT && reload_completed"
a0f94409 678 [(parallel [(set (reg:CC_C CC_REGNUM)
679 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
680 (match_dup 1)))
681 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 682 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
683 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
a0f94409 684 "
685 {
686 operands[3] = gen_highpart (SImode, operands[0]);
687 operands[0] = gen_lowpart (SImode, operands[0]);
688 operands[4] = gen_highpart (SImode, operands[1]);
689 operands[1] = gen_lowpart (SImode, operands[1]);
690 operands[2] = gen_lowpart (SImode, operands[2]);
691 }"
cffb2a26 692 [(set_attr "conds" "clob")
693 (set_attr "length" "8")]
694)
b11cae9e 695
87b22bf7 696(define_expand "addsi3"
cffb2a26 697 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 698 (plus:SI (match_operand:SI 1 "s_register_operand" "")
699 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 700 "TARGET_EITHER"
87b22bf7 701 "
25f905c2 702 if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
87b22bf7 703 {
96f57e36 704 arm_split_constant (PLUS, SImode, NULL_RTX,
705 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 706 optimize && can_create_pseudo_p ());
87b22bf7 707 DONE;
708 }
cffb2a26 709 "
710)
87b22bf7 711
5bd751ff 712; If there is a scratch available, this will be faster than synthesizing the
a0f94409 713; addition.
714(define_peephole2
715 [(match_scratch:SI 3 "r")
372575c7 716 (set (match_operand:SI 0 "arm_general_register_operand" "")
717 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 718 (match_operand:SI 2 "const_int_operand" "")))]
25f905c2 719 "TARGET_32BIT &&
a0f94409 720 !(const_ok_for_arm (INTVAL (operands[2]))
721 || const_ok_for_arm (-INTVAL (operands[2])))
722 && const_ok_for_arm (~INTVAL (operands[2]))"
723 [(set (match_dup 3) (match_dup 2))
724 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
725 ""
726)
87b22bf7 727
2f02c19f 728;; The r/r/k alternative is required when reloading the address
729;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
730;; put the duplicated register first, and not try the commutative version.
a0f94409 731(define_insn_and_split "*arm_addsi3"
d5cbae34 732 [(set (match_operand:SI 0 "s_register_operand" "=r, k,r,r, k, r, k,r, k, r")
733 (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,k,r,rk,k, rk,k,rk,k, rk")
734 (match_operand:SI 2 "reg_or_int_operand" "rI,rI,k,Pj,Pj,L, L,PJ,PJ,?n")))]
25f905c2 735 "TARGET_32BIT"
5565501b 736 "@
737 add%?\\t%0, %1, %2
aaa37ad6 738 add%?\\t%0, %1, %2
2f02c19f 739 add%?\\t%0, %2, %1
d5cbae34 740 addw%?\\t%0, %1, %2
741 addw%?\\t%0, %1, %2
aaa37ad6 742 sub%?\\t%0, %1, #%n2
87b22bf7 743 sub%?\\t%0, %1, #%n2
d5cbae34 744 subw%?\\t%0, %1, #%n2
745 subw%?\\t%0, %1, #%n2
87b22bf7 746 #"
a3ffc315 747 "TARGET_32BIT
748 && GET_CODE (operands[2]) == CONST_INT
d5cbae34 749 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
a3ffc315 750 && (reload_completed || !arm_eliminable_register (operands[1]))"
a0f94409 751 [(clobber (const_int 0))]
752 "
96f57e36 753 arm_split_constant (PLUS, SImode, curr_insn,
754 INTVAL (operands[2]), operands[0],
a0f94409 755 operands[1], 0);
756 DONE;
757 "
d5cbae34 758 [(set_attr "length" "4,4,4,4,4,4,4,4,4,16")
759 (set_attr "predicable" "yes")
760 (set_attr "arch" "*,*,*,t2,t2,*,*,t2,t2,*")]
cffb2a26 761)
762
0bdb6455 763(define_insn_and_split "*thumb1_addsi3"
bf7bc2f6 764 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,k,l,l,l")
765 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,k,k,0,l,k")
766 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,M,O,Pa,Pb,Pc")))]
25f905c2 767 "TARGET_THUMB1"
cffb2a26 768 "*
0d66636f 769 static const char * const asms[] =
cffb2a26 770 {
771 \"add\\t%0, %0, %2\",
772 \"sub\\t%0, %0, #%n2\",
773 \"add\\t%0, %1, %2\",
774 \"add\\t%0, %0, %2\",
775 \"add\\t%0, %0, %2\",
776 \"add\\t%0, %1, %2\",
0bdb6455 777 \"add\\t%0, %1, %2\",
778 \"#\",
bf7bc2f6 779 \"#\",
0bdb6455 780 \"#\"
cffb2a26 781 };
782 if ((which_alternative == 2 || which_alternative == 6)
783 && GET_CODE (operands[2]) == CONST_INT
784 && INTVAL (operands[2]) < 0)
785 return \"sub\\t%0, %1, #%n2\";
786 return asms[which_alternative];
787 "
0bdb6455 788 "&& reload_completed && CONST_INT_P (operands[2])
bf7bc2f6 789 && ((operands[1] != stack_pointer_rtx
790 && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255))
791 || (operands[1] == stack_pointer_rtx
792 && INTVAL (operands[2]) > 1020))"
0bdb6455 793 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
794 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
795 {
796 HOST_WIDE_INT offset = INTVAL (operands[2]);
bf7bc2f6 797 if (operands[1] == stack_pointer_rtx)
798 offset -= 1020;
799 else
800 {
801 if (offset > 255)
802 offset = 255;
803 else if (offset < -255)
804 offset = -255;
805 }
0bdb6455 806 operands[3] = GEN_INT (offset);
807 operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
808 }
bf7bc2f6 809 [(set_attr "length" "2,2,2,2,2,2,2,4,4,4")]
cffb2a26 810)
811
812;; Reloading and elimination of the frame pointer can
813;; sometimes cause this optimization to be missed.
a0f94409 814(define_peephole2
372575c7 815 [(set (match_operand:SI 0 "arm_general_register_operand" "")
a058e94a 816 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 817 (set (match_dup 0)
372575c7 818 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
25f905c2 819 "TARGET_THUMB1
cffb2a26 820 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
821 && (INTVAL (operands[1]) & 3) == 0"
372575c7 822 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
a0f94409 823 ""
cffb2a26 824)
b11cae9e 825
90c2bcf0 826(define_insn "addsi3_compare0"
bd5b4116 827 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 828 (compare:CC_NOOV
215b30b3 829 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
830 (match_operand:SI 2 "arm_add_operand" "rI,L"))
5565501b 831 (const_int 0)))
832 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 833 (plus:SI (match_dup 1) (match_dup 2)))]
ec792a7b 834 "TARGET_ARM"
5565501b 835 "@
25f905c2 836 add%.\\t%0, %1, %2
837 sub%.\\t%0, %1, #%n2"
cffb2a26 838 [(set_attr "conds" "set")]
839)
9c08d1fa 840
aea4c774 841(define_insn "*addsi3_compare0_scratch"
bd5b4116 842 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 843 (compare:CC_NOOV
215b30b3 844 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
845 (match_operand:SI 1 "arm_add_operand" "rI,L"))
aea4c774 846 (const_int 0)))]
ec792a7b 847 "TARGET_ARM"
cffb2a26 848 "@
849 cmn%?\\t%0, %1
850 cmp%?\\t%0, #%n1"
0d66636f 851 [(set_attr "conds" "set")]
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"
0d66636f 861 [(set_attr "conds" "set")]
862)
aea4c774 863
203c488f 864;; This is the canonicalization of addsi3_compare0_for_combiner when the
865;; addend is a constant.
866(define_insn "*cmpsi2_addneg"
867 [(set (reg:CC CC_REGNUM)
868 (compare:CC
869 (match_operand:SI 1 "s_register_operand" "r,r")
2a977b78 870 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
203c488f 871 (set (match_operand:SI 0 "s_register_operand" "=r,r")
872 (plus:SI (match_dup 1)
2a977b78 873 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
25f905c2 874 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
203c488f 875 "@
2a977b78 876 add%.\\t%0, %1, %3
877 sub%.\\t%0, %1, #%n3"
203c488f 878 [(set_attr "conds" "set")]
879)
880
881;; Convert the sequence
882;; sub rd, rn, #1
883;; cmn rd, #1 (equivalent to cmp rd, #-1)
884;; bne dest
885;; into
886;; subs rd, rn, #1
887;; bcs dest ((unsigned)rn >= 1)
888;; similarly for the beq variant using bcc.
889;; This is a common looping idiom (while (n--))
890(define_peephole2
372575c7 891 [(set (match_operand:SI 0 "arm_general_register_operand" "")
892 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 893 (const_int -1)))
894 (set (match_operand 2 "cc_register" "")
895 (compare (match_dup 0) (const_int -1)))
896 (set (pc)
897 (if_then_else (match_operator 3 "equality_operator"
898 [(match_dup 2) (const_int 0)])
899 (match_operand 4 "" "")
900 (match_operand 5 "" "")))]
25f905c2 901 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
203c488f 902 [(parallel[
903 (set (match_dup 2)
904 (compare:CC
905 (match_dup 1) (const_int 1)))
906 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
907 (set (pc)
908 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
909 (match_dup 4)
910 (match_dup 5)))]
911 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
912 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
913 ? GEU : LTU),
914 VOIDmode,
915 operands[2], const0_rtx);"
916)
917
ebcc79bc 918;; The next four insns work because they compare the result with one of
919;; the operands, and we know that the use of the condition code is
920;; either GEU or LTU, so we can use the carry flag from the addition
921;; instead of doing the compare a second time.
922(define_insn "*addsi3_compare_op1"
bd5b4116 923 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 924 (compare:CC_C
925 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
926 (match_operand:SI 2 "arm_add_operand" "rI,L"))
927 (match_dup 1)))
928 (set (match_operand:SI 0 "s_register_operand" "=r,r")
929 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 930 "TARGET_32BIT"
ebcc79bc 931 "@
25f905c2 932 add%.\\t%0, %1, %2
933 sub%.\\t%0, %1, #%n2"
0d66636f 934 [(set_attr "conds" "set")]
935)
ebcc79bc 936
937(define_insn "*addsi3_compare_op2"
bd5b4116 938 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 939 (compare:CC_C
940 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
941 (match_operand:SI 2 "arm_add_operand" "rI,L"))
942 (match_dup 2)))
5565501b 943 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 944 (plus:SI (match_dup 1) (match_dup 2)))]
25f905c2 945 "TARGET_32BIT"
5565501b 946 "@
25f905c2 947 add%.\\t%0, %1, %2
948 sub%.\\t%0, %1, #%n2"
0d66636f 949 [(set_attr "conds" "set")]
950)
9c08d1fa 951
ebcc79bc 952(define_insn "*compare_addsi2_op0"
bd5b4116 953 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 954 (compare:CC_C
955 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
956 (match_operand:SI 1 "arm_add_operand" "rI,L"))
957 (match_dup 0)))]
25f905c2 958 "TARGET_32BIT"
ebcc79bc 959 "@
960 cmn%?\\t%0, %1
961 cmp%?\\t%0, #%n1"
0d66636f 962 [(set_attr "conds" "set")]
963)
ebcc79bc 964
965(define_insn "*compare_addsi2_op1"
bd5b4116 966 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 967 (compare:CC_C
968 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
969 (match_operand:SI 1 "arm_add_operand" "rI,L"))
970 (match_dup 1)))]
25f905c2 971 "TARGET_32BIT"
ebcc79bc 972 "@
973 cmn%?\\t%0, %1
974 cmp%?\\t%0, #%n1"
0d66636f 975 [(set_attr "conds" "set")]
976)
ebcc79bc 977
080c0b9a 978(define_insn "*addsi3_carryin_<optab>"
ebcc79bc 979 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 980 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
ebcc79bc 981 (match_operand:SI 2 "arm_rhs_operand" "rI"))
080c0b9a 982 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 983 "TARGET_32BIT"
ebcc79bc 984 "adc%?\\t%0, %1, %2"
cffb2a26 985 [(set_attr "conds" "use")]
986)
ebcc79bc 987
080c0b9a 988(define_insn "*addsi3_carryin_alt2_<optab>"
ebcc79bc 989 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 990 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
991 (match_operand:SI 1 "s_register_operand" "%r"))
ebcc79bc 992 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 993 "TARGET_32BIT"
ebcc79bc 994 "adc%?\\t%0, %1, %2"
0d66636f 995 [(set_attr "conds" "use")]
996)
ebcc79bc 997
080c0b9a 998(define_insn "*addsi3_carryin_shift_<optab>"
ebcc79bc 999 [(set (match_operand:SI 0 "s_register_operand" "=r")
080c0b9a 1000 (plus:SI (plus:SI
1001 (match_operator:SI 2 "shift_operator"
1002 [(match_operand:SI 3 "s_register_operand" "r")
1003 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1004 (match_operand:SI 1 "s_register_operand" "r"))
1005 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
25f905c2 1006 "TARGET_32BIT"
080c0b9a 1007 "adc%?\\t%0, %1, %3%S2"
1008 [(set_attr "conds" "use")
1009 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
1010 (const_string "alu_shift")
1011 (const_string "alu_shift_reg")))]
cffb2a26 1012)
ebcc79bc 1013
922b6913 1014(define_insn "*addsi3_carryin_clobercc_<optab>"
1015 [(set (match_operand:SI 0 "s_register_operand" "=r")
1016 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
1017 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1018 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
1019 (clobber (reg:CC CC_REGNUM))]
1020 "TARGET_32BIT"
1021 "adc%.\\t%0, %1, %2"
1022 [(set_attr "conds" "set")]
1023)
1024
25f905c2 1025(define_expand "incscc"
1026 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1027 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
1028 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
1029 (match_operand:SI 1 "s_register_operand" "0,?r")))]
1030 "TARGET_32BIT"
1031 ""
1032)
1033
1034(define_insn "*arm_incscc"
9c08d1fa 1035 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 1036 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1037 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
9c08d1fa 1038 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 1039 "TARGET_ARM"
5565501b 1040 "@
1041 add%d2\\t%0, %1, #1
1042 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
8fa3ba89 1043 [(set_attr "conds" "use")
215b30b3 1044 (set_attr "length" "4,8")]
1045)
9c08d1fa 1046
d795fb69 1047; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
1048(define_split
1049 [(set (match_operand:SI 0 "s_register_operand" "")
1050 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1051 (match_operand:SI 2 "s_register_operand" ""))
1052 (const_int -1)))
1053 (clobber (match_operand:SI 3 "s_register_operand" ""))]
25f905c2 1054 "TARGET_32BIT"
d795fb69 1055 [(set (match_dup 3) (match_dup 1))
1056 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1057 "
1058 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1059")
1060
604f3a0a 1061(define_expand "addsf3"
1062 [(set (match_operand:SF 0 "s_register_operand" "")
1063 (plus:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1064 (match_operand:SF 2 "arm_float_add_operand" "")))]
25f905c2 1065 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1066 "
a2cd141b 1067 if (TARGET_MAVERICK
604f3a0a 1068 && !cirrus_fp_register (operands[2], SFmode))
1069 operands[2] = force_reg (SFmode, operands[2]);
1070")
1071
604f3a0a 1072(define_expand "adddf3"
1073 [(set (match_operand:DF 0 "s_register_operand" "")
1074 (plus:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1075 (match_operand:DF 2 "arm_float_add_operand" "")))]
a50d7267 1076 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1077 "
a2cd141b 1078 if (TARGET_MAVERICK
604f3a0a 1079 && !cirrus_fp_register (operands[2], DFmode))
1080 operands[2] = force_reg (DFmode, operands[2]);
1081")
1082
cffb2a26 1083(define_expand "subdi3"
1084 [(parallel
1085 [(set (match_operand:DI 0 "s_register_operand" "")
1086 (minus:DI (match_operand:DI 1 "s_register_operand" "")
1087 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 1088 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 1089 "TARGET_EITHER"
1090 "
a2cd141b 1091 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
25f905c2 1092 && TARGET_32BIT
7d57ec45 1093 && cirrus_fp_register (operands[0], DImode)
1094 && cirrus_fp_register (operands[1], DImode))
1095 {
1096 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
1097 DONE;
1098 }
1099
25f905c2 1100 if (TARGET_THUMB1)
cffb2a26 1101 {
1102 if (GET_CODE (operands[1]) != REG)
5aa8c5f0 1103 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 1104 if (GET_CODE (operands[2]) != REG)
5aa8c5f0 1105 operands[2] = force_reg (DImode, operands[2]);
cffb2a26 1106 }
1107 "
1108)
1109
1110(define_insn "*arm_subdi3"
1111 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 1112 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1113 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 1114 (clobber (reg:CC CC_REGNUM))]
94829feb 1115 "TARGET_32BIT && !TARGET_NEON"
97499065 1116 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
cffb2a26 1117 [(set_attr "conds" "clob")
1118 (set_attr "length" "8")]
1119)
1120
1121(define_insn "*thumb_subdi3"
1122 [(set (match_operand:DI 0 "register_operand" "=l")
1123 (minus:DI (match_operand:DI 1 "register_operand" "0")
1124 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 1125 (clobber (reg:CC CC_REGNUM))]
25f905c2 1126 "TARGET_THUMB1"
cffb2a26 1127 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
1128 [(set_attr "length" "4")]
1129)
9c08d1fa 1130
f7fbdd4a 1131(define_insn "*subdi_di_zesidi"
cffb2a26 1132 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1133 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1134 (zero_extend:DI
cffb2a26 1135 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1136 (clobber (reg:CC CC_REGNUM))]
25f905c2 1137 "TARGET_32BIT"
97499065 1138 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
cffb2a26 1139 [(set_attr "conds" "clob")
1140 (set_attr "length" "8")]
1141)
9c08d1fa 1142
f7fbdd4a 1143(define_insn "*subdi_di_sesidi"
cffb2a26 1144 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 1145 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
9c08d1fa 1146 (sign_extend:DI
cffb2a26 1147 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 1148 (clobber (reg:CC CC_REGNUM))]
25f905c2 1149 "TARGET_32BIT"
97499065 1150 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
cffb2a26 1151 [(set_attr "conds" "clob")
1152 (set_attr "length" "8")]
1153)
9c08d1fa 1154
f7fbdd4a 1155(define_insn "*subdi_zesidi_di"
cffb2a26 1156 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1157 (minus:DI (zero_extend:DI
cffb2a26 1158 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1159 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1160 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1161 "TARGET_ARM"
97499065 1162 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
cffb2a26 1163 [(set_attr "conds" "clob")
1164 (set_attr "length" "8")]
1165)
9c08d1fa 1166
f7fbdd4a 1167(define_insn "*subdi_sesidi_di"
cffb2a26 1168 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1169 (minus:DI (sign_extend:DI
cffb2a26 1170 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 1171 (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 1172 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1173 "TARGET_ARM"
97499065 1174 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
cffb2a26 1175 [(set_attr "conds" "clob")
1176 (set_attr "length" "8")]
1177)
9c08d1fa 1178
f7fbdd4a 1179(define_insn "*subdi_zesidi_zesidi"
cffb2a26 1180 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 1181 (minus:DI (zero_extend:DI
cffb2a26 1182 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 1183 (zero_extend:DI
cffb2a26 1184 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 1185 (clobber (reg:CC CC_REGNUM))]
25f905c2 1186 "TARGET_32BIT"
1187 "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
cffb2a26 1188 [(set_attr "conds" "clob")
1189 (set_attr "length" "8")]
1190)
b11cae9e 1191
87b22bf7 1192(define_expand "subsi3"
cffb2a26 1193 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1194 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1195 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1196 "TARGET_EITHER"
87b22bf7 1197 "
1198 if (GET_CODE (operands[1]) == CONST_INT)
1199 {
25f905c2 1200 if (TARGET_32BIT)
cffb2a26 1201 {
96f57e36 1202 arm_split_constant (MINUS, SImode, NULL_RTX,
1203 INTVAL (operands[1]), operands[0],
e1ba4a27 1204 operands[2], optimize && can_create_pseudo_p ());
cffb2a26 1205 DONE;
1206 }
25f905c2 1207 else /* TARGET_THUMB1 */
cffb2a26 1208 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1209 }
cffb2a26 1210 "
1211)
87b22bf7 1212
747b7458 1213(define_insn "thumb1_subsi3_insn"
cffb2a26 1214 [(set (match_operand:SI 0 "register_operand" "=l")
1215 (minus:SI (match_operand:SI 1 "register_operand" "l")
747b7458 1216 (match_operand:SI 2 "reg_or_int_operand" "lPd")))]
25f905c2 1217 "TARGET_THUMB1"
cffb2a26 1218 "sub\\t%0, %1, %2"
747b7458 1219 [(set_attr "length" "2")
1220 (set_attr "conds" "set")])
cffb2a26 1221
25f905c2 1222; ??? Check Thumb-2 split length
a0f94409 1223(define_insn_and_split "*arm_subsi3_insn"
91a5e339 1224 [(set (match_operand:SI 0 "s_register_operand" "=r,r,rk,r")
1225 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,k,?n")
1226 (match_operand:SI 2 "reg_or_int_operand" "r,rI,r, r")))]
25f905c2 1227 "TARGET_32BIT"
e2348bcb 1228 "@
87b22bf7 1229 rsb%?\\t%0, %2, %1
aaa37ad6 1230 sub%?\\t%0, %1, %2
080c0b9a 1231 sub%?\\t%0, %1, %2
87b22bf7 1232 #"
91a5e339 1233 "&& (GET_CODE (operands[1]) == CONST_INT
1234 && !const_ok_for_arm (INTVAL (operands[1])))"
87b22bf7 1235 [(clobber (const_int 0))]
1236 "
96f57e36 1237 arm_split_constant (MINUS, SImode, curr_insn,
1238 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 1239 DONE;
cffb2a26 1240 "
91a5e339 1241 [(set_attr "length" "4,4,4,16")
a0f94409 1242 (set_attr "predicable" "yes")]
1243)
1244
1245(define_peephole2
1246 [(match_scratch:SI 3 "r")
372575c7 1247 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 1248 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 1249 (match_operand:SI 2 "arm_general_register_operand" "")))]
25f905c2 1250 "TARGET_32BIT
a0f94409 1251 && !const_ok_for_arm (INTVAL (operands[1]))
1252 && const_ok_for_arm (~INTVAL (operands[1]))"
1253 [(set (match_dup 3) (match_dup 1))
1254 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1255 ""
cffb2a26 1256)
b11cae9e 1257
f7fbdd4a 1258(define_insn "*subsi3_compare0"
bd5b4116 1259 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1260 (compare:CC_NOOV
1261 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1262 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1263 (const_int 0)))
9c08d1fa 1264 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1265 (minus:SI (match_dup 1) (match_dup 2)))]
25f905c2 1266 "TARGET_32BIT"
e2348bcb 1267 "@
25f905c2 1268 sub%.\\t%0, %1, %2
1269 rsb%.\\t%0, %2, %1"
cffb2a26 1270 [(set_attr "conds" "set")]
1271)
9c08d1fa 1272
080c0b9a 1273(define_insn "*subsi3_compare"
1274 [(set (reg:CC CC_REGNUM)
1275 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,I")
1276 (match_operand:SI 2 "arm_rhs_operand" "rI,r")))
2df9477b 1277 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1278 (minus:SI (match_dup 1) (match_dup 2)))]
1279 "TARGET_32BIT"
1280 "@
1281 sub%.\\t%0, %1, %2
1282 rsb%.\\t%0, %2, %1"
1283 [(set_attr "conds" "set")]
1284)
1285
25f905c2 1286(define_expand "decscc"
1287 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1288 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1289 (match_operator:SI 2 "arm_comparison_operator"
1290 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1291 "TARGET_32BIT"
1292 ""
1293)
1294
1295(define_insn "*arm_decscc"
cffb2a26 1296 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1297 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 1298 (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1299 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1300 "TARGET_ARM"
e2348bcb 1301 "@
215b30b3 1302 sub%d2\\t%0, %1, #1
1303 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
cffb2a26 1304 [(set_attr "conds" "use")
1305 (set_attr "length" "*,8")]
1306)
9c08d1fa 1307
604f3a0a 1308(define_expand "subsf3"
1309 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1310 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1311 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1312 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1313 "
a2cd141b 1314 if (TARGET_MAVERICK)
604f3a0a 1315 {
1316 if (!cirrus_fp_register (operands[1], SFmode))
1317 operands[1] = force_reg (SFmode, operands[1]);
1318 if (!cirrus_fp_register (operands[2], SFmode))
1319 operands[2] = force_reg (SFmode, operands[2]);
1320 }
1321")
1322
604f3a0a 1323(define_expand "subdf3"
1324 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1325 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1326 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1327 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1328 "
a2cd141b 1329 if (TARGET_MAVERICK)
604f3a0a 1330 {
1331 if (!cirrus_fp_register (operands[1], DFmode))
1332 operands[1] = force_reg (DFmode, operands[1]);
1333 if (!cirrus_fp_register (operands[2], DFmode))
1334 operands[2] = force_reg (DFmode, operands[2]);
1335 }
1336")
1337
b11cae9e 1338\f
1339;; Multiplication insns
1340
cffb2a26 1341(define_expand "mulsi3"
1342 [(set (match_operand:SI 0 "s_register_operand" "")
1343 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1344 (match_operand:SI 1 "s_register_operand" "")))]
1345 "TARGET_EITHER"
1346 ""
1347)
1348
9c08d1fa 1349;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1350(define_insn "*arm_mulsi3"
1351 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1352 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1353 (match_operand:SI 1 "s_register_operand" "%0,r")))]
58d7d654 1354 "TARGET_32BIT && !arm_arch6"
f7fbdd4a 1355 "mul%?\\t%0, %2, %1"
a2cd141b 1356 [(set_attr "insn" "mul")
0d66636f 1357 (set_attr "predicable" "yes")]
cffb2a26 1358)
1359
58d7d654 1360(define_insn "*arm_mulsi3_v6"
1361 [(set (match_operand:SI 0 "s_register_operand" "=r")
1362 (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1363 (match_operand:SI 2 "s_register_operand" "r")))]
1364 "TARGET_32BIT && arm_arch6"
1365 "mul%?\\t%0, %1, %2"
1366 [(set_attr "insn" "mul")
1367 (set_attr "predicable" "yes")]
1368)
1369
215b30b3 1370; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1371; 1 and 2; are the same, because reload will make operand 0 match
1372; operand 1 without realizing that this conflicts with operand 2. We fix
1373; this by adding another alternative to match this case, and then `reload'
1374; it ourselves. This alternative must come first.
cffb2a26 1375(define_insn "*thumb_mulsi3"
1376 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1377 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1378 (match_operand:SI 2 "register_operand" "l,l,l")))]
58d7d654 1379 "TARGET_THUMB1 && !arm_arch6"
cffb2a26 1380 "*
1381 if (which_alternative < 2)
20c4e896 1382 return \"mov\\t%0, %1\;mul\\t%0, %2\";
cffb2a26 1383 else
20c4e896 1384 return \"mul\\t%0, %2\";
cffb2a26 1385 "
1386 [(set_attr "length" "4,4,2")
a2cd141b 1387 (set_attr "insn" "mul")]
cffb2a26 1388)
b11cae9e 1389
58d7d654 1390(define_insn "*thumb_mulsi3_v6"
1391 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
1392 (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1393 (match_operand:SI 2 "register_operand" "l,0,0")))]
1394 "TARGET_THUMB1 && arm_arch6"
1395 "@
1490694c 1396 mul\\t%0, %2
1397 mul\\t%0, %1
58d7d654 1398 mul\\t%0, %1"
1399 [(set_attr "length" "2")
1400 (set_attr "insn" "mul")]
1401)
1402
f7fbdd4a 1403(define_insn "*mulsi3_compare0"
bd5b4116 1404 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1405 (compare:CC_NOOV (mult:SI
1406 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1407 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1408 (const_int 0)))
1409 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1410 (mult:SI (match_dup 2) (match_dup 1)))]
58d7d654 1411 "TARGET_ARM && !arm_arch6"
1412 "mul%.\\t%0, %2, %1"
1413 [(set_attr "conds" "set")
1414 (set_attr "insn" "muls")]
1415)
1416
1417(define_insn "*mulsi3_compare0_v6"
1418 [(set (reg:CC_NOOV CC_REGNUM)
1419 (compare:CC_NOOV (mult:SI
1420 (match_operand:SI 2 "s_register_operand" "r")
1421 (match_operand:SI 1 "s_register_operand" "r"))
1422 (const_int 0)))
1423 (set (match_operand:SI 0 "s_register_operand" "=r")
1424 (mult:SI (match_dup 2) (match_dup 1)))]
1425 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1426 "mul%.\\t%0, %2, %1"
cffb2a26 1427 [(set_attr "conds" "set")
a2cd141b 1428 (set_attr "insn" "muls")]
cffb2a26 1429)
9c08d1fa 1430
f7fbdd4a 1431(define_insn "*mulsi_compare0_scratch"
bd5b4116 1432 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1433 (compare:CC_NOOV (mult:SI
1434 (match_operand:SI 2 "s_register_operand" "r,r")
e5fea38e 1435 (match_operand:SI 1 "s_register_operand" "%0,r"))
9c08d1fa 1436 (const_int 0)))
1437 (clobber (match_scratch:SI 0 "=&r,&r"))]
58d7d654 1438 "TARGET_ARM && !arm_arch6"
1439 "mul%.\\t%0, %2, %1"
1440 [(set_attr "conds" "set")
1441 (set_attr "insn" "muls")]
1442)
1443
1444(define_insn "*mulsi_compare0_scratch_v6"
1445 [(set (reg:CC_NOOV CC_REGNUM)
1446 (compare:CC_NOOV (mult:SI
1447 (match_operand:SI 2 "s_register_operand" "r")
1448 (match_operand:SI 1 "s_register_operand" "r"))
1449 (const_int 0)))
1450 (clobber (match_scratch:SI 0 "=r"))]
1451 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1452 "mul%.\\t%0, %2, %1"
cffb2a26 1453 [(set_attr "conds" "set")
a2cd141b 1454 (set_attr "insn" "muls")]
cffb2a26 1455)
9c08d1fa 1456
b11cae9e 1457;; Unnamed templates to match MLA instruction.
1458
f7fbdd4a 1459(define_insn "*mulsi3addsi"
9c08d1fa 1460 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1461 (plus:SI
9c08d1fa 1462 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1463 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1464 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
58d7d654 1465 "TARGET_32BIT && !arm_arch6"
1466 "mla%?\\t%0, %2, %1, %3"
1467 [(set_attr "insn" "mla")
1468 (set_attr "predicable" "yes")]
1469)
1470
1471(define_insn "*mulsi3addsi_v6"
1472 [(set (match_operand:SI 0 "s_register_operand" "=r")
1473 (plus:SI
1474 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1475 (match_operand:SI 1 "s_register_operand" "r"))
1476 (match_operand:SI 3 "s_register_operand" "r")))]
1477 "TARGET_32BIT && arm_arch6"
f7fbdd4a 1478 "mla%?\\t%0, %2, %1, %3"
a2cd141b 1479 [(set_attr "insn" "mla")
0d66636f 1480 (set_attr "predicable" "yes")]
1481)
b11cae9e 1482
f7fbdd4a 1483(define_insn "*mulsi3addsi_compare0"
bd5b4116 1484 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1485 (compare:CC_NOOV
1486 (plus:SI (mult:SI
1487 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1488 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1489 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
215b30b3 1490 (const_int 0)))
9c08d1fa 1491 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1492 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1493 (match_dup 3)))]
58d7d654 1494 "TARGET_ARM && arm_arch6"
1495 "mla%.\\t%0, %2, %1, %3"
1496 [(set_attr "conds" "set")
1497 (set_attr "insn" "mlas")]
1498)
1499
1500(define_insn "*mulsi3addsi_compare0_v6"
1501 [(set (reg:CC_NOOV CC_REGNUM)
1502 (compare:CC_NOOV
1503 (plus:SI (mult:SI
1504 (match_operand:SI 2 "s_register_operand" "r")
1505 (match_operand:SI 1 "s_register_operand" "r"))
1506 (match_operand:SI 3 "s_register_operand" "r"))
1507 (const_int 0)))
1508 (set (match_operand:SI 0 "s_register_operand" "=r")
1509 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1510 (match_dup 3)))]
1511 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1512 "mla%.\\t%0, %2, %1, %3"
0d66636f 1513 [(set_attr "conds" "set")
a2cd141b 1514 (set_attr "insn" "mlas")]
0d66636f 1515)
9c08d1fa 1516
f7fbdd4a 1517(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1518 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1519 (compare:CC_NOOV
1520 (plus:SI (mult:SI
1521 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
e5fea38e 1522 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
215b30b3 1523 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1524 (const_int 0)))
9c08d1fa 1525 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
58d7d654 1526 "TARGET_ARM && !arm_arch6"
1527 "mla%.\\t%0, %2, %1, %3"
1528 [(set_attr "conds" "set")
1529 (set_attr "insn" "mlas")]
1530)
1531
1532(define_insn "*mulsi3addsi_compare0_scratch_v6"
1533 [(set (reg:CC_NOOV CC_REGNUM)
1534 (compare:CC_NOOV
1535 (plus:SI (mult:SI
1536 (match_operand:SI 2 "s_register_operand" "r")
1537 (match_operand:SI 1 "s_register_operand" "r"))
1538 (match_operand:SI 3 "s_register_operand" "r"))
1539 (const_int 0)))
1540 (clobber (match_scratch:SI 0 "=r"))]
1541 "TARGET_ARM && arm_arch6 && optimize_size"
25f905c2 1542 "mla%.\\t%0, %2, %1, %3"
cffb2a26 1543 [(set_attr "conds" "set")
a2cd141b 1544 (set_attr "insn" "mlas")]
cffb2a26 1545)
f7fbdd4a 1546
89545238 1547(define_insn "*mulsi3subsi"
1548 [(set (match_operand:SI 0 "s_register_operand" "=r")
1549 (minus:SI
1550 (match_operand:SI 3 "s_register_operand" "r")
1551 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1552 (match_operand:SI 1 "s_register_operand" "r"))))]
1553 "TARGET_32BIT && arm_arch_thumb2"
1554 "mls%?\\t%0, %2, %1, %3"
1555 [(set_attr "insn" "mla")
1556 (set_attr "predicable" "yes")]
1557)
1558
5cdca009 1559(define_expand "maddsidi4"
1560 [(set (match_operand:DI 0 "s_register_operand" "")
1561 (plus:DI
1562 (mult:DI
1563 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1564 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1565 (match_operand:DI 3 "s_register_operand" "")))]
1566 "TARGET_32BIT && arm_arch3m"
1567 "")
82b85d08 1568
1569(define_insn "*mulsidi3adddi"
fe8dbf85 1570 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1571 (plus:DI
215b30b3 1572 (mult:DI
fe8dbf85 1573 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1574 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1575 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1576 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1577 "smlal%?\\t%Q0, %R0, %3, %2"
1578 [(set_attr "insn" "smlal")
1579 (set_attr "predicable" "yes")]
1580)
1581
1582(define_insn "*mulsidi3adddi_v6"
1583 [(set (match_operand:DI 0 "s_register_operand" "=r")
1584 (plus:DI
1585 (mult:DI
1586 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1587 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1588 (match_operand:DI 1 "s_register_operand" "0")))]
1589 "TARGET_32BIT && arm_arch6"
fe8dbf85 1590 "smlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1591 [(set_attr "insn" "smlal")
0d66636f 1592 (set_attr "predicable" "yes")]
1593)
82b85d08 1594
957788b0 1595;; 32x32->64 widening multiply.
1596;; As with mulsi3, the only difference between the v3-5 and v6+
1597;; versions of these patterns is the requirement that the output not
1598;; overlap the inputs, but that still means we have to have a named
1599;; expander and two different starred insns.
1600
1601(define_expand "mulsidi3"
1602 [(set (match_operand:DI 0 "s_register_operand" "")
1603 (mult:DI
1604 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1605 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1606 "TARGET_32BIT && arm_arch3m"
1607 ""
1608)
1609
1610(define_insn "*mulsidi3_nov6"
f7fbdd4a 1611 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1612 (mult:DI
1613 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1614 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1615 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1616 "smull%?\\t%Q0, %R0, %1, %2"
1617 [(set_attr "insn" "smull")
1618 (set_attr "predicable" "yes")]
1619)
1620
957788b0 1621(define_insn "*mulsidi3_v6"
58d7d654 1622 [(set (match_operand:DI 0 "s_register_operand" "=r")
1623 (mult:DI
1624 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1625 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1626 "TARGET_32BIT && arm_arch6"
97499065 1627 "smull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1628 [(set_attr "insn" "smull")
0d66636f 1629 (set_attr "predicable" "yes")]
1630)
f7fbdd4a 1631
957788b0 1632(define_expand "umulsidi3"
1633 [(set (match_operand:DI 0 "s_register_operand" "")
1634 (mult:DI
1635 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1636 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1637 "TARGET_32BIT && arm_arch3m"
1638 ""
1639)
1640
1641(define_insn "*umulsidi3_nov6"
f7fbdd4a 1642 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1643 (mult:DI
1644 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1645 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
58d7d654 1646 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1647 "umull%?\\t%Q0, %R0, %1, %2"
1648 [(set_attr "insn" "umull")
1649 (set_attr "predicable" "yes")]
1650)
1651
957788b0 1652(define_insn "*umulsidi3_v6"
58d7d654 1653 [(set (match_operand:DI 0 "s_register_operand" "=r")
1654 (mult:DI
1655 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1656 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1657 "TARGET_32BIT && arm_arch6"
97499065 1658 "umull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1659 [(set_attr "insn" "umull")
0d66636f 1660 (set_attr "predicable" "yes")]
1661)
b11cae9e 1662
5cdca009 1663(define_expand "umaddsidi4"
1664 [(set (match_operand:DI 0 "s_register_operand" "")
1665 (plus:DI
1666 (mult:DI
1667 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1668 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1669 (match_operand:DI 3 "s_register_operand" "")))]
1670 "TARGET_32BIT && arm_arch3m"
1671 "")
82b85d08 1672
1673(define_insn "*umulsidi3adddi"
8ead09f9 1674 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1675 (plus:DI
215b30b3 1676 (mult:DI
fe8dbf85 1677 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1678 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1679 (match_operand:DI 1 "s_register_operand" "0")))]
58d7d654 1680 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1681 "umlal%?\\t%Q0, %R0, %3, %2"
1682 [(set_attr "insn" "umlal")
1683 (set_attr "predicable" "yes")]
1684)
1685
1686(define_insn "*umulsidi3adddi_v6"
1687 [(set (match_operand:DI 0 "s_register_operand" "=r")
1688 (plus:DI
1689 (mult:DI
1690 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1691 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1692 (match_operand:DI 1 "s_register_operand" "0")))]
1693 "TARGET_32BIT && arm_arch6"
fe8dbf85 1694 "umlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1695 [(set_attr "insn" "umlal")
0d66636f 1696 (set_attr "predicable" "yes")]
1697)
82b85d08 1698
957788b0 1699(define_expand "smulsi3_highpart"
1700 [(parallel
1701 [(set (match_operand:SI 0 "s_register_operand" "")
1702 (truncate:SI
1703 (lshiftrt:DI
1704 (mult:DI
1705 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1706 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1707 (const_int 32))))
1708 (clobber (match_scratch:SI 3 ""))])]
1709 "TARGET_32BIT && arm_arch3m"
1710 ""
1711)
1712
1713(define_insn "*smulsi3_highpart_nov6"
f082f1c4 1714 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1715 (truncate:SI
1716 (lshiftrt:DI
215b30b3 1717 (mult:DI
e5fea38e 1718 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1719 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1720 (const_int 32))))
1721 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1722 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1723 "smull%?\\t%3, %0, %2, %1"
1724 [(set_attr "insn" "smull")
1725 (set_attr "predicable" "yes")]
1726)
1727
957788b0 1728(define_insn "*smulsi3_highpart_v6"
58d7d654 1729 [(set (match_operand:SI 0 "s_register_operand" "=r")
1730 (truncate:SI
1731 (lshiftrt:DI
1732 (mult:DI
1733 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1734 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1735 (const_int 32))))
1736 (clobber (match_scratch:SI 3 "=r"))]
1737 "TARGET_32BIT && arm_arch6"
f082f1c4 1738 "smull%?\\t%3, %0, %2, %1"
a2cd141b 1739 [(set_attr "insn" "smull")
0d66636f 1740 (set_attr "predicable" "yes")]
cffb2a26 1741)
f082f1c4 1742
957788b0 1743(define_expand "umulsi3_highpart"
1744 [(parallel
1745 [(set (match_operand:SI 0 "s_register_operand" "")
1746 (truncate:SI
1747 (lshiftrt:DI
1748 (mult:DI
1749 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1750 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1751 (const_int 32))))
1752 (clobber (match_scratch:SI 3 ""))])]
1753 "TARGET_32BIT && arm_arch3m"
1754 ""
1755)
1756
1757(define_insn "*umulsi3_highpart_nov6"
f082f1c4 1758 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1759 (truncate:SI
1760 (lshiftrt:DI
215b30b3 1761 (mult:DI
e5fea38e 1762 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
215b30b3 1763 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1764 (const_int 32))))
1765 (clobber (match_scratch:SI 3 "=&r,&r"))]
58d7d654 1766 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1767 "umull%?\\t%3, %0, %2, %1"
1768 [(set_attr "insn" "umull")
1769 (set_attr "predicable" "yes")]
1770)
1771
957788b0 1772(define_insn "*umulsi3_highpart_v6"
58d7d654 1773 [(set (match_operand:SI 0 "s_register_operand" "=r")
1774 (truncate:SI
1775 (lshiftrt:DI
1776 (mult:DI
1777 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1778 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1779 (const_int 32))))
1780 (clobber (match_scratch:SI 3 "=r"))]
1781 "TARGET_32BIT && arm_arch6"
f082f1c4 1782 "umull%?\\t%3, %0, %2, %1"
a2cd141b 1783 [(set_attr "insn" "umull")
0d66636f 1784 (set_attr "predicable" "yes")]
cffb2a26 1785)
f082f1c4 1786
331beb1a 1787(define_insn "mulhisi3"
1788 [(set (match_operand:SI 0 "s_register_operand" "=r")
1789 (mult:SI (sign_extend:SI
1790 (match_operand:HI 1 "s_register_operand" "%r"))
1791 (sign_extend:SI
1792 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1793 "TARGET_DSP_MULTIPLY"
61a2d04c 1794 "smulbb%?\\t%0, %1, %2"
a2cd141b 1795 [(set_attr "insn" "smulxy")
fec538d9 1796 (set_attr "predicable" "yes")]
1797)
1798
1799(define_insn "*mulhisi3tb"
1800 [(set (match_operand:SI 0 "s_register_operand" "=r")
1801 (mult:SI (ashiftrt:SI
1802 (match_operand:SI 1 "s_register_operand" "r")
1803 (const_int 16))
1804 (sign_extend:SI
1805 (match_operand:HI 2 "s_register_operand" "r"))))]
25f905c2 1806 "TARGET_DSP_MULTIPLY"
fec538d9 1807 "smultb%?\\t%0, %1, %2"
a2cd141b 1808 [(set_attr "insn" "smulxy")
fec538d9 1809 (set_attr "predicable" "yes")]
1810)
1811
1812(define_insn "*mulhisi3bt"
1813 [(set (match_operand:SI 0 "s_register_operand" "=r")
1814 (mult:SI (sign_extend:SI
1815 (match_operand:HI 1 "s_register_operand" "r"))
1816 (ashiftrt:SI
1817 (match_operand:SI 2 "s_register_operand" "r")
1818 (const_int 16))))]
25f905c2 1819 "TARGET_DSP_MULTIPLY"
fec538d9 1820 "smulbt%?\\t%0, %1, %2"
a2cd141b 1821 [(set_attr "insn" "smulxy")
fec538d9 1822 (set_attr "predicable" "yes")]
1823)
1824
1825(define_insn "*mulhisi3tt"
1826 [(set (match_operand:SI 0 "s_register_operand" "=r")
1827 (mult:SI (ashiftrt:SI
1828 (match_operand:SI 1 "s_register_operand" "r")
1829 (const_int 16))
1830 (ashiftrt:SI
1831 (match_operand:SI 2 "s_register_operand" "r")
1832 (const_int 16))))]
25f905c2 1833 "TARGET_DSP_MULTIPLY"
fec538d9 1834 "smultt%?\\t%0, %1, %2"
a2cd141b 1835 [(set_attr "insn" "smulxy")
fec538d9 1836 (set_attr "predicable" "yes")]
331beb1a 1837)
1838
5cdca009 1839(define_insn "maddhisi4"
331beb1a 1840 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfa6c608 1841 (plus:SI (mult:SI (sign_extend:SI
1842 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1843 (sign_extend:SI
cfa6c608 1844 (match_operand:HI 2 "s_register_operand" "r")))
1845 (match_operand:SI 3 "s_register_operand" "r")))]
25f905c2 1846 "TARGET_DSP_MULTIPLY"
5cdca009 1847 "smlabb%?\\t%0, %1, %2, %3"
a2cd141b 1848 [(set_attr "insn" "smlaxy")
fec538d9 1849 (set_attr "predicable" "yes")]
331beb1a 1850)
1851
9a92f368 1852;; Note: there is no maddhisi4ibt because this one is canonical form
1853(define_insn "*maddhisi4tb"
1854 [(set (match_operand:SI 0 "s_register_operand" "=r")
1855 (plus:SI (mult:SI (ashiftrt:SI
1856 (match_operand:SI 1 "s_register_operand" "r")
1857 (const_int 16))
1858 (sign_extend:SI
1859 (match_operand:HI 2 "s_register_operand" "r")))
1860 (match_operand:SI 3 "s_register_operand" "r")))]
1861 "TARGET_DSP_MULTIPLY"
1862 "smlatb%?\\t%0, %1, %2, %3"
1863 [(set_attr "insn" "smlaxy")
1864 (set_attr "predicable" "yes")]
1865)
1866
1867(define_insn "*maddhisi4tt"
1868 [(set (match_operand:SI 0 "s_register_operand" "=r")
1869 (plus:SI (mult:SI (ashiftrt:SI
1870 (match_operand:SI 1 "s_register_operand" "r")
1871 (const_int 16))
1872 (ashiftrt:SI
1873 (match_operand:SI 2 "s_register_operand" "r")
1874 (const_int 16)))
1875 (match_operand:SI 3 "s_register_operand" "r")))]
1876 "TARGET_DSP_MULTIPLY"
1877 "smlatt%?\\t%0, %1, %2, %3"
1878 [(set_attr "insn" "smlaxy")
1879 (set_attr "predicable" "yes")]
1880)
1881
aff5fb4d 1882(define_insn "maddhidi4"
331beb1a 1883 [(set (match_operand:DI 0 "s_register_operand" "=r")
1884 (plus:DI
331beb1a 1885 (mult:DI (sign_extend:DI
cfa6c608 1886 (match_operand:HI 1 "s_register_operand" "r"))
331beb1a 1887 (sign_extend:DI
cfa6c608 1888 (match_operand:HI 2 "s_register_operand" "r")))
1889 (match_operand:DI 3 "s_register_operand" "0")))]
25f905c2 1890 "TARGET_DSP_MULTIPLY"
5cdca009 1891 "smlalbb%?\\t%Q0, %R0, %1, %2"
a2cd141b 1892 [(set_attr "insn" "smlalxy")
fec538d9 1893 (set_attr "predicable" "yes")])
331beb1a 1894
9a92f368 1895;; Note: there is no maddhidi4ibt because this one is canonical form
1896(define_insn "*maddhidi4tb"
1897 [(set (match_operand:DI 0 "s_register_operand" "=r")
1898 (plus:DI
1899 (mult:DI (sign_extend:DI
1900 (ashiftrt:SI
1901 (match_operand:SI 1 "s_register_operand" "r")
1902 (const_int 16)))
1903 (sign_extend:DI
1904 (match_operand:HI 2 "s_register_operand" "r")))
1905 (match_operand:DI 3 "s_register_operand" "0")))]
1906 "TARGET_DSP_MULTIPLY"
1907 "smlaltb%?\\t%Q0, %R0, %1, %2"
1908 [(set_attr "insn" "smlalxy")
1909 (set_attr "predicable" "yes")])
1910
1911(define_insn "*maddhidi4tt"
1912 [(set (match_operand:DI 0 "s_register_operand" "=r")
1913 (plus:DI
1914 (mult:DI (sign_extend:DI
1915 (ashiftrt:SI
1916 (match_operand:SI 1 "s_register_operand" "r")
1917 (const_int 16)))
1918 (sign_extend:DI
1919 (ashiftrt:SI
1920 (match_operand:SI 2 "s_register_operand" "r")
1921 (const_int 16))))
1922 (match_operand:DI 3 "s_register_operand" "0")))]
1923 "TARGET_DSP_MULTIPLY"
1924 "smlaltt%?\\t%Q0, %R0, %1, %2"
1925 [(set_attr "insn" "smlalxy")
1926 (set_attr "predicable" "yes")])
1927
604f3a0a 1928(define_expand "mulsf3"
1929 [(set (match_operand:SF 0 "s_register_operand" "")
1930 (mult:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1931 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1932 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 1933 "
a2cd141b 1934 if (TARGET_MAVERICK
604f3a0a 1935 && !cirrus_fp_register (operands[2], SFmode))
1936 operands[2] = force_reg (SFmode, operands[2]);
1937")
1938
604f3a0a 1939(define_expand "muldf3"
1940 [(set (match_operand:DF 0 "s_register_operand" "")
1941 (mult:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1942 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1943 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 1944 "
a2cd141b 1945 if (TARGET_MAVERICK
604f3a0a 1946 && !cirrus_fp_register (operands[2], DFmode))
1947 operands[2] = force_reg (DFmode, operands[2]);
1948")
b11cae9e 1949\f
1950;; Division insns
1951
7db9af5d 1952(define_expand "divsf3"
1953 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1954 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1955 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1956 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1957 "")
9c08d1fa 1958
7db9af5d 1959(define_expand "divdf3"
1960 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1961 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1962 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
a50d7267 1963 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7db9af5d 1964 "")
b11cae9e 1965\f
1966;; Modulo insns
1967
7db9af5d 1968(define_expand "modsf3"
1969 [(set (match_operand:SF 0 "s_register_operand" "")
1970 (mod:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1971 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
25f905c2 1972 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1973 "")
9c08d1fa 1974
7db9af5d 1975(define_expand "moddf3"
1976 [(set (match_operand:DF 0 "s_register_operand" "")
1977 (mod:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1978 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
25f905c2 1979 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1980 "")
b11cae9e 1981\f
1982;; Boolean and,ior,xor insns
1983
f6ebffac 1984;; Split up double word logical operations
1985
1986;; Split up simple DImode logical operations. Simply perform the logical
1987;; operation on the upper and lower halves of the registers.
1988(define_split
1989 [(set (match_operand:DI 0 "s_register_operand" "")
1990 (match_operator:DI 6 "logical_binary_operator"
1991 [(match_operand:DI 1 "s_register_operand" "")
1992 (match_operand:DI 2 "s_register_operand" "")]))]
25f905c2 1993 "TARGET_32BIT && reload_completed
e2669ea7 1994 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
25f905c2 1995 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1996 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1997 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1998 "
215b30b3 1999 {
2000 operands[3] = gen_highpart (SImode, operands[0]);
2001 operands[0] = gen_lowpart (SImode, operands[0]);
2002 operands[4] = gen_highpart (SImode, operands[1]);
2003 operands[1] = gen_lowpart (SImode, operands[1]);
2004 operands[5] = gen_highpart (SImode, operands[2]);
2005 operands[2] = gen_lowpart (SImode, operands[2]);
2006 }"
2007)
f6ebffac 2008
f6ebffac 2009(define_split
2010 [(set (match_operand:DI 0 "s_register_operand" "")
2011 (match_operator:DI 6 "logical_binary_operator"
2012 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2013 (match_operand:DI 1 "s_register_operand" "")]))]
25f905c2 2014 "TARGET_32BIT && reload_completed"
f6ebffac 2015 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2016 (set (match_dup 3) (match_op_dup:SI 6
2017 [(ashiftrt:SI (match_dup 2) (const_int 31))
2018 (match_dup 4)]))]
2019 "
215b30b3 2020 {
2021 operands[3] = gen_highpart (SImode, operands[0]);
2022 operands[0] = gen_lowpart (SImode, operands[0]);
2023 operands[4] = gen_highpart (SImode, operands[1]);
2024 operands[1] = gen_lowpart (SImode, operands[1]);
2025 operands[5] = gen_highpart (SImode, operands[2]);
2026 operands[2] = gen_lowpart (SImode, operands[2]);
2027 }"
2028)
f6ebffac 2029
f6ebffac 2030;; The zero extend of operand 2 means we can just copy the high part of
2031;; operand1 into operand0.
2032(define_split
2033 [(set (match_operand:DI 0 "s_register_operand" "")
2034 (ior:DI
2035 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2036 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2037 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2038 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
2039 (set (match_dup 3) (match_dup 4))]
2040 "
215b30b3 2041 {
2042 operands[4] = gen_highpart (SImode, operands[1]);
2043 operands[3] = gen_highpart (SImode, operands[0]);
2044 operands[0] = gen_lowpart (SImode, operands[0]);
2045 operands[1] = gen_lowpart (SImode, operands[1]);
2046 }"
2047)
f6ebffac 2048
2049;; The zero extend of operand 2 means we can just copy the high part of
2050;; operand1 into operand0.
2051(define_split
2052 [(set (match_operand:DI 0 "s_register_operand" "")
2053 (xor:DI
2054 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2055 (match_operand:DI 1 "s_register_operand" "")))]
25f905c2 2056 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
f6ebffac 2057 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
2058 (set (match_dup 3) (match_dup 4))]
2059 "
215b30b3 2060 {
2061 operands[4] = gen_highpart (SImode, operands[1]);
2062 operands[3] = gen_highpart (SImode, operands[0]);
2063 operands[0] = gen_lowpart (SImode, operands[0]);
2064 operands[1] = gen_lowpart (SImode, operands[1]);
2065 }"
2066)
f6ebffac 2067
e2669ea7 2068(define_expand "anddi3"
2069 [(set (match_operand:DI 0 "s_register_operand" "")
2070 (and:DI (match_operand:DI 1 "s_register_operand" "")
2071 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
2072 "TARGET_32BIT"
2073 ""
2074)
2075
2076(define_insn "*anddi3_insn"
cffb2a26 2077 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2078 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2079 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2080 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2081 "#"
215b30b3 2082 [(set_attr "length" "8")]
2083)
b11cae9e 2084
a0f94409 2085(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 2086 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2087 (and:DI (zero_extend:DI
2088 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2089 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2090 "TARGET_32BIT"
f6ebffac 2091 "#"
25f905c2 2092 "TARGET_32BIT && reload_completed"
a0f94409 2093 ; The zero extend of operand 2 clears the high word of the output
2094 ; operand.
2095 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2096 (set (match_dup 3) (const_int 0))]
2097 "
2098 {
2099 operands[3] = gen_highpart (SImode, operands[0]);
2100 operands[0] = gen_lowpart (SImode, operands[0]);
2101 operands[1] = gen_lowpart (SImode, operands[1]);
2102 }"
215b30b3 2103 [(set_attr "length" "8")]
2104)
b11cae9e 2105
f7fbdd4a 2106(define_insn "*anddi_sesdi_di"
cffb2a26 2107 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 2108 (and:DI (sign_extend:DI
2109 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2110 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2111 "TARGET_32BIT"
f6ebffac 2112 "#"
cffb2a26 2113 [(set_attr "length" "8")]
2114)
b11cae9e 2115
87b22bf7 2116(define_expand "andsi3"
cffb2a26 2117 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2118 (and:SI (match_operand:SI 1 "s_register_operand" "")
2119 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2120 "TARGET_EITHER"
87b22bf7 2121 "
25f905c2 2122 if (TARGET_32BIT)
87b22bf7 2123 {
cffb2a26 2124 if (GET_CODE (operands[2]) == CONST_INT)
2125 {
47b5b27b 2126 if (INTVAL (operands[2]) == 255 && arm_arch6)
2127 {
2128 operands[1] = convert_to_mode (QImode, operands[1], 1);
2129 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2130 operands[1]));
2131 }
2132 else
2133 arm_split_constant (AND, SImode, NULL_RTX,
2134 INTVAL (operands[2]), operands[0],
2135 operands[1],
2136 optimize && can_create_pseudo_p ());
615caa51 2137
cffb2a26 2138 DONE;
2139 }
87b22bf7 2140 }
25f905c2 2141 else /* TARGET_THUMB1 */
cffb2a26 2142 {
2143 if (GET_CODE (operands[2]) != CONST_INT)
923ffadb 2144 {
2145 rtx tmp = force_reg (SImode, operands[2]);
2146 if (rtx_equal_p (operands[0], operands[1]))
2147 operands[2] = tmp;
2148 else
2149 {
2150 operands[2] = operands[1];
2151 operands[1] = tmp;
2152 }
2153 }
cffb2a26 2154 else
2155 {
2156 int i;
2157
215b30b3 2158 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 2159 {
215b30b3 2160 operands[2] = force_reg (SImode,
2161 GEN_INT (~INTVAL (operands[2])));
cffb2a26 2162
747b7458 2163 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
cffb2a26 2164
2165 DONE;
2166 }
87b22bf7 2167
cffb2a26 2168 for (i = 9; i <= 31; i++)
2169 {
2170 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2171 {
2172 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2173 const0_rtx));
2174 DONE;
2175 }
215b30b3 2176 else if ((((HOST_WIDE_INT) 1) << i) - 1
2177 == ~INTVAL (operands[2]))
cffb2a26 2178 {
2179 rtx shift = GEN_INT (i);
2180 rtx reg = gen_reg_rtx (SImode);
2181
2182 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2183 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2184
2185 DONE;
2186 }
2187 }
2188
2189 operands[2] = force_reg (SImode, operands[2]);
2190 }
215b30b3 2191 }
2192 "
cffb2a26 2193)
2194
25f905c2 2195; ??? Check split length for Thumb-2
a0f94409 2196(define_insn_and_split "*arm_andsi3_insn"
cffb2a26 2197 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87b22bf7 2198 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2199 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
25f905c2 2200 "TARGET_32BIT"
5565501b 2201 "@
2202 and%?\\t%0, %1, %2
87b22bf7 2203 bic%?\\t%0, %1, #%B2
2204 #"
25f905c2 2205 "TARGET_32BIT
a0f94409 2206 && GET_CODE (operands[2]) == CONST_INT
2207 && !(const_ok_for_arm (INTVAL (operands[2]))
2208 || const_ok_for_arm (~INTVAL (operands[2])))"
2209 [(clobber (const_int 0))]
2210 "
96f57e36 2211 arm_split_constant (AND, SImode, curr_insn,
2212 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2213 DONE;
2214 "
0d66636f 2215 [(set_attr "length" "4,4,16")
2216 (set_attr "predicable" "yes")]
cffb2a26 2217)
2218
25f905c2 2219(define_insn "*thumb1_andsi3_insn"
cffb2a26 2220 [(set (match_operand:SI 0 "register_operand" "=l")
2221 (and:SI (match_operand:SI 1 "register_operand" "%0")
2222 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2223 "TARGET_THUMB1"
747b7458 2224 "and\\t%0, %2"
2225 [(set_attr "length" "2")
2226 (set_attr "conds" "set")])
87b22bf7 2227
f7fbdd4a 2228(define_insn "*andsi3_compare0"
bd5b4116 2229 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2230 (compare:CC_NOOV
2231 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
2232 (match_operand:SI 2 "arm_not_operand" "rI,K"))
2233 (const_int 0)))
cffb2a26 2234 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 2235 (and:SI (match_dup 1) (match_dup 2)))]
25f905c2 2236 "TARGET_32BIT"
5565501b 2237 "@
25f905c2 2238 and%.\\t%0, %1, %2
2239 bic%.\\t%0, %1, #%B2"
cffb2a26 2240 [(set_attr "conds" "set")]
2241)
9c08d1fa 2242
f7fbdd4a 2243(define_insn "*andsi3_compare0_scratch"
bd5b4116 2244 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 2245 (compare:CC_NOOV
2246 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
2247 (match_operand:SI 1 "arm_not_operand" "rI,K"))
2248 (const_int 0)))
dd193d7c 2249 (clobber (match_scratch:SI 2 "=X,r"))]
25f905c2 2250 "TARGET_32BIT"
5565501b 2251 "@
2252 tst%?\\t%0, %1
25f905c2 2253 bic%.\\t%2, %0, #%B1"
0d66636f 2254 [(set_attr "conds" "set")]
2255)
9c08d1fa 2256
f7fbdd4a 2257(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 2258 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2259 (compare:CC_NOOV (zero_extract:SI
2260 (match_operand:SI 0 "s_register_operand" "r")
206ee9a2 2261 (match_operand 1 "const_int_operand" "n")
2262 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 2263 (const_int 0)))]
25f905c2 2264 "TARGET_32BIT
cffb2a26 2265 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2266 && INTVAL (operands[1]) > 0
2267 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2268 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 2269 "*
5c49a439 2270 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2271 << INTVAL (operands[2]));
40dbec34 2272 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 2273 return \"\";
0d66636f 2274 "
2275 [(set_attr "conds" "set")]
2276)
9c08d1fa 2277
f4462328 2278(define_insn_and_split "*ne_zeroextractsi"
c4034607 2279 [(set (match_operand:SI 0 "s_register_operand" "=r")
2280 (ne:SI (zero_extract:SI
2281 (match_operand:SI 1 "s_register_operand" "r")
2282 (match_operand:SI 2 "const_int_operand" "n")
2283 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 2284 (const_int 0)))
2285 (clobber (reg:CC CC_REGNUM))]
25f905c2 2286 "TARGET_32BIT
cffb2a26 2287 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2288 && INTVAL (operands[2]) > 0
2289 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2290 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 2291 "#"
25f905c2 2292 "TARGET_32BIT
f4462328 2293 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2294 && INTVAL (operands[2]) > 0
2295 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2296 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2297 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2298 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2299 (const_int 0)))
2300 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2301 (set (match_dup 0)
2302 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2303 (match_dup 0) (const_int 1)))]
2304 "
2305 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2306 << INTVAL (operands[3]));
2307 "
2308 [(set_attr "conds" "clob")
25f905c2 2309 (set (attr "length")
2310 (if_then_else (eq_attr "is_thumb" "yes")
2311 (const_int 12)
2312 (const_int 8)))]
f4462328 2313)
2314
2315(define_insn_and_split "*ne_zeroextractsi_shifted"
2316 [(set (match_operand:SI 0 "s_register_operand" "=r")
2317 (ne:SI (zero_extract:SI
2318 (match_operand:SI 1 "s_register_operand" "r")
2319 (match_operand:SI 2 "const_int_operand" "n")
2320 (const_int 0))
2321 (const_int 0)))
2322 (clobber (reg:CC CC_REGNUM))]
2323 "TARGET_ARM"
2324 "#"
2325 "TARGET_ARM"
2326 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2327 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2328 (const_int 0)))
2329 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2330 (set (match_dup 0)
2331 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2332 (match_dup 0) (const_int 1)))]
2333 "
2334 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2335 "
2336 [(set_attr "conds" "clob")
2337 (set_attr "length" "8")]
2338)
2339
2340(define_insn_and_split "*ite_ne_zeroextractsi"
2341 [(set (match_operand:SI 0 "s_register_operand" "=r")
2342 (if_then_else:SI (ne (zero_extract:SI
2343 (match_operand:SI 1 "s_register_operand" "r")
2344 (match_operand:SI 2 "const_int_operand" "n")
2345 (match_operand:SI 3 "const_int_operand" "n"))
2346 (const_int 0))
2347 (match_operand:SI 4 "arm_not_operand" "rIK")
2348 (const_int 0)))
2349 (clobber (reg:CC CC_REGNUM))]
2350 "TARGET_ARM
2351 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2352 && INTVAL (operands[2]) > 0
2353 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2354 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2355 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2356 "#"
2357 "TARGET_ARM
2358 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2359 && INTVAL (operands[2]) > 0
2360 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 2361 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2362 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 2363 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2364 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2365 (const_int 0)))
2366 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2367 (set (match_dup 0)
2368 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2369 (match_dup 0) (match_dup 4)))]
2370 "
c4034607 2371 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 2372 << INTVAL (operands[3]));
2373 "
2374 [(set_attr "conds" "clob")
2375 (set_attr "length" "8")]
2376)
2377
2378(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2379 [(set (match_operand:SI 0 "s_register_operand" "=r")
2380 (if_then_else:SI (ne (zero_extract:SI
2381 (match_operand:SI 1 "s_register_operand" "r")
2382 (match_operand:SI 2 "const_int_operand" "n")
2383 (const_int 0))
2384 (const_int 0))
2385 (match_operand:SI 3 "arm_not_operand" "rIK")
2386 (const_int 0)))
2387 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 2388 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2389 "#"
f8d7bf2f 2390 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 2391 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2392 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2393 (const_int 0)))
2394 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2395 (set (match_dup 0)
2396 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2397 (match_dup 0) (match_dup 3)))]
2398 "
2399 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 2400 "
2401 [(set_attr "conds" "clob")
215b30b3 2402 (set_attr "length" "8")]
2403)
9c08d1fa 2404
58d6528b 2405(define_split
2406 [(set (match_operand:SI 0 "s_register_operand" "")
2407 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2408 (match_operand:SI 2 "const_int_operand" "")
2409 (match_operand:SI 3 "const_int_operand" "")))
2410 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 2411 "TARGET_THUMB1"
58d6528b 2412 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2413 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2414 "{
2415 HOST_WIDE_INT temp = INTVAL (operands[2]);
2416
2417 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2418 operands[3] = GEN_INT (32 - temp);
2419 }"
2420)
2421
25f905c2 2422;; ??? Use Thumb-2 has bitfield insert/extract instructions.
d7863cfe 2423(define_split
2424 [(set (match_operand:SI 0 "s_register_operand" "")
2425 (match_operator:SI 1 "shiftable_operator"
2426 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2427 (match_operand:SI 3 "const_int_operand" "")
2428 (match_operand:SI 4 "const_int_operand" ""))
2429 (match_operand:SI 5 "s_register_operand" "")]))
2430 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2431 "TARGET_ARM"
2432 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2433 (set (match_dup 0)
2434 (match_op_dup 1
2435 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2436 (match_dup 5)]))]
2437 "{
2438 HOST_WIDE_INT temp = INTVAL (operands[3]);
2439
2440 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2441 operands[4] = GEN_INT (32 - temp);
2442 }"
2443)
2444
58d6528b 2445(define_split
2446 [(set (match_operand:SI 0 "s_register_operand" "")
2447 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2448 (match_operand:SI 2 "const_int_operand" "")
2449 (match_operand:SI 3 "const_int_operand" "")))]
25f905c2 2450 "TARGET_THUMB1"
58d6528b 2451 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2452 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2453 "{
2454 HOST_WIDE_INT temp = INTVAL (operands[2]);
2455
2456 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2457 operands[3] = GEN_INT (32 - temp);
2458 }"
2459)
2460
d7863cfe 2461(define_split
2462 [(set (match_operand:SI 0 "s_register_operand" "")
2463 (match_operator:SI 1 "shiftable_operator"
2464 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2465 (match_operand:SI 3 "const_int_operand" "")
2466 (match_operand:SI 4 "const_int_operand" ""))
2467 (match_operand:SI 5 "s_register_operand" "")]))
2468 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2469 "TARGET_ARM"
2470 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2471 (set (match_dup 0)
2472 (match_op_dup 1
2473 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2474 (match_dup 5)]))]
2475 "{
2476 HOST_WIDE_INT temp = INTVAL (operands[3]);
2477
2478 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2479 operands[4] = GEN_INT (32 - temp);
2480 }"
2481)
2482
a42059fd 2483;;; ??? This pattern is bogus. If operand3 has bits outside the range
2484;;; represented by the bitfield, then this will produce incorrect results.
2485;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 2486;;; which have a real bit-field insert instruction, the truncation happens
2487;;; in the bit-field insert instruction itself. Since arm does not have a
2488;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 2489;;; the value before we insert. This loses some of the advantage of having
2490;;; this insv pattern, so this pattern needs to be reevalutated.
2491
8a18b90c 2492(define_expand "insv"
eb04cafb 2493 [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2494 (match_operand 1 "general_operand" "")
2495 (match_operand 2 "general_operand" ""))
2496 (match_operand 3 "reg_or_int_operand" ""))]
8b054d5a 2497 "TARGET_ARM || arm_arch_thumb2"
8a18b90c 2498 "
215b30b3 2499 {
2500 int start_bit = INTVAL (operands[2]);
2501 int width = INTVAL (operands[1]);
2502 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2503 rtx target, subtarget;
2504
8b054d5a 2505 if (arm_arch_thumb2)
2506 {
eb04cafb 2507 if (unaligned_access && MEM_P (operands[0])
2508 && s_register_operand (operands[3], GET_MODE (operands[3]))
2509 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
8b054d5a 2510 {
eb04cafb 2511 rtx base_addr;
2512
2513 if (BYTES_BIG_ENDIAN)
2514 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2515 - start_bit;
8b054d5a 2516
eb04cafb 2517 if (width == 32)
8b054d5a 2518 {
eb04cafb 2519 base_addr = adjust_address (operands[0], SImode,
2520 start_bit / BITS_PER_UNIT);
2521 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
8b054d5a 2522 }
eb04cafb 2523 else
2524 {
2525 rtx tmp = gen_reg_rtx (HImode);
8b054d5a 2526
eb04cafb 2527 base_addr = adjust_address (operands[0], HImode,
2528 start_bit / BITS_PER_UNIT);
2529 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2530 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2531 }
2532 DONE;
8b054d5a 2533 }
eb04cafb 2534 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
8b054d5a 2535 {
eb04cafb 2536 bool use_bfi = TRUE;
8b054d5a 2537
eb04cafb 2538 if (GET_CODE (operands[3]) == CONST_INT)
2539 {
2540 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2541
2542 if (val == 0)
2543 {
2544 emit_insn (gen_insv_zero (operands[0], operands[1],
2545 operands[2]));
2546 DONE;
2547 }
2548
2549 /* See if the set can be done with a single orr instruction. */
2550 if (val == mask && const_ok_for_arm (val << start_bit))
2551 use_bfi = FALSE;
2552 }
2553
2554 if (use_bfi)
2555 {
2556 if (GET_CODE (operands[3]) != REG)
2557 operands[3] = force_reg (SImode, operands[3]);
2558
2559 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2560 operands[3]));
2561 DONE;
2562 }
8b054d5a 2563 }
eb04cafb 2564 else
2565 FAIL;
8b054d5a 2566 }
2567
eb04cafb 2568 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2569 FAIL;
2570
3f8fde42 2571 target = copy_rtx (operands[0]);
215b30b3 2572 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2573 subreg as the final target. */
2574 if (GET_CODE (target) == SUBREG)
2575 {
2576 subtarget = gen_reg_rtx (SImode);
2577 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2578 < GET_MODE_SIZE (SImode))
2579 target = SUBREG_REG (target);
2580 }
2581 else
2582 subtarget = target;
8a18b90c 2583
215b30b3 2584 if (GET_CODE (operands[3]) == CONST_INT)
2585 {
2586 /* Since we are inserting a known constant, we may be able to
2587 reduce the number of bits that we have to clear so that
2588 the mask becomes simple. */
2589 /* ??? This code does not check to see if the new mask is actually
2590 simpler. It may not be. */
2591 rtx op1 = gen_reg_rtx (SImode);
2592 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2593 start of this pattern. */
2594 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2595 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2596
c5b3a71b 2597 emit_insn (gen_andsi3 (op1, operands[0],
2598 gen_int_mode (~mask2, SImode)));
215b30b3 2599 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 2600 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 2601 }
2602 else if (start_bit == 0
2603 && !(const_ok_for_arm (mask)
2604 || const_ok_for_arm (~mask)))
2605 {
2606 /* A Trick, since we are setting the bottom bits in the word,
2607 we can shift operand[3] up, operand[0] down, OR them together
2608 and rotate the result back again. This takes 3 insns, and
5910bb95 2609 the third might be mergeable into another op. */
215b30b3 2610 /* The shift up copes with the possibility that operand[3] is
2611 wider than the bitfield. */
2612 rtx op0 = gen_reg_rtx (SImode);
2613 rtx op1 = gen_reg_rtx (SImode);
2614
2615 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2616 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2617 emit_insn (gen_iorsi3 (op1, op1, op0));
2618 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2619 }
2620 else if ((width + start_bit == 32)
2621 && !(const_ok_for_arm (mask)
2622 || const_ok_for_arm (~mask)))
2623 {
2624 /* Similar trick, but slightly less efficient. */
8a18b90c 2625
215b30b3 2626 rtx op0 = gen_reg_rtx (SImode);
2627 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2628
215b30b3 2629 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2630 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2631 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2632 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2633 }
2634 else
2635 {
c5b3a71b 2636 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 2637 rtx op1 = gen_reg_rtx (SImode);
2638 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2639
215b30b3 2640 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2641 {
2642 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2643
215b30b3 2644 emit_insn (gen_movsi (tmp, op0));
2645 op0 = tmp;
2646 }
8a18b90c 2647
215b30b3 2648 /* Mask out any bits in operand[3] that are not needed. */
2649 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2650
215b30b3 2651 if (GET_CODE (op0) == CONST_INT
2652 && (const_ok_for_arm (mask << start_bit)
2653 || const_ok_for_arm (~(mask << start_bit))))
2654 {
c5b3a71b 2655 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 2656 emit_insn (gen_andsi3 (op2, operands[0], op0));
2657 }
2658 else
2659 {
2660 if (GET_CODE (op0) == CONST_INT)
2661 {
2662 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2663
215b30b3 2664 emit_insn (gen_movsi (tmp, op0));
2665 op0 = tmp;
2666 }
2667
2668 if (start_bit != 0)
2669 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2670
215b30b3 2671 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2672 }
8a18b90c 2673
215b30b3 2674 if (start_bit != 0)
2675 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2676
215b30b3 2677 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2678 }
f082f1c4 2679
215b30b3 2680 if (subtarget != target)
2681 {
2682 /* If TARGET is still a SUBREG, then it must be wider than a word,
2683 so we must be careful only to set the subword we were asked to. */
2684 if (GET_CODE (target) == SUBREG)
2685 emit_move_insn (target, subtarget);
2686 else
2687 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2688 }
8a18b90c 2689
215b30b3 2690 DONE;
2691 }"
2692)
8a18b90c 2693
8b054d5a 2694(define_insn "insv_zero"
2695 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2696 (match_operand:SI 1 "const_int_operand" "M")
2697 (match_operand:SI 2 "const_int_operand" "M"))
2698 (const_int 0))]
2699 "arm_arch_thumb2"
2700 "bfc%?\t%0, %2, %1"
2701 [(set_attr "length" "4")
2702 (set_attr "predicable" "yes")]
2703)
2704
2705(define_insn "insv_t2"
2706 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2707 (match_operand:SI 1 "const_int_operand" "M")
2708 (match_operand:SI 2 "const_int_operand" "M"))
2709 (match_operand:SI 3 "s_register_operand" "r"))]
2710 "arm_arch_thumb2"
2711 "bfi%?\t%0, %3, %2, %1"
2712 [(set_attr "length" "4")
2713 (set_attr "predicable" "yes")]
2714)
2715
215b30b3 2716; constants for op 2 will never be given to these patterns.
a0f94409 2717(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2718 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 2719 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2720 (match_operand:DI 2 "s_register_operand" "r,0")))]
25f905c2 2721 "TARGET_32BIT"
f6ebffac 2722 "#"
e2669ea7 2723 "TARGET_32BIT && reload_completed
2724 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2725 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2726 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2727 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2728 "
2729 {
2730 operands[3] = gen_highpart (SImode, operands[0]);
2731 operands[0] = gen_lowpart (SImode, operands[0]);
2732 operands[4] = gen_highpart (SImode, operands[1]);
2733 operands[1] = gen_lowpart (SImode, operands[1]);
2734 operands[5] = gen_highpart (SImode, operands[2]);
2735 operands[2] = gen_lowpart (SImode, operands[2]);
2736 }"
0d66636f 2737 [(set_attr "length" "8")
2738 (set_attr "predicable" "yes")]
2739)
9c08d1fa 2740
a0f94409 2741(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2742 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2743 (and:DI (not:DI (zero_extend:DI
2744 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2745 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2746 "TARGET_32BIT"
e2348bcb 2747 "@
97499065 2748 bic%?\\t%Q0, %Q1, %2
f6ebffac 2749 #"
a0f94409 2750 ; (not (zero_extend ...)) allows us to just copy the high word from
2751 ; operand1 to operand0.
25f905c2 2752 "TARGET_32BIT
a0f94409 2753 && reload_completed
2754 && operands[0] != operands[1]"
5a097f7d 2755 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2756 (set (match_dup 3) (match_dup 4))]
2757 "
2758 {
2759 operands[3] = gen_highpart (SImode, operands[0]);
2760 operands[0] = gen_lowpart (SImode, operands[0]);
2761 operands[4] = gen_highpart (SImode, operands[1]);
2762 operands[1] = gen_lowpart (SImode, operands[1]);
2763 }"
0d66636f 2764 [(set_attr "length" "4,8")
2765 (set_attr "predicable" "yes")]
2766)
9c08d1fa 2767
a0f94409 2768(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2769 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2770 (and:DI (not:DI (sign_extend:DI
2771 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2772 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2773 "TARGET_32BIT"
f6ebffac 2774 "#"
25f905c2 2775 "TARGET_32BIT && reload_completed"
5a097f7d 2776 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2777 (set (match_dup 3) (and:SI (not:SI
2778 (ashiftrt:SI (match_dup 2) (const_int 31)))
2779 (match_dup 4)))]
2780 "
2781 {
2782 operands[3] = gen_highpart (SImode, operands[0]);
2783 operands[0] = gen_lowpart (SImode, operands[0]);
2784 operands[4] = gen_highpart (SImode, operands[1]);
2785 operands[1] = gen_lowpart (SImode, operands[1]);
2786 }"
0d66636f 2787 [(set_attr "length" "8")
2788 (set_attr "predicable" "yes")]
2789)
9c08d1fa 2790
8a18b90c 2791(define_insn "andsi_notsi_si"
9c08d1fa 2792 [(set (match_operand:SI 0 "s_register_operand" "=r")
2793 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2794 (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 2795 "TARGET_32BIT"
0d66636f 2796 "bic%?\\t%0, %1, %2"
2797 [(set_attr "predicable" "yes")]
2798)
b11cae9e 2799
747b7458 2800(define_insn "thumb1_bicsi3"
cffb2a26 2801 [(set (match_operand:SI 0 "register_operand" "=l")
2802 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2803 (match_operand:SI 2 "register_operand" "0")))]
25f905c2 2804 "TARGET_THUMB1"
747b7458 2805 "bic\\t%0, %1"
2806 [(set_attr "length" "2")
2807 (set_attr "conds" "set")])
cffb2a26 2808
8a18b90c 2809(define_insn "andsi_not_shiftsi_si"
a2cd141b 2810 [(set (match_operand:SI 0 "s_register_operand" "=r")
2811 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2812 [(match_operand:SI 2 "s_register_operand" "r")
2813 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2814 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2815 "TARGET_ARM"
6c4c2133 2816 "bic%?\\t%0, %1, %2%S4"
344495ea 2817 [(set_attr "predicable" "yes")
331beb1a 2818 (set_attr "shift" "2")
a2cd141b 2819 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2820 (const_string "alu_shift")
2821 (const_string "alu_shift_reg")))]
6c4c2133 2822)
8a18b90c 2823
f7fbdd4a 2824(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2825 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2826 (compare:CC_NOOV
2827 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2828 (match_operand:SI 1 "s_register_operand" "r"))
2829 (const_int 0)))
9c08d1fa 2830 (set (match_operand:SI 0 "s_register_operand" "=r")
2831 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
25f905c2 2832 "TARGET_32BIT"
2833 "bic%.\\t%0, %1, %2"
0d66636f 2834 [(set_attr "conds" "set")]
2835)
9c08d1fa 2836
f7fbdd4a 2837(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2838 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2839 (compare:CC_NOOV
2840 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2841 (match_operand:SI 1 "s_register_operand" "r"))
2842 (const_int 0)))
9c08d1fa 2843 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2844 "TARGET_32BIT"
2845 "bic%.\\t%0, %1, %2"
0d66636f 2846 [(set_attr "conds" "set")]
2847)
9c08d1fa 2848
e2669ea7 2849(define_expand "iordi3"
2850 [(set (match_operand:DI 0 "s_register_operand" "")
2851 (ior:DI (match_operand:DI 1 "s_register_operand" "")
2852 (match_operand:DI 2 "neon_logic_op2" "")))]
2853 "TARGET_32BIT"
2854 ""
2855)
2856
2857(define_insn "*iordi3_insn"
cffb2a26 2858 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2859 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2860 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 2861 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 2862 "#"
0d66636f 2863 [(set_attr "length" "8")
2864 (set_attr "predicable" "yes")]
cffb2a26 2865)
9c08d1fa 2866
f7fbdd4a 2867(define_insn "*iordi_zesidi_di"
9c08d1fa 2868 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2869 (ior:DI (zero_extend:DI
2870 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2871 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 2872 "TARGET_32BIT"
e2348bcb 2873 "@
97499065 2874 orr%?\\t%Q0, %Q1, %2
f6ebffac 2875 #"
0d66636f 2876 [(set_attr "length" "4,8")
2877 (set_attr "predicable" "yes")]
cffb2a26 2878)
9c08d1fa 2879
f7fbdd4a 2880(define_insn "*iordi_sesidi_di"
9c08d1fa 2881 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2882 (ior:DI (sign_extend:DI
2883 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 2884 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 2885 "TARGET_32BIT"
f6ebffac 2886 "#"
0d66636f 2887 [(set_attr "length" "8")
2888 (set_attr "predicable" "yes")]
cffb2a26 2889)
9c08d1fa 2890
87b22bf7 2891(define_expand "iorsi3"
cffb2a26 2892 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2893 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2894 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2895 "TARGET_EITHER"
87b22bf7 2896 "
2897 if (GET_CODE (operands[2]) == CONST_INT)
2898 {
25f905c2 2899 if (TARGET_32BIT)
cffb2a26 2900 {
96f57e36 2901 arm_split_constant (IOR, SImode, NULL_RTX,
2902 INTVAL (operands[2]), operands[0], operands[1],
e1ba4a27 2903 optimize && can_create_pseudo_p ());
cffb2a26 2904 DONE;
2905 }
25f905c2 2906 else /* TARGET_THUMB1 */
923ffadb 2907 {
2908 rtx tmp = force_reg (SImode, operands[2]);
2909 if (rtx_equal_p (operands[0], operands[1]))
2910 operands[2] = tmp;
2911 else
2912 {
2913 operands[2] = operands[1];
2914 operands[1] = tmp;
2915 }
2916 }
87b22bf7 2917 }
cffb2a26 2918 "
2919)
87b22bf7 2920
d5d4dc8d 2921(define_insn_and_split "*iorsi3_insn"
2922 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2923 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
2924 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
2925 "TARGET_32BIT"
87b22bf7 2926 "@
2927 orr%?\\t%0, %1, %2
d5d4dc8d 2928 orn%?\\t%0, %1, #%B2
87b22bf7 2929 #"
d5d4dc8d 2930 "TARGET_32BIT
a0f94409 2931 && GET_CODE (operands[2]) == CONST_INT
d5d4dc8d 2932 && !(const_ok_for_arm (INTVAL (operands[2]))
2933 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
a0f94409 2934 [(clobber (const_int 0))]
d5d4dc8d 2935{
96f57e36 2936 arm_split_constant (IOR, SImode, curr_insn,
2937 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2938 DONE;
d5d4dc8d 2939}
2940 [(set_attr "length" "4,4,16")
2941 (set_attr "arch" "32,t2,32")
2942 (set_attr "predicable" "yes")])
cffb2a26 2943
747b7458 2944(define_insn "*thumb1_iorsi3_insn"
cffb2a26 2945 [(set (match_operand:SI 0 "register_operand" "=l")
2946 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2947 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 2948 "TARGET_THUMB1"
747b7458 2949 "orr\\t%0, %2"
2950 [(set_attr "length" "2")
2951 (set_attr "conds" "set")])
9c08d1fa 2952
a0f94409 2953(define_peephole2
2954 [(match_scratch:SI 3 "r")
372575c7 2955 (set (match_operand:SI 0 "arm_general_register_operand" "")
2956 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2957 (match_operand:SI 2 "const_int_operand" "")))]
90560cad 2958 "TARGET_ARM
a0f94409 2959 && !const_ok_for_arm (INTVAL (operands[2]))
2960 && const_ok_for_arm (~INTVAL (operands[2]))"
2961 [(set (match_dup 3) (match_dup 2))
2962 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2963 ""
215b30b3 2964)
a0f94409 2965
f7fbdd4a 2966(define_insn "*iorsi3_compare0"
bd5b4116 2967 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2968 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2969 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2970 (const_int 0)))
2971 (set (match_operand:SI 0 "s_register_operand" "=r")
2972 (ior:SI (match_dup 1) (match_dup 2)))]
25f905c2 2973 "TARGET_32BIT"
2974 "orr%.\\t%0, %1, %2"
cffb2a26 2975 [(set_attr "conds" "set")]
2976)
9c08d1fa 2977
f7fbdd4a 2978(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2979 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2980 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2981 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2982 (const_int 0)))
2983 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 2984 "TARGET_32BIT"
2985 "orr%.\\t%0, %1, %2"
0d66636f 2986 [(set_attr "conds" "set")]
2987)
9c08d1fa 2988
e2669ea7 2989(define_expand "xordi3"
2990 [(set (match_operand:DI 0 "s_register_operand" "")
2991 (xor:DI (match_operand:DI 1 "s_register_operand" "")
2992 (match_operand:DI 2 "s_register_operand" "")))]
2993 "TARGET_32BIT"
2994 ""
2995)
2996
2997(define_insn "*xordi3_insn"
cffb2a26 2998 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2999 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
3000 (match_operand:DI 2 "s_register_operand" "r,r")))]
e2669ea7 3001 "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
f6ebffac 3002 "#"
0d66636f 3003 [(set_attr "length" "8")
3004 (set_attr "predicable" "yes")]
cffb2a26 3005)
9c08d1fa 3006
f7fbdd4a 3007(define_insn "*xordi_zesidi_di"
9c08d1fa 3008 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3009 (xor:DI (zero_extend:DI
3010 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 3011 (match_operand:DI 1 "s_register_operand" "0,?r")))]
25f905c2 3012 "TARGET_32BIT"
e2348bcb 3013 "@
97499065 3014 eor%?\\t%Q0, %Q1, %2
f6ebffac 3015 #"
0d66636f 3016 [(set_attr "length" "4,8")
3017 (set_attr "predicable" "yes")]
cffb2a26 3018)
9c08d1fa 3019
f7fbdd4a 3020(define_insn "*xordi_sesidi_di"
9c08d1fa 3021 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3022 (xor:DI (sign_extend:DI
3023 (match_operand:SI 2 "s_register_operand" "r,r"))
e5fea38e 3024 (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 3025 "TARGET_32BIT"
f6ebffac 3026 "#"
0d66636f 3027 [(set_attr "length" "8")
3028 (set_attr "predicable" "yes")]
cffb2a26 3029)
9c08d1fa 3030
cffb2a26 3031(define_expand "xorsi3"
3032 [(set (match_operand:SI 0 "s_register_operand" "")
3033 (xor:SI (match_operand:SI 1 "s_register_operand" "")
923ffadb 3034 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 3035 "TARGET_EITHER"
923ffadb 3036 "if (GET_CODE (operands[2]) == CONST_INT)
3037 {
3038 if (TARGET_32BIT)
3039 {
3040 arm_split_constant (XOR, SImode, NULL_RTX,
3041 INTVAL (operands[2]), operands[0], operands[1],
3042 optimize && can_create_pseudo_p ());
3043 DONE;
3044 }
3045 else /* TARGET_THUMB1 */
3046 {
3047 rtx tmp = force_reg (SImode, operands[2]);
3048 if (rtx_equal_p (operands[0], operands[1]))
3049 operands[2] = tmp;
3050 else
3051 {
3052 operands[2] = operands[1];
3053 operands[1] = tmp;
3054 }
3055 }
3056 }"
cffb2a26 3057)
3058
3059(define_insn "*arm_xorsi3"
3060 [(set (match_operand:SI 0 "s_register_operand" "=r")
9c08d1fa 3061 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
3062 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
25f905c2 3063 "TARGET_32BIT"
cffb2a26 3064 "eor%?\\t%0, %1, %2"
0d66636f 3065 [(set_attr "predicable" "yes")]
cffb2a26 3066)
3067
747b7458 3068(define_insn "*thumb1_xorsi3_insn"
cffb2a26 3069 [(set (match_operand:SI 0 "register_operand" "=l")
3070 (xor:SI (match_operand:SI 1 "register_operand" "%0")
3071 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3072 "TARGET_THUMB1"
747b7458 3073 "eor\\t%0, %2"
3074 [(set_attr "length" "2")
3075 (set_attr "conds" "set")])
9c08d1fa 3076
f7fbdd4a 3077(define_insn "*xorsi3_compare0"
bd5b4116 3078 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3079 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
3080 (match_operand:SI 2 "arm_rhs_operand" "rI"))
3081 (const_int 0)))
3082 (set (match_operand:SI 0 "s_register_operand" "=r")
3083 (xor:SI (match_dup 1) (match_dup 2)))]
25f905c2 3084 "TARGET_32BIT"
3085 "eor%.\\t%0, %1, %2"
0d66636f 3086 [(set_attr "conds" "set")]
3087)
9c08d1fa 3088
f7fbdd4a 3089(define_insn "*xorsi3_compare0_scratch"
bd5b4116 3090 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3091 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
3092 (match_operand:SI 1 "arm_rhs_operand" "rI"))
3093 (const_int 0)))]
25f905c2 3094 "TARGET_32BIT"
40dbec34 3095 "teq%?\\t%0, %1"
cffb2a26 3096 [(set_attr "conds" "set")]
3097)
9c08d1fa 3098
215b30b3 3099; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3100; (NOT D) we can sometimes merge the final NOT into one of the following
3101; insns.
9c08d1fa 3102
3103(define_split
a058e94a 3104 [(set (match_operand:SI 0 "s_register_operand" "")
3105 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3106 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3107 (match_operand:SI 3 "arm_rhs_operand" "")))
3108 (clobber (match_operand:SI 4 "s_register_operand" ""))]
25f905c2 3109 "TARGET_32BIT"
9c08d1fa 3110 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3111 (not:SI (match_dup 3))))
3112 (set (match_dup 0) (not:SI (match_dup 4)))]
3113 ""
3114)
3115
f7fbdd4a 3116(define_insn "*andsi_iorsi3_notsi"
9c08d1fa 3117 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
e5fea38e 3118 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
9c08d1fa 3119 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3120 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
25f905c2 3121 "TARGET_32BIT"
40dbec34 3122 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
0d66636f 3123 [(set_attr "length" "8")
25f905c2 3124 (set_attr "ce_count" "2")
0d66636f 3125 (set_attr "predicable" "yes")]
cffb2a26 3126)
9c08d1fa 3127
25f905c2 3128; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3129; insns are available?
d7863cfe 3130(define_split
3131 [(set (match_operand:SI 0 "s_register_operand" "")
3132 (match_operator:SI 1 "logical_binary_operator"
3133 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3134 (match_operand:SI 3 "const_int_operand" "")
3135 (match_operand:SI 4 "const_int_operand" ""))
3136 (match_operator:SI 9 "logical_binary_operator"
3137 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3138 (match_operand:SI 6 "const_int_operand" ""))
3139 (match_operand:SI 7 "s_register_operand" "")])]))
3140 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3141 "TARGET_32BIT
d7863cfe 3142 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3143 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3144 [(set (match_dup 8)
3145 (match_op_dup 1
3146 [(ashift:SI (match_dup 2) (match_dup 4))
3147 (match_dup 5)]))
3148 (set (match_dup 0)
3149 (match_op_dup 1
3150 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3151 (match_dup 7)]))]
3152 "
3153 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3154")
3155
3156(define_split
3157 [(set (match_operand:SI 0 "s_register_operand" "")
3158 (match_operator:SI 1 "logical_binary_operator"
3159 [(match_operator:SI 9 "logical_binary_operator"
3160 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3161 (match_operand:SI 6 "const_int_operand" ""))
3162 (match_operand:SI 7 "s_register_operand" "")])
3163 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3164 (match_operand:SI 3 "const_int_operand" "")
3165 (match_operand:SI 4 "const_int_operand" ""))]))
3166 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3167 "TARGET_32BIT
d7863cfe 3168 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3169 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3170 [(set (match_dup 8)
3171 (match_op_dup 1
3172 [(ashift:SI (match_dup 2) (match_dup 4))
3173 (match_dup 5)]))
3174 (set (match_dup 0)
3175 (match_op_dup 1
3176 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3177 (match_dup 7)]))]
3178 "
3179 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3180")
3181
3182(define_split
3183 [(set (match_operand:SI 0 "s_register_operand" "")
3184 (match_operator:SI 1 "logical_binary_operator"
3185 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3186 (match_operand:SI 3 "const_int_operand" "")
3187 (match_operand:SI 4 "const_int_operand" ""))
3188 (match_operator:SI 9 "logical_binary_operator"
3189 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3190 (match_operand:SI 6 "const_int_operand" ""))
3191 (match_operand:SI 7 "s_register_operand" "")])]))
3192 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3193 "TARGET_32BIT
d7863cfe 3194 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3195 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3196 [(set (match_dup 8)
3197 (match_op_dup 1
3198 [(ashift:SI (match_dup 2) (match_dup 4))
3199 (match_dup 5)]))
3200 (set (match_dup 0)
3201 (match_op_dup 1
3202 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3203 (match_dup 7)]))]
3204 "
3205 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3206")
3207
3208(define_split
3209 [(set (match_operand:SI 0 "s_register_operand" "")
3210 (match_operator:SI 1 "logical_binary_operator"
3211 [(match_operator:SI 9 "logical_binary_operator"
3212 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3213 (match_operand:SI 6 "const_int_operand" ""))
3214 (match_operand:SI 7 "s_register_operand" "")])
3215 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3216 (match_operand:SI 3 "const_int_operand" "")
3217 (match_operand:SI 4 "const_int_operand" ""))]))
3218 (clobber (match_operand:SI 8 "s_register_operand" ""))]
25f905c2 3219 "TARGET_32BIT
d7863cfe 3220 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3221 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3222 [(set (match_dup 8)
3223 (match_op_dup 1
3224 [(ashift:SI (match_dup 2) (match_dup 4))
3225 (match_dup 5)]))
3226 (set (match_dup 0)
3227 (match_op_dup 1
3228 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3229 (match_dup 7)]))]
3230 "
3231 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3232")
9c08d1fa 3233\f
3234
3235;; Minimum and maximum insns
3236
8b9dc177 3237(define_expand "smaxsi3"
3238 [(parallel [
3239 (set (match_operand:SI 0 "s_register_operand" "")
3240 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3241 (match_operand:SI 2 "arm_rhs_operand" "")))
3242 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3243 "TARGET_32BIT"
8b9dc177 3244 "
8774928b 3245 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
8b9dc177 3246 {
3247 /* No need for a clobber of the condition code register here. */
3248 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3249 gen_rtx_SMAX (SImode, operands[1],
3250 operands[2])));
3251 DONE;
3252 }
3253")
3254
3255(define_insn "*smax_0"
3256 [(set (match_operand:SI 0 "s_register_operand" "=r")
3257 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3258 (const_int 0)))]
25f905c2 3259 "TARGET_32BIT"
8b9dc177 3260 "bic%?\\t%0, %1, %1, asr #31"
3261 [(set_attr "predicable" "yes")]
3262)
3263
8774928b 3264(define_insn "*smax_m1"
3265 [(set (match_operand:SI 0 "s_register_operand" "=r")
3266 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3267 (const_int -1)))]
25f905c2 3268 "TARGET_32BIT"
8774928b 3269 "orr%?\\t%0, %1, %1, asr #31"
3270 [(set_attr "predicable" "yes")]
3271)
3272
25f905c2 3273(define_insn "*arm_smax_insn"
8b9dc177 3274 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3275 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3276 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3277 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3278 "TARGET_ARM"
e2348bcb 3279 "@
3280 cmp\\t%1, %2\;movlt\\t%0, %2
e2348bcb 3281 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
cffb2a26 3282 [(set_attr "conds" "clob")
8b9dc177 3283 (set_attr "length" "8,12")]
cffb2a26 3284)
9c08d1fa 3285
8b9dc177 3286(define_expand "sminsi3"
3287 [(parallel [
3288 (set (match_operand:SI 0 "s_register_operand" "")
3289 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3290 (match_operand:SI 2 "arm_rhs_operand" "")))
3291 (clobber (reg:CC CC_REGNUM))])]
25f905c2 3292 "TARGET_32BIT"
8b9dc177 3293 "
3294 if (operands[2] == const0_rtx)
3295 {
3296 /* No need for a clobber of the condition code register here. */
3297 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3298 gen_rtx_SMIN (SImode, operands[1],
3299 operands[2])));
3300 DONE;
3301 }
3302")
3303
3304(define_insn "*smin_0"
3305 [(set (match_operand:SI 0 "s_register_operand" "=r")
3306 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3307 (const_int 0)))]
25f905c2 3308 "TARGET_32BIT"
8b9dc177 3309 "and%?\\t%0, %1, %1, asr #31"
3310 [(set_attr "predicable" "yes")]
3311)
3312
25f905c2 3313(define_insn "*arm_smin_insn"
8b9dc177 3314 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3315 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3316 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
bd5b4116 3317 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3318 "TARGET_ARM"
e2348bcb 3319 "@
3320 cmp\\t%1, %2\;movge\\t%0, %2
e2348bcb 3321 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
0d66636f 3322 [(set_attr "conds" "clob")
8b9dc177 3323 (set_attr "length" "8,12")]
0d66636f 3324)
9c08d1fa 3325
25f905c2 3326(define_expand "umaxsi3"
3327 [(parallel [
3328 (set (match_operand:SI 0 "s_register_operand" "")
3329 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3330 (match_operand:SI 2 "arm_rhs_operand" "")))
3331 (clobber (reg:CC CC_REGNUM))])]
3332 "TARGET_32BIT"
3333 ""
3334)
3335
3336(define_insn "*arm_umaxsi3"
9c08d1fa 3337 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3338 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3339 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3340 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3341 "TARGET_ARM"
e2348bcb 3342 "@
3343 cmp\\t%1, %2\;movcc\\t%0, %2
3344 cmp\\t%1, %2\;movcs\\t%0, %1
3345 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
0d66636f 3346 [(set_attr "conds" "clob")
3347 (set_attr "length" "8,8,12")]
3348)
9c08d1fa 3349
25f905c2 3350(define_expand "uminsi3"
3351 [(parallel [
3352 (set (match_operand:SI 0 "s_register_operand" "")
3353 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3354 (match_operand:SI 2 "arm_rhs_operand" "")))
3355 (clobber (reg:CC CC_REGNUM))])]
3356 "TARGET_32BIT"
3357 ""
3358)
3359
3360(define_insn "*arm_uminsi3"
9c08d1fa 3361 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3362 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3363 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 3364 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3365 "TARGET_ARM"
e2348bcb 3366 "@
3367 cmp\\t%1, %2\;movcs\\t%0, %2
3368 cmp\\t%1, %2\;movcc\\t%0, %1
3369 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
0d66636f 3370 [(set_attr "conds" "clob")
3371 (set_attr "length" "8,8,12")]
3372)
9c08d1fa 3373
8a18b90c 3374(define_insn "*store_minmaxsi"
9c08d1fa 3375 [(set (match_operand:SI 0 "memory_operand" "=m")
3376 (match_operator:SI 3 "minmax_operator"
3377 [(match_operand:SI 1 "s_register_operand" "r")
3378 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 3379 (clobber (reg:CC CC_REGNUM))]
25f905c2 3380 "TARGET_32BIT"
9c08d1fa 3381 "*
dc55b8a9 3382 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3383 operands[1], operands[2]);
e2348bcb 3384 output_asm_insn (\"cmp\\t%1, %2\", operands);
25f905c2 3385 if (TARGET_THUMB2)
3386 output_asm_insn (\"ite\t%d3\", operands);
e2348bcb 3387 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3388 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3389 return \"\";
0d66636f 3390 "
3391 [(set_attr "conds" "clob")
25f905c2 3392 (set (attr "length")
3393 (if_then_else (eq_attr "is_thumb" "yes")
3394 (const_int 14)
3395 (const_int 12)))
0d66636f 3396 (set_attr "type" "store1")]
3397)
9c08d1fa 3398
8a18b90c 3399; Reject the frame pointer in operand[1], since reloading this after
3400; it has been eliminated can cause carnage.
f7fbdd4a 3401(define_insn "*minmax_arithsi"
9c08d1fa 3402 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3403 (match_operator:SI 4 "shiftable_operator"
3404 [(match_operator:SI 5 "minmax_operator"
3405 [(match_operand:SI 2 "s_register_operand" "r,r")
3406 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3407 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 3408 (clobber (reg:CC CC_REGNUM))]
25f905c2 3409 "TARGET_32BIT && !arm_eliminable_register (operands[1])"
9c08d1fa 3410 "*
0d66636f 3411 {
3412 enum rtx_code code = GET_CODE (operands[4]);
25f905c2 3413 bool need_else;
3414
3415 if (which_alternative != 0 || operands[3] != const0_rtx
3416 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
3417 need_else = true;
3418 else
3419 need_else = false;
0d66636f 3420
dc55b8a9 3421 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3422 operands[2], operands[3]);
0d66636f 3423 output_asm_insn (\"cmp\\t%2, %3\", operands);
25f905c2 3424 if (TARGET_THUMB2)
3425 {
3426 if (need_else)
3427 output_asm_insn (\"ite\\t%d5\", operands);
3428 else
3429 output_asm_insn (\"it\\t%d5\", operands);
3430 }
0d66636f 3431 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
25f905c2 3432 if (need_else)
0d66636f 3433 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3434 return \"\";
215b30b3 3435 }"
0d66636f 3436 [(set_attr "conds" "clob")
25f905c2 3437 (set (attr "length")
3438 (if_then_else (eq_attr "is_thumb" "yes")
3439 (const_int 14)
3440 (const_int 12)))]
0d66636f 3441)
9c08d1fa 3442
b11cae9e 3443\f
3444;; Shift and rotation insns
3445
a2cd141b 3446(define_expand "ashldi3"
3447 [(set (match_operand:DI 0 "s_register_operand" "")
3448 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
3449 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3450 "TARGET_32BIT"
a2cd141b 3451 "
3452 if (GET_CODE (operands[2]) == CONST_INT)
3453 {
3454 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3455 {
3456 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3457 DONE;
3458 }
3459 /* Ideally we shouldn't fail here if we could know that operands[1]
3460 ends up already living in an iwmmxt register. Otherwise it's
3461 cheaper to have the alternate code being generated than moving
1d60d981 3462 values to iwmmxt regs and back. */
a2cd141b 3463 FAIL;
3464 }
3465 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
3466 FAIL;
3467 "
3468)
3469
3470(define_insn "arm_ashldi3_1bit"
50ad1bf9 3471 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3472 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3473 (const_int 1)))
3474 (clobber (reg:CC CC_REGNUM))]
25f905c2 3475 "TARGET_32BIT"
a2cd141b 3476 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3477 [(set_attr "conds" "clob")
3478 (set_attr "length" "8")]
3479)
3480
87b22bf7 3481(define_expand "ashlsi3"
cffb2a26 3482 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3483 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3484 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3485 "TARGET_EITHER"
87b22bf7 3486 "
3487 if (GET_CODE (operands[2]) == CONST_INT
3488 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3489 {
3490 emit_insn (gen_movsi (operands[0], const0_rtx));
3491 DONE;
3492 }
cffb2a26 3493 "
3494)
3495
25f905c2 3496(define_insn "*thumb1_ashlsi3"
cffb2a26 3497 [(set (match_operand:SI 0 "register_operand" "=l,l")
3498 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3499 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3500 "TARGET_THUMB1"
cffb2a26 3501 "lsl\\t%0, %1, %2"
747b7458 3502 [(set_attr "length" "2")
3503 (set_attr "conds" "set")])
b11cae9e 3504
a2cd141b 3505(define_expand "ashrdi3"
3506 [(set (match_operand:DI 0 "s_register_operand" "")
3507 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3508 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3509 "TARGET_32BIT"
a2cd141b 3510 "
3511 if (GET_CODE (operands[2]) == CONST_INT)
3512 {
3513 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3514 {
3515 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3516 DONE;
3517 }
3518 /* Ideally we shouldn't fail here if we could know that operands[1]
3519 ends up already living in an iwmmxt register. Otherwise it's
3520 cheaper to have the alternate code being generated than moving
1d60d981 3521 values to iwmmxt regs and back. */
a2cd141b 3522 FAIL;
3523 }
3524 else if (!TARGET_REALLY_IWMMXT)
3525 FAIL;
3526 "
3527)
3528
3529(define_insn "arm_ashrdi3_1bit"
50ad1bf9 3530 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3531 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3532 (const_int 1)))
3533 (clobber (reg:CC CC_REGNUM))]
25f905c2 3534 "TARGET_32BIT"
a2cd141b 3535 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3536 [(set_attr "conds" "clob")
d2a518d1 3537 (set_attr "insn" "mov")
a2cd141b 3538 (set_attr "length" "8")]
3539)
3540
87b22bf7 3541(define_expand "ashrsi3"
cffb2a26 3542 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3543 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3544 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3545 "TARGET_EITHER"
87b22bf7 3546 "
3547 if (GET_CODE (operands[2]) == CONST_INT
3548 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3549 operands[2] = GEN_INT (31);
cffb2a26 3550 "
3551)
3552
25f905c2 3553(define_insn "*thumb1_ashrsi3"
cffb2a26 3554 [(set (match_operand:SI 0 "register_operand" "=l,l")
3555 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3556 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3557 "TARGET_THUMB1"
cffb2a26 3558 "asr\\t%0, %1, %2"
747b7458 3559 [(set_attr "length" "2")
3560 (set_attr "conds" "set")])
b11cae9e 3561
a2cd141b 3562(define_expand "lshrdi3"
3563 [(set (match_operand:DI 0 "s_register_operand" "")
3564 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3565 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3566 "TARGET_32BIT"
a2cd141b 3567 "
3568 if (GET_CODE (operands[2]) == CONST_INT)
3569 {
3570 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3571 {
3572 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3573 DONE;
3574 }
3575 /* Ideally we shouldn't fail here if we could know that operands[1]
3576 ends up already living in an iwmmxt register. Otherwise it's
3577 cheaper to have the alternate code being generated than moving
1d60d981 3578 values to iwmmxt regs and back. */
a2cd141b 3579 FAIL;
3580 }
3581 else if (!TARGET_REALLY_IWMMXT)
3582 FAIL;
3583 "
3584)
3585
3586(define_insn "arm_lshrdi3_1bit"
50ad1bf9 3587 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 3588 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
a2cd141b 3589 (const_int 1)))
3590 (clobber (reg:CC CC_REGNUM))]
25f905c2 3591 "TARGET_32BIT"
a2cd141b 3592 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3593 [(set_attr "conds" "clob")
d2a518d1 3594 (set_attr "insn" "mov")
a2cd141b 3595 (set_attr "length" "8")]
3596)
3597
87b22bf7 3598(define_expand "lshrsi3"
cffb2a26 3599 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3600 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3601 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3602 "TARGET_EITHER"
87b22bf7 3603 "
3604 if (GET_CODE (operands[2]) == CONST_INT
3605 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3606 {
3607 emit_insn (gen_movsi (operands[0], const0_rtx));
3608 DONE;
3609 }
cffb2a26 3610 "
3611)
3612
25f905c2 3613(define_insn "*thumb1_lshrsi3"
cffb2a26 3614 [(set (match_operand:SI 0 "register_operand" "=l,l")
3615 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3616 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
25f905c2 3617 "TARGET_THUMB1"
cffb2a26 3618 "lsr\\t%0, %1, %2"
747b7458 3619 [(set_attr "length" "2")
3620 (set_attr "conds" "set")])
b11cae9e 3621
87b22bf7 3622(define_expand "rotlsi3"
cffb2a26 3623 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3624 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3625 (match_operand:SI 2 "reg_or_int_operand" "")))]
25f905c2 3626 "TARGET_32BIT"
87b22bf7 3627 "
3628 if (GET_CODE (operands[2]) == CONST_INT)
3629 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3630 else
b11cae9e 3631 {
87b22bf7 3632 rtx reg = gen_reg_rtx (SImode);
3633 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3634 operands[2] = reg;
b11cae9e 3635 }
cffb2a26 3636 "
3637)
9c08d1fa 3638
87b22bf7 3639(define_expand "rotrsi3"
cffb2a26 3640 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3641 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3642 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 3643 "TARGET_EITHER"
87b22bf7 3644 "
25f905c2 3645 if (TARGET_32BIT)
cffb2a26 3646 {
3647 if (GET_CODE (operands[2]) == CONST_INT
3648 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3649 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3650 }
25f905c2 3651 else /* TARGET_THUMB1 */
cffb2a26 3652 {
3653 if (GET_CODE (operands [2]) == CONST_INT)
3654 operands [2] = force_reg (SImode, operands[2]);
3655 }
3656 "
3657)
87b22bf7 3658
25f905c2 3659(define_insn "*thumb1_rotrsi3"
cffb2a26 3660 [(set (match_operand:SI 0 "register_operand" "=l")
3661 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3662 (match_operand:SI 2 "register_operand" "l")))]
25f905c2 3663 "TARGET_THUMB1"
cffb2a26 3664 "ror\\t%0, %0, %2"
3665 [(set_attr "length" "2")]
3666)
3667
3668(define_insn "*arm_shiftsi3"
3669 [(set (match_operand:SI 0 "s_register_operand" "=r")
3670 (match_operator:SI 3 "shift_operator"
3671 [(match_operand:SI 1 "s_register_operand" "r")
87b22bf7 3672 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
25f905c2 3673 "TARGET_32BIT"
3674 "* return arm_output_shift(operands, 0);"
344495ea 3675 [(set_attr "predicable" "yes")
331beb1a 3676 (set_attr "shift" "1")
a2cd141b 3677 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3678 (const_string "alu_shift")
3679 (const_string "alu_shift_reg")))]
6c4c2133 3680)
87b22bf7 3681
f7fbdd4a 3682(define_insn "*shiftsi3_compare0"
bd5b4116 3683 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3684 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3685 [(match_operand:SI 1 "s_register_operand" "r")
3686 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3687 (const_int 0)))
3688 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 3689 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
25f905c2 3690 "TARGET_32BIT"
3691 "* return arm_output_shift(operands, 1);"
344495ea 3692 [(set_attr "conds" "set")
331beb1a 3693 (set_attr "shift" "1")
a2cd141b 3694 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3695 (const_string "alu_shift")
3696 (const_string "alu_shift_reg")))]
0d66636f 3697)
9c08d1fa 3698
f7fbdd4a 3699(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 3700 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 3701 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3702 [(match_operand:SI 1 "s_register_operand" "r")
3703 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 3704 (const_int 0)))
3705 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 3706 "TARGET_32BIT"
3707 "* return arm_output_shift(operands, 1);"
344495ea 3708 [(set_attr "conds" "set")
a2cd141b 3709 (set_attr "shift" "1")]
0d66636f 3710)
9c08d1fa 3711
d5d4dc8d 3712(define_insn "*not_shiftsi"
3713 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3714 (not:SI (match_operator:SI 3 "shift_operator"
d5d4dc8d 3715 [(match_operand:SI 1 "s_register_operand" "r,r")
3716 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3717 "TARGET_32BIT"
6c4c2133 3718 "mvn%?\\t%0, %1%S3"
344495ea 3719 [(set_attr "predicable" "yes")
331beb1a 3720 (set_attr "shift" "1")
d2a518d1 3721 (set_attr "insn" "mvn")
d5d4dc8d 3722 (set_attr "arch" "32,a")
3723 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3724
d5d4dc8d 3725(define_insn "*not_shiftsi_compare0"
bd5b4116 3726 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3727 (compare:CC_NOOV
3728 (not:SI (match_operator:SI 3 "shift_operator"
3729 [(match_operand:SI 1 "s_register_operand" "r,r")
3730 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3731 (const_int 0)))
3732 (set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 3733 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
d5d4dc8d 3734 "TARGET_32BIT"
25f905c2 3735 "mvn%.\\t%0, %1%S3"
344495ea 3736 [(set_attr "conds" "set")
331beb1a 3737 (set_attr "shift" "1")
d2a518d1 3738 (set_attr "insn" "mvn")
d5d4dc8d 3739 (set_attr "arch" "32,a")
3740 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3741
d5d4dc8d 3742(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 3743 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 3744 (compare:CC_NOOV
3745 (not:SI (match_operator:SI 3 "shift_operator"
3746 [(match_operand:SI 1 "s_register_operand" "r,r")
3747 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3748 (const_int 0)))
3749 (clobber (match_scratch:SI 0 "=r,r"))]
3750 "TARGET_32BIT"
25f905c2 3751 "mvn%.\\t%0, %1%S3"
344495ea 3752 [(set_attr "conds" "set")
331beb1a 3753 (set_attr "shift" "1")
d2a518d1 3754 (set_attr "insn" "mvn")
d5d4dc8d 3755 (set_attr "arch" "32,a")
3756 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 3757
cffb2a26 3758;; We don't really have extzv, but defining this using shifts helps
3759;; to reduce register pressure later on.
3760
3761(define_expand "extzv"
eb04cafb 3762 [(set (match_operand 0 "s_register_operand" "")
3763 (zero_extract (match_operand 1 "nonimmediate_operand" "")
3764 (match_operand 2 "const_int_operand" "")
3765 (match_operand 3 "const_int_operand" "")))]
8b054d5a 3766 "TARGET_THUMB1 || arm_arch_thumb2"
cffb2a26 3767 "
3768 {
3769 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3770 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3771
8b054d5a 3772 if (arm_arch_thumb2)
3773 {
eb04cafb 3774 HOST_WIDE_INT width = INTVAL (operands[2]);
3775 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
3776
3777 if (unaligned_access && MEM_P (operands[1])
3778 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
3779 {
3780 rtx base_addr;
3781
3782 if (BYTES_BIG_ENDIAN)
3783 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
3784 - bitpos;
3785
3786 if (width == 32)
3787 {
3788 base_addr = adjust_address (operands[1], SImode,
3789 bitpos / BITS_PER_UNIT);
3790 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
3791 }
3792 else
3793 {
3794 rtx dest = operands[0];
3795 rtx tmp = gen_reg_rtx (SImode);
3796
3797 /* We may get a paradoxical subreg here. Strip it off. */
3798 if (GET_CODE (dest) == SUBREG
3799 && GET_MODE (dest) == SImode
3800 && GET_MODE (SUBREG_REG (dest)) == HImode)
3801 dest = SUBREG_REG (dest);
3802
3803 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
3804 FAIL;
3805
3806 base_addr = adjust_address (operands[1], HImode,
3807 bitpos / BITS_PER_UNIT);
3808 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
3809 emit_move_insn (gen_lowpart (SImode, dest), tmp);
3810 }
3811 DONE;
3812 }
3813 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
3814 {
3815 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3816 operands[3]));
3817 DONE;
3818 }
3819 else
3820 FAIL;
8b054d5a 3821 }
eb04cafb 3822
3823 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
3824 FAIL;
8b054d5a 3825
cffb2a26 3826 operands[3] = GEN_INT (rshift);
3827
3828 if (lshift == 0)
3829 {
3830 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3831 DONE;
3832 }
3833
eb04cafb 3834 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
3835 operands[3], gen_reg_rtx (SImode)));
3836 DONE;
215b30b3 3837 }"
cffb2a26 3838)
3839
eb04cafb 3840;; Helper for extzv, for the Thumb-1 register-shifts case.
3841
3842(define_expand "extzv_t1"
3843 [(set (match_operand:SI 4 "s_register_operand" "")
3844 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
3845 (match_operand:SI 2 "const_int_operand" "")))
3846 (set (match_operand:SI 0 "s_register_operand" "")
3847 (lshiftrt:SI (match_dup 4)
3848 (match_operand:SI 3 "const_int_operand" "")))]
3849 "TARGET_THUMB1"
3850 "")
3851
3852(define_expand "extv"
3853 [(set (match_operand 0 "s_register_operand" "")
3854 (sign_extract (match_operand 1 "nonimmediate_operand" "")
3855 (match_operand 2 "const_int_operand" "")
3856 (match_operand 3 "const_int_operand" "")))]
3857 "arm_arch_thumb2"
3858{
3859 HOST_WIDE_INT width = INTVAL (operands[2]);
3860 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
3861
3862 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
3863 && (bitpos % BITS_PER_UNIT) == 0)
3864 {
3865 rtx base_addr;
3866
3867 if (BYTES_BIG_ENDIAN)
3868 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
3869
3870 if (width == 32)
3871 {
3872 base_addr = adjust_address (operands[1], SImode,
3873 bitpos / BITS_PER_UNIT);
3874 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
3875 }
3876 else
3877 {
3878 rtx dest = operands[0];
3879 rtx tmp = gen_reg_rtx (SImode);
3880
3881 /* We may get a paradoxical subreg here. Strip it off. */
3882 if (GET_CODE (dest) == SUBREG
3883 && GET_MODE (dest) == SImode
3884 && GET_MODE (SUBREG_REG (dest)) == HImode)
3885 dest = SUBREG_REG (dest);
3886
3887 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
3888 FAIL;
3889
3890 base_addr = adjust_address (operands[1], HImode,
3891 bitpos / BITS_PER_UNIT);
3892 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
3893 emit_move_insn (gen_lowpart (SImode, dest), tmp);
3894 }
3895
3896 DONE;
3897 }
3898 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
3899 FAIL;
3900 else if (GET_MODE (operands[0]) == SImode
3901 && GET_MODE (operands[1]) == SImode)
3902 {
3903 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
3904 operands[3]));
3905 DONE;
3906 }
3907
3908 FAIL;
3909})
3910
3911; Helper to expand register forms of extv with the proper modes.
3912
3913(define_expand "extv_regsi"
3914 [(set (match_operand:SI 0 "s_register_operand" "")
3915 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
3916 (match_operand 2 "const_int_operand" "")
3917 (match_operand 3 "const_int_operand" "")))]
3918 ""
3919{
3920})
3921
3922; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
3923
3924(define_insn "unaligned_loadsi"
3925 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
3926 (unspec:SI [(match_operand:SI 1 "memory_operand" "Uw,m")]
3927 UNSPEC_UNALIGNED_LOAD))]
3928 "unaligned_access && TARGET_32BIT"
3929 "ldr%?\t%0, %1\t@ unaligned"
3930 [(set_attr "arch" "t2,any")
3931 (set_attr "length" "2,4")
3932 (set_attr "predicable" "yes")
3933 (set_attr "type" "load1")])
3934
3935(define_insn "unaligned_loadhis"
3936 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
3937 (sign_extend:SI
3938 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
3939 UNSPEC_UNALIGNED_LOAD)))]
3940 "unaligned_access && TARGET_32BIT"
3941 "ldr%(sh%)\t%0, %1\t@ unaligned"
3942 [(set_attr "arch" "t2,any")
3943 (set_attr "length" "2,4")
3944 (set_attr "predicable" "yes")
3945 (set_attr "type" "load_byte")])
3946
3947(define_insn "unaligned_loadhiu"
3948 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
3949 (zero_extend:SI
3950 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
3951 UNSPEC_UNALIGNED_LOAD)))]
3952 "unaligned_access && TARGET_32BIT"
3953 "ldr%(h%)\t%0, %1\t@ unaligned"
3954 [(set_attr "arch" "t2,any")
3955 (set_attr "length" "2,4")
3956 (set_attr "predicable" "yes")
3957 (set_attr "type" "load_byte")])
3958
3959(define_insn "unaligned_storesi"
3960 [(set (match_operand:SI 0 "memory_operand" "=Uw,m")
3961 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,r")]
3962 UNSPEC_UNALIGNED_STORE))]
3963 "unaligned_access && TARGET_32BIT"
3964 "str%?\t%1, %0\t@ unaligned"
3965 [(set_attr "arch" "t2,any")
3966 (set_attr "length" "2,4")
3967 (set_attr "predicable" "yes")
3968 (set_attr "type" "store1")])
3969
3970(define_insn "unaligned_storehi"
3971 [(set (match_operand:HI 0 "memory_operand" "=Uw,m")
3972 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
3973 UNSPEC_UNALIGNED_STORE))]
3974 "unaligned_access && TARGET_32BIT"
3975 "str%(h%)\t%1, %0\t@ unaligned"
3976 [(set_attr "arch" "t2,any")
3977 (set_attr "length" "2,4")
3978 (set_attr "predicable" "yes")
3979 (set_attr "type" "store1")])
3980
3981(define_insn "*extv_reg"
8b054d5a 3982 [(set (match_operand:SI 0 "s_register_operand" "=r")
3983 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3984 (match_operand:SI 2 "const_int_operand" "M")
3985 (match_operand:SI 3 "const_int_operand" "M")))]
3986 "arm_arch_thumb2"
3987 "sbfx%?\t%0, %1, %3, %2"
3988 [(set_attr "length" "4")
3989 (set_attr "predicable" "yes")]
3990)
3991
3992(define_insn "extzv_t2"
3993 [(set (match_operand:SI 0 "s_register_operand" "=r")
3994 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3995 (match_operand:SI 2 "const_int_operand" "M")
3996 (match_operand:SI 3 "const_int_operand" "M")))]
3997 "arm_arch_thumb2"
3998 "ubfx%?\t%0, %1, %3, %2"
3999 [(set_attr "length" "4")
4000 (set_attr "predicable" "yes")]
4001)
4002
7d3cda8c 4003
4004;; Division instructions
4005(define_insn "divsi3"
4006 [(set (match_operand:SI 0 "s_register_operand" "=r")
4007 (div:SI (match_operand:SI 1 "s_register_operand" "r")
4008 (match_operand:SI 2 "s_register_operand" "r")))]
4009 "TARGET_IDIV"
4010 "sdiv%?\t%0, %1, %2"
4011 [(set_attr "predicable" "yes")
4012 (set_attr "insn" "sdiv")]
4013)
4014
4015(define_insn "udivsi3"
4016 [(set (match_operand:SI 0 "s_register_operand" "=r")
4017 (udiv:SI (match_operand:SI 1 "s_register_operand" "r")
4018 (match_operand:SI 2 "s_register_operand" "r")))]
4019 "TARGET_IDIV"
4020 "udiv%?\t%0, %1, %2"
4021 [(set_attr "predicable" "yes")
4022 (set_attr "insn" "udiv")]
4023)
4024
b11cae9e 4025\f
4026;; Unary arithmetic insns
4027
cffb2a26 4028(define_expand "negdi2"
4029 [(parallel
8135a42b 4030 [(set (match_operand:DI 0 "s_register_operand" "")
4031 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 4032 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 4033 "TARGET_EITHER"
8135a42b 4034 ""
cffb2a26 4035)
4036
4037;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
e5fea38e 4038;; The first alternative allows the common case of a *full* overlap.
cffb2a26 4039(define_insn "*arm_negdi2"
458a8706 4040 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
e5fea38e 4041 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
bd5b4116 4042 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4043 "TARGET_ARM"
97499065 4044 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
cffb2a26 4045 [(set_attr "conds" "clob")
4046 (set_attr "length" "8")]
4047)
b11cae9e 4048
25f905c2 4049(define_insn "*thumb1_negdi2"
8135a42b 4050 [(set (match_operand:DI 0 "register_operand" "=&l")
4051 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 4052 (clobber (reg:CC CC_REGNUM))]
25f905c2 4053 "TARGET_THUMB1"
cffb2a26 4054 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
4055 [(set_attr "length" "6")]
4056)
4057
4058(define_expand "negsi2"
4059 [(set (match_operand:SI 0 "s_register_operand" "")
4060 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
4061 "TARGET_EITHER"
b11cae9e 4062 ""
cffb2a26 4063)
4064
4065(define_insn "*arm_negsi2"
4066 [(set (match_operand:SI 0 "s_register_operand" "=r")
4067 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 4068 "TARGET_32BIT"
cffb2a26 4069 "rsb%?\\t%0, %1, #0"
0d66636f 4070 [(set_attr "predicable" "yes")]
cffb2a26 4071)
4072
25f905c2 4073(define_insn "*thumb1_negsi2"
cffb2a26 4074 [(set (match_operand:SI 0 "register_operand" "=l")
4075 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 4076 "TARGET_THUMB1"
cffb2a26 4077 "neg\\t%0, %1"
4078 [(set_attr "length" "2")]
4079)
b11cae9e 4080
604f3a0a 4081(define_expand "negsf2"
4082 [(set (match_operand:SF 0 "s_register_operand" "")
4083 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 4084 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 4085 ""
4086)
4087
4088(define_expand "negdf2"
4089 [(set (match_operand:DF 0 "s_register_operand" "")
4090 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4091 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
604f3a0a 4092 "")
4093
9c08d1fa 4094;; abssi2 doesn't really clobber the condition codes if a different register
4095;; is being set. To keep things simple, assume during rtl manipulations that
4096;; it does, but tell the final scan operator the truth. Similarly for
4097;; (neg (abs...))
4098
604f3a0a 4099(define_expand "abssi2"
4100 [(parallel
4101 [(set (match_operand:SI 0 "s_register_operand" "")
4102 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ba156559 4103 (clobber (match_dup 2))])]
4104 "TARGET_EITHER"
4105 "
25f905c2 4106 if (TARGET_THUMB1)
ba156559 4107 operands[2] = gen_rtx_SCRATCH (SImode);
4108 else
4109 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4110")
604f3a0a 4111
7d57ec45 4112(define_insn "*arm_abssi2"
ba156559 4113 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 4114 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 4115 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4116 "TARGET_ARM"
e2348bcb 4117 "@
4118 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
40dbec34 4119 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
cffb2a26 4120 [(set_attr "conds" "clob,*")
331beb1a 4121 (set_attr "shift" "1")
0d66636f 4122 ;; predicable can't be set based on the variant, so left as no
cffb2a26 4123 (set_attr "length" "8")]
4124)
9c08d1fa 4125
25f905c2 4126(define_insn_and_split "*thumb1_abssi2"
ba156559 4127 [(set (match_operand:SI 0 "s_register_operand" "=l")
4128 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
4129 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 4130 "TARGET_THUMB1"
ba156559 4131 "#"
25f905c2 4132 "TARGET_THUMB1 && reload_completed"
ba156559 4133 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
4134 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
4135 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
4136 ""
4137 [(set_attr "length" "6")]
4138)
4139
4140(define_insn "*arm_neg_abssi2"
9c08d1fa 4141 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4142 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 4143 (clobber (reg:CC CC_REGNUM))]
cffb2a26 4144 "TARGET_ARM"
e2348bcb 4145 "@
4146 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
40dbec34 4147 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
cffb2a26 4148 [(set_attr "conds" "clob,*")
331beb1a 4149 (set_attr "shift" "1")
0d66636f 4150 ;; predicable can't be set based on the variant, so left as no
cffb2a26 4151 (set_attr "length" "8")]
4152)
b11cae9e 4153
25f905c2 4154(define_insn_and_split "*thumb1_neg_abssi2"
ba156559 4155 [(set (match_operand:SI 0 "s_register_operand" "=l")
4156 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
4157 (clobber (match_scratch:SI 2 "=&l"))]
25f905c2 4158 "TARGET_THUMB1"
ba156559 4159 "#"
25f905c2 4160 "TARGET_THUMB1 && reload_completed"
ba156559 4161 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
4162 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
4163 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
4164 ""
4165 [(set_attr "length" "6")]
4166)
4167
604f3a0a 4168(define_expand "abssf2"
4169 [(set (match_operand:SF 0 "s_register_operand" "")
4170 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 4171 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4172 "")
4173
604f3a0a 4174(define_expand "absdf2"
4175 [(set (match_operand:DF 0 "s_register_operand" "")
4176 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4177 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4178 "")
4179
7db9af5d 4180(define_expand "sqrtsf2"
4181 [(set (match_operand:SF 0 "s_register_operand" "")
4182 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
25f905c2 4183 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 4184 "")
9c08d1fa 4185
7db9af5d 4186(define_expand "sqrtdf2"
4187 [(set (match_operand:DF 0 "s_register_operand" "")
4188 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4189 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
7db9af5d 4190 "")
9c08d1fa 4191
a0f94409 4192(define_insn_and_split "one_cmpldi2"
9c08d1fa 4193 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
e5fea38e 4194 (not:DI (match_operand:DI 1 "s_register_operand" "0,r")))]
25f905c2 4195 "TARGET_32BIT"
f6ebffac 4196 "#"
25f905c2 4197 "TARGET_32BIT && reload_completed"
a0f94409 4198 [(set (match_dup 0) (not:SI (match_dup 1)))
4199 (set (match_dup 2) (not:SI (match_dup 3)))]
4200 "
4201 {
4202 operands[2] = gen_highpart (SImode, operands[0]);
4203 operands[0] = gen_lowpart (SImode, operands[0]);
4204 operands[3] = gen_highpart (SImode, operands[1]);
4205 operands[1] = gen_lowpart (SImode, operands[1]);
4206 }"
0d66636f 4207 [(set_attr "length" "8")
4208 (set_attr "predicable" "yes")]
cffb2a26 4209)
b11cae9e 4210
cffb2a26 4211(define_expand "one_cmplsi2"
4212 [(set (match_operand:SI 0 "s_register_operand" "")
4213 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
4214 "TARGET_EITHER"
b11cae9e 4215 ""
cffb2a26 4216)
4217
4218(define_insn "*arm_one_cmplsi2"
4219 [(set (match_operand:SI 0 "s_register_operand" "=r")
4220 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 4221 "TARGET_32BIT"
cffb2a26 4222 "mvn%?\\t%0, %1"
d2a518d1 4223 [(set_attr "predicable" "yes")
4224 (set_attr "insn" "mvn")]
cffb2a26 4225)
4226
25f905c2 4227(define_insn "*thumb1_one_cmplsi2"
cffb2a26 4228 [(set (match_operand:SI 0 "register_operand" "=l")
4229 (not:SI (match_operand:SI 1 "register_operand" "l")))]
25f905c2 4230 "TARGET_THUMB1"
cffb2a26 4231 "mvn\\t%0, %1"
d2a518d1 4232 [(set_attr "length" "2")
4233 (set_attr "insn" "mvn")]
cffb2a26 4234)
9c08d1fa 4235
f7fbdd4a 4236(define_insn "*notsi_compare0"
bd5b4116 4237 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4238 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4239 (const_int 0)))
4240 (set (match_operand:SI 0 "s_register_operand" "=r")
4241 (not:SI (match_dup 1)))]
25f905c2 4242 "TARGET_32BIT"
4243 "mvn%.\\t%0, %1"
d2a518d1 4244 [(set_attr "conds" "set")
4245 (set_attr "insn" "mvn")]
cffb2a26 4246)
9c08d1fa 4247
f7fbdd4a 4248(define_insn "*notsi_compare0_scratch"
bd5b4116 4249 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 4250 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4251 (const_int 0)))
4252 (clobber (match_scratch:SI 0 "=r"))]
25f905c2 4253 "TARGET_32BIT"
4254 "mvn%.\\t%0, %1"
d2a518d1 4255 [(set_attr "conds" "set")
4256 (set_attr "insn" "mvn")]
cffb2a26 4257)
b11cae9e 4258\f
4259;; Fixed <--> Floating conversion insns
4260
9b8516be 4261(define_expand "floatsihf2"
4262 [(set (match_operand:HF 0 "general_operand" "")
4263 (float:HF (match_operand:SI 1 "general_operand" "")))]
4264 "TARGET_EITHER"
4265 "
4266 {
4267 rtx op1 = gen_reg_rtx (SFmode);
4268 expand_float (op1, operands[1], 0);
4269 op1 = convert_to_mode (HFmode, op1, 0);
4270 emit_move_insn (operands[0], op1);
4271 DONE;
4272 }"
4273)
4274
4275(define_expand "floatdihf2"
4276 [(set (match_operand:HF 0 "general_operand" "")
4277 (float:HF (match_operand:DI 1 "general_operand" "")))]
4278 "TARGET_EITHER"
4279 "
4280 {
4281 rtx op1 = gen_reg_rtx (SFmode);
4282 expand_float (op1, operands[1], 0);
4283 op1 = convert_to_mode (HFmode, op1, 0);
4284 emit_move_insn (operands[0], op1);
4285 DONE;
4286 }"
4287)
4288
604f3a0a 4289(define_expand "floatsisf2"
4290 [(set (match_operand:SF 0 "s_register_operand" "")
4291 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
25f905c2 4292 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4293 "
a2cd141b 4294 if (TARGET_MAVERICK)
604f3a0a 4295 {
4296 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
4297 DONE;
4298 }
4299")
4300
604f3a0a 4301(define_expand "floatsidf2"
4302 [(set (match_operand:DF 0 "s_register_operand" "")
4303 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a50d7267 4304 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4305 "
a2cd141b 4306 if (TARGET_MAVERICK)
604f3a0a 4307 {
4308 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
4309 DONE;
4310 }
4311")
4312
9b8516be 4313(define_expand "fix_trunchfsi2"
4314 [(set (match_operand:SI 0 "general_operand" "")
4315 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4316 "TARGET_EITHER"
4317 "
4318 {
4319 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4320 expand_fix (operands[0], op1, 0);
4321 DONE;
4322 }"
4323)
4324
4325(define_expand "fix_trunchfdi2"
4326 [(set (match_operand:DI 0 "general_operand" "")
4327 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4328 "TARGET_EITHER"
4329 "
4330 {
4331 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4332 expand_fix (operands[0], op1, 0);
4333 DONE;
4334 }"
4335)
4336
604f3a0a 4337(define_expand "fix_truncsfsi2"
4338 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4339 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
25f905c2 4340 "TARGET_32BIT && TARGET_HARD_FLOAT"
604f3a0a 4341 "
a2cd141b 4342 if (TARGET_MAVERICK)
604f3a0a 4343 {
4344 if (!cirrus_fp_register (operands[0], SImode))
4345 operands[0] = force_reg (SImode, operands[0]);
4346 if (!cirrus_fp_register (operands[1], SFmode))
4347 operands[1] = force_reg (SFmode, operands[0]);
4348 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
4349 DONE;
4350 }
4351")
4352
604f3a0a 4353(define_expand "fix_truncdfsi2"
4354 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 4355 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a50d7267 4356 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4357 "
a2cd141b 4358 if (TARGET_MAVERICK)
604f3a0a 4359 {
4360 if (!cirrus_fp_register (operands[1], DFmode))
4361 operands[1] = force_reg (DFmode, operands[0]);
4362 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
4363 DONE;
4364 }
4365")
4366
f544c6d2 4367;; Truncation insns
b11cae9e 4368
604f3a0a 4369(define_expand "truncdfsf2"
4370 [(set (match_operand:SF 0 "s_register_operand" "")
4371 (float_truncate:SF
4372 (match_operand:DF 1 "s_register_operand" "")))]
a50d7267 4373 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
604f3a0a 4374 ""
4375)
9b8516be 4376
4377/* DFmode -> HFmode conversions have to go through SFmode. */
4378(define_expand "truncdfhf2"
4379 [(set (match_operand:HF 0 "general_operand" "")
4380 (float_truncate:HF
4381 (match_operand:DF 1 "general_operand" "")))]
4382 "TARGET_EITHER"
4383 "
4384 {
4385 rtx op1;
4386 op1 = convert_to_mode (SFmode, operands[1], 0);
4387 op1 = convert_to_mode (HFmode, op1, 0);
4388 emit_move_insn (operands[0], op1);
4389 DONE;
4390 }"
4391)
b11cae9e 4392\f
9c08d1fa 4393;; Zero and sign extension instructions.
b11cae9e 4394
848e66ac 4395(define_insn "zero_extend<mode>di2"
4396 [(set (match_operand:DI 0 "s_register_operand" "=r")
6d97728e 4397 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
4398 "<qhs_zextenddi_cstr>")))]
848e66ac 4399 "TARGET_32BIT <qhs_zextenddi_cond>"
4400 "#"
4401 [(set_attr "length" "8")
4402 (set_attr "ce_count" "2")
4403 (set_attr "predicable" "yes")]
25f905c2 4404)
4405
848e66ac 4406(define_insn "extend<mode>di2"
9c08d1fa 4407 [(set (match_operand:DI 0 "s_register_operand" "=r")
63d204a8 4408 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4409 "<qhs_extenddi_cstr>")))]
848e66ac 4410 "TARGET_32BIT <qhs_sextenddi_cond>"
4411 "#"
0d66636f 4412 [(set_attr "length" "8")
848e66ac 4413 (set_attr "ce_count" "2")
4414 (set_attr "shift" "1")
0d66636f 4415 (set_attr "predicable" "yes")]
4416)
9c08d1fa 4417
848e66ac 4418;; Splits for all extensions to DImode
4419(define_split
4420 [(set (match_operand:DI 0 "s_register_operand" "")
4421 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
25f905c2 4422 "TARGET_32BIT"
848e66ac 4423 [(set (match_dup 0) (match_dup 1))]
4424{
848e66ac 4425 rtx lo_part = gen_lowpart (SImode, operands[0]);
4426 enum machine_mode src_mode = GET_MODE (operands[1]);
4427
4428 if (REG_P (operands[0])
4429 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4430 emit_clobber (operands[0]);
4431 if (!REG_P (lo_part) || src_mode != SImode
4432 || !rtx_equal_p (lo_part, operands[1]))
4433 {
4434 if (src_mode == SImode)
4435 emit_move_insn (lo_part, operands[1]);
4436 else
4437 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4438 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4439 operands[1] = lo_part;
4440 }
4441 operands[0] = gen_highpart (SImode, operands[0]);
4442 operands[1] = const0_rtx;
4443})
9c08d1fa 4444
848e66ac 4445(define_split
25f905c2 4446 [(set (match_operand:DI 0 "s_register_operand" "")
848e66ac 4447 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
25f905c2 4448 "TARGET_32BIT"
848e66ac 4449 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4450{
4451 rtx lo_part = gen_lowpart (SImode, operands[0]);
4452 enum machine_mode src_mode = GET_MODE (operands[1]);
25f905c2 4453
848e66ac 4454 if (REG_P (operands[0])
4455 && !reg_overlap_mentioned_p (operands[0], operands[1]))
4456 emit_clobber (operands[0]);
4457
4458 if (!REG_P (lo_part) || src_mode != SImode
4459 || !rtx_equal_p (lo_part, operands[1]))
4460 {
4461 if (src_mode == SImode)
4462 emit_move_insn (lo_part, operands[1]);
4463 else
4464 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4465 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4466 operands[1] = lo_part;
4467 }
4468 operands[0] = gen_highpart (SImode, operands[0]);
4469})
9c08d1fa 4470
4471(define_expand "zero_extendhisi2"
ef51b8e1 4472 [(set (match_operand:SI 0 "s_register_operand" "")
4473 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4474 "TARGET_EITHER"
ef51b8e1 4475{
4476 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
f7fbdd4a 4477 {
ef51b8e1 4478 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4479 DONE;
25f7a26e 4480 }
ef51b8e1 4481 if (!arm_arch6 && !MEM_P (operands[1]))
4482 {
4483 rtx t = gen_lowpart (SImode, operands[1]);
4484 rtx tmp = gen_reg_rtx (SImode);
4485 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4486 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4487 DONE;
4488 }
4489})
9c08d1fa 4490
ef51b8e1 4491(define_split
b146458f 4492 [(set (match_operand:SI 0 "s_register_operand" "")
4493 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
ef51b8e1 4494 "!TARGET_THUMB2 && !arm_arch6"
4495 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4496 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4497{
4498 operands[2] = gen_lowpart (SImode, operands[1]);
4499})
4500
4501(define_insn "*thumb1_zero_extendhisi2"
a2cd141b 4502 [(set (match_operand:SI 0 "register_operand" "=l,l")
4503 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
ef51b8e1 4504 "TARGET_THUMB1"
848e66ac 4505{
a2cd141b 4506 rtx mem;
4507
ef51b8e1 4508 if (which_alternative == 0 && arm_arch6)
848e66ac 4509 return "uxth\t%0, %1";
ef51b8e1 4510 if (which_alternative == 0)
848e66ac 4511 return "#";
a2cd141b 4512
4513 mem = XEXP (operands[1], 0);
4514
4515 if (GET_CODE (mem) == CONST)
4516 mem = XEXP (mem, 0);
4517
a2cd141b 4518 if (GET_CODE (mem) == PLUS)
4519 {
4520 rtx a = XEXP (mem, 0);
a2cd141b 4521
4522 /* This can happen due to bugs in reload. */
4523 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4524 {
4525 rtx ops[2];
4526 ops[0] = operands[0];
4527 ops[1] = a;
4528
848e66ac 4529 output_asm_insn ("mov\t%0, %1", ops);
a2cd141b 4530
4531 XEXP (mem, 0) = operands[0];
4532 }
a2cd141b 4533 }
4534
848e66ac 4535 return "ldrh\t%0, %1";
4536}
ef51b8e1 4537 [(set_attr_alternative "length"
4538 [(if_then_else (eq_attr "is_arch6" "yes")
4539 (const_int 2) (const_int 4))
4540 (const_int 4)])
848e66ac 4541 (set_attr "type" "alu_shift,load_byte")]
a2cd141b 4542)
4543
cffb2a26 4544(define_insn "*arm_zero_extendhisi2"
ef51b8e1 4545 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4546 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4547 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4548 "@
4549 #
4550 ldr%(h%)\\t%0, %1"
4551 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4552 (set_attr "predicable" "yes")]
cffb2a26 4553)
f7fbdd4a 4554
a2cd141b 4555(define_insn "*arm_zero_extendhisi2_v6"
4556 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4557 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4558 "TARGET_ARM && arm_arch6"
4559 "@
4560 uxth%?\\t%0, %1
25f905c2 4561 ldr%(h%)\\t%0, %1"
a2cd141b 4562 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4563 (set_attr "predicable" "yes")]
a2cd141b 4564)
4565
4566(define_insn "*arm_zero_extendhisi2addsi"
4567 [(set (match_operand:SI 0 "s_register_operand" "=r")
4568 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4569 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4570 "TARGET_INT_SIMD"
a2cd141b 4571 "uxtah%?\\t%0, %2, %1"
4572 [(set_attr "type" "alu_shift")
4573 (set_attr "predicable" "yes")]
4574)
4575
87b22bf7 4576(define_expand "zero_extendqisi2"
cffb2a26 4577 [(set (match_operand:SI 0 "s_register_operand" "")
4578 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4579 "TARGET_EITHER"
ef51b8e1 4580{
4581 if (TARGET_ARM && !arm_arch6 && GET_CODE (operands[1]) != MEM)
87b22bf7 4582 {
ef51b8e1 4583 emit_insn (gen_andsi3 (operands[0],
4584 gen_lowpart (SImode, operands[1]),
4585 GEN_INT (255)));
4586 DONE;
4587 }
4588 if (!arm_arch6 && !MEM_P (operands[1]))
4589 {
4590 rtx t = gen_lowpart (SImode, operands[1]);
4591 rtx tmp = gen_reg_rtx (SImode);
4592 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4593 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
4594 DONE;
4595 }
4596})
cffb2a26 4597
ef51b8e1 4598(define_split
b146458f 4599 [(set (match_operand:SI 0 "s_register_operand" "")
4600 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
ef51b8e1 4601 "!arm_arch6"
4602 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4603 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
4604{
4605 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4606 if (TARGET_ARM)
4607 {
4608 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
87b22bf7 4609 DONE;
4610 }
ef51b8e1 4611})
9c08d1fa 4612
25f905c2 4613(define_insn "*thumb1_zero_extendqisi2"
ef51b8e1 4614 [(set (match_operand:SI 0 "register_operand" "=l,l")
4615 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4616 "TARGET_THUMB1 && !arm_arch6"
ef51b8e1 4617 "@
4618 #
4619 ldrb\\t%0, %1"
4620 [(set_attr "length" "4,2")
4621 (set_attr "type" "alu_shift,load_byte")
4622 (set_attr "pool_range" "*,32")]
cffb2a26 4623)
4624
25f905c2 4625(define_insn "*thumb1_zero_extendqisi2_v6"
a2cd141b 4626 [(set (match_operand:SI 0 "register_operand" "=l,l")
4627 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
25f905c2 4628 "TARGET_THUMB1 && arm_arch6"
a2cd141b 4629 "@
4630 uxtb\\t%0, %1
4631 ldrb\\t%0, %1"
848e66ac 4632 [(set_attr "length" "2")
4633 (set_attr "type" "alu_shift,load_byte")]
a2cd141b 4634)
4635
cffb2a26 4636(define_insn "*arm_zero_extendqisi2"
ef51b8e1 4637 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4638 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4639 "TARGET_ARM && !arm_arch6"
ef51b8e1 4640 "@
4641 #
4642 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4643 [(set_attr "length" "8,4")
4644 (set_attr "type" "alu_shift,load_byte")
848e66ac 4645 (set_attr "predicable" "yes")]
cffb2a26 4646)
87b22bf7 4647
a2cd141b 4648(define_insn "*arm_zero_extendqisi2_v6"
4649 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4650 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4651 "TARGET_ARM && arm_arch6"
4652 "@
25f905c2 4653 uxtb%(%)\\t%0, %1
4654 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 4655 [(set_attr "type" "alu_shift,load_byte")
848e66ac 4656 (set_attr "predicable" "yes")]
a2cd141b 4657)
4658
4659(define_insn "*arm_zero_extendqisi2addsi"
4660 [(set (match_operand:SI 0 "s_register_operand" "=r")
4661 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4662 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4663 "TARGET_INT_SIMD"
a2cd141b 4664 "uxtab%?\\t%0, %2, %1"
4665 [(set_attr "predicable" "yes")
bcaec148 4666 (set_attr "insn" "xtab")
a2cd141b 4667 (set_attr "type" "alu_shift")]
4668)
4669
87b22bf7 4670(define_split
4671 [(set (match_operand:SI 0 "s_register_operand" "")
4672 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4673 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4674 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
87b22bf7 4675 [(set (match_dup 2) (match_dup 1))
4676 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 4677 ""
4678)
9c08d1fa 4679
8a4d25d6 4680(define_split
4681 [(set (match_operand:SI 0 "s_register_operand" "")
4682 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4683 (clobber (match_operand:SI 2 "s_register_operand" ""))]
25f905c2 4684 "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
8a4d25d6 4685 [(set (match_dup 2) (match_dup 1))
4686 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4687 ""
4688)
4689
1c274529 4690
4691(define_split
4692 [(set (match_operand:SI 0 "s_register_operand" "")
4693 (ior_xor:SI (and:SI (ashift:SI
4694 (match_operand:SI 1 "s_register_operand" "")
4695 (match_operand:SI 2 "const_int_operand" ""))
4696 (match_operand:SI 3 "const_int_operand" ""))
4697 (zero_extend:SI
4698 (match_operator 5 "subreg_lowpart_operator"
4699 [(match_operand:SI 4 "s_register_operand" "")]))))]
4700 "TARGET_32BIT
63787642 4701 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
1c274529 4702 == (GET_MODE_MASK (GET_MODE (operands[5]))
4703 & (GET_MODE_MASK (GET_MODE (operands[5]))
4704 << (INTVAL (operands[2])))))"
4705 [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
4706 (match_dup 4)))
4707 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4708 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4709)
4710
f7fbdd4a 4711(define_insn "*compareqi_eq0"
bd5b4116 4712 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 4713 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 4714 (const_int 0)))]
25f905c2 4715 "TARGET_32BIT"
87b22bf7 4716 "tst\\t%0, #255"
cffb2a26 4717 [(set_attr "conds" "set")]
4718)
b11cae9e 4719
b11cae9e 4720(define_expand "extendhisi2"
ef51b8e1 4721 [(set (match_operand:SI 0 "s_register_operand" "")
4722 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
cffb2a26 4723 "TARGET_EITHER"
ef51b8e1 4724{
4725 if (TARGET_THUMB1)
4726 {
4727 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4728 DONE;
4729 }
4730 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
4731 {
4732 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4733 DONE;
4734 }
ed29c566 4735
ef51b8e1 4736 if (!arm_arch6 && !MEM_P (operands[1]))
4737 {
4738 rtx t = gen_lowpart (SImode, operands[1]);
4739 rtx tmp = gen_reg_rtx (SImode);
4740 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4741 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
4742 DONE;
4743 }
4744})
cffb2a26 4745
ef51b8e1 4746(define_split
4747 [(parallel
4748 [(set (match_operand:SI 0 "register_operand" "")
4749 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
4750 (clobber (match_scratch:SI 2 ""))])]
4751 "!arm_arch6"
4752 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4753 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4754{
4755 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4756})
25f7a26e 4757
a2cd141b 4758;; We used to have an early-clobber on the scratch register here.
4759;; However, there's a bug somewhere in reload which means that this
4760;; can be partially ignored during spill allocation if the memory
ed29c566 4761;; address also needs reloading; this causes us to die later on when
a2cd141b 4762;; we try to verify the operands. Fortunately, we don't really need
4763;; the early-clobber: we can always use operand 0 if operand 2
4764;; overlaps the address.
ef51b8e1 4765(define_insn "thumb1_extendhisi2"
a2cd141b 4766 [(set (match_operand:SI 0 "register_operand" "=l,l")
4767 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4768 (clobber (match_scratch:SI 2 "=X,l"))]
ef51b8e1 4769 "TARGET_THUMB1"
a2cd141b 4770 "*
4771 {
4772 rtx ops[4];
4773 rtx mem;
4774
ef51b8e1 4775 if (which_alternative == 0 && !arm_arch6)
4776 return \"#\";
a2cd141b 4777 if (which_alternative == 0)
4778 return \"sxth\\t%0, %1\";
4779
4780 mem = XEXP (operands[1], 0);
4781
4782 /* This code used to try to use 'V', and fix the address only if it was
4783 offsettable, but this fails for e.g. REG+48 because 48 is outside the
4784 range of QImode offsets, and offsettable_address_p does a QImode
4785 address check. */
4786
4787 if (GET_CODE (mem) == CONST)
4788 mem = XEXP (mem, 0);
4789
4790 if (GET_CODE (mem) == LABEL_REF)
4791 return \"ldr\\t%0, %1\";
4792
4793 if (GET_CODE (mem) == PLUS)
4794 {
4795 rtx a = XEXP (mem, 0);
4796 rtx b = XEXP (mem, 1);
4797
4798 if (GET_CODE (a) == LABEL_REF
4799 && GET_CODE (b) == CONST_INT)
4800 return \"ldr\\t%0, %1\";
4801
4802 if (GET_CODE (b) == REG)
4803 return \"ldrsh\\t%0, %1\";
4804
4805 ops[1] = a;
4806 ops[2] = b;
4807 }
4808 else
4809 {
4810 ops[1] = mem;
4811 ops[2] = const0_rtx;
4812 }
4813
ed29c566 4814 gcc_assert (GET_CODE (ops[1]) == REG);
a2cd141b 4815
4816 ops[0] = operands[0];
4817 if (reg_mentioned_p (operands[2], ops[1]))
4818 ops[3] = ops[0];
4819 else
4820 ops[3] = operands[2];
4821 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4822 return \"\";
4823 }"
ef51b8e1 4824 [(set_attr_alternative "length"
4825 [(if_then_else (eq_attr "is_arch6" "yes")
4826 (const_int 2) (const_int 4))
4827 (const_int 4)])
a2cd141b 4828 (set_attr "type" "alu_shift,load_byte")
4829 (set_attr "pool_range" "*,1020")]
4830)
4831
25f905c2 4832;; This pattern will only be used when ldsh is not available
25f7a26e 4833(define_expand "extendhisi2_mem"
eab14235 4834 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4835 (set (match_dup 3)
eab14235 4836 (zero_extend:SI (match_dup 7)))
25f7a26e 4837 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4838 (set (match_operand:SI 0 "" "")
4839 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 4840 "TARGET_ARM"
25f7a26e 4841 "
215b30b3 4842 {
4843 rtx mem1, mem2;
4844 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4845
788fcce0 4846 mem1 = change_address (operands[1], QImode, addr);
4847 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 4848 operands[0] = gen_lowpart (SImode, operands[0]);
4849 operands[1] = mem1;
4850 operands[2] = gen_reg_rtx (SImode);
4851 operands[3] = gen_reg_rtx (SImode);
4852 operands[6] = gen_reg_rtx (SImode);
4853 operands[7] = mem2;
25f7a26e 4854
215b30b3 4855 if (BYTES_BIG_ENDIAN)
4856 {
4857 operands[4] = operands[2];
4858 operands[5] = operands[3];
4859 }
4860 else
4861 {
4862 operands[4] = operands[3];
4863 operands[5] = operands[2];
4864 }
4865 }"
4866)
b11cae9e 4867
ef51b8e1 4868(define_split
4869 [(set (match_operand:SI 0 "register_operand" "")
4870 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
4871 "!arm_arch6"
4872 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4873 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4874{
4875 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4876})
4877
a2cd141b 4878(define_insn "*arm_extendhisi2"
ef51b8e1 4879 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4880 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
a2cd141b 4881 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4882 "@
4883 #
4884 ldr%(sh%)\\t%0, %1"
4885 [(set_attr "length" "8,4")
4886 (set_attr "type" "alu_shift,load_byte")
0d66636f 4887 (set_attr "predicable" "yes")
ef51b8e1 4888 (set_attr "pool_range" "*,256")
4889 (set_attr "neg_pool_range" "*,244")]
cffb2a26 4890)
f7fbdd4a 4891
25f905c2 4892;; ??? Check Thumb-2 pool range
a2cd141b 4893(define_insn "*arm_extendhisi2_v6"
4894 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4895 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
25f905c2 4896 "TARGET_32BIT && arm_arch6"
a2cd141b 4897 "@
4898 sxth%?\\t%0, %1
25f905c2 4899 ldr%(sh%)\\t%0, %1"
a2cd141b 4900 [(set_attr "type" "alu_shift,load_byte")
4901 (set_attr "predicable" "yes")
4902 (set_attr "pool_range" "*,256")
4903 (set_attr "neg_pool_range" "*,244")]
4904)
4905
4906(define_insn "*arm_extendhisi2addsi"
4907 [(set (match_operand:SI 0 "s_register_operand" "=r")
4908 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4909 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 4910 "TARGET_INT_SIMD"
a2cd141b 4911 "sxtah%?\\t%0, %2, %1"
4912)
4913
c8f69309 4914(define_expand "extendqihi2"
4915 [(set (match_dup 2)
bed7d9a5 4916 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
c8f69309 4917 (const_int 24)))
9c08d1fa 4918 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 4919 (ashiftrt:SI (match_dup 2)
4920 (const_int 24)))]
cffb2a26 4921 "TARGET_ARM"
c8f69309 4922 "
215b30b3 4923 {
4924 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4925 {
4926 emit_insn (gen_rtx_SET (VOIDmode,
4927 operands[0],
4928 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4929 DONE;
4930 }
4931 if (!s_register_operand (operands[1], QImode))
4932 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4933 operands[0] = gen_lowpart (SImode, operands[0]);
4934 operands[1] = gen_lowpart (SImode, operands[1]);
4935 operands[2] = gen_reg_rtx (SImode);
4936 }"
4937)
f7fbdd4a 4938
25f905c2 4939(define_insn "*arm_extendqihi_insn"
b4e8a300 4940 [(set (match_operand:HI 0 "s_register_operand" "=r")
bed7d9a5 4941 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
cffb2a26 4942 "TARGET_ARM && arm_arch4"
25f905c2 4943 "ldr%(sb%)\\t%0, %1"
a2cd141b 4944 [(set_attr "type" "load_byte")
0d66636f 4945 (set_attr "predicable" "yes")
cffb2a26 4946 (set_attr "pool_range" "256")
4947 (set_attr "neg_pool_range" "244")]
4948)
3fc2009e 4949
b11cae9e 4950(define_expand "extendqisi2"
ef51b8e1 4951 [(set (match_operand:SI 0 "s_register_operand" "")
4952 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
cffb2a26 4953 "TARGET_EITHER"
ef51b8e1 4954{
4955 if (!arm_arch4 && MEM_P (operands[1]))
4956 operands[1] = copy_to_mode_reg (QImode, operands[1]);
a2cd141b 4957
ef51b8e1 4958 if (!arm_arch6 && !MEM_P (operands[1]))
4959 {
4960 rtx t = gen_lowpart (SImode, operands[1]);
4961 rtx tmp = gen_reg_rtx (SImode);
4962 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4963 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
4964 DONE;
4965 }
4966})
a2cd141b 4967
ef51b8e1 4968(define_split
4969 [(set (match_operand:SI 0 "register_operand" "")
4970 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
4971 "!arm_arch6"
4972 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4973 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
4974{
4975 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4976})
f7fbdd4a 4977
a2cd141b 4978(define_insn "*arm_extendqisi"
ef51b8e1 4979 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4980 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4981 "TARGET_ARM && arm_arch4 && !arm_arch6"
ef51b8e1 4982 "@
4983 #
4984 ldr%(sb%)\\t%0, %1"
4985 [(set_attr "length" "8,4")
4986 (set_attr "type" "alu_shift,load_byte")
0d66636f 4987 (set_attr "predicable" "yes")
ef51b8e1 4988 (set_attr "pool_range" "*,256")
4989 (set_attr "neg_pool_range" "*,244")]
cffb2a26 4990)
3fc2009e 4991
a2cd141b 4992(define_insn "*arm_extendqisi_v6"
4993 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
bed7d9a5 4994 (sign_extend:SI
4995 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
a2cd141b 4996 "TARGET_ARM && arm_arch6"
b4e8a300 4997 "@
4998 sxtb%?\\t%0, %1
25f905c2 4999 ldr%(sb%)\\t%0, %1"
a2cd141b 5000 [(set_attr "type" "alu_shift,load_byte")
5001 (set_attr "predicable" "yes")
a2cd141b 5002 (set_attr "pool_range" "*,256")
5003 (set_attr "neg_pool_range" "*,244")]
5004)
5005
5006(define_insn "*arm_extendqisi2addsi"
5007 [(set (match_operand:SI 0 "s_register_operand" "=r")
5008 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5009 (match_operand:SI 2 "s_register_operand" "r")))]
25f905c2 5010 "TARGET_INT_SIMD"
a2cd141b 5011 "sxtab%?\\t%0, %2, %1"
5012 [(set_attr "type" "alu_shift")
bcaec148 5013 (set_attr "insn" "xtab")
a2cd141b 5014 (set_attr "predicable" "yes")]
5015)
5016
ef51b8e1 5017(define_split
5018 [(set (match_operand:SI 0 "register_operand" "")
5019 (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))]
5020 "TARGET_THUMB1 && reload_completed"
5021 [(set (match_dup 0) (match_dup 2))
5022 (set (match_dup 0) (sign_extend:SI (match_dup 3)))]
5023{
5024 rtx addr = XEXP (operands[1], 0);
cffb2a26 5025
ef51b8e1 5026 if (GET_CODE (addr) == CONST)
5027 addr = XEXP (addr, 0);
cffb2a26 5028
ef51b8e1 5029 if (GET_CODE (addr) == PLUS
5030 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
5031 /* No split necessary. */
5032 FAIL;
5033
5034 if (GET_CODE (addr) == PLUS
5035 && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1)))
5036 FAIL;
5037
5038 if (reg_overlap_mentioned_p (operands[0], addr))
5039 {
5040 rtx t = gen_lowpart (QImode, operands[0]);
5041 emit_move_insn (t, operands[1]);
5042 emit_insn (gen_thumb1_extendqisi2 (operands[0], t));
5043 DONE;
5044 }
5045
5046 if (REG_P (addr))
5047 {
5048 addr = gen_rtx_PLUS (Pmode, addr, operands[0]);
5049 operands[2] = const0_rtx;
5050 }
5051 else if (GET_CODE (addr) != PLUS)
5052 FAIL;
5053 else if (REG_P (XEXP (addr, 0)))
5054 {
5055 operands[2] = XEXP (addr, 1);
5056 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]);
5057 }
5058 else
5059 {
5060 operands[2] = XEXP (addr, 0);
5061 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]);
5062 }
cffb2a26 5063
ef51b8e1 5064 operands[3] = change_address (operands[1], QImode, addr);
5065})
5066
8a3b73a1 5067(define_peephole2
5068 [(set (match_operand:SI 0 "register_operand" "")
5069 (plus:SI (match_dup 0) (match_operand 1 "const_int_operand")))
5070 (set (match_operand:SI 2 "register_operand" "") (const_int 0))
5071 (set (match_operand:SI 3 "register_operand" "")
5072 (sign_extend:SI (match_operand:QI 4 "memory_operand" "")))]
5073 "TARGET_THUMB1
5074 && GET_CODE (XEXP (operands[4], 0)) == PLUS
5075 && rtx_equal_p (operands[0], XEXP (XEXP (operands[4], 0), 0))
5076 && rtx_equal_p (operands[2], XEXP (XEXP (operands[4], 0), 1))
5077 && (peep2_reg_dead_p (3, operands[0])
5078 || rtx_equal_p (operands[0], operands[3]))
5079 && (peep2_reg_dead_p (3, operands[2])
5080 || rtx_equal_p (operands[2], operands[3]))"
5081 [(set (match_dup 2) (match_dup 1))
5082 (set (match_dup 3) (sign_extend:SI (match_dup 4)))]
5083{
5084 rtx addr = gen_rtx_PLUS (Pmode, operands[0], operands[2]);
5085 operands[4] = change_address (operands[4], QImode, addr);
5086})
5087
ef51b8e1 5088(define_insn "thumb1_extendqisi2"
a2cd141b 5089 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
5090 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
ef51b8e1 5091 "TARGET_THUMB1"
5092{
5093 rtx addr;
a2cd141b 5094
ef51b8e1 5095 if (which_alternative == 0 && arm_arch6)
5096 return "sxtb\\t%0, %1";
5097 if (which_alternative == 0)
5098 return "#";
a2cd141b 5099
ef51b8e1 5100 addr = XEXP (operands[1], 0);
5101 if (GET_CODE (addr) == PLUS
5102 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
5103 return "ldrsb\\t%0, %1";
a2cd141b 5104
ef51b8e1 5105 return "#";
5106}
5107 [(set_attr_alternative "length"
5108 [(if_then_else (eq_attr "is_arch6" "yes")
5109 (const_int 2) (const_int 4))
5110 (const_int 2)
5111 (if_then_else (eq_attr "is_arch6" "yes")
5112 (const_int 4) (const_int 6))])
5113 (set_attr "type" "alu_shift,load_byte,load_byte")]
a2cd141b 5114)
5115
caedf871 5116(define_expand "extendsfdf2"
5117 [(set (match_operand:DF 0 "s_register_operand" "")
5118 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a50d7267 5119 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
caedf871 5120 ""
5121)
9b8516be 5122
5123/* HFmode -> DFmode conversions have to go through SFmode. */
5124(define_expand "extendhfdf2"
5125 [(set (match_operand:DF 0 "general_operand" "")
5126 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
5127 "TARGET_EITHER"
5128 "
5129 {
5130 rtx op1;
5131 op1 = convert_to_mode (SFmode, operands[1], 0);
5132 op1 = convert_to_mode (DFmode, op1, 0);
5133 emit_insn (gen_movdf (operands[0], op1));
5134 DONE;
5135 }"
5136)
b11cae9e 5137\f
5138;; Move insns (including loads and stores)
5139
5140;; XXX Just some ideas about movti.
9c08d1fa 5141;; I don't think these are a good idea on the arm, there just aren't enough
5142;; registers
b11cae9e 5143;;(define_expand "loadti"
9c08d1fa 5144;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 5145;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
5146;; "" "")
5147
5148;;(define_expand "storeti"
5149;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 5150;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 5151;; "" "")
5152
5153;;(define_expand "movti"
5154;; [(set (match_operand:TI 0 "general_operand" "")
5155;; (match_operand:TI 1 "general_operand" ""))]
5156;; ""
5157;; "
5158;;{
5159;; rtx insn;
5160;;
5161;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
5162;; operands[1] = copy_to_reg (operands[1]);
5163;; if (GET_CODE (operands[0]) == MEM)
5164;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
5165;; else if (GET_CODE (operands[1]) == MEM)
5166;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5167;; else
5168;; FAIL;
5169;;
5170;; emit_insn (insn);
5171;; DONE;
5172;;}")
5173
a2f10574 5174;; Recognize garbage generated above.
b11cae9e 5175
5176;;(define_insn ""
5177;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5178;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5179;; ""
5180;; "*
5181;; {
5182;; register mem = (which_alternative < 3);
0d66636f 5183;; register const char *template;
b11cae9e 5184;;
5185;; operands[mem] = XEXP (operands[mem], 0);
5186;; switch (which_alternative)
5187;; {
5188;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5189;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5190;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5191;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5192;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5193;; case 5: template = \"stmia\\t%0, %M1\"; break;
5194;; }
e2348bcb 5195;; output_asm_insn (template, operands);
5196;; return \"\";
b11cae9e 5197;; }")
5198
cffb2a26 5199(define_expand "movdi"
5200 [(set (match_operand:DI 0 "general_operand" "")
5201 (match_operand:DI 1 "general_operand" ""))]
5202 "TARGET_EITHER"
5203 "
e1ba4a27 5204 if (can_create_pseudo_p ())
cffb2a26 5205 {
b2778788 5206 if (GET_CODE (operands[0]) != REG)
5207 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 5208 }
5209 "
5210)
b11cae9e 5211
cffb2a26 5212(define_insn "*arm_movdi"
d51f92df 5213 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
5214 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
cde1623a 5215 "TARGET_32BIT
b2778788 5216 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
5217 && !TARGET_IWMMXT
5218 && ( register_operand (operands[0], DImode)
5219 || register_operand (operands[1], DImode))"
b11cae9e 5220 "*
d51f92df 5221 switch (which_alternative)
5222 {
5223 case 0:
5224 case 1:
5225 case 2:
5226 return \"#\";
5227 default:
26ff80c0 5228 return output_move_double (operands, true, NULL);
d51f92df 5229 }
cffb2a26 5230 "
359a6e9f 5231 [(set_attr "length" "8,12,16,8,8")
5232 (set_attr "type" "*,*,*,load2,store2")
cde1623a 5233 (set_attr "arm_pool_range" "*,*,*,1020,*")
8848d797 5234 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 5235 (set_attr "thumb2_pool_range" "*,*,*,4096,*")
5236 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 5237)
5238
d51f92df 5239(define_split
5240 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5241 (match_operand:ANY64 1 "const_double_operand" ""))]
25f905c2 5242 "TARGET_32BIT
d51f92df 5243 && reload_completed
5244 && (arm_const_double_inline_cost (operands[1])
5245 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
5246 [(const_int 0)]
5247 "
5248 arm_split_constant (SET, SImode, curr_insn,
5249 INTVAL (gen_lowpart (SImode, operands[1])),
5250 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5251 arm_split_constant (SET, SImode, curr_insn,
5252 INTVAL (gen_highpart_mode (SImode,
5253 GET_MODE (operands[0]),
5254 operands[1])),
5255 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5256 DONE;
5257 "
5258)
5259
e5ba9289 5260; If optimizing for size, or if we have load delay slots, then
5261; we want to split the constant into two separate operations.
5262; In both cases this may split a trivial part into a single data op
5263; leaving a single complex constant to load. We can also get longer
5264; offsets in a LDR which means we get better chances of sharing the pool
5265; entries. Finally, we can normally do a better job of scheduling
5266; LDR instructions than we can with LDM.
5267; This pattern will only match if the one above did not.
5268(define_split
5269 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5270 (match_operand:ANY64 1 "const_double_operand" ""))]
5271 "TARGET_ARM && reload_completed
5272 && arm_const_double_by_parts (operands[1])"
5273 [(set (match_dup 0) (match_dup 1))
5274 (set (match_dup 2) (match_dup 3))]
5275 "
5276 operands[2] = gen_highpart (SImode, operands[0]);
5277 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5278 operands[1]);
5279 operands[0] = gen_lowpart (SImode, operands[0]);
5280 operands[1] = gen_lowpart (SImode, operands[1]);
5281 "
5282)
5283
d51f92df 5284(define_split
5285 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5286 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5287 "TARGET_EITHER && reload_completed"
5288 [(set (match_dup 0) (match_dup 1))
5289 (set (match_dup 2) (match_dup 3))]
5290 "
5291 operands[2] = gen_highpart (SImode, operands[0]);
5292 operands[3] = gen_highpart (SImode, operands[1]);
5293 operands[0] = gen_lowpart (SImode, operands[0]);
5294 operands[1] = gen_lowpart (SImode, operands[1]);
5295
5296 /* Handle a partial overlap. */
5297 if (rtx_equal_p (operands[0], operands[3]))
5298 {
5299 rtx tmp0 = operands[0];
5300 rtx tmp1 = operands[1];
5301
5302 operands[0] = operands[2];
5303 operands[1] = operands[3];
5304 operands[2] = tmp0;
5305 operands[3] = tmp1;
5306 }
5307 "
5308)
5309
a8a3b539 5310;; We can't actually do base+index doubleword loads if the index and
5311;; destination overlap. Split here so that we at least have chance to
5312;; schedule.
5313(define_split
5314 [(set (match_operand:DI 0 "s_register_operand" "")
5315 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5316 (match_operand:SI 2 "s_register_operand" ""))))]
5317 "TARGET_LDRD
5318 && reg_overlap_mentioned_p (operands[0], operands[1])
5319 && reg_overlap_mentioned_p (operands[0], operands[2])"
5320 [(set (match_dup 4)
5321 (plus:SI (match_dup 1)
5322 (match_dup 2)))
5323 (set (match_dup 0)
5324 (mem:DI (match_dup 4)))]
5325 "
5326 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5327 "
5328)
5329
cffb2a26 5330;;; ??? This should have alternatives for constants.
5331;;; ??? This was originally identical to the movdf_insn pattern.
5332;;; ??? The 'i' constraint looks funny, but it should always be replaced by
5333;;; thumb_reorg with a memory reference.
25f905c2 5334(define_insn "*thumb1_movdi_insn"
215b30b3 5335 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
5336 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
25f905c2 5337 "TARGET_THUMB1
a2cd141b 5338 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
cffb2a26 5339 && ( register_operand (operands[0], DImode)
5340 || register_operand (operands[1], DImode))"
5341 "*
5342 {
5343 switch (which_alternative)
5344 {
5345 default:
5346 case 0:
5347 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5348 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5349 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5350 case 1:
5351 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
5352 case 2:
5353 operands[1] = GEN_INT (- INTVAL (operands[1]));
5354 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
5355 case 3:
5356 return \"ldmia\\t%1, {%0, %H0}\";
5357 case 4:
5358 return \"stmia\\t%0, {%1, %H1}\";
5359 case 5:
5360 return thumb_load_double_from_address (operands);
5361 case 6:
1a83b3ff 5362 operands[2] = gen_rtx_MEM (SImode,
215b30b3 5363 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 5364 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5365 return \"\";
5366 case 7:
5367 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5368 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5369 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5370 }
5371 }"
5372 [(set_attr "length" "4,4,6,2,2,6,4,4")
a2cd141b 5373 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
d2a518d1 5374 (set_attr "insn" "*,mov,*,*,*,*,*,mov")
cffb2a26 5375 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
5376)
b11cae9e 5377
9c08d1fa 5378(define_expand "movsi"
5379 [(set (match_operand:SI 0 "general_operand" "")
5380 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 5381 "TARGET_EITHER"
9c08d1fa 5382 "
befb0bac 5383 {
e348ff3e 5384 rtx base, offset, tmp;
5385
25f905c2 5386 if (TARGET_32BIT)
9c08d1fa 5387 {
674a8f0b 5388 /* Everything except mem = const or mem = mem can be done easily. */
cffb2a26 5389 if (GET_CODE (operands[0]) == MEM)
5390 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 5391 if (arm_general_register_operand (operands[0], SImode)
5392 && GET_CODE (operands[1]) == CONST_INT
cffb2a26 5393 && !(const_ok_for_arm (INTVAL (operands[1]))
5394 || const_ok_for_arm (~INTVAL (operands[1]))))
5395 {
96f57e36 5396 arm_split_constant (SET, SImode, NULL_RTX,
5397 INTVAL (operands[1]), operands[0], NULL_RTX,
e1ba4a27 5398 optimize && can_create_pseudo_p ());
cffb2a26 5399 DONE;
5400 }
d0e6a121 5401
5402 if (TARGET_USE_MOVT && !target_word_relocations
5403 && GET_CODE (operands[1]) == SYMBOL_REF
5404 && !flag_pic && !arm_tls_referenced_p (operands[1]))
5405 {
5406 arm_emit_movpair (operands[0], operands[1]);
5407 DONE;
5408 }
cffb2a26 5409 }
25f905c2 5410 else /* TARGET_THUMB1... */
cffb2a26 5411 {
e1ba4a27 5412 if (can_create_pseudo_p ())
cffb2a26 5413 {
5414 if (GET_CODE (operands[0]) != REG)
5415 operands[1] = force_reg (SImode, operands[1]);
5416 }
9c08d1fa 5417 }
f655717d 5418
e348ff3e 5419 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5420 {
5421 split_const (operands[1], &base, &offset);
5422 if (GET_CODE (base) == SYMBOL_REF
5423 && !offset_within_block_p (base, INTVAL (offset)))
5424 {
b308ddcf 5425 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
e348ff3e 5426 emit_move_insn (tmp, base);
5427 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5428 DONE;
5429 }
5430 }
5431
f655717d 5432 /* Recognize the case where operand[1] is a reference to thread-local
5433 data and load its address to a register. */
5434 if (arm_tls_referenced_p (operands[1]))
5435 {
5436 rtx tmp = operands[1];
5437 rtx addend = NULL;
5438
5439 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5440 {
5441 addend = XEXP (XEXP (tmp, 0), 1);
5442 tmp = XEXP (XEXP (tmp, 0), 0);
5443 }
5444
5445 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5446 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5447
e1ba4a27 5448 tmp = legitimize_tls_address (tmp,
5449 !can_create_pseudo_p () ? operands[0] : 0);
f655717d 5450 if (addend)
5451 {
5452 tmp = gen_rtx_PLUS (SImode, tmp, addend);
5453 tmp = force_operand (tmp, operands[0]);
5454 }
5455 operands[1] = tmp;
5456 }
5457 else if (flag_pic
5458 && (CONSTANT_P (operands[1])
5459 || symbol_mentioned_p (operands[1])
5460 || label_mentioned_p (operands[1])))
5461 operands[1] = legitimize_pic_address (operands[1], SImode,
e1ba4a27 5462 (!can_create_pseudo_p ()
5463 ? operands[0]
5464 : 0));
befb0bac 5465 }
215b30b3 5466 "
5467)
9c08d1fa 5468
d0e6a121 5469;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5470;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5471;; so this does not matter.
5472(define_insn "*arm_movt"
5473 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5474 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5475 (match_operand:SI 2 "general_operand" "i")))]
c9b2ce40 5476 "arm_arch_thumb2"
d0e6a121 5477 "movt%?\t%0, #:upper16:%c2"
5478 [(set_attr "predicable" "yes")
5479 (set_attr "length" "4")]
5480)
5481
cffb2a26 5482(define_insn "*arm_movsi_insn"
aaa37ad6 5483 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
110eae03 5484 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
755eb2b4 5485 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 5486 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 5487 && ( register_operand (operands[0], SImode)
5488 || register_operand (operands[1], SImode))"
f7fbdd4a 5489 "@
aaa37ad6 5490 mov%?\\t%0, %1
f7fbdd4a 5491 mov%?\\t%0, %1
5492 mvn%?\\t%0, #%B1
25f905c2 5493 movw%?\\t%0, %1
f7fbdd4a 5494 ldr%?\\t%0, %1
5495 str%?\\t%1, %0"
aaa37ad6 5496 [(set_attr "type" "*,*,*,*,load1,store1")
d2a518d1 5497 (set_attr "insn" "mov,mov,mvn,mov,*,*")
0d66636f 5498 (set_attr "predicable" "yes")
aaa37ad6 5499 (set_attr "pool_range" "*,*,*,*,4096,*")
5500 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
cffb2a26 5501)
87b22bf7 5502
5503(define_split
a2cd141b 5504 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 5505 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5506 "TARGET_32BIT
215b30b3 5507 && (!(const_ok_for_arm (INTVAL (operands[1]))
5508 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 5509 [(clobber (const_int 0))]
5510 "
96f57e36 5511 arm_split_constant (SET, SImode, NULL_RTX,
5512 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 5513 DONE;
215b30b3 5514 "
5515)
9c08d1fa 5516
25f905c2 5517(define_insn "*thumb1_movsi_insn"
55a0d64c 5518 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*l*h*k")
5519 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*l*h*k"))]
25f905c2 5520 "TARGET_THUMB1
cffb2a26 5521 && ( register_operand (operands[0], SImode)
5522 || register_operand (operands[1], SImode))"
5523 "@
5524 mov %0, %1
5525 mov %0, %1
5526 #
5527 #
5528 ldmia\\t%1, {%0}
5529 stmia\\t%0, {%1}
5530 ldr\\t%0, %1
5531 str\\t%1, %0
5532 mov\\t%0, %1"
5533 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 5534 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
747b7458 5535 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")
5536 (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")])
cffb2a26 5537
5538(define_split
5539 [(set (match_operand:SI 0 "register_operand" "")
5540 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5541 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
1276f1b8 5542 [(set (match_dup 2) (match_dup 1))
5543 (set (match_dup 0) (neg:SI (match_dup 2)))]
5544 "
5545 {
5546 operands[1] = GEN_INT (- INTVAL (operands[1]));
5547 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5548 }"
cffb2a26 5549)
5550
5551(define_split
5552 [(set (match_operand:SI 0 "register_operand" "")
5553 (match_operand:SI 1 "const_int_operand" ""))]
25f905c2 5554 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
1276f1b8 5555 [(set (match_dup 2) (match_dup 1))
5556 (set (match_dup 0) (ashift:SI (match_dup 2) (match_dup 3)))]
cffb2a26 5557 "
5558 {
e4aeee53 5559 unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
cffb2a26 5560 unsigned HOST_WIDE_INT mask = 0xff;
5561 int i;
5562
5563 for (i = 0; i < 25; i++)
5564 if ((val & (mask << i)) == val)
5565 break;
5566
1276f1b8 5567 /* Don't split if the shift is zero. */
cffb2a26 5568 if (i == 0)
5569 FAIL;
5570
5571 operands[1] = GEN_INT (val >> i);
1276f1b8 5572 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5573 operands[3] = GEN_INT (i);
cffb2a26 5574 }"
5575)
5576
67336bcf 5577;; When generating pic, we need to load the symbol offset into a register.
5578;; So that the optimizer does not confuse this with a normal symbol load
5579;; we use an unspec. The offset will be loaded from a constant pool entry,
5580;; since that is the only type of relocation we can use.
5581
94f8caca 5582;; Wrap calculation of the whole PIC address in a single pattern for the
5583;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5584;; a PIC address involves two loads from memory, so we want to CSE it
5585;; as often as possible.
5586;; This pattern will be split into one of the pic_load_addr_* patterns
5587;; and a move after GCSE optimizations.
5588;;
5589;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5590(define_expand "calculate_pic_address"
5591 [(set (match_operand:SI 0 "register_operand" "")
5592 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5593 (unspec:SI [(match_operand:SI 2 "" "")]
5594 UNSPEC_PIC_SYM))))]
5595 "flag_pic"
5596)
5597
5598;; Split calculate_pic_address into pic_load_addr_* and a move.
5599(define_split
5600 [(set (match_operand:SI 0 "register_operand" "")
5601 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5602 (unspec:SI [(match_operand:SI 2 "" "")]
5603 UNSPEC_PIC_SYM))))]
5604 "flag_pic"
5605 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5606 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5607 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5608)
5609
67336bcf 5610;; The rather odd constraints on the following are to force reload to leave
5611;; the insn alone, and to force the minipool generation pass to then move
5612;; the GOT symbol to memory.
849170fd 5613
b3cd5f55 5614(define_insn "pic_load_addr_32bit"
849170fd 5615 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 5616 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
b3cd5f55 5617 "TARGET_32BIT && flag_pic"
67336bcf 5618 "ldr%?\\t%0, %1"
a2cd141b 5619 [(set_attr "type" "load1")
b3cd5f55 5620 (set_attr "pool_range" "4096")
5621 (set (attr "neg_pool_range")
5622 (if_then_else (eq_attr "is_thumb" "no")
5623 (const_int 4084)
5624 (const_int 0)))]
8c4d8060 5625)
5626
25f905c2 5627(define_insn "pic_load_addr_thumb1"
8c4d8060 5628 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 5629 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
25f905c2 5630 "TARGET_THUMB1 && flag_pic"
8c4d8060 5631 "ldr\\t%0, %1"
a2cd141b 5632 [(set_attr "type" "load1")
8c4d8060 5633 (set (attr "pool_range") (const_int 1024))]
cffb2a26 5634)
849170fd 5635
cffb2a26 5636(define_insn "pic_add_dot_plus_four"
15d5d060 5637 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5638 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5639 (const_int 4)
beef0fb5 5640 (match_operand 2 "" "")]
5641 UNSPEC_PIC_BASE))]
b3cd5f55 5642 "TARGET_THUMB"
cffb2a26 5643 "*
6cdcb15c 5644 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5645 INTVAL (operands[2]));
cffb2a26 5646 return \"add\\t%0, %|pc\";
5647 "
5648 [(set_attr "length" "2")]
5649)
849170fd 5650
5651(define_insn "pic_add_dot_plus_eight"
15d5d060 5652 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5653 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5654 (const_int 8)
beef0fb5 5655 (match_operand 2 "" "")]
5656 UNSPEC_PIC_BASE))]
f655717d 5657 "TARGET_ARM"
c4034607 5658 "*
6cdcb15c 5659 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5660 INTVAL (operands[2]));
15d5d060 5661 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 5662 "
0d66636f 5663 [(set_attr "predicable" "yes")]
cffb2a26 5664)
849170fd 5665
f655717d 5666(define_insn "tls_load_dot_plus_eight"
cc071db6 5667 [(set (match_operand:SI 0 "register_operand" "=r")
c0c1fba5 5668 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5669 (const_int 8)
beef0fb5 5670 (match_operand 2 "" "")]
5671 UNSPEC_PIC_BASE)))]
f655717d 5672 "TARGET_ARM"
5673 "*
6cdcb15c 5674 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5675 INTVAL (operands[2]));
f655717d 5676 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5677 "
5678 [(set_attr "predicable" "yes")]
5679)
5680
5681;; PIC references to local variables can generate pic_add_dot_plus_eight
5682;; followed by a load. These sequences can be crunched down to
5683;; tls_load_dot_plus_eight by a peephole.
5684
5685(define_peephole2
c0c1fba5 5686 [(set (match_operand:SI 0 "register_operand" "")
5687 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5688 (const_int 8)
5689 (match_operand 1 "" "")]
5690 UNSPEC_PIC_BASE))
f655717d 5691 (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
5692 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
c0c1fba5 5693 [(set (match_dup 2)
5694 (mem:SI (unspec:SI [(match_dup 3)
5695 (const_int 8)
5696 (match_dup 1)]
5697 UNSPEC_PIC_BASE)))]
f655717d 5698 ""
5699)
5700
bac7fc85 5701(define_insn "pic_offset_arm"
5702 [(set (match_operand:SI 0 "register_operand" "=r")
5703 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5704 (unspec:SI [(match_operand:SI 2 "" "X")]
5705 UNSPEC_PIC_OFFSET))))]
5706 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5707 "ldr%?\\t%0, [%1,%2]"
5708 [(set_attr "type" "load1")]
5709)
5710
95373f08 5711(define_expand "builtin_setjmp_receiver"
5712 [(label_ref (match_operand 0 "" ""))]
5713 "flag_pic"
5714 "
5715{
b935b306 5716 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5717 register. */
2cb7d577 5718 if (arm_pic_register != INVALID_REGNUM)
5719 arm_load_pic_register (1UL << 3);
95373f08 5720 DONE;
5721}")
5722
9c08d1fa 5723;; If copying one reg to another we can set the condition codes according to
5724;; its value. Such a move is common after a return from subroutine and the
5725;; result is being tested against zero.
5726
f7fbdd4a 5727(define_insn "*movsi_compare0"
bd5b4116 5728 [(set (reg:CC CC_REGNUM)
cffb2a26 5729 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5730 (const_int 0)))
5731 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5732 (match_dup 1))]
25f905c2 5733 "TARGET_32BIT"
e2348bcb 5734 "@
40dbec34 5735 cmp%?\\t%0, #0
25f905c2 5736 sub%.\\t%0, %1, #0"
cffb2a26 5737 [(set_attr "conds" "set")]
5738)
b11cae9e 5739
b11cae9e 5740;; Subroutine to store a half word from a register into memory.
5741;; Operand 0 is the source register (HImode)
c8f69309 5742;; Operand 1 is the destination address in a register (SImode)
b11cae9e 5743
9c08d1fa 5744;; In both this routine and the next, we must be careful not to spill
01cc3b75 5745;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 5746;; can generate unrecognizable rtl.
5747
b11cae9e 5748(define_expand "storehi"
c8f69309 5749 [;; store the low byte
f082f1c4 5750 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 5751 ;; extract the high byte
c8f69309 5752 (set (match_dup 2)
5753 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 5754 ;; store the high byte
787f8210 5755 (set (match_dup 4) (match_dup 5))]
cffb2a26 5756 "TARGET_ARM"
b11cae9e 5757 "
215b30b3 5758 {
537ffcfc 5759 rtx op1 = operands[1];
5760 rtx addr = XEXP (op1, 0);
215b30b3 5761 enum rtx_code code = GET_CODE (addr);
5762
5763 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5764 || code == MINUS)
537ffcfc 5765 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 5766
537ffcfc 5767 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5768 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5769 operands[3] = gen_lowpart (QImode, operands[0]);
5770 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 5771 operands[2] = gen_reg_rtx (SImode);
5772 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5773 }"
5774)
b11cae9e 5775
c7597b5d 5776(define_expand "storehi_bigend"
f082f1c4 5777 [(set (match_dup 4) (match_dup 3))
c7597b5d 5778 (set (match_dup 2)
5779 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 5780 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 5781 "TARGET_ARM"
b11cae9e 5782 "
215b30b3 5783 {
537ffcfc 5784 rtx op1 = operands[1];
5785 rtx addr = XEXP (op1, 0);
215b30b3 5786 enum rtx_code code = GET_CODE (addr);
5787
5788 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5789 || code == MINUS)
537ffcfc 5790 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 5791
537ffcfc 5792 operands[4] = adjust_address (op1, QImode, 1);
e513d163 5793 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 5794 operands[3] = gen_lowpart (QImode, operands[0]);
5795 operands[0] = gen_lowpart (SImode, operands[0]);
5796 operands[2] = gen_reg_rtx (SImode);
787f8210 5797 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 5798 }"
5799)
c7597b5d 5800
5801;; Subroutine to store a half word integer constant into memory.
5802(define_expand "storeinthi"
f082f1c4 5803 [(set (match_operand 0 "" "")
787f8210 5804 (match_operand 1 "" ""))
9e8503e6 5805 (set (match_dup 3) (match_dup 2))]
cffb2a26 5806 "TARGET_ARM"
c7597b5d 5807 "
215b30b3 5808 {
5809 HOST_WIDE_INT value = INTVAL (operands[1]);
5810 rtx addr = XEXP (operands[0], 0);
537ffcfc 5811 rtx op0 = operands[0];
215b30b3 5812 enum rtx_code code = GET_CODE (addr);
c7597b5d 5813
215b30b3 5814 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5815 || code == MINUS)
537ffcfc 5816 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 5817
215b30b3 5818 operands[1] = gen_reg_rtx (SImode);
5819 if (BYTES_BIG_ENDIAN)
5820 {
5821 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5822 if ((value & 255) == ((value >> 8) & 255))
5823 operands[2] = operands[1];
5824 else
5825 {
5826 operands[2] = gen_reg_rtx (SImode);
5827 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5828 }
5829 }
5830 else
5831 {
5832 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5833 if ((value & 255) == ((value >> 8) & 255))
5834 operands[2] = operands[1];
5835 else
5836 {
5837 operands[2] = gen_reg_rtx (SImode);
5838 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5839 }
5840 }
c7597b5d 5841
537ffcfc 5842 operands[3] = adjust_address (op0, QImode, 1);
e513d163 5843 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 5844 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 5845 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 5846 }"
5847)
b11cae9e 5848
f7fbdd4a 5849(define_expand "storehi_single_op"
5850 [(set (match_operand:HI 0 "memory_operand" "")
5851 (match_operand:HI 1 "general_operand" ""))]
25f905c2 5852 "TARGET_32BIT && arm_arch4"
f7fbdd4a 5853 "
215b30b3 5854 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 5855 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 5856 "
5857)
f7fbdd4a 5858
b11cae9e 5859(define_expand "movhi"
5860 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 5861 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 5862 "TARGET_EITHER"
b11cae9e 5863 "
cffb2a26 5864 if (TARGET_ARM)
b11cae9e 5865 {
e1ba4a27 5866 if (can_create_pseudo_p ())
cffb2a26 5867 {
5868 if (GET_CODE (operands[0]) == MEM)
b11cae9e 5869 {
cffb2a26 5870 if (arm_arch4)
5871 {
5872 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5873 DONE;
5874 }
5875 if (GET_CODE (operands[1]) == CONST_INT)
5876 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 5877 else
cffb2a26 5878 {
5879 if (GET_CODE (operands[1]) == MEM)
5880 operands[1] = force_reg (HImode, operands[1]);
5881 if (BYTES_BIG_ENDIAN)
5882 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5883 else
5884 emit_insn (gen_storehi (operands[1], operands[0]));
5885 }
5886 DONE;
b11cae9e 5887 }
cffb2a26 5888 /* Sign extend a constant, and keep it in an SImode reg. */
5889 else if (GET_CODE (operands[1]) == CONST_INT)
9c08d1fa 5890 {
cffb2a26 5891 rtx reg = gen_reg_rtx (SImode);
5892 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5893
5894 /* If the constant is already valid, leave it alone. */
215b30b3 5895 if (!const_ok_for_arm (val))
cffb2a26 5896 {
5897 /* If setting all the top bits will make the constant
5898 loadable in a single instruction, then set them.
5899 Otherwise, sign extend the number. */
5900
215b30b3 5901 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 5902 val |= ~0xffff;
5903 else if (val & 0x8000)
5904 val |= ~0xffff;
5905 }
5906
5907 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 5908 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 5909 }
e1ba4a27 5910 else if (arm_arch4 && optimize && can_create_pseudo_p ()
0045890a 5911 && GET_CODE (operands[1]) == MEM)
5912 {
5913 rtx reg = gen_reg_rtx (SImode);
5914
5915 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5916 operands[1] = gen_lowpart (HImode, reg);
5917 }
215b30b3 5918 else if (!arm_arch4)
f7fbdd4a 5919 {
cffb2a26 5920 if (GET_CODE (operands[1]) == MEM)
5921 {
c1a66faf 5922 rtx base;
5923 rtx offset = const0_rtx;
5924 rtx reg = gen_reg_rtx (SImode);
5925
5926 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5927 || (GET_CODE (base) == PLUS
5928 && (GET_CODE (offset = XEXP (base, 1))
5929 == CONST_INT)
5930 && ((INTVAL(offset) & 1) != 1)
5931 && GET_CODE (base = XEXP (base, 0)) == REG))
5932 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 5933 {
8deb3959 5934 rtx new_rtx;
c1a66faf 5935
8deb3959 5936 new_rtx = widen_memory_access (operands[1], SImode,
5937 ((INTVAL (offset) & ~3)
5938 - INTVAL (offset)));
5939 emit_insn (gen_movsi (reg, new_rtx));
c1a66faf 5940 if (((INTVAL (offset) & 2) != 0)
5941 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5942 {
5943 rtx reg2 = gen_reg_rtx (SImode);
5944
5945 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5946 reg = reg2;
5947 }
206ee9a2 5948 }
c1a66faf 5949 else
5950 emit_insn (gen_movhi_bytes (reg, operands[1]));
5951
5952 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 5953 }
5954 }
5955 }
674a8f0b 5956 /* Handle loading a large integer during reload. */
cffb2a26 5957 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 5958 && !const_ok_for_arm (INTVAL (operands[1]))
5959 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 5960 {
5961 /* Writing a constant to memory needs a scratch, which should
5962 be handled with SECONDARY_RELOADs. */
ed29c566 5963 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5964
5965 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5966 emit_insn (gen_movsi (operands[0], operands[1]));
5967 DONE;
5968 }
5969 }
25f905c2 5970 else if (TARGET_THUMB2)
5971 {
5972 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
e1ba4a27 5973 if (can_create_pseudo_p ())
25f905c2 5974 {
5975 if (GET_CODE (operands[0]) != REG)
5976 operands[1] = force_reg (HImode, operands[1]);
5977 /* Zero extend a constant, and keep it in an SImode reg. */
5978 else if (GET_CODE (operands[1]) == CONST_INT)
5979 {
5980 rtx reg = gen_reg_rtx (SImode);
5981 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5982
5983 emit_insn (gen_movsi (reg, GEN_INT (val)));
5984 operands[1] = gen_lowpart (HImode, reg);
5985 }
5986 }
5987 }
5988 else /* TARGET_THUMB1 */
cffb2a26 5989 {
e1ba4a27 5990 if (can_create_pseudo_p ())
cffb2a26 5991 {
6cffc037 5992 if (GET_CODE (operands[1]) == CONST_INT)
5993 {
5994 rtx reg = gen_reg_rtx (SImode);
5995
5996 emit_insn (gen_movsi (reg, operands[1]));
5997 operands[1] = gen_lowpart (HImode, reg);
5998 }
cffb2a26 5999
6000 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6001 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6002 virtual register (also rejected as illegitimate for HImode/QImode)
6003 relative address. */
cffb2a26 6004 /* ??? This should perhaps be fixed elsewhere, for instance, in
6005 fixup_stack_1, by checking for other kinds of invalid addresses,
6006 e.g. a bare reference to a virtual register. This may confuse the
6007 alpha though, which must handle this case differently. */
6008 if (GET_CODE (operands[0]) == MEM
215b30b3 6009 && !memory_address_p (GET_MODE (operands[0]),
6010 XEXP (operands[0], 0)))
537ffcfc 6011 operands[0]
6012 = replace_equiv_address (operands[0],
6013 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 6014
6015 if (GET_CODE (operands[1]) == MEM
215b30b3 6016 && !memory_address_p (GET_MODE (operands[1]),
6017 XEXP (operands[1], 0)))
537ffcfc 6018 operands[1]
6019 = replace_equiv_address (operands[1],
6020 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6021
6022 if (GET_CODE (operands[1]) == MEM && optimize > 0)
6023 {
6024 rtx reg = gen_reg_rtx (SImode);
6025
6026 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6027 operands[1] = gen_lowpart (HImode, reg);
6028 }
6029
6030 if (GET_CODE (operands[0]) == MEM)
6031 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 6032 }
cffb2a26 6033 else if (GET_CODE (operands[1]) == CONST_INT
234f6557 6034 && !satisfies_constraint_I (operands[1]))
cffb2a26 6035 {
6cffc037 6036 /* Handle loading a large integer during reload. */
6037
cffb2a26 6038 /* Writing a constant to memory needs a scratch, which should
6039 be handled with SECONDARY_RELOADs. */
ed29c566 6040 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 6041
1a83b3ff 6042 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 6043 emit_insn (gen_movsi (operands[0], operands[1]));
6044 DONE;
6045 }
b11cae9e 6046 }
cffb2a26 6047 "
6048)
6049
25f905c2 6050(define_insn "*thumb1_movhi_insn"
a941568e 6051 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
6052 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
25f905c2 6053 "TARGET_THUMB1
cffb2a26 6054 && ( register_operand (operands[0], HImode)
6055 || register_operand (operands[1], HImode))"
6056 "*
6057 switch (which_alternative)
d79300ac 6058 {
cffb2a26 6059 case 0: return \"add %0, %1, #0\";
6060 case 2: return \"strh %1, %0\";
6061 case 3: return \"mov %0, %1\";
6062 case 4: return \"mov %0, %1\";
6063 case 5: return \"mov %0, %1\";
ed29c566 6064 default: gcc_unreachable ();
cffb2a26 6065 case 1:
6066 /* The stack pointer can end up being taken as an index register.
6067 Catch this case here and deal with it. */
6068 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
6069 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
6070 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
6071 {
6072 rtx ops[2];
6073 ops[0] = operands[0];
6074 ops[1] = XEXP (XEXP (operands[1], 0), 0);
6075
6076 output_asm_insn (\"mov %0, %1\", ops);
6077
6078 XEXP (XEXP (operands[1], 0), 0) = operands[0];
6079
6080 }
6081 return \"ldrh %0, %1\";
6082 }"
6083 [(set_attr "length" "2,4,2,2,2,2")
747b7458 6084 (set_attr "type" "*,load1,store1,*,*,*")
6085 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
d79300ac 6086
b11cae9e 6087
25f7a26e 6088(define_expand "movhi_bytes"
eab14235 6089 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 6090 (set (match_dup 3)
eab14235 6091 (zero_extend:SI (match_dup 6)))
25f7a26e 6092 (set (match_operand:SI 0 "" "")
6093 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 6094 "TARGET_ARM"
25f7a26e 6095 "
215b30b3 6096 {
6097 rtx mem1, mem2;
6098 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6099
788fcce0 6100 mem1 = change_address (operands[1], QImode, addr);
6101 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 6102 operands[0] = gen_lowpart (SImode, operands[0]);
6103 operands[1] = mem1;
6104 operands[2] = gen_reg_rtx (SImode);
6105 operands[3] = gen_reg_rtx (SImode);
6106 operands[6] = mem2;
25f7a26e 6107
215b30b3 6108 if (BYTES_BIG_ENDIAN)
6109 {
6110 operands[4] = operands[2];
6111 operands[5] = operands[3];
6112 }
6113 else
6114 {
6115 operands[4] = operands[3];
6116 operands[5] = operands[2];
6117 }
6118 }"
6119)
25f7a26e 6120
c7597b5d 6121(define_expand "movhi_bigend"
6122 [(set (match_dup 2)
6123 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
6124 (const_int 16)))
6125 (set (match_dup 3)
6126 (ashiftrt:SI (match_dup 2) (const_int 16)))
6127 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 6128 (match_dup 4))]
cffb2a26 6129 "TARGET_ARM"
c7597b5d 6130 "
6131 operands[2] = gen_reg_rtx (SImode);
6132 operands[3] = gen_reg_rtx (SImode);
787f8210 6133 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 6134 "
6135)
b11cae9e 6136
a2f10574 6137;; Pattern to recognize insn generated default case above
f7fbdd4a 6138(define_insn "*movhi_insn_arch4"
cde1623a 6139 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
85e02ccb 6140 (match_operand:HI 1 "general_operand" "rI,K,r,mi"))]
cffb2a26 6141 "TARGET_ARM
6142 && arm_arch4
85e02ccb 6143 && (register_operand (operands[0], HImode)
6144 || register_operand (operands[1], HImode))"
f7fbdd4a 6145 "@
6146 mov%?\\t%0, %1\\t%@ movhi
6147 mvn%?\\t%0, #%B1\\t%@ movhi
25f905c2 6148 str%(h%)\\t%1, %0\\t%@ movhi
6149 ldr%(h%)\\t%0, %1\\t%@ movhi"
a2cd141b 6150 [(set_attr "type" "*,*,store1,load1")
0d66636f 6151 (set_attr "predicable" "yes")
d2a518d1 6152 (set_attr "insn" "mov,mvn,*,*")
cffb2a26 6153 (set_attr "pool_range" "*,*,*,256")
6154 (set_attr "neg_pool_range" "*,*,*,244")]
6155)
f7fbdd4a 6156
f7fbdd4a 6157(define_insn "*movhi_bytes"
25f7a26e 6158 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
6159 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
c1a66faf 6160 "TARGET_ARM"
25f7a26e 6161 "@
6162 mov%?\\t%0, %1\\t%@ movhi
0d66636f 6163 mvn%?\\t%0, #%B1\\t%@ movhi"
d2a518d1 6164 [(set_attr "predicable" "yes")
6165 (set_attr "insn" "mov,mvn")]
0d66636f 6166)
25f7a26e 6167
f90b51f1 6168(define_expand "thumb_movhi_clobber"
6169 [(set (match_operand:HI 0 "memory_operand" "")
6170 (match_operand:HI 1 "register_operand" ""))
6171 (clobber (match_operand:DI 2 "register_operand" ""))]
25f905c2 6172 "TARGET_THUMB1"
f90b51f1 6173 "
6174 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
6175 && REGNO (operands[1]) <= LAST_LO_REGNUM)
6176 {
6177 emit_insn (gen_movhi (operands[0], operands[1]));
6178 DONE;
6179 }
6180 /* XXX Fixme, need to handle other cases here as well. */
6181 gcc_unreachable ();
6182 "
cffb2a26 6183)
6184
bc5c7e08 6185;; We use a DImode scratch because we may occasionally need an additional
6186;; temporary if the address isn't offsettable -- push_reload doesn't seem
6187;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 6188(define_expand "reload_outhi"
cffb2a26 6189 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 6190 (match_operand:HI 1 "s_register_operand" "r")
6191 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 6192 "TARGET_EITHER"
6193 "if (TARGET_ARM)
6194 arm_reload_out_hi (operands);
6195 else
6196 thumb_reload_out_hi (operands);
d3373b54 6197 DONE;
cffb2a26 6198 "
6199)
d3373b54 6200
25f7a26e 6201(define_expand "reload_inhi"
6202 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 6203 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 6204 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 6205 "TARGET_EITHER"
25f7a26e 6206 "
cffb2a26 6207 if (TARGET_ARM)
6208 arm_reload_in_hi (operands);
6209 else
6210 thumb_reload_out_hi (operands);
25f7a26e 6211 DONE;
6212")
6213
9c08d1fa 6214(define_expand "movqi"
6215 [(set (match_operand:QI 0 "general_operand" "")
6216 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 6217 "TARGET_EITHER"
9c08d1fa 6218 "
6cffc037 6219 /* Everything except mem = const or mem = mem can be done easily */
0045890a 6220
e1ba4a27 6221 if (can_create_pseudo_p ())
cffb2a26 6222 {
6cffc037 6223 if (GET_CODE (operands[1]) == CONST_INT)
6224 {
6225 rtx reg = gen_reg_rtx (SImode);
6226
03770691 6227 /* For thumb we want an unsigned immediate, then we are more likely
6228 to be able to use a movs insn. */
6229 if (TARGET_THUMB)
6230 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6231
6cffc037 6232 emit_insn (gen_movsi (reg, operands[1]));
6233 operands[1] = gen_lowpart (QImode, reg);
6234 }
cffb2a26 6235
6cffc037 6236 if (TARGET_THUMB)
6237 {
cffb2a26 6238 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 6239 happen if we are passed a SP (never OK for HImode/QImode) or
bc409cb4 6240 virtual register (also rejected as illegitimate for HImode/QImode)
6241 relative address. */
cffb2a26 6242 /* ??? This should perhaps be fixed elsewhere, for instance, in
6243 fixup_stack_1, by checking for other kinds of invalid addresses,
6244 e.g. a bare reference to a virtual register. This may confuse the
6245 alpha though, which must handle this case differently. */
6246 if (GET_CODE (operands[0]) == MEM
215b30b3 6247 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 6248 XEXP (operands[0], 0)))
537ffcfc 6249 operands[0]
6250 = replace_equiv_address (operands[0],
6251 copy_to_reg (XEXP (operands[0], 0)));
215b30b3 6252 if (GET_CODE (operands[1]) == MEM
6253 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 6254 XEXP (operands[1], 0)))
537ffcfc 6255 operands[1]
6256 = replace_equiv_address (operands[1],
6257 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 6258 }
6259
6260 if (GET_CODE (operands[1]) == MEM && optimize > 0)
6261 {
6262 rtx reg = gen_reg_rtx (SImode);
6263
6264 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6265 operands[1] = gen_lowpart (QImode, reg);
6266 }
6267
6268 if (GET_CODE (operands[0]) == MEM)
6269 operands[1] = force_reg (QImode, operands[1]);
6270 }
6271 else if (TARGET_THUMB
6272 && GET_CODE (operands[1]) == CONST_INT
234f6557 6273 && !satisfies_constraint_I (operands[1]))
6cffc037 6274 {
674a8f0b 6275 /* Handle loading a large integer during reload. */
cffb2a26 6276
6cffc037 6277 /* Writing a constant to memory needs a scratch, which should
6278 be handled with SECONDARY_RELOADs. */
6279 gcc_assert (GET_CODE (operands[0]) == REG);
6280
6281 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6282 emit_insn (gen_movsi (operands[0], operands[1]));
6283 DONE;
cffb2a26 6284 }
6285 "
6286)
b11cae9e 6287
9c08d1fa 6288
cffb2a26 6289(define_insn "*arm_movqi_insn"
a54e3e7b 6290 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,l,Uu,r,m")
6291 (match_operand:QI 1 "general_operand" "rI,K,Uu,l,m,r"))]
25f905c2 6292 "TARGET_32BIT
cffb2a26 6293 && ( register_operand (operands[0], QImode)
6294 || register_operand (operands[1], QImode))"
5565501b 6295 "@
6296 mov%?\\t%0, %1
6297 mvn%?\\t%0, #%B1
25f905c2 6298 ldr%(b%)\\t%0, %1
a54e3e7b 6299 str%(b%)\\t%1, %0
6300 ldr%(b%)\\t%0, %1
25f905c2 6301 str%(b%)\\t%1, %0"
a54e3e7b 6302 [(set_attr "type" "*,*,load1,store1,load1,store1")
6303 (set_attr "insn" "mov,mvn,*,*,*,*")
6304 (set_attr "predicable" "yes")
6305 (set_attr "arch" "any,any,t2,t2,any,any")
6306 (set_attr "length" "4,4,2,2,4,4")]
cffb2a26 6307)
6308
25f905c2 6309(define_insn "*thumb1_movqi_insn"
cffb2a26 6310 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 6311 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
25f905c2 6312 "TARGET_THUMB1
cffb2a26 6313 && ( register_operand (operands[0], QImode)
6314 || register_operand (operands[1], QImode))"
6315 "@
6316 add\\t%0, %1, #0
6317 ldrb\\t%0, %1
6318 strb\\t%1, %0
6319 mov\\t%0, %1
6320 mov\\t%0, %1
6321 mov\\t%0, %1"
6322 [(set_attr "length" "2")
a2cd141b 6323 (set_attr "type" "*,load1,store1,*,*,*")
d2a518d1 6324 (set_attr "insn" "*,*,*,mov,mov,mov")
747b7458 6325 (set_attr "pool_range" "*,32,*,*,*,*")
6326 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
b11cae9e 6327
9b8516be 6328;; HFmode moves
6329(define_expand "movhf"
6330 [(set (match_operand:HF 0 "general_operand" "")
6331 (match_operand:HF 1 "general_operand" ""))]
6332 "TARGET_EITHER"
6333 "
6334 if (TARGET_32BIT)
6335 {
6336 if (GET_CODE (operands[0]) == MEM)
6337 operands[1] = force_reg (HFmode, operands[1]);
6338 }
6339 else /* TARGET_THUMB1 */
6340 {
6341 if (can_create_pseudo_p ())
6342 {
6343 if (GET_CODE (operands[0]) != REG)
6344 operands[1] = force_reg (HFmode, operands[1]);
6345 }
6346 }
6347 "
6348)
6349
6350(define_insn "*arm32_movhf"
6351 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6352 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
a50d7267 6353 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
9b8516be 6354 && ( s_register_operand (operands[0], HFmode)
6355 || s_register_operand (operands[1], HFmode))"
6356 "*
6357 switch (which_alternative)
6358 {
6359 case 0: /* ARM register from memory */
6360 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
6361 case 1: /* memory from ARM register */
6362 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
6363 case 2: /* ARM register from ARM register */
6364 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6365 case 3: /* ARM register from constant */
6366 {
6367 REAL_VALUE_TYPE r;
6368 long bits;
6369 rtx ops[4];
6370
6371 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
6372 bits = real_to_target (NULL, &r, HFmode);
6373 ops[0] = operands[0];
6374 ops[1] = GEN_INT (bits);
6375 ops[2] = GEN_INT (bits & 0xff00);
6376 ops[3] = GEN_INT (bits & 0x00ff);
6377
6378 if (arm_arch_thumb2)
6379 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6380 else
6381 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6382 return \"\";
6383 }
6384 default:
6385 gcc_unreachable ();
6386 }
6387 "
6388 [(set_attr "conds" "unconditional")
6389 (set_attr "type" "load1,store1,*,*")
d2a518d1 6390 (set_attr "insn" "*,*,mov,mov")
9b8516be 6391 (set_attr "length" "4,4,4,8")
d2a518d1 6392 (set_attr "predicable" "yes")]
9b8516be 6393)
6394
6395(define_insn "*thumb1_movhf"
6396 [(set (match_operand:HF 0 "nonimmediate_operand" "=l,l,m,*r,*h")
6397 (match_operand:HF 1 "general_operand" "l,mF,l,*h,*r"))]
6398 "TARGET_THUMB1
6399 && ( s_register_operand (operands[0], HFmode)
6400 || s_register_operand (operands[1], HFmode))"
6401 "*
6402 switch (which_alternative)
6403 {
6404 case 1:
6405 {
6406 rtx addr;
6407 gcc_assert (GET_CODE(operands[1]) == MEM);
6408 addr = XEXP (operands[1], 0);
6409 if (GET_CODE (addr) == LABEL_REF
6410 || (GET_CODE (addr) == CONST
6411 && GET_CODE (XEXP (addr, 0)) == PLUS
6412 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
6413 && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT))
6414 {
6415 /* Constant pool entry. */
6416 return \"ldr\\t%0, %1\";
6417 }
6418 return \"ldrh\\t%0, %1\";
6419 }
6420 case 2: return \"strh\\t%1, %0\";
6421 default: return \"mov\\t%0, %1\";
6422 }
6423 "
6424 [(set_attr "length" "2")
6425 (set_attr "type" "*,load1,store1,*,*")
d2a518d1 6426 (set_attr "insn" "mov,*,*,mov,mov")
747b7458 6427 (set_attr "pool_range" "*,1020,*,*,*")
6428 (set_attr "conds" "clob,nocond,nocond,nocond,nocond")])
9b8516be 6429
87b22bf7 6430(define_expand "movsf"
6431 [(set (match_operand:SF 0 "general_operand" "")
6432 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 6433 "TARGET_EITHER"
87b22bf7 6434 "
25f905c2 6435 if (TARGET_32BIT)
cffb2a26 6436 {
6437 if (GET_CODE (operands[0]) == MEM)
6438 operands[1] = force_reg (SFmode, operands[1]);
6439 }
25f905c2 6440 else /* TARGET_THUMB1 */
cffb2a26 6441 {
e1ba4a27 6442 if (can_create_pseudo_p ())
cffb2a26 6443 {
6444 if (GET_CODE (operands[0]) != REG)
6445 operands[1] = force_reg (SFmode, operands[1]);
6446 }
6447 }
6448 "
6449)
6450
03d440a6 6451;; Transform a floating-point move of a constant into a core register into
6452;; an SImode operation.
cffb2a26 6453(define_split
03d440a6 6454 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 6455 (match_operand:SF 1 "immediate_operand" ""))]
339034d0 6456 "TARGET_EITHER
cffb2a26 6457 && reload_completed
6458 && GET_CODE (operands[1]) == CONST_DOUBLE"
6459 [(set (match_dup 2) (match_dup 3))]
6460 "
6461 operands[2] = gen_lowpart (SImode, operands[0]);
6462 operands[3] = gen_lowpart (SImode, operands[1]);
6463 if (operands[2] == 0 || operands[3] == 0)
6464 FAIL;
215b30b3 6465 "
6466)
87b22bf7 6467
cffb2a26 6468(define_insn "*arm_movsf_soft_insn"
6469 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6470 (match_operand:SF 1 "general_operand" "r,mE,r"))]
cde1623a 6471 "TARGET_32BIT
cffb2a26 6472 && TARGET_SOFT_FLOAT
215b30b3 6473 && (GET_CODE (operands[0]) != MEM
6474 || register_operand (operands[1], SFmode))"
9a1112d7 6475 "@
6476 mov%?\\t%0, %1
6477 ldr%?\\t%0, %1\\t%@ float
6478 str%?\\t%1, %0\\t%@ float"
cde1623a 6479 [(set_attr "predicable" "yes")
a2cd141b 6480 (set_attr "type" "*,load1,store1")
d2a518d1 6481 (set_attr "insn" "mov,*,*")
cffb2a26 6482 (set_attr "pool_range" "*,4096,*")
cde1623a 6483 (set_attr "arm_neg_pool_range" "*,4084,*")
6484 (set_attr "thumb2_neg_pool_range" "*,0,*")]
cffb2a26 6485)
6486
6487;;; ??? This should have alternatives for constants.
25f905c2 6488(define_insn "*thumb1_movsf_insn"
215b30b3 6489 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
6490 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
25f905c2 6491 "TARGET_THUMB1
cffb2a26 6492 && ( register_operand (operands[0], SFmode)
6493 || register_operand (operands[1], SFmode))"
6494 "@
6495 add\\t%0, %1, #0
6496 ldmia\\t%1, {%0}
6497 stmia\\t%0, {%1}
6498 ldr\\t%0, %1
6499 str\\t%1, %0
6500 mov\\t%0, %1
6501 mov\\t%0, %1"
6502 [(set_attr "length" "2")
a2cd141b 6503 (set_attr "type" "*,load1,store1,load1,store1,*,*")
747b7458 6504 (set_attr "pool_range" "*,*,*,1020,*,*,*")
d2a518d1 6505 (set_attr "insn" "*,*,*,*,*,mov,mov")
747b7458 6506 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,nocond,nocond")]
cffb2a26 6507)
9a1112d7 6508
9c08d1fa 6509(define_expand "movdf"
87b22bf7 6510 [(set (match_operand:DF 0 "general_operand" "")
6511 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 6512 "TARGET_EITHER"
9c08d1fa 6513 "
25f905c2 6514 if (TARGET_32BIT)
cffb2a26 6515 {
6516 if (GET_CODE (operands[0]) == MEM)
6517 operands[1] = force_reg (DFmode, operands[1]);
6518 }
6519 else /* TARGET_THUMB */
6520 {
e1ba4a27 6521 if (can_create_pseudo_p ())
cffb2a26 6522 {
6523 if (GET_CODE (operands[0]) != REG)
6524 operands[1] = force_reg (DFmode, operands[1]);
6525 }
6526 }
6527 "
6528)
b11cae9e 6529
9c08d1fa 6530;; Reloading a df mode value stored in integer regs to memory can require a
6531;; scratch reg.
6532(define_expand "reload_outdf"
cffb2a26 6533 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 6534 (match_operand:DF 1 "s_register_operand" "r")
6535 (match_operand:SI 2 "s_register_operand" "=&r")]
06adefdc 6536 "TARGET_THUMB2"
87b22bf7 6537 "
215b30b3 6538 {
6539 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 6540
215b30b3 6541 if (code == REG)
6542 operands[2] = XEXP (operands[0], 0);
6543 else if (code == POST_INC || code == PRE_DEC)
6544 {
6545 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6546 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6547 emit_insn (gen_movdi (operands[0], operands[1]));
6548 DONE;
6549 }
6550 else if (code == PRE_INC)
6551 {
6552 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 6553
215b30b3 6554 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6555 operands[2] = reg;
6556 }
6557 else if (code == POST_DEC)
6558 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6559 else
6560 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6561 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 6562
788fcce0 6563 emit_insn (gen_rtx_SET (VOIDmode,
6564 replace_equiv_address (operands[0], operands[2]),
215b30b3 6565 operands[1]));
f7fbdd4a 6566
215b30b3 6567 if (code == POST_DEC)
6568 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6569
6570 DONE;
6571 }"
6572)
9c08d1fa 6573
9a1112d7 6574(define_insn "*movdf_soft_insn"
359a6e9f 6575 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6576 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
cde1623a 6577 "TARGET_32BIT && TARGET_SOFT_FLOAT
b2778788 6578 && ( register_operand (operands[0], DFmode)
6579 || register_operand (operands[1], DFmode))"
d51f92df 6580 "*
6581 switch (which_alternative)
6582 {
6583 case 0:
6584 case 1:
6585 case 2:
6586 return \"#\";
6587 default:
26ff80c0 6588 return output_move_double (operands, true, NULL);
d51f92df 6589 }
6590 "
359a6e9f 6591 [(set_attr "length" "8,12,16,8,8")
6592 (set_attr "type" "*,*,*,load2,store2")
cde1623a 6593 (set_attr "pool_range" "*,*,*,1020,*")
8848d797 6594 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
cde1623a 6595 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
cffb2a26 6596)
6597
6598;;; ??? This should have alternatives for constants.
6599;;; ??? This was originally identical to the movdi_insn pattern.
6600;;; ??? The 'F' constraint looks funny, but it should always be replaced by
6601;;; thumb_reorg with a memory reference.
6602(define_insn "*thumb_movdf_insn"
215b30b3 6603 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
6604 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
25f905c2 6605 "TARGET_THUMB1
cffb2a26 6606 && ( register_operand (operands[0], DFmode)
6607 || register_operand (operands[1], DFmode))"
6608 "*
6609 switch (which_alternative)
6610 {
6611 default:
6612 case 0:
6613 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6614 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6615 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6616 case 1:
6617 return \"ldmia\\t%1, {%0, %H0}\";
6618 case 2:
6619 return \"stmia\\t%0, {%1, %H1}\";
6620 case 3:
6621 return thumb_load_double_from_address (operands);
6622 case 4:
1a83b3ff 6623 operands[2] = gen_rtx_MEM (SImode,
6624 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 6625 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6626 return \"\";
6627 case 5:
6628 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6629 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6630 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6631 }
6632 "
6633 [(set_attr "length" "4,2,2,6,4,4")
a2cd141b 6634 (set_attr "type" "*,load2,store2,load2,store2,*")
d2a518d1 6635 (set_attr "insn" "*,*,*,*,*,mov")
cffb2a26 6636 (set_attr "pool_range" "*,*,*,1020,*,*")]
6637)
755eb2b4 6638
ccd90aaa 6639(define_expand "movxf"
6640 [(set (match_operand:XF 0 "general_operand" "")
6641 (match_operand:XF 1 "general_operand" ""))]
25f905c2 6642 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
ccd90aaa 6643 "
6644 if (GET_CODE (operands[0]) == MEM)
6645 operands[1] = force_reg (XFmode, operands[1]);
6646 "
6647)
6648
b11cae9e 6649\f
b11cae9e 6650
9c08d1fa 6651;; load- and store-multiple insns
6652;; The arm can load/store any set of registers, provided that they are in
320ea44d 6653;; ascending order, but these expanders assume a contiguous set.
b11cae9e 6654
9c08d1fa 6655(define_expand "load_multiple"
6656 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6657 (match_operand:SI 1 "" ""))
6658 (use (match_operand:SI 2 "" ""))])]
25f905c2 6659 "TARGET_32BIT"
9580c25f 6660{
6661 HOST_WIDE_INT offset = 0;
6662
bd5b4116 6663 /* Support only fixed point registers. */
9c08d1fa 6664 if (GET_CODE (operands[2]) != CONST_INT
6665 || INTVAL (operands[2]) > 14
6666 || INTVAL (operands[2]) < 2
6667 || GET_CODE (operands[1]) != MEM
6668 || GET_CODE (operands[0]) != REG
bd5b4116 6669 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6670 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6671 FAIL;
6672
6673 operands[3]
320ea44d 6674 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6675 INTVAL (operands[2]),
f082f1c4 6676 force_reg (SImode, XEXP (operands[1], 0)),
320ea44d 6677 FALSE, operands[1], &offset);
9580c25f 6678})
b11cae9e 6679
9c08d1fa 6680(define_expand "store_multiple"
6681 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6682 (match_operand:SI 1 "" ""))
6683 (use (match_operand:SI 2 "" ""))])]
25f905c2 6684 "TARGET_32BIT"
9580c25f 6685{
6686 HOST_WIDE_INT offset = 0;
6687
674a8f0b 6688 /* Support only fixed point registers. */
9c08d1fa 6689 if (GET_CODE (operands[2]) != CONST_INT
6690 || INTVAL (operands[2]) > 14
6691 || INTVAL (operands[2]) < 2
6692 || GET_CODE (operands[1]) != REG
6693 || GET_CODE (operands[0]) != MEM
bd5b4116 6694 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6695 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 6696 FAIL;
6697
6698 operands[3]
320ea44d 6699 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6700 INTVAL (operands[2]),
f082f1c4 6701 force_reg (SImode, XEXP (operands[0], 0)),
320ea44d 6702 FALSE, operands[0], &offset);
9580c25f 6703})
b11cae9e 6704
9c08d1fa 6705
6706;; Move a block of memory if it is word aligned and MORE than 2 words long.
6707;; We could let this apply for blocks of less than this, but it clobbers so
6708;; many registers that there is then probably a better way.
6709
008c057d 6710(define_expand "movmemqi"
34191dd1 6711 [(match_operand:BLK 0 "general_operand" "")
6712 (match_operand:BLK 1 "general_operand" "")
6713 (match_operand:SI 2 "const_int_operand" "")
6714 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 6715 "TARGET_EITHER"
9c08d1fa 6716 "
25f905c2 6717 if (TARGET_32BIT)
cffb2a26 6718 {
008c057d 6719 if (arm_gen_movmemqi (operands))
cffb2a26 6720 DONE;
6721 FAIL;
6722 }
25f905c2 6723 else /* TARGET_THUMB1 */
cffb2a26 6724 {
6725 if ( INTVAL (operands[3]) != 4
6726 || INTVAL (operands[2]) > 48)
6727 FAIL;
6728
008c057d 6729 thumb_expand_movmemqi (operands);
cffb2a26 6730 DONE;
6731 }
6732 "
6733)
6734
2162064c 6735;; Thumb block-move insns
cffb2a26 6736
6737(define_insn "movmem12b"
960f3acf 6738 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6739 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6740 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6741 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6742 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6743 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6744 (set (match_operand:SI 0 "register_operand" "=l")
6745 (plus:SI (match_dup 2) (const_int 12)))
6746 (set (match_operand:SI 1 "register_operand" "=l")
6747 (plus:SI (match_dup 3) (const_int 12)))
6748 (clobber (match_scratch:SI 4 "=&l"))
6749 (clobber (match_scratch:SI 5 "=&l"))
6750 (clobber (match_scratch:SI 6 "=&l"))]
25f905c2 6751 "TARGET_THUMB1"
cffb2a26 6752 "* return thumb_output_move_mem_multiple (3, operands);"
6753 [(set_attr "length" "4")
215b30b3 6754 ; This isn't entirely accurate... It loads as well, but in terms of
6755 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6756 (set_attr "type" "store3")]
6757)
6758
6759(define_insn "movmem8b"
960f3acf 6760 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6761 (mem:SI (match_operand:SI 3 "register_operand" "1")))
6762 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6763 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6764 (set (match_operand:SI 0 "register_operand" "=l")
6765 (plus:SI (match_dup 2) (const_int 8)))
6766 (set (match_operand:SI 1 "register_operand" "=l")
6767 (plus:SI (match_dup 3) (const_int 8)))
6768 (clobber (match_scratch:SI 4 "=&l"))
6769 (clobber (match_scratch:SI 5 "=&l"))]
25f905c2 6770 "TARGET_THUMB1"
cffb2a26 6771 "* return thumb_output_move_mem_multiple (2, operands);"
6772 [(set_attr "length" "4")
215b30b3 6773 ; This isn't entirely accurate... It loads as well, but in terms of
6774 ; scheduling the following insn it is better to consider it as a store
cffb2a26 6775 (set_attr "type" "store2")]
6776)
6777
9c08d1fa 6778\f
b11cae9e 6779
341940e8 6780;; Compare & branch insns
8d232dc7 6781;; The range calculations are based as follows:
341940e8 6782;; For forward branches, the address calculation returns the address of
6783;; the next instruction. This is 2 beyond the branch instruction.
6784;; For backward branches, the address calculation returns the address of
6785;; the first instruction in this pattern (cmp). This is 2 before the branch
6786;; instruction for the shortest sequence, and 4 before the branch instruction
6787;; if we have to jump around an unconditional branch.
6788;; To the basic branch range the PC offset must be added (this is +4).
6789;; So for forward branches we have
6790;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6791;; And for backward branches we have
6792;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6793;;
6794;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6795;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 6796
aeac46d4 6797(define_expand "cbranchsi4"
6798 [(set (pc) (if_then_else
aa06947a 6799 (match_operator 0 "expandable_comparison_operator"
aeac46d4 6800 [(match_operand:SI 1 "s_register_operand" "")
6801 (match_operand:SI 2 "nonmemory_operand" "")])
6802 (label_ref (match_operand 3 "" ""))
6803 (pc)))]
74f4459c 6804 "TARGET_THUMB1 || TARGET_32BIT"
aeac46d4 6805 "
74f4459c 6806 if (!TARGET_THUMB1)
6807 {
6808 if (!arm_add_operand (operands[2], SImode))
6809 operands[2] = force_reg (SImode, operands[2]);
6810 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6811 operands[3]));
6812 DONE;
6813 }
25f905c2 6814 if (thumb1_cmpneg_operand (operands[2], SImode))
aeac46d4 6815 {
6816 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6817 operands[3], operands[0]));
6818 DONE;
6819 }
25f905c2 6820 if (!thumb1_cmp_operand (operands[2], SImode))
aeac46d4 6821 operands[2] = force_reg (SImode, operands[2]);
6822 ")
6823
a8e6c15d 6824;; A pattern to recognize a special situation and optimize for it.
6825;; On the thumb, zero-extension from memory is preferrable to sign-extension
6826;; due to the available addressing modes. Hence, convert a signed comparison
6827;; with zero into an unsigned comparison with 127 if possible.
6828(define_expand "cbranchqi4"
6829 [(set (pc) (if_then_else
6830 (match_operator 0 "lt_ge_comparison_operator"
6831 [(match_operand:QI 1 "memory_operand" "")
6832 (match_operand:QI 2 "const0_operand" "")])
6833 (label_ref (match_operand 3 "" ""))
6834 (pc)))]
6835 "TARGET_THUMB1"
6836{
d0f6c30d 6837 rtx xops[4];
a8e6c15d 6838 xops[1] = gen_reg_rtx (SImode);
6839 emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
6840 xops[2] = GEN_INT (127);
6841 xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
6842 VOIDmode, xops[1], xops[2]);
6843 xops[3] = operands[3];
6844 emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
6845 DONE;
6846})
6847
74f4459c 6848(define_expand "cbranchsf4"
6849 [(set (pc) (if_then_else
aa06947a 6850 (match_operator 0 "expandable_comparison_operator"
74f4459c 6851 [(match_operand:SF 1 "s_register_operand" "")
6852 (match_operand:SF 2 "arm_float_compare_operand" "")])
6853 (label_ref (match_operand 3 "" ""))
6854 (pc)))]
6855 "TARGET_32BIT && TARGET_HARD_FLOAT"
6856 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6857 operands[3])); DONE;"
6858)
6859
6860(define_expand "cbranchdf4"
6861 [(set (pc) (if_then_else
aa06947a 6862 (match_operator 0 "expandable_comparison_operator"
74f4459c 6863 [(match_operand:DF 1 "s_register_operand" "")
6864 (match_operand:DF 2 "arm_float_compare_operand" "")])
6865 (label_ref (match_operand 3 "" ""))
6866 (pc)))]
a50d7267 6867 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 6868 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6869 operands[3])); DONE;"
6870)
6871
74f4459c 6872(define_expand "cbranchdi4"
6873 [(set (pc) (if_then_else
aa06947a 6874 (match_operator 0 "expandable_comparison_operator"
a8045a4f 6875 [(match_operand:DI 1 "cmpdi_operand" "")
6876 (match_operand:DI 2 "cmpdi_operand" "")])
74f4459c 6877 (label_ref (match_operand 3 "" ""))
6878 (pc)))]
a8045a4f 6879 "TARGET_32BIT"
6880 "{
6881 rtx swap = NULL_RTX;
6882 enum rtx_code code = GET_CODE (operands[0]);
6883
6884 /* We should not have two constants. */
6885 gcc_assert (GET_MODE (operands[1]) == DImode
6886 || GET_MODE (operands[2]) == DImode);
6887
6888 /* Flip unimplemented DImode comparisons to a form that
6889 arm_gen_compare_reg can handle. */
6890 switch (code)
6891 {
6892 case GT:
6893 swap = gen_rtx_LT (VOIDmode, operands[2], operands[1]); break;
6894 case LE:
6895 swap = gen_rtx_GE (VOIDmode, operands[2], operands[1]); break;
6896 case GTU:
6897 swap = gen_rtx_LTU (VOIDmode, operands[2], operands[1]); break;
6898 case LEU:
6899 swap = gen_rtx_GEU (VOIDmode, operands[2], operands[1]); break;
6900 default:
6901 break;
6902 }
6903 if (swap)
6904 emit_jump_insn (gen_cbranch_cc (swap, operands[2], operands[1],
6905 operands[3]));
6906 else
6907 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6908 operands[3]));
6909 DONE;
6910 }"
74f4459c 6911)
6912
d60047aa 6913(define_insn "cbranchsi4_insn"
aeac46d4 6914 [(set (pc) (if_then_else
6915 (match_operator 0 "arm_comparison_operator"
747b7458 6916 [(match_operand:SI 1 "s_register_operand" "l,l*h")
25f905c2 6917 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
aeac46d4 6918 (label_ref (match_operand 3 "" ""))
6919 (pc)))]
25f905c2 6920 "TARGET_THUMB1"
747b7458 6921{
6922 rtx t = cfun->machine->thumb1_cc_insn;
6923 if (t != NULL_RTX)
d60047aa 6924 {
747b7458 6925 if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
6926 || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2]))
6927 t = NULL_RTX;
6928 if (cfun->machine->thumb1_cc_mode == CC_NOOVmode)
6929 {
6930 if (!noov_comparison_operator (operands[0], VOIDmode))
6931 t = NULL_RTX;
6932 }
6933 else if (cfun->machine->thumb1_cc_mode != CCmode)
d60047aa 6934 t = NULL_RTX;
6935 }
d60047aa 6936 if (t == NULL_RTX)
747b7458 6937 {
6938 output_asm_insn ("cmp\t%1, %2", operands);
6939 cfun->machine->thumb1_cc_insn = insn;
6940 cfun->machine->thumb1_cc_op0 = operands[1];
6941 cfun->machine->thumb1_cc_op1 = operands[2];
6942 cfun->machine->thumb1_cc_mode = CCmode;
6943 }
6944 else
6945 /* Ensure we emit the right type of condition code on the jump. */
6946 XEXP (operands[0], 0) = gen_rtx_REG (cfun->machine->thumb1_cc_mode,
6947 CC_REGNUM);
aeac46d4 6948
cffb2a26 6949 switch (get_attr_length (insn))
6950 {
6951 case 4: return \"b%d0\\t%l3\";
6952 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6953 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6954 }
747b7458 6955}
cffb2a26 6956 [(set (attr "far_jump")
6957 (if_then_else
6958 (eq_attr "length" "8")
6959 (const_string "yes")
6960 (const_string "no")))
6961 (set (attr "length")
6962 (if_then_else
6963 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6964 (le (minus (match_dup 3) (pc)) (const_int 256)))
6965 (const_int 4)
6966 (if_then_else
6967 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 6968 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 6969 (const_int 6)
6970 (const_int 8))))]
6971)
6972
aeac46d4 6973(define_insn "cbranchsi4_scratch"
6974 [(set (pc) (if_then_else
6975 (match_operator 4 "arm_comparison_operator"
6976 [(match_operand:SI 1 "s_register_operand" "l,0")
25f905c2 6977 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
aeac46d4 6978 (label_ref (match_operand 3 "" ""))
6979 (pc)))
6980 (clobber (match_scratch:SI 0 "=l,l"))]
25f905c2 6981 "TARGET_THUMB1"
aeac46d4 6982 "*
6983 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
6984
6985 switch (get_attr_length (insn))
6986 {
6987 case 4: return \"b%d4\\t%l3\";
6988 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6989 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6990 }
6991 "
6992 [(set (attr "far_jump")
6993 (if_then_else
6994 (eq_attr "length" "8")
6995 (const_string "yes")
6996 (const_string "no")))
6997 (set (attr "length")
6998 (if_then_else
6999 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7000 (le (minus (match_dup 3) (pc)) (const_int 256)))
7001 (const_int 4)
7002 (if_then_else
7003 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7004 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7005 (const_int 6)
7006 (const_int 8))))]
7007)
446a1e96 7008
747b7458 7009;; Two peepholes to generate subtract of 0 instead of a move if the
7010;; condition codes will be useful.
446a1e96 7011(define_peephole2
7012 [(set (match_operand:SI 0 "low_register_operand" "")
7013 (match_operand:SI 1 "low_register_operand" ""))
7014 (set (pc)
7015 (if_then_else (match_operator 2 "arm_comparison_operator"
7016 [(match_dup 1) (const_int 0)])
7017 (label_ref (match_operand 3 "" ""))
7018 (pc)))]
7019 "TARGET_THUMB1"
747b7458 7020 [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
7021 (set (pc)
7022 (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
446a1e96 7023 (label_ref (match_dup 3))
747b7458 7024 (pc)))]
7025 "")
446a1e96 7026
7027;; Sigh! This variant shouldn't be needed, but combine often fails to
7028;; merge cases like this because the op1 is a hard register in
07d32235 7029;; arm_class_likely_spilled_p.
446a1e96 7030(define_peephole2
7031 [(set (match_operand:SI 0 "low_register_operand" "")
7032 (match_operand:SI 1 "low_register_operand" ""))
7033 (set (pc)
7034 (if_then_else (match_operator 2 "arm_comparison_operator"
7035 [(match_dup 0) (const_int 0)])
7036 (label_ref (match_operand 3 "" ""))
7037 (pc)))]
7038 "TARGET_THUMB1"
747b7458 7039 [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
7040 (set (pc)
7041 (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
446a1e96 7042 (label_ref (match_dup 3))
747b7458 7043 (pc)))]
7044 "")
446a1e96 7045
cffb2a26 7046(define_insn "*negated_cbranchsi4"
7047 [(set (pc)
7048 (if_then_else
aed179ae 7049 (match_operator 0 "equality_operator"
aeac46d4 7050 [(match_operand:SI 1 "s_register_operand" "l")
7051 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
7052 (label_ref (match_operand 3 "" ""))
215b30b3 7053 (pc)))]
25f905c2 7054 "TARGET_THUMB1"
cffb2a26 7055 "*
7056 output_asm_insn (\"cmn\\t%1, %2\", operands);
7057 switch (get_attr_length (insn))
7058 {
7059 case 4: return \"b%d0\\t%l3\";
7060 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7061 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7062 }
7063 "
7064 [(set (attr "far_jump")
7065 (if_then_else
7066 (eq_attr "length" "8")
7067 (const_string "yes")
7068 (const_string "no")))
7069 (set (attr "length")
7070 (if_then_else
7071 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 7072 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 7073 (const_int 4)
7074 (if_then_else
341940e8 7075 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7076 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 7077 (const_int 6)
7078 (const_int 8))))]
7079)
7080
58d6528b 7081(define_insn "*tbit_cbranch"
7082 [(set (pc)
7083 (if_then_else
7084 (match_operator 0 "equality_operator"
7085 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
7086 (const_int 1)
7087 (match_operand:SI 2 "const_int_operand" "i"))
7088 (const_int 0)])
7089 (label_ref (match_operand 3 "" ""))
7090 (pc)))
7091 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 7092 "TARGET_THUMB1"
58d6528b 7093 "*
7094 {
7095 rtx op[3];
7096 op[0] = operands[4];
7097 op[1] = operands[1];
7098 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
7099
86efa74d 7100 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
7101 switch (get_attr_length (insn))
7102 {
7103 case 4: return \"b%d0\\t%l3\";
7104 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7105 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7106 }
7107 }"
7108 [(set (attr "far_jump")
7109 (if_then_else
7110 (eq_attr "length" "8")
7111 (const_string "yes")
7112 (const_string "no")))
7113 (set (attr "length")
7114 (if_then_else
7115 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7116 (le (minus (match_dup 3) (pc)) (const_int 256)))
7117 (const_int 4)
7118 (if_then_else
7119 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7120 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7121 (const_int 6)
7122 (const_int 8))))]
7123)
7124
7125(define_insn "*tlobits_cbranch"
7126 [(set (pc)
7127 (if_then_else
7128 (match_operator 0 "equality_operator"
7129 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
7130 (match_operand:SI 2 "const_int_operand" "i")
7131 (const_int 0))
7132 (const_int 0)])
7133 (label_ref (match_operand 3 "" ""))
7134 (pc)))
7135 (clobber (match_scratch:SI 4 "=l"))]
25f905c2 7136 "TARGET_THUMB1"
86efa74d 7137 "*
7138 {
7139 rtx op[3];
7140 op[0] = operands[4];
7141 op[1] = operands[1];
7142 op[2] = GEN_INT (32 - INTVAL (operands[2]));
7143
58d6528b 7144 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
7145 switch (get_attr_length (insn))
7146 {
7147 case 4: return \"b%d0\\t%l3\";
7148 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7149 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7150 }
7151 }"
7152 [(set (attr "far_jump")
7153 (if_then_else
7154 (eq_attr "length" "8")
7155 (const_string "yes")
7156 (const_string "no")))
7157 (set (attr "length")
7158 (if_then_else
7159 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7160 (le (minus (match_dup 3) (pc)) (const_int 256)))
7161 (const_int 4)
7162 (if_then_else
7163 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7164 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7165 (const_int 6)
7166 (const_int 8))))]
7167)
747b7458 7168
aeac46d4 7169(define_insn "*tstsi3_cbranch"
58d6528b 7170 [(set (pc)
7171 (if_then_else
aeac46d4 7172 (match_operator 3 "equality_operator"
7173 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
7174 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 7175 (const_int 0)])
aeac46d4 7176 (label_ref (match_operand 2 "" ""))
7177 (pc)))]
25f905c2 7178 "TARGET_THUMB1"
58d6528b 7179 "*
7180 {
aeac46d4 7181 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 7182 switch (get_attr_length (insn))
7183 {
aeac46d4 7184 case 4: return \"b%d3\\t%l2\";
7185 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
7186 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 7187 }
7188 }"
7189 [(set (attr "far_jump")
7190 (if_then_else
7191 (eq_attr "length" "8")
7192 (const_string "yes")
7193 (const_string "no")))
7194 (set (attr "length")
7195 (if_then_else
aeac46d4 7196 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
7197 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 7198 (const_int 4)
7199 (if_then_else
aeac46d4 7200 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
7201 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 7202 (const_int 6)
7203 (const_int 8))))]
7204)
7205
203c488f 7206(define_insn "*cbranchne_decr1"
7207 [(set (pc)
7208 (if_then_else (match_operator 3 "equality_operator"
7209 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
7210 (const_int 0)])
7211 (label_ref (match_operand 4 "" ""))
7212 (pc)))
aeac46d4 7213 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 7214 (plus:SI (match_dup 2) (const_int -1)))
7215 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
25f905c2 7216 "TARGET_THUMB1"
203c488f 7217 "*
7218 {
7219 rtx cond[2];
7220 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
7221 ? GEU : LTU),
58d6528b 7222 VOIDmode, operands[2], const1_rtx);
203c488f 7223 cond[1] = operands[4];
7224
7225 if (which_alternative == 0)
7226 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
7227 else if (which_alternative == 1)
7228 {
7229 /* We must provide an alternative for a hi reg because reload
7230 cannot handle output reloads on a jump instruction, but we
7231 can't subtract into that. Fortunately a mov from lo to hi
7232 does not clobber the condition codes. */
7233 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7234 output_asm_insn (\"mov\\t%0, %1\", operands);
7235 }
7236 else
7237 {
7238 /* Similarly, but the target is memory. */
7239 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7240 output_asm_insn (\"str\\t%1, %0\", operands);
7241 }
7242
7243 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7244 {
7245 case 4:
8aea555f 7246 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 7247 return \"\";
7248 case 6:
8aea555f 7249 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 7250 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
7251 default:
8aea555f 7252 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 7253 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7254 }
7255 }
7256 "
7257 [(set (attr "far_jump")
7258 (if_then_else
7259 (ior (and (eq (symbol_ref ("which_alternative"))
7260 (const_int 0))
7261 (eq_attr "length" "8"))
7262 (eq_attr "length" "10"))
7263 (const_string "yes")
7264 (const_string "no")))
7265 (set_attr_alternative "length"
7266 [
7267 ;; Alternative 0
7268 (if_then_else
7269 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7270 (le (minus (match_dup 4) (pc)) (const_int 256)))
7271 (const_int 4)
7272 (if_then_else
7273 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7274 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7275 (const_int 6)
7276 (const_int 8)))
7277 ;; Alternative 1
7278 (if_then_else
7279 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7280 (le (minus (match_dup 4) (pc)) (const_int 256)))
7281 (const_int 6)
7282 (if_then_else
7283 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7284 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7285 (const_int 8)
7286 (const_int 10)))
7287 ;; Alternative 2
7288 (if_then_else
7289 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7290 (le (minus (match_dup 4) (pc)) (const_int 256)))
7291 (const_int 6)
7292 (if_then_else
7293 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7294 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7295 (const_int 8)
7296 (const_int 10)))
7297 ;; Alternative 3
7298 (if_then_else
7299 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7300 (le (minus (match_dup 4) (pc)) (const_int 256)))
7301 (const_int 6)
7302 (if_then_else
7303 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7304 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7305 (const_int 8)
7306 (const_int 10)))])]
7307)
cffb2a26 7308
58d6528b 7309(define_insn "*addsi3_cbranch"
7310 [(set (pc)
7311 (if_then_else
b0694be0 7312 (match_operator 4 "arm_comparison_operator"
58d6528b 7313 [(plus:SI
e54011cb 7314 (match_operand:SI 2 "s_register_operand" "%0,l,*l,1,1,1")
7315 (match_operand:SI 3 "reg_or_int_operand" "IJ,lL,*l,lIJ,lIJ,lIJ"))
58d6528b 7316 (const_int 0)])
7317 (label_ref (match_operand 5 "" ""))
7318 (pc)))
aeac46d4 7319 (set
7320 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
7321 (plus:SI (match_dup 2) (match_dup 3)))
956a6170 7322 (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
25f905c2 7323 "TARGET_THUMB1
58d6528b 7324 && (GET_CODE (operands[4]) == EQ
7325 || GET_CODE (operands[4]) == NE
7326 || GET_CODE (operands[4]) == GE
7327 || GET_CODE (operands[4]) == LT)"
7328 "*
7329 {
7330 rtx cond[3];
7331
956a6170 7332 cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
58d6528b 7333 cond[1] = operands[2];
7334 cond[2] = operands[3];
7335
7336 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
7337 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
7338 else
7339 output_asm_insn (\"add\\t%0, %1, %2\", cond);
7340
956a6170 7341 if (which_alternative >= 2
58d6528b 7342 && which_alternative < 4)
7343 output_asm_insn (\"mov\\t%0, %1\", operands);
7344 else if (which_alternative >= 4)
7345 output_asm_insn (\"str\\t%1, %0\", operands);
7346
d0f6c30d 7347 switch (get_attr_length (insn) - ((which_alternative >= 2) ? 2 : 0))
58d6528b 7348 {
7349 case 4:
7350 return \"b%d4\\t%l5\";
7351 case 6:
7352 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7353 default:
7354 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7355 }
7356 }
7357 "
7358 [(set (attr "far_jump")
7359 (if_then_else
7360 (ior (and (lt (symbol_ref ("which_alternative"))
d0f6c30d 7361 (const_int 2))
58d6528b 7362 (eq_attr "length" "8"))
7363 (eq_attr "length" "10"))
7364 (const_string "yes")
7365 (const_string "no")))
7366 (set (attr "length")
7367 (if_then_else
7368 (lt (symbol_ref ("which_alternative"))
d0f6c30d 7369 (const_int 2))
58d6528b 7370 (if_then_else
7371 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7372 (le (minus (match_dup 5) (pc)) (const_int 256)))
7373 (const_int 4)
7374 (if_then_else
7375 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7376 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7377 (const_int 6)
7378 (const_int 8)))
7379 (if_then_else
7380 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7381 (le (minus (match_dup 5) (pc)) (const_int 256)))
7382 (const_int 6)
7383 (if_then_else
7384 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7385 (le (minus (match_dup 5) (pc)) (const_int 2048)))
7386 (const_int 8)
7387 (const_int 10)))))]
7388)
7389
7390(define_insn "*addsi3_cbranch_scratch"
7391 [(set (pc)
7392 (if_then_else
b0694be0 7393 (match_operator 3 "arm_comparison_operator"
58d6528b 7394 [(plus:SI
7395 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 7396 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 7397 (const_int 0)])
7398 (label_ref (match_operand 4 "" ""))
7399 (pc)))
7400 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
25f905c2 7401 "TARGET_THUMB1
58d6528b 7402 && (GET_CODE (operands[3]) == EQ
7403 || GET_CODE (operands[3]) == NE
7404 || GET_CODE (operands[3]) == GE
7405 || GET_CODE (operands[3]) == LT)"
7406 "*
7407 {
7408 switch (which_alternative)
7409 {
7410 case 0:
7411 output_asm_insn (\"cmp\t%1, #%n2\", operands);
7412 break;
7413 case 1:
7414 output_asm_insn (\"cmn\t%1, %2\", operands);
7415 break;
0f5e9701 7416 case 2:
3a445a04 7417 if (INTVAL (operands[2]) < 0)
7418 output_asm_insn (\"sub\t%0, %1, %2\", operands);
7419 else
7420 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 7421 break;
0f5e9701 7422 case 3:
3a445a04 7423 if (INTVAL (operands[2]) < 0)
7424 output_asm_insn (\"sub\t%0, %0, %2\", operands);
7425 else
7426 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 7427 break;
7428 }
7429
7430 switch (get_attr_length (insn))
7431 {
7432 case 4:
7433 return \"b%d3\\t%l4\";
7434 case 6:
7435 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7436 default:
7437 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7438 }
7439 }
7440 "
7441 [(set (attr "far_jump")
7442 (if_then_else
7443 (eq_attr "length" "8")
7444 (const_string "yes")
7445 (const_string "no")))
7446 (set (attr "length")
7447 (if_then_else
7448 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7449 (le (minus (match_dup 4) (pc)) (const_int 256)))
7450 (const_int 4)
7451 (if_then_else
7452 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7453 (le (minus (match_dup 4) (pc)) (const_int 2048)))
7454 (const_int 6)
7455 (const_int 8))))]
7456)
7457
58d6528b 7458
9c08d1fa 7459;; Comparison and test insns
7460
cffb2a26 7461(define_insn "*arm_cmpsi_insn"
bd5b4116 7462 [(set (reg:CC CC_REGNUM)
a6864a24 7463 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r")
7464 (match_operand:SI 1 "arm_add_operand" "Py,r,rI,L")))]
25f905c2 7465 "TARGET_32BIT"
5565501b 7466 "@
a6864a24 7467 cmp%?\\t%0, %1
7468 cmp%?\\t%0, %1
aea4c774 7469 cmp%?\\t%0, %1
7470 cmn%?\\t%0, #%n1"
a6864a24 7471 [(set_attr "conds" "set")
7472 (set_attr "arch" "t2,t2,any,any")
7473 (set_attr "length" "2,2,4,4")]
cffb2a26 7474)
b11cae9e 7475
d5d4dc8d 7476(define_insn "*cmpsi_shiftsi"
bd5b4116 7477 [(set (reg:CC CC_REGNUM)
d5d4dc8d 7478 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 7479 (match_operator:SI 3 "shift_operator"
d5d4dc8d 7480 [(match_operand:SI 1 "s_register_operand" "r,r")
7481 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
7482 "TARGET_32BIT"
aea4c774 7483 "cmp%?\\t%0, %1%S3"
344495ea 7484 [(set_attr "conds" "set")
331beb1a 7485 (set_attr "shift" "1")
d5d4dc8d 7486 (set_attr "arch" "32,a")
7487 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7488
d5d4dc8d 7489(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 7490 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 7491 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
d5d4dc8d 7492 [(match_operand:SI 1 "s_register_operand" "r,r")
7493 (match_operand:SI 2 "shift_amount_operand" "M,rM")])
7494 (match_operand:SI 0 "s_register_operand" "r,r")))]
7495 "TARGET_32BIT"
aea4c774 7496 "cmp%?\\t%0, %1%S3"
344495ea 7497 [(set_attr "conds" "set")
331beb1a 7498 (set_attr "shift" "1")
d5d4dc8d 7499 (set_attr "arch" "32,a")
7500 (set_attr "type" "alu_shift,alu_shift_reg")])
b11cae9e 7501
25f905c2 7502(define_insn "*arm_cmpsi_negshiftsi_si"
aed179ae 7503 [(set (reg:CC_Z CC_REGNUM)
7504 (compare:CC_Z
7505 (neg:SI (match_operator:SI 1 "shift_operator"
7506 [(match_operand:SI 2 "s_register_operand" "r")
7507 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7508 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 7509 "TARGET_ARM"
aed179ae 7510 "cmn%?\\t%0, %2%S1"
344495ea 7511 [(set_attr "conds" "set")
aed179ae 7512 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7513 (const_string "alu_shift")
7514 (const_string "alu_shift_reg")))]
0d66636f 7515)
b11cae9e 7516
a8045a4f 7517;; DImode comparisons. The generic code generates branches that
7518;; if-conversion can not reduce to a conditional compare, so we do
7519;; that directly.
7520
7521(define_insn "*arm_cmpdi_insn"
7522 [(set (reg:CC_NCV CC_REGNUM)
7523 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7524 (match_operand:DI 1 "arm_di_operand" "rDi")))
7525 (clobber (match_scratch:SI 2 "=r"))]
7526 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
7527 "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7528 [(set_attr "conds" "set")
7529 (set_attr "length" "8")]
7530)
7531
7532(define_insn "*arm_cmpdi_unsigned"
7533 [(set (reg:CC_CZ CC_REGNUM)
7534 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "r")
7535 (match_operand:DI 1 "arm_di_operand" "rDi")))]
7536 "TARGET_ARM"
7537 "cmp%?\\t%R0, %R1\;cmpeq\\t%Q0, %Q1"
7538 [(set_attr "conds" "set")
7539 (set_attr "length" "8")]
7540)
7541
7542(define_insn "*arm_cmpdi_zero"
7543 [(set (reg:CC_Z CC_REGNUM)
7544 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7545 (const_int 0)))
7546 (clobber (match_scratch:SI 1 "=r"))]
7547 "TARGET_32BIT"
7548 "orr%.\\t%1, %Q0, %R0"
7549 [(set_attr "conds" "set")]
7550)
7551
7552(define_insn "*thumb_cmpdi_zero"
7553 [(set (reg:CC_Z CC_REGNUM)
7554 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
7555 (const_int 0)))
7556 (clobber (match_scratch:SI 1 "=l"))]
7557 "TARGET_THUMB1"
7558 "orr\\t%1, %Q0, %R0"
7559 [(set_attr "conds" "set")
7560 (set_attr "length" "2")]
7561)
7562
7d57ec45 7563;; Cirrus SF compare instruction
7564(define_insn "*cirrus_cmpsf"
7565 [(set (reg:CCFP CC_REGNUM)
7566 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7567 (match_operand:SF 1 "cirrus_fp_register" "v")))]
a2cd141b 7568 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7569 "cfcmps%?\\tr15, %V0, %V1"
2c6c7d8b 7570 [(set_attr "type" "mav_farith")
7d57ec45 7571 (set_attr "cirrus" "compare")]
7572)
7573
7574;; Cirrus DF compare instruction
7575(define_insn "*cirrus_cmpdf"
7576 [(set (reg:CCFP CC_REGNUM)
7577 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7578 (match_operand:DF 1 "cirrus_fp_register" "v")))]
a2cd141b 7579 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7580 "cfcmpd%?\\tr15, %V0, %V1"
2c6c7d8b 7581 [(set_attr "type" "mav_farith")
7d57ec45 7582 (set_attr "cirrus" "compare")]
7583)
7584
7d57ec45 7585(define_insn "*cirrus_cmpdi"
7586 [(set (reg:CC CC_REGNUM)
7587 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7588 (match_operand:DI 1 "cirrus_fp_register" "v")))]
a2cd141b 7589 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 7590 "cfcmp64%?\\tr15, %V0, %V1"
2c6c7d8b 7591 [(set_attr "type" "mav_farith")
7d57ec45 7592 (set_attr "cirrus" "compare")]
7593)
7594
9c08d1fa 7595; This insn allows redundant compares to be removed by cse, nothing should
7596; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7597; is deleted later on. The match_dup will match the mode here, so that
7598; mode changes of the condition codes aren't lost by this even though we don't
7599; specify what they are.
7600
8a18b90c 7601(define_insn "*deleted_compare"
9c08d1fa 7602 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
25f905c2 7603 "TARGET_32BIT"
40dbec34 7604 "\\t%@ deleted compare"
cffb2a26 7605 [(set_attr "conds" "set")
7606 (set_attr "length" "0")]
7607)
9c08d1fa 7608
7609\f
7610;; Conditional branch insns
7611
74f4459c 7612(define_expand "cbranch_cc"
9c08d1fa 7613 [(set (pc)
74f4459c 7614 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7615 (match_operand 2 "" "")])
7616 (label_ref (match_operand 3 "" ""))
9c08d1fa 7617 (pc)))]
25f905c2 7618 "TARGET_32BIT"
74f4459c 7619 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
7620 operands[1], operands[2]);
7621 operands[2] = const0_rtx;"
8fa3ba89 7622)
7623
7624;;
7625;; Patterns to match conditional branch insns.
7626;;
7627
cffb2a26 7628(define_insn "*arm_cond_branch"
9c08d1fa 7629 [(set (pc)
8fa3ba89 7630 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7631 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7632 (label_ref (match_operand 0 "" ""))
7633 (pc)))]
25f905c2 7634 "TARGET_32BIT"
d75350ce 7635 "*
9c08d1fa 7636 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7637 {
7638 arm_ccfsm_state += 2;
7639 return \"\";
7640 }
e2348bcb 7641 return \"b%d1\\t%l0\";
cffb2a26 7642 "
a2cd141b 7643 [(set_attr "conds" "use")
a6864a24 7644 (set_attr "type" "branch")
7645 (set (attr "length")
7646 (if_then_else
0bf497f5 7647 (and (match_test "TARGET_THUMB2")
a6864a24 7648 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7649 (le (minus (match_dup 0) (pc)) (const_int 256))))
7650 (const_int 2)
7651 (const_int 4)))]
cffb2a26 7652)
d75350ce 7653
cffb2a26 7654(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7655 [(set (pc)
8fa3ba89 7656 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7657 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7658 (pc)
7659 (label_ref (match_operand 0 "" ""))))]
25f905c2 7660 "TARGET_32BIT"
d75350ce 7661 "*
9c08d1fa 7662 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7663 {
7664 arm_ccfsm_state += 2;
7665 return \"\";
7666 }
e2348bcb 7667 return \"b%D1\\t%l0\";
cffb2a26 7668 "
a2cd141b 7669 [(set_attr "conds" "use")
a6864a24 7670 (set_attr "type" "branch")
7671 (set (attr "length")
7672 (if_then_else
0bf497f5 7673 (and (match_test "TARGET_THUMB2")
a6864a24 7674 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7675 (le (minus (match_dup 0) (pc)) (const_int 256))))
7676 (const_int 2)
7677 (const_int 4)))]
cffb2a26 7678)
7679
b11cae9e 7680\f
9c08d1fa 7681
7682; scc insns
7683
74f4459c 7684(define_expand "cstore_cc"
7db9af5d 7685 [(set (match_operand:SI 0 "s_register_operand" "")
74f4459c 7686 (match_operator:SI 1 "" [(match_operand 2 "" "")
7687 (match_operand 3 "" "")]))]
25f905c2 7688 "TARGET_32BIT"
74f4459c 7689 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7690 operands[2], operands[3]);
7691 operands[3] = const0_rtx;"
8fa3ba89 7692)
7693
f7fbdd4a 7694(define_insn "*mov_scc"
9c08d1fa 7695 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7696 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7697 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7698 "TARGET_ARM"
4d61e570 7699 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 7700 [(set_attr "conds" "use")
d2a518d1 7701 (set_attr "insn" "mov")
cffb2a26 7702 (set_attr "length" "8")]
7703)
9c08d1fa 7704
f7fbdd4a 7705(define_insn "*mov_negscc"
9c08d1fa 7706 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7707 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7708 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7709 "TARGET_ARM"
4d61e570 7710 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 7711 [(set_attr "conds" "use")
d2a518d1 7712 (set_attr "insn" "mov")
cffb2a26 7713 (set_attr "length" "8")]
7714)
9c08d1fa 7715
f7fbdd4a 7716(define_insn "*mov_notscc"
9c08d1fa 7717 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7718 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7719 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7720 "TARGET_ARM"
4d61e570 7721 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 7722 [(set_attr "conds" "use")
d2a518d1 7723 (set_attr "insn" "mov")
cffb2a26 7724 (set_attr "length" "8")]
7725)
9c08d1fa 7726
595d88b5 7727(define_expand "cstoresi4"
7728 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7729 (match_operator:SI 1 "expandable_comparison_operator"
595d88b5 7730 [(match_operand:SI 2 "s_register_operand" "")
7731 (match_operand:SI 3 "reg_or_int_operand" "")]))]
74f4459c 7732 "TARGET_32BIT || TARGET_THUMB1"
595d88b5 7733 "{
7734 rtx op3, scratch, scratch2;
7735
74f4459c 7736 if (!TARGET_THUMB1)
7737 {
7738 if (!arm_add_operand (operands[3], SImode))
7739 operands[3] = force_reg (SImode, operands[3]);
7740 emit_insn (gen_cstore_cc (operands[0], operands[1],
7741 operands[2], operands[3]));
7742 DONE;
7743 }
7744
595d88b5 7745 if (operands[3] == const0_rtx)
7746 {
7747 switch (GET_CODE (operands[1]))
7748 {
7749 case EQ:
25f905c2 7750 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
595d88b5 7751 break;
7752
7753 case NE:
25f905c2 7754 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
595d88b5 7755 break;
7756
7757 case LE:
7758 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7759 NULL_RTX, 0, OPTAB_WIDEN);
7760 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7761 NULL_RTX, 0, OPTAB_WIDEN);
7762 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7763 operands[0], 1, OPTAB_WIDEN);
7764 break;
7765
7766 case GE:
7767 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7768 NULL_RTX, 1);
7769 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7770 NULL_RTX, 1, OPTAB_WIDEN);
7771 break;
7772
7773 case GT:
7774 scratch = expand_binop (SImode, ashr_optab, operands[2],
7775 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7776 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7777 NULL_RTX, 0, OPTAB_WIDEN);
7778 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7779 0, OPTAB_WIDEN);
7780 break;
7781
7782 /* LT is handled by generic code. No need for unsigned with 0. */
7783 default:
7784 FAIL;
7785 }
7786 DONE;
7787 }
7788
7789 switch (GET_CODE (operands[1]))
7790 {
7791 case EQ:
7792 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7793 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7794 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
595d88b5 7795 break;
7796
7797 case NE:
7798 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7799 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7800 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
595d88b5 7801 break;
7802
7803 case LE:
7804 op3 = force_reg (SImode, operands[3]);
7805
7806 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7807 NULL_RTX, 1, OPTAB_WIDEN);
7808 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7809 NULL_RTX, 0, OPTAB_WIDEN);
25f905c2 7810 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7811 op3, operands[2]));
7812 break;
7813
7814 case GE:
7815 op3 = operands[3];
25f905c2 7816 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7817 op3 = force_reg (SImode, op3);
7818 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7819 NULL_RTX, 0, OPTAB_WIDEN);
7820 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7821 NULL_RTX, 1, OPTAB_WIDEN);
25f905c2 7822 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
595d88b5 7823 operands[2], op3));
7824 break;
7825
7826 case LEU:
7827 op3 = force_reg (SImode, operands[3]);
7828 scratch = force_reg (SImode, const0_rtx);
25f905c2 7829 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7830 op3, operands[2]));
7831 break;
7832
7833 case GEU:
7834 op3 = operands[3];
25f905c2 7835 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7836 op3 = force_reg (SImode, op3);
7837 scratch = force_reg (SImode, const0_rtx);
25f905c2 7838 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
595d88b5 7839 operands[2], op3));
7840 break;
7841
7842 case LTU:
7843 op3 = operands[3];
25f905c2 7844 if (!thumb1_cmp_operand (op3, SImode))
595d88b5 7845 op3 = force_reg (SImode, op3);
7846 scratch = gen_reg_rtx (SImode);
408b7ae5 7847 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
595d88b5 7848 break;
7849
7850 case GTU:
7851 op3 = force_reg (SImode, operands[3]);
7852 scratch = gen_reg_rtx (SImode);
408b7ae5 7853 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
595d88b5 7854 break;
7855
7856 /* No good sequences for GT, LT. */
7857 default:
7858 FAIL;
7859 }
7860 DONE;
7861}")
7862
74f4459c 7863(define_expand "cstoresf4"
7864 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7865 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7866 [(match_operand:SF 2 "s_register_operand" "")
7867 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
7868 "TARGET_32BIT && TARGET_HARD_FLOAT"
7869 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7870 operands[2], operands[3])); DONE;"
7871)
7872
7873(define_expand "cstoredf4"
7874 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7875 (match_operator:SI 1 "expandable_comparison_operator"
74f4459c 7876 [(match_operand:DF 2 "s_register_operand" "")
7877 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
d63ed457 7878 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
74f4459c 7879 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7880 operands[2], operands[3])); DONE;"
7881)
7882
74f4459c 7883(define_expand "cstoredi4"
7884 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 7885 (match_operator:SI 1 "expandable_comparison_operator"
a8045a4f 7886 [(match_operand:DI 2 "cmpdi_operand" "")
7887 (match_operand:DI 3 "cmpdi_operand" "")]))]
7888 "TARGET_32BIT"
7889 "{
7890 rtx swap = NULL_RTX;
7891 enum rtx_code code = GET_CODE (operands[1]);
7892
7893 /* We should not have two constants. */
7894 gcc_assert (GET_MODE (operands[2]) == DImode
7895 || GET_MODE (operands[3]) == DImode);
7896
7897 /* Flip unimplemented DImode comparisons to a form that
7898 arm_gen_compare_reg can handle. */
7899 switch (code)
7900 {
7901 case GT:
7902 swap = gen_rtx_LT (VOIDmode, operands[3], operands[2]); break;
7903 case LE:
7904 swap = gen_rtx_GE (VOIDmode, operands[3], operands[2]); break;
7905 case GTU:
7906 swap = gen_rtx_LTU (VOIDmode, operands[3], operands[2]); break;
7907 case LEU:
7908 swap = gen_rtx_GEU (VOIDmode, operands[3], operands[2]); break;
7909 default:
7910 break;
7911 }
7912 if (swap)
7913 emit_insn (gen_cstore_cc (operands[0], swap, operands[3],
7914 operands[2]));
7915 else
7916 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
7917 operands[3]));
7918 DONE;
7919 }"
74f4459c 7920)
7921
25f905c2 7922(define_expand "cstoresi_eq0_thumb1"
595d88b5 7923 [(parallel
7924 [(set (match_operand:SI 0 "s_register_operand" "")
7925 (eq:SI (match_operand:SI 1 "s_register_operand" "")
7926 (const_int 0)))
7927 (clobber (match_dup:SI 2))])]
25f905c2 7928 "TARGET_THUMB1"
595d88b5 7929 "operands[2] = gen_reg_rtx (SImode);"
7930)
7931
25f905c2 7932(define_expand "cstoresi_ne0_thumb1"
595d88b5 7933 [(parallel
7934 [(set (match_operand:SI 0 "s_register_operand" "")
7935 (ne:SI (match_operand:SI 1 "s_register_operand" "")
7936 (const_int 0)))
7937 (clobber (match_dup:SI 2))])]
25f905c2 7938 "TARGET_THUMB1"
595d88b5 7939 "operands[2] = gen_reg_rtx (SImode);"
7940)
7941
25f905c2 7942(define_insn "*cstoresi_eq0_thumb1_insn"
595d88b5 7943 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
7944 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
7945 (const_int 0)))
7946 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
25f905c2 7947 "TARGET_THUMB1"
595d88b5 7948 "@
7949 neg\\t%0, %1\;adc\\t%0, %0, %1
7950 neg\\t%2, %1\;adc\\t%0, %1, %2"
7951 [(set_attr "length" "4")]
7952)
7953
25f905c2 7954(define_insn "*cstoresi_ne0_thumb1_insn"
595d88b5 7955 [(set (match_operand:SI 0 "s_register_operand" "=l")
7956 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
7957 (const_int 0)))
7958 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
25f905c2 7959 "TARGET_THUMB1"
595d88b5 7960 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
7961 [(set_attr "length" "4")]
7962)
7963
408b7ae5 7964;; Used as part of the expansion of thumb ltu and gtu sequences
25f905c2 7965(define_insn "cstoresi_nltu_thumb1"
595d88b5 7966 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
a277ddf3 7967 (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
25f905c2 7968 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
7969 "TARGET_THUMB1"
595d88b5 7970 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
7971 [(set_attr "length" "4")]
7972)
7973
408b7ae5 7974(define_insn_and_split "cstoresi_ltu_thumb1"
7975 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
7976 (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
7977 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
7978 "TARGET_THUMB1"
7979 "#"
7980 "TARGET_THUMB1"
7981 [(set (match_dup 3)
7982 (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
7983 (set (match_dup 0) (neg:SI (match_dup 3)))]
7984 "operands[3] = gen_reg_rtx (SImode);"
7985 [(set_attr "length" "4")]
7986)
7987
595d88b5 7988;; Used as part of the expansion of thumb les sequence.
25f905c2 7989(define_insn "thumb1_addsi3_addgeu"
595d88b5 7990 [(set (match_operand:SI 0 "s_register_operand" "=l")
7991 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7992 (match_operand:SI 2 "s_register_operand" "l"))
7993 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
25f905c2 7994 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
7995 "TARGET_THUMB1"
595d88b5 7996 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
7997 [(set_attr "length" "4")]
7998)
7999
9c08d1fa 8000\f
39b5e676 8001;; Conditional move insns
8002
8003(define_expand "movsicc"
8a18b90c 8004 [(set (match_operand:SI 0 "s_register_operand" "")
aa06947a 8005 (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
aea4c774 8006 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 8007 (match_operand:SI 3 "arm_not_operand" "")))]
25f905c2 8008 "TARGET_32BIT"
39b5e676 8009 "
215b30b3 8010 {
8011 enum rtx_code code = GET_CODE (operands[1]);
278b301d 8012 rtx ccreg;
8013
8014 if (code == UNEQ || code == LTGT)
8015 FAIL;
39b5e676 8016
74f4459c 8017 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8018 XEXP (operands[1], 1));
29bb088d 8019 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8020 }"
8021)
39b5e676 8022
8023(define_expand "movsfcc"
8a18b90c 8024 [(set (match_operand:SF 0 "s_register_operand" "")
aa06947a 8025 (if_then_else:SF (match_operand 1 "expandable_comparison_operator" "")
8a18b90c 8026 (match_operand:SF 2 "s_register_operand" "")
8027 (match_operand:SF 3 "nonmemory_operand" "")))]
19f6bf8d 8028 "TARGET_32BIT && TARGET_HARD_FLOAT"
39b5e676 8029 "
215b30b3 8030 {
8031 enum rtx_code code = GET_CODE (operands[1]);
8032 rtx ccreg;
f082f1c4 8033
278b301d 8034 if (code == UNEQ || code == LTGT)
8035 FAIL;
8036
215b30b3 8037 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
a2cd141b 8038 Otherwise, ensure it is a valid FP add operand */
8039 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
8040 || (!arm_float_add_operand (operands[3], SFmode)))
215b30b3 8041 operands[3] = force_reg (SFmode, operands[3]);
39b5e676 8042
74f4459c 8043 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8044 XEXP (operands[1], 1));
29bb088d 8045 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8046 }"
8047)
39b5e676 8048
8049(define_expand "movdfcc"
8a18b90c 8050 [(set (match_operand:DF 0 "s_register_operand" "")
aa06947a 8051 (if_then_else:DF (match_operand 1 "expandable_comparison_operator" "")
8a18b90c 8052 (match_operand:DF 2 "s_register_operand" "")
a2cd141b 8053 (match_operand:DF 3 "arm_float_add_operand" "")))]
a50d7267 8054 "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
39b5e676 8055 "
215b30b3 8056 {
8057 enum rtx_code code = GET_CODE (operands[1]);
278b301d 8058 rtx ccreg;
39b5e676 8059
278b301d 8060 if (code == UNEQ || code == LTGT)
8061 FAIL;
8062
74f4459c 8063 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8064 XEXP (operands[1], 1));
29bb088d 8065 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 8066 }"
8067)
39b5e676 8068
8069(define_insn "*movsicc_insn"
f082f1c4 8070 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 8071 (if_then_else:SI
8fa3ba89 8072 (match_operator 3 "arm_comparison_operator"
8a18b90c 8073 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8074 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8075 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 8076 "TARGET_ARM"
39b5e676 8077 "@
8a18b90c 8078 mov%D3\\t%0, %2
8079 mvn%D3\\t%0, #%B2
f082f1c4 8080 mov%d3\\t%0, %1
8081 mvn%d3\\t%0, #%B1
8a18b90c 8082 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8083 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8084 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8085 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 8086 [(set_attr "length" "4,4,4,4,8,8,8,8")
d2a518d1 8087 (set_attr "conds" "use")
8088 (set_attr "insn" "mov,mvn,mov,mvn,mov,mov,mvn,mvn")]
215b30b3 8089)
39b5e676 8090
39b5e676 8091(define_insn "*movsfcc_soft_insn"
f082f1c4 8092 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 8093 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 8094 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 8095 (match_operand:SF 1 "s_register_operand" "0,r")
8096 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 8097 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 8098 "@
8099 mov%D3\\t%0, %2
8100 mov%d3\\t%0, %1"
d2a518d1 8101 [(set_attr "conds" "use")
8102 (set_attr "insn" "mov")]
8fa3ba89 8103)
39b5e676 8104
39b5e676 8105\f
9c08d1fa 8106;; Jump and linkage insns
8107
cffb2a26 8108(define_expand "jump"
9c08d1fa 8109 [(set (pc)
8110 (label_ref (match_operand 0 "" "")))]
cffb2a26 8111 "TARGET_EITHER"
9c08d1fa 8112 ""
cffb2a26 8113)
8114
8115(define_insn "*arm_jump"
8116 [(set (pc)
8117 (label_ref (match_operand 0 "" "")))]
25f905c2 8118 "TARGET_32BIT"
9c08d1fa 8119 "*
0d66636f 8120 {
8121 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8122 {
8123 arm_ccfsm_state += 2;
8124 return \"\";
8125 }
8126 return \"b%?\\t%l0\";
8127 }
8128 "
a6864a24 8129 [(set_attr "predicable" "yes")
8130 (set (attr "length")
8131 (if_then_else
0bf497f5 8132 (and (match_test "TARGET_THUMB2")
a6864a24 8133 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8134 (le (minus (match_dup 0) (pc)) (const_int 2048))))
8135 (const_int 2)
8136 (const_int 4)))]
0d66636f 8137)
9c08d1fa 8138
cffb2a26 8139(define_insn "*thumb_jump"
8140 [(set (pc)
8141 (label_ref (match_operand 0 "" "")))]
25f905c2 8142 "TARGET_THUMB1"
cffb2a26 8143 "*
8144 if (get_attr_length (insn) == 2)
8145 return \"b\\t%l0\";
8146 return \"bl\\t%l0\\t%@ far jump\";
8147 "
8148 [(set (attr "far_jump")
8149 (if_then_else
8150 (eq_attr "length" "4")
8151 (const_string "yes")
8152 (const_string "no")))
8153 (set (attr "length")
8154 (if_then_else
911ed8af 8155 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8156 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 8157 (const_int 2)
8158 (const_int 4)))]
8159)
8160
d3373b54 8161(define_expand "call"
8162 [(parallel [(call (match_operand 0 "memory_operand" "")
8163 (match_operand 1 "general_operand" ""))
cffb2a26 8164 (use (match_operand 2 "" ""))
bd5b4116 8165 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8166 "TARGET_EITHER"
6c4c2133 8167 "
8168 {
bac7fc85 8169 rtx callee, pat;
bbe777ea 8170
bbe777ea 8171 /* In an untyped call, we can get NULL for operand 2. */
8172 if (operands[2] == NULL_RTX)
8173 operands[2] = const0_rtx;
8174
de55252a 8175 /* Decide if we should generate indirect calls by loading the
85c36fd1 8176 32-bit address of the callee into a register before performing the
de55252a 8177 branch and link. */
8178 callee = XEXP (operands[0], 0);
8179 if (GET_CODE (callee) == SYMBOL_REF
8180 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8181 : !REG_P (callee))
bbe777ea 8182 XEXP (operands[0], 0) = force_reg (Pmode, callee);
bac7fc85 8183
8184 pat = gen_call_internal (operands[0], operands[1], operands[2]);
8185 arm_emit_call_insn (pat, XEXP (operands[0], 0));
8186 DONE;
6c4c2133 8187 }"
8188)
d3373b54 8189
bac7fc85 8190(define_expand "call_internal"
8191 [(parallel [(call (match_operand 0 "memory_operand" "")
8192 (match_operand 1 "general_operand" ""))
8193 (use (match_operand 2 "" ""))
8194 (clobber (reg:SI LR_REGNUM))])])
8195
f1039640 8196(define_insn "*call_reg_armv5"
d3373b54 8197 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 8198 (match_operand 1 "" ""))
8199 (use (match_operand 2 "" ""))
bd5b4116 8200 (clobber (reg:SI LR_REGNUM))]
f1039640 8201 "TARGET_ARM && arm_arch5"
8202 "blx%?\\t%0"
8203 [(set_attr "type" "call")]
8204)
8205
8206(define_insn "*call_reg_arm"
8207 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8208 (match_operand 1 "" ""))
8209 (use (match_operand 2 "" ""))
8210 (clobber (reg:SI LR_REGNUM))]
8211 "TARGET_ARM && !arm_arch5"
9c08d1fa 8212 "*
5565501b 8213 return output_call (operands);
cffb2a26 8214 "
8215 ;; length is worst case, normally it is only two
8216 [(set_attr "length" "12")
8217 (set_attr "type" "call")]
8218)
9c08d1fa 8219
89504fc1 8220
8221;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
8222;; considered a function call by the branch predictor of some cores (PR40887).
8223;; Falls back to blx rN (*call_reg_armv5).
8224
f7fbdd4a 8225(define_insn "*call_mem"
a3c63a9d 8226 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 8227 (match_operand 1 "" ""))
8228 (use (match_operand 2 "" ""))
bd5b4116 8229 (clobber (reg:SI LR_REGNUM))]
89504fc1 8230 "TARGET_ARM && !arm_arch5"
9c08d1fa 8231 "*
5565501b 8232 return output_call_mem (operands);
cffb2a26 8233 "
8234 [(set_attr "length" "12")
8235 (set_attr "type" "call")]
8236)
8237
25f905c2 8238(define_insn "*call_reg_thumb1_v5"
cffb2a26 8239 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8240 (match_operand 1 "" ""))
8241 (use (match_operand 2 "" ""))
bd5b4116 8242 (clobber (reg:SI LR_REGNUM))]
25f905c2 8243 "TARGET_THUMB1 && arm_arch5"
f1039640 8244 "blx\\t%0"
8245 [(set_attr "length" "2")
8246 (set_attr "type" "call")]
cffb2a26 8247)
8248
25f905c2 8249(define_insn "*call_reg_thumb1"
f1039640 8250 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8251 (match_operand 1 "" ""))
8252 (use (match_operand 2 "" ""))
bd5b4116 8253 (clobber (reg:SI LR_REGNUM))]
25f905c2 8254 "TARGET_THUMB1 && !arm_arch5"
cffb2a26 8255 "*
8256 {
150502c9 8257 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8258 return thumb_call_via_reg (operands[0]);
150502c9 8259 else if (operands[1] == const0_rtx)
f1039640 8260 return \"bl\\t%__interwork_call_via_%0\";
150502c9 8261 else if (frame_pointer_needed)
8262 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 8263 else
150502c9 8264 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 8265 }"
8266 [(set_attr "type" "call")]
8267)
9c08d1fa 8268
d3373b54 8269(define_expand "call_value"
e0698af7 8270 [(parallel [(set (match_operand 0 "" "")
8271 (call (match_operand 1 "memory_operand" "")
8272 (match_operand 2 "general_operand" "")))
cffb2a26 8273 (use (match_operand 3 "" ""))
bd5b4116 8274 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 8275 "TARGET_EITHER"
6c4c2133 8276 "
8277 {
bac7fc85 8278 rtx pat, callee;
bbe777ea 8279
8280 /* In an untyped call, we can get NULL for operand 2. */
8281 if (operands[3] == 0)
8282 operands[3] = const0_rtx;
8283
de55252a 8284 /* Decide if we should generate indirect calls by loading the
8285 32-bit address of the callee into a register before performing the
8286 branch and link. */
8287 callee = XEXP (operands[1], 0);
8288 if (GET_CODE (callee) == SYMBOL_REF
8289 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8290 : !REG_P (callee))
78fe751b 8291 XEXP (operands[1], 0) = force_reg (Pmode, callee);
bac7fc85 8292
8293 pat = gen_call_value_internal (operands[0], operands[1],
8294 operands[2], operands[3]);
8295 arm_emit_call_insn (pat, XEXP (operands[1], 0));
8296 DONE;
6c4c2133 8297 }"
8298)
d3373b54 8299
bac7fc85 8300(define_expand "call_value_internal"
8301 [(parallel [(set (match_operand 0 "" "")
8302 (call (match_operand 1 "memory_operand" "")
8303 (match_operand 2 "general_operand" "")))
8304 (use (match_operand 3 "" ""))
8305 (clobber (reg:SI LR_REGNUM))])])
8306
f1039640 8307(define_insn "*call_value_reg_armv5"
27ed6835 8308 [(set (match_operand 0 "" "")
755eb2b4 8309 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 8310 (match_operand 2 "" "")))
bbe777ea 8311 (use (match_operand 3 "" ""))
bd5b4116 8312 (clobber (reg:SI LR_REGNUM))]
f1039640 8313 "TARGET_ARM && arm_arch5"
8314 "blx%?\\t%1"
8315 [(set_attr "type" "call")]
8316)
8317
8318(define_insn "*call_value_reg_arm"
8319 [(set (match_operand 0 "" "")
8320 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8321 (match_operand 2 "" "")))
8322 (use (match_operand 3 "" ""))
8323 (clobber (reg:SI LR_REGNUM))]
8324 "TARGET_ARM && !arm_arch5"
9c08d1fa 8325 "*
215b30b3 8326 return output_call (&operands[1]);
cffb2a26 8327 "
8328 [(set_attr "length" "12")
8329 (set_attr "type" "call")]
8330)
9c08d1fa 8331
89504fc1 8332;; Note: see *call_mem
8333
f7fbdd4a 8334(define_insn "*call_value_mem"
27ed6835 8335 [(set (match_operand 0 "" "")
a3c63a9d 8336 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 8337 (match_operand 2 "" "")))
bbe777ea 8338 (use (match_operand 3 "" ""))
bd5b4116 8339 (clobber (reg:SI LR_REGNUM))]
89504fc1 8340 "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 8341 "*
215b30b3 8342 return output_call_mem (&operands[1]);
cffb2a26 8343 "
8344 [(set_attr "length" "12")
8345 (set_attr "type" "call")]
8346)
9c08d1fa 8347
25f905c2 8348(define_insn "*call_value_reg_thumb1_v5"
f1039640 8349 [(set (match_operand 0 "" "")
8350 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8351 (match_operand 2 "" "")))
8352 (use (match_operand 3 "" ""))
8353 (clobber (reg:SI LR_REGNUM))]
25f905c2 8354 "TARGET_THUMB1 && arm_arch5"
f1039640 8355 "blx\\t%1"
8356 [(set_attr "length" "2")
8357 (set_attr "type" "call")]
8358)
8359
25f905c2 8360(define_insn "*call_value_reg_thumb1"
f1039640 8361 [(set (match_operand 0 "" "")
8362 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8363 (match_operand 2 "" "")))
8364 (use (match_operand 3 "" ""))
8365 (clobber (reg:SI LR_REGNUM))]
25f905c2 8366 "TARGET_THUMB1 && !arm_arch5"
f1039640 8367 "*
8368 {
150502c9 8369 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 8370 return thumb_call_via_reg (operands[1]);
150502c9 8371 else if (operands[2] == const0_rtx)
f1039640 8372 return \"bl\\t%__interwork_call_via_%1\";
150502c9 8373 else if (frame_pointer_needed)
8374 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 8375 else
150502c9 8376 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 8377 }"
8378 [(set_attr "type" "call")]
8379)
8380
9c08d1fa 8381;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8382;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8383
f7fbdd4a 8384(define_insn "*call_symbol"
27ed6835 8385 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8386 (match_operand 1 "" ""))
bbe777ea 8387 (use (match_operand 2 "" ""))
bd5b4116 8388 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8389 "TARGET_32BIT
cffb2a26 8390 && (GET_CODE (operands[0]) == SYMBOL_REF)
de55252a 8391 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
6ebaa29d 8392 "*
8393 {
55c1e470 8394 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 8395 }"
cffb2a26 8396 [(set_attr "type" "call")]
8397)
9c08d1fa 8398
f7fbdd4a 8399(define_insn "*call_value_symbol"
ccd90aaa 8400 [(set (match_operand 0 "" "")
27ed6835 8401 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 8402 (match_operand:SI 2 "" "")))
bbe777ea 8403 (use (match_operand 3 "" ""))
bd5b4116 8404 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8405 "TARGET_32BIT
cffb2a26 8406 && (GET_CODE (operands[1]) == SYMBOL_REF)
de55252a 8407 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
6ebaa29d 8408 "*
8409 {
55c1e470 8410 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 8411 }"
cffb2a26 8412 [(set_attr "type" "call")]
8413)
8414
8415(define_insn "*call_insn"
27ed6835 8416 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 8417 (match_operand:SI 1 "" ""))
8418 (use (match_operand 2 "" ""))
bd5b4116 8419 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8420 "TARGET_THUMB1
1675c6e9 8421 && GET_CODE (operands[0]) == SYMBOL_REF
de55252a 8422 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
cffb2a26 8423 "bl\\t%a0"
8424 [(set_attr "length" "4")
8425 (set_attr "type" "call")]
8426)
8427
8428(define_insn "*call_value_insn"
ccd90aaa 8429 [(set (match_operand 0 "" "")
27ed6835 8430 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 8431 (match_operand 2 "" "")))
8432 (use (match_operand 3 "" ""))
bd5b4116 8433 (clobber (reg:SI LR_REGNUM))]
d68c2c10 8434 "TARGET_THUMB1
1675c6e9 8435 && GET_CODE (operands[1]) == SYMBOL_REF
de55252a 8436 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
cffb2a26 8437 "bl\\t%a1"
8438 [(set_attr "length" "4")
8439 (set_attr "type" "call")]
8440)
9c08d1fa 8441
1c494086 8442;; We may also be able to do sibcalls for Thumb, but it's much harder...
8443(define_expand "sibcall"
8444 [(parallel [(call (match_operand 0 "memory_operand" "")
8445 (match_operand 1 "general_operand" ""))
2ba80634 8446 (return)
8447 (use (match_operand 2 "" ""))])]
d68c2c10 8448 "TARGET_32BIT"
1c494086 8449 "
8450 {
8451 if (operands[2] == NULL_RTX)
8452 operands[2] = const0_rtx;
1c494086 8453 }"
8454)
8455
8456(define_expand "sibcall_value"
ccd90aaa 8457 [(parallel [(set (match_operand 0 "" "")
1c494086 8458 (call (match_operand 1 "memory_operand" "")
8459 (match_operand 2 "general_operand" "")))
2ba80634 8460 (return)
8461 (use (match_operand 3 "" ""))])]
d68c2c10 8462 "TARGET_32BIT"
1c494086 8463 "
8464 {
8465 if (operands[3] == NULL_RTX)
8466 operands[3] = const0_rtx;
1c494086 8467 }"
8468)
8469
8470(define_insn "*sibcall_insn"
8471 [(call (mem:SI (match_operand:SI 0 "" "X"))
8472 (match_operand 1 "" ""))
2ba80634 8473 (return)
8474 (use (match_operand 2 "" ""))]
d68c2c10 8475 "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF"
1c494086 8476 "*
8477 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8478 "
8479 [(set_attr "type" "call")]
8480)
8481
8482(define_insn "*sibcall_value_insn"
ccd90aaa 8483 [(set (match_operand 0 "" "")
755eb2b4 8484 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 8485 (match_operand 2 "" "")))
2ba80634 8486 (return)
8487 (use (match_operand 3 "" ""))]
d68c2c10 8488 "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF"
1c494086 8489 "*
8490 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8491 "
8492 [(set_attr "type" "call")]
8493)
8494
d68c2c10 8495(define_expand "return"
8496 [(return)]
8497 "TARGET_32BIT && USE_RETURN_INSN (FALSE)"
8498 "")
8499
9c08d1fa 8500;; Often the return insn will be the same as loading from memory, so set attr
d68c2c10 8501(define_insn "*arm_return"
9c08d1fa 8502 [(return)]
cffb2a26 8503 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 8504 "*
9c08d1fa 8505 {
cffb2a26 8506 if (arm_ccfsm_state == 2)
8507 {
8508 arm_ccfsm_state += 2;
8509 return \"\";
8510 }
5db468b7 8511 return output_return_instruction (const_true_rtx, TRUE, FALSE);
cffb2a26 8512 }"
a2cd141b 8513 [(set_attr "type" "load1")
755eb2b4 8514 (set_attr "length" "12")
0d66636f 8515 (set_attr "predicable" "yes")]
cffb2a26 8516)
9c08d1fa 8517
f7fbdd4a 8518(define_insn "*cond_return"
9c08d1fa 8519 [(set (pc)
8fa3ba89 8520 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8521 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8522 (return)
8523 (pc)))]
cffb2a26 8524 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8525 "*
8fa3ba89 8526 {
8527 if (arm_ccfsm_state == 2)
8528 {
8529 arm_ccfsm_state += 2;
8530 return \"\";
8531 }
8532 return output_return_instruction (operands[0], TRUE, FALSE);
8533 }"
8534 [(set_attr "conds" "use")
755eb2b4 8535 (set_attr "length" "12")
a2cd141b 8536 (set_attr "type" "load1")]
8fa3ba89 8537)
9c08d1fa 8538
f7fbdd4a 8539(define_insn "*cond_return_inverted"
9c08d1fa 8540 [(set (pc)
8fa3ba89 8541 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 8542 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 8543 (pc)
8544 (return)))]
cffb2a26 8545 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 8546 "*
8fa3ba89 8547 {
8548 if (arm_ccfsm_state == 2)
8549 {
8550 arm_ccfsm_state += 2;
8551 return \"\";
8552 }
8553 return output_return_instruction (operands[0], TRUE, TRUE);
8554 }"
8555 [(set_attr "conds" "use")
37a1317b 8556 (set_attr "length" "12")
a2cd141b 8557 (set_attr "type" "load1")]
8fa3ba89 8558)
9c08d1fa 8559
68121397 8560;; Generate a sequence of instructions to determine if the processor is
8561;; in 26-bit or 32-bit mode, and return the appropriate return address
8562;; mask.
8563
8564(define_expand "return_addr_mask"
8565 [(set (match_dup 1)
8566 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8567 (const_int 0)))
8568 (set (match_operand:SI 0 "s_register_operand" "")
8569 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8570 (const_int -1)
8571 (const_int 67108860)))] ; 0x03fffffc
8572 "TARGET_ARM"
8573 "
62eddbd4 8574 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 8575 ")
8576
8577(define_insn "*check_arch2"
8578 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8579 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8580 (const_int 0)))]
8581 "TARGET_ARM"
8582 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8583 [(set_attr "length" "8")
8584 (set_attr "conds" "set")]
8585)
8586
9c08d1fa 8587;; Call subroutine returning any type.
8588
8589(define_expand "untyped_call"
8590 [(parallel [(call (match_operand 0 "" "")
8591 (const_int 0))
8592 (match_operand 1 "" "")
8593 (match_operand 2 "" "")])]
ccd90aaa 8594 "TARGET_EITHER"
9c08d1fa 8595 "
215b30b3 8596 {
8597 int i;
ccd90aaa 8598 rtx par = gen_rtx_PARALLEL (VOIDmode,
8599 rtvec_alloc (XVECLEN (operands[2], 0)));
8600 rtx addr = gen_reg_rtx (Pmode);
8601 rtx mem;
8602 int size = 0;
9c08d1fa 8603
ccd90aaa 8604 emit_move_insn (addr, XEXP (operands[1], 0));
8605 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 8606
215b30b3 8607 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8608 {
ccd90aaa 8609 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 8610
ccd90aaa 8611 /* Default code only uses r0 as a return value, but we could
8612 be using anything up to 4 registers. */
8613 if (REGNO (src) == R0_REGNUM)
8614 src = gen_rtx_REG (TImode, R0_REGNUM);
8615
8616 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8617 GEN_INT (size));
8618 size += GET_MODE_SIZE (GET_MODE (src));
8619 }
8620
8621 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8622 const0_rtx));
8623
8624 size = 0;
8625
8626 for (i = 0; i < XVECLEN (par, 0); i++)
8627 {
8628 HOST_WIDE_INT offset = 0;
8629 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8630
8631 if (size != 0)
8632 emit_move_insn (addr, plus_constant (addr, size));
8633
8634 mem = change_address (mem, GET_MODE (reg), NULL);
8635 if (REGNO (reg) == R0_REGNUM)
8636 {
8637 /* On thumb we have to use a write-back instruction. */
320ea44d 8638 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8639 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8640 size = TARGET_ARM ? 16 : 0;
8641 }
8642 else
8643 {
8644 emit_move_insn (mem, reg);
8645 size = GET_MODE_SIZE (GET_MODE (reg));
8646 }
215b30b3 8647 }
9c08d1fa 8648
215b30b3 8649 /* The optimizer does not know that the call sets the function value
8650 registers we stored in the result block. We avoid problems by
8651 claiming that all hard registers are used and clobbered at this
8652 point. */
8653 emit_insn (gen_blockage ());
8654
8655 DONE;
8656 }"
8657)
9c08d1fa 8658
ccd90aaa 8659(define_expand "untyped_return"
8660 [(match_operand:BLK 0 "memory_operand" "")
8661 (match_operand 1 "" "")]
8662 "TARGET_EITHER"
8663 "
8664 {
8665 int i;
8666 rtx addr = gen_reg_rtx (Pmode);
8667 rtx mem;
8668 int size = 0;
8669
8670 emit_move_insn (addr, XEXP (operands[0], 0));
8671 mem = change_address (operands[0], BLKmode, addr);
8672
8673 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8674 {
8675 HOST_WIDE_INT offset = 0;
8676 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8677
8678 if (size != 0)
8679 emit_move_insn (addr, plus_constant (addr, size));
8680
8681 mem = change_address (mem, GET_MODE (reg), NULL);
8682 if (REGNO (reg) == R0_REGNUM)
8683 {
8684 /* On thumb we have to use a write-back instruction. */
320ea44d 8685 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8686 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
ccd90aaa 8687 size = TARGET_ARM ? 16 : 0;
8688 }
8689 else
8690 {
8691 emit_move_insn (reg, mem);
8692 size = GET_MODE_SIZE (GET_MODE (reg));
8693 }
8694 }
8695
8696 /* Emit USE insns before the return. */
8697 for (i = 0; i < XVECLEN (operands[1], 0); i++)
18b42941 8698 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
ccd90aaa 8699
8700 /* Construct the return. */
8701 expand_naked_return ();
8702
8703 DONE;
8704 }"
8705)
8706
9c08d1fa 8707;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8708;; all of memory. This blocks insns from being moved across this point.
8709
8710(define_insn "blockage"
e1159bbe 8711 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8712 "TARGET_EITHER"
9c08d1fa 8713 ""
cffb2a26 8714 [(set_attr "length" "0")
8715 (set_attr "type" "block")]
8716)
9c08d1fa 8717
f7fbdd4a 8718(define_expand "casesi"
8719 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8720 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8721 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8722 (match_operand:SI 3 "" "") ; table label
8723 (match_operand:SI 4 "" "")] ; Out of range label
e6ac8414 8724 "TARGET_32BIT || optimize_size || flag_pic"
f7fbdd4a 8725 "
215b30b3 8726 {
e6ac8414 8727 enum insn_code code;
215b30b3 8728 if (operands[1] != const0_rtx)
8729 {
e6ac8414 8730 rtx reg = gen_reg_rtx (SImode);
f7fbdd4a 8731
215b30b3 8732 emit_insn (gen_addsi3 (reg, operands[0],
d022fa24 8733 gen_int_mode (-INTVAL (operands[1]),
8734 SImode)));
215b30b3 8735 operands[0] = reg;
8736 }
9c08d1fa 8737
25f905c2 8738 if (TARGET_ARM)
e6ac8414 8739 code = CODE_FOR_arm_casesi_internal;
3db2019b 8740 else if (TARGET_THUMB1)
e6ac8414 8741 code = CODE_FOR_thumb1_casesi_internal_pic;
25f905c2 8742 else if (flag_pic)
e6ac8414 8743 code = CODE_FOR_thumb2_casesi_internal_pic;
25f905c2 8744 else
e6ac8414 8745 code = CODE_FOR_thumb2_casesi_internal;
8746
8747 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8748 operands[2] = force_reg (SImode, operands[2]);
8749
8750 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8751 operands[3], operands[4]));
215b30b3 8752 DONE;
8753 }"
8754)
f7fbdd4a 8755
f082f1c4 8756;; The USE in this pattern is needed to tell flow analysis that this is
8757;; a CASESI insn. It has no other purpose.
25f905c2 8758(define_insn "arm_casesi_internal"
f082f1c4 8759 [(parallel [(set (pc)
8760 (if_then_else
8761 (leu (match_operand:SI 0 "s_register_operand" "r")
8762 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8763 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8764 (label_ref (match_operand 2 "" ""))))
8765 (label_ref (match_operand 3 "" ""))))
bd5b4116 8766 (clobber (reg:CC CC_REGNUM))
f082f1c4 8767 (use (label_ref (match_dup 2)))])]
cffb2a26 8768 "TARGET_ARM"
f7fbdd4a 8769 "*
0d66636f 8770 if (flag_pic)
8771 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8772 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8773 "
8774 [(set_attr "conds" "clob")
8775 (set_attr "length" "12")]
8776)
9c08d1fa 8777
e6ac8414 8778(define_expand "thumb1_casesi_internal_pic"
8779 [(match_operand:SI 0 "s_register_operand" "")
8780 (match_operand:SI 1 "thumb1_cmp_operand" "")
8781 (match_operand 2 "" "")
8782 (match_operand 3 "" "")]
3db2019b 8783 "TARGET_THUMB1"
e6ac8414 8784 {
8785 rtx reg0;
8786 rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
8787 emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
8788 operands[3]));
8789 reg0 = gen_rtx_REG (SImode, 0);
8790 emit_move_insn (reg0, operands[0]);
8791 emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
8792 DONE;
8793 }
8794)
8795
8796(define_insn "thumb1_casesi_dispatch"
8797 [(parallel [(set (pc) (unspec [(reg:SI 0)
8798 (label_ref (match_operand 0 "" ""))
8799;; (label_ref (match_operand 1 "" ""))
8800]
8801 UNSPEC_THUMB1_CASESI))
8802 (clobber (reg:SI IP_REGNUM))
8803 (clobber (reg:SI LR_REGNUM))])]
3db2019b 8804 "TARGET_THUMB1"
e6ac8414 8805 "* return thumb1_output_casesi(operands);"
8806 [(set_attr "length" "4")]
8807)
8808
cffb2a26 8809(define_expand "indirect_jump"
9c08d1fa 8810 [(set (pc)
cffb2a26 8811 (match_operand:SI 0 "s_register_operand" ""))]
8812 "TARGET_EITHER"
25f905c2 8813 "
8814 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8815 address and use bx. */
8816 if (TARGET_THUMB2)
8817 {
8818 rtx tmp;
8819 tmp = gen_reg_rtx (SImode);
8820 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8821 operands[0] = tmp;
8822 }
8823 "
cffb2a26 8824)
8825
f1039640 8826;; NB Never uses BX.
cffb2a26 8827(define_insn "*arm_indirect_jump"
8828 [(set (pc)
8829 (match_operand:SI 0 "s_register_operand" "r"))]
8830 "TARGET_ARM"
8831 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 8832 [(set_attr "predicable" "yes")]
cffb2a26 8833)
9c08d1fa 8834
f7fbdd4a 8835(define_insn "*load_indirect_jump"
9c08d1fa 8836 [(set (pc)
8837 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8838 "TARGET_ARM"
8839 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8840 [(set_attr "type" "load1")
61a2d04c 8841 (set_attr "pool_range" "4096")
8842 (set_attr "neg_pool_range" "4084")
0d66636f 8843 (set_attr "predicable" "yes")]
cffb2a26 8844)
8845
f1039640 8846;; NB Never uses BX.
25f905c2 8847(define_insn "*thumb1_indirect_jump"
cffb2a26 8848 [(set (pc)
8849 (match_operand:SI 0 "register_operand" "l*r"))]
25f905c2 8850 "TARGET_THUMB1"
cffb2a26 8851 "mov\\tpc, %0"
8852 [(set_attr "conds" "clob")
8853 (set_attr "length" "2")]
8854)
8855
9c08d1fa 8856\f
8857;; Misc insns
8858
8859(define_insn "nop"
8860 [(const_int 0)]
cffb2a26 8861 "TARGET_EITHER"
8862 "*
25f905c2 8863 if (TARGET_UNIFIED_ASM)
8864 return \"nop\";
cffb2a26 8865 if (TARGET_ARM)
8866 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8867 return \"mov\\tr8, r8\";
8868 "
8869 [(set (attr "length")
8870 (if_then_else (eq_attr "is_thumb" "yes")
8871 (const_int 2)
8872 (const_int 4)))]
8873)
8874
9c08d1fa 8875\f
8876;; Patterns to allow combination of arithmetic, cond code and shifts
8877
f7fbdd4a 8878(define_insn "*arith_shiftsi"
7392680c 8879 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9c08d1fa 8880 (match_operator:SI 1 "shiftable_operator"
8881 [(match_operator:SI 3 "shift_operator"
7392680c 8882 [(match_operand:SI 4 "s_register_operand" "r,r,r,r")
8883 (match_operand:SI 5 "shift_amount_operand" "M,M,M,r")])
8884 (match_operand:SI 2 "s_register_operand" "rk,rk,r,rk")]))]
d5d4dc8d 8885 "TARGET_32BIT"
6c4c2133 8886 "%i1%?\\t%0, %2, %4%S3"
344495ea 8887 [(set_attr "predicable" "yes")
331beb1a 8888 (set_attr "shift" "4")
7392680c 8889 (set_attr "arch" "a,t2,t2,a")
8890 ;; Thumb2 doesn't allow the stack pointer to be used for
8891 ;; operand1 for all operations other than add and sub. In this case
8892 ;; the minus operation is a candidate for an rsub and hence needs
8893 ;; to be disabled.
8894 ;; We have to make sure to disable the fourth alternative if
d5d4dc8d 8895 ;; the shift_operator is MULT, since otherwise the insn will
8896 ;; also match a multiply_accumulate pattern and validate_change
8897 ;; will allow a replacement of the constant with a register
8898 ;; despite the checks done in shift_operator.
8899 (set_attr_alternative "insn_enabled"
8900 [(const_string "yes")
7392680c 8901 (if_then_else
8902 (match_operand:SI 1 "add_operator" "")
8903 (const_string "yes") (const_string "no"))
8904 (const_string "yes")
d5d4dc8d 8905 (if_then_else
8906 (match_operand:SI 3 "mult_operator" "")
8907 (const_string "no") (const_string "yes"))])
7392680c 8908 (set_attr "type" "alu_shift,alu_shift,alu_shift,alu_shift_reg")])
9c08d1fa 8909
d7863cfe 8910(define_split
8911 [(set (match_operand:SI 0 "s_register_operand" "")
8912 (match_operator:SI 1 "shiftable_operator"
8913 [(match_operator:SI 2 "shiftable_operator"
8914 [(match_operator:SI 3 "shift_operator"
8915 [(match_operand:SI 4 "s_register_operand" "")
8916 (match_operand:SI 5 "reg_or_int_operand" "")])
8917 (match_operand:SI 6 "s_register_operand" "")])
8918 (match_operand:SI 7 "arm_rhs_operand" "")]))
8919 (clobber (match_operand:SI 8 "s_register_operand" ""))]
d5d4dc8d 8920 "TARGET_32BIT"
d7863cfe 8921 [(set (match_dup 8)
8922 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8923 (match_dup 6)]))
8924 (set (match_dup 0)
8925 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8926 "")
8927
f7fbdd4a 8928(define_insn "*arith_shiftsi_compare0"
bd5b4116 8929 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8930 (compare:CC_NOOV
8931 (match_operator:SI 1 "shiftable_operator"
8932 [(match_operator:SI 3 "shift_operator"
8933 [(match_operand:SI 4 "s_register_operand" "r,r")
8934 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8935 (match_operand:SI 2 "s_register_operand" "r,r")])
8936 (const_int 0)))
8937 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 8938 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8939 (match_dup 2)]))]
d5d4dc8d 8940 "TARGET_32BIT"
25f905c2 8941 "%i1%.\\t%0, %2, %4%S3"
344495ea 8942 [(set_attr "conds" "set")
331beb1a 8943 (set_attr "shift" "4")
d5d4dc8d 8944 (set_attr "arch" "32,a")
8945 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8946
f7fbdd4a 8947(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8948 [(set (reg:CC_NOOV CC_REGNUM)
d5d4dc8d 8949 (compare:CC_NOOV
8950 (match_operator:SI 1 "shiftable_operator"
8951 [(match_operator:SI 3 "shift_operator"
8952 [(match_operand:SI 4 "s_register_operand" "r,r")
8953 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8954 (match_operand:SI 2 "s_register_operand" "r,r")])
8955 (const_int 0)))
8956 (clobber (match_scratch:SI 0 "=r,r"))]
8957 "TARGET_32BIT"
25f905c2 8958 "%i1%.\\t%0, %2, %4%S3"
344495ea 8959 [(set_attr "conds" "set")
331beb1a 8960 (set_attr "shift" "4")
d5d4dc8d 8961 (set_attr "arch" "32,a")
8962 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8963
f7fbdd4a 8964(define_insn "*sub_shiftsi"
d5d4dc8d 8965 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8966 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9c08d1fa 8967 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8968 [(match_operand:SI 3 "s_register_operand" "r,r")
8969 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8970 "TARGET_32BIT"
6c4c2133 8971 "sub%?\\t%0, %1, %3%S2"
344495ea 8972 [(set_attr "predicable" "yes")
331beb1a 8973 (set_attr "shift" "3")
d5d4dc8d 8974 (set_attr "arch" "32,a")
8975 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8976
f7fbdd4a 8977(define_insn "*sub_shiftsi_compare0"
bd5b4116 8978 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8979 (compare:CC_NOOV
d5d4dc8d 8980 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 8981 (match_operator:SI 2 "shift_operator"
d5d4dc8d 8982 [(match_operand:SI 3 "s_register_operand" "r,r")
8983 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 8984 (const_int 0)))
d5d4dc8d 8985 (set (match_operand:SI 0 "s_register_operand" "=r,r")
8986 (minus:SI (match_dup 1)
8987 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8988 "TARGET_32BIT"
25f905c2 8989 "sub%.\\t%0, %1, %3%S2"
344495ea 8990 [(set_attr "conds" "set")
a2cd141b 8991 (set_attr "shift" "3")
d5d4dc8d 8992 (set_attr "arch" "32,a")
8993 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 8994
f7fbdd4a 8995(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8996 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8997 (compare:CC_NOOV
d5d4dc8d 8998 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
40dbec34 8999 (match_operator:SI 2 "shift_operator"
d5d4dc8d 9000 [(match_operand:SI 3 "s_register_operand" "r,r")
9001 (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
40dbec34 9002 (const_int 0)))
d5d4dc8d 9003 (clobber (match_scratch:SI 0 "=r,r"))]
9004 "TARGET_32BIT"
25f905c2 9005 "sub%.\\t%0, %1, %3%S2"
344495ea 9006 [(set_attr "conds" "set")
a2cd141b 9007 (set_attr "shift" "3")
d5d4dc8d 9008 (set_attr "arch" "32,a")
9009 (set_attr "type" "alu_shift,alu_shift_reg")])
9c08d1fa 9010\f
9011
f7fbdd4a 9012(define_insn "*and_scc"
9c08d1fa 9013 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9014 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 9015 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 9016 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 9017 "TARGET_ARM"
e2348bcb 9018 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 9019 [(set_attr "conds" "use")
d2a518d1 9020 (set_attr "insn" "mov")
8fa3ba89 9021 (set_attr "length" "8")]
9022)
9c08d1fa 9023
f7fbdd4a 9024(define_insn "*ior_scc"
9c08d1fa 9025 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9026 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 9027 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 9028 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 9029 "TARGET_ARM"
e2348bcb 9030 "@
899850b0 9031 orr%d2\\t%0, %1, #1
9032 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 9033 [(set_attr "conds" "use")
9034 (set_attr "length" "4,8")]
9035)
9c08d1fa 9036
2df9477b 9037; A series of splitters for the compare_scc pattern below. Note that
9038; order is important.
9039(define_split
9040 [(set (match_operand:SI 0 "s_register_operand" "")
9041 (lt:SI (match_operand:SI 1 "s_register_operand" "")
9042 (const_int 0)))
9043 (clobber (reg:CC CC_REGNUM))]
9044 "TARGET_32BIT && reload_completed"
9045 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
9046
9047(define_split
9048 [(set (match_operand:SI 0 "s_register_operand" "")
9049 (ge:SI (match_operand:SI 1 "s_register_operand" "")
9050 (const_int 0)))
9051 (clobber (reg:CC CC_REGNUM))]
9052 "TARGET_32BIT && reload_completed"
9053 [(set (match_dup 0) (not:SI (match_dup 1)))
9054 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
9055
9056(define_split
9057 [(set (match_operand:SI 0 "s_register_operand" "")
9058 (eq:SI (match_operand:SI 1 "s_register_operand" "")
9059 (const_int 0)))
9060 (clobber (reg:CC CC_REGNUM))]
9061 "TARGET_32BIT && reload_completed"
9062 [(parallel
080c0b9a 9063 [(set (reg:CC CC_REGNUM)
9064 (compare:CC (const_int 1) (match_dup 1)))
2df9477b 9065 (set (match_dup 0)
9066 (minus:SI (const_int 1) (match_dup 1)))])
080c0b9a 9067 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
2df9477b 9068 (set (match_dup 0) (const_int 0)))])
9069
9070(define_split
9071 [(set (match_operand:SI 0 "s_register_operand" "")
9072 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9073 (match_operand:SI 2 "const_int_operand" "")))
9074 (clobber (reg:CC CC_REGNUM))]
9075 "TARGET_32BIT && reload_completed"
9076 [(parallel
9077 [(set (reg:CC CC_REGNUM)
9078 (compare:CC (match_dup 1) (match_dup 2)))
9079 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
9080 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
9081 (set (match_dup 0) (const_int 1)))]
9082{
9083 operands[3] = GEN_INT (-INTVAL (operands[2]));
9084})
9085
9086(define_split
9087 [(set (match_operand:SI 0 "s_register_operand" "")
9088 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9089 (match_operand:SI 2 "arm_add_operand" "")))
9090 (clobber (reg:CC CC_REGNUM))]
9091 "TARGET_32BIT && reload_completed"
9092 [(parallel
9093 [(set (reg:CC_NOOV CC_REGNUM)
9094 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
9095 (const_int 0)))
9096 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
9097 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
9098 (set (match_dup 0) (const_int 1)))])
9099
9100(define_insn_and_split "*compare_scc"
5565501b 9101 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9102 (match_operator:SI 1 "arm_comparison_operator"
5565501b 9103 [(match_operand:SI 2 "s_register_operand" "r,r")
9104 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 9105 (clobber (reg:CC CC_REGNUM))]
2df9477b 9106 "TARGET_32BIT"
9107 "#"
9108 "&& reload_completed"
9109 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
9110 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
9111 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
9112{
9113 rtx tmp1;
9114 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9115 operands[2], operands[3]);
9116 enum rtx_code rc = GET_CODE (operands[1]);
e2348bcb 9117
2df9477b 9118 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
080c0b9a 9119
2df9477b 9120 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9121 if (mode == CCFPmode || mode == CCFPEmode)
9122 rc = reverse_condition_maybe_unordered (rc);
9123 else
9124 rc = reverse_condition (rc);
9125 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9126})
9c08d1fa 9127
080c0b9a 9128;; Attempt to improve the sequence generated by the compare_scc splitters
9129;; not to use conditional execution.
9130(define_peephole2
9131 [(set (reg:CC CC_REGNUM)
9132 (compare:CC (match_operand:SI 1 "register_operand" "")
9133 (match_operand:SI 2 "arm_rhs_operand" "")))
9134 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9135 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9136 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9137 (set (match_dup 0) (const_int 1)))
9138 (match_scratch:SI 3 "r")]
9139 "TARGET_32BIT"
922b6913 9140 [(parallel
9141 [(set (reg:CC CC_REGNUM)
9142 (compare:CC (match_dup 1) (match_dup 2)))
9143 (set (match_dup 3) (minus:SI (match_dup 1) (match_dup 2)))])
080c0b9a 9144 (parallel
9145 [(set (reg:CC CC_REGNUM)
9146 (compare:CC (const_int 0) (match_dup 3)))
9147 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
922b6913 9148 (parallel
9149 [(set (match_dup 0)
9150 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
9151 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))
9152 (clobber (reg:CC CC_REGNUM))])])
080c0b9a 9153
f7fbdd4a 9154(define_insn "*cond_move"
9c08d1fa 9155 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 9156 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 9157 [(match_operator 4 "arm_comparison_operator"
8a18b90c 9158 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 9159 (const_int 0)])
9160 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9161 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 9162 "TARGET_ARM"
9c08d1fa 9163 "*
8fa3ba89 9164 if (GET_CODE (operands[3]) == NE)
9165 {
9166 if (which_alternative != 1)
9167 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9168 if (which_alternative != 0)
9169 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9170 return \"\";
9171 }
9172 if (which_alternative != 0)
9173 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9174 if (which_alternative != 1)
9175 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9176 return \"\";
9177 "
9178 [(set_attr "conds" "use")
d2a518d1 9179 (set_attr "insn" "mov")
8fa3ba89 9180 (set_attr "length" "4,4,8")]
9181)
9c08d1fa 9182
f7fbdd4a 9183(define_insn "*cond_arith"
9c08d1fa 9184 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9185 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 9186 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9187 [(match_operand:SI 2 "s_register_operand" "r,r")
9188 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9189 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 9190 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9191 "TARGET_ARM"
9c08d1fa 9192 "*
8fa3ba89 9193 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9194 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 9195
8fa3ba89 9196 output_asm_insn (\"cmp\\t%2, %3\", operands);
9197 if (GET_CODE (operands[5]) == AND)
9198 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9199 else if (GET_CODE (operands[5]) == MINUS)
9200 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9201 else if (which_alternative != 0)
9202 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9203 return \"%i5%d4\\t%0, %1, #1\";
9204 "
9205 [(set_attr "conds" "clob")
9206 (set_attr "length" "12")]
9207)
9c08d1fa 9208
f7fbdd4a 9209(define_insn "*cond_sub"
9c08d1fa 9210 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9211 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 9212 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 9213 [(match_operand:SI 2 "s_register_operand" "r,r")
9214 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9215 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9216 "TARGET_ARM"
9c08d1fa 9217 "*
8fa3ba89 9218 output_asm_insn (\"cmp\\t%2, %3\", operands);
9219 if (which_alternative != 0)
9220 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9221 return \"sub%d4\\t%0, %1, #1\";
9222 "
9223 [(set_attr "conds" "clob")
9224 (set_attr "length" "8,12")]
9225)
9c08d1fa 9226
aea4c774 9227(define_insn "*cmp_ite0"
cffb2a26 9228 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9229 (compare
9230 (if_then_else:SI
8fa3ba89 9231 (match_operator 4 "arm_comparison_operator"
2ff91fec 9232 [(match_operand:SI 0 "s_register_operand"
9233 "l,l,l,r,r,r,r,r,r")
9234 (match_operand:SI 1 "arm_add_operand"
9235 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 9236 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9237 [(match_operand:SI 2 "s_register_operand"
9238 "l,r,r,l,l,r,r,r,r")
9239 (match_operand:SI 3 "arm_add_operand"
9240 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 9241 (const_int 0))
9242 (const_int 0)))]
2ff91fec 9243 "TARGET_32BIT"
9c08d1fa 9244 "*
aea4c774 9245 {
2ff91fec 9246 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9247 {
9248 {\"cmp%d5\\t%0, %1\",
9249 \"cmp%d4\\t%2, %3\"},
9250 {\"cmn%d5\\t%0, #%n1\",
9251 \"cmp%d4\\t%2, %3\"},
9252 {\"cmp%d5\\t%0, %1\",
9253 \"cmn%d4\\t%2, #%n3\"},
9254 {\"cmn%d5\\t%0, #%n1\",
9255 \"cmn%d4\\t%2, #%n3\"}
9256 };
9257 static const char * const cmp2[NUM_OF_COND_CMP][2] =
9258 {
9259 {\"cmp\\t%2, %3\",
9260 \"cmp\\t%0, %1\"},
9261 {\"cmp\\t%2, %3\",
9262 \"cmn\\t%0, #%n1\"},
9263 {\"cmn\\t%2, #%n3\",
9264 \"cmp\\t%0, %1\"},
9265 {\"cmn\\t%2, #%n3\",
9266 \"cmn\\t%0, #%n1\"}
9267 };
9268 static const char * const ite[2] =
8fa3ba89 9269 {
2ff91fec 9270 \"it\\t%d5\",
9271 \"it\\t%d4\"
8fa3ba89 9272 };
2ff91fec 9273 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9274 CMP_CMP, CMN_CMP, CMP_CMP,
9275 CMN_CMP, CMP_CMN, CMN_CMN};
8fa3ba89 9276 int swap =
9277 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9278
2ff91fec 9279 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9280 if (TARGET_THUMB2) {
9281 output_asm_insn (ite[swap], operands);
9282 }
9283 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9284 return \"\";
8fa3ba89 9285 }"
9286 [(set_attr "conds" "set")
2ff91fec 9287 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9288 (set_attr_alternative "length"
9289 [(const_int 6)
9290 (const_int 8)
9291 (const_int 8)
9292 (const_int 8)
9293 (const_int 8)
9294 (if_then_else (eq_attr "is_thumb" "no")
9295 (const_int 8)
9296 (const_int 10))
9297 (if_then_else (eq_attr "is_thumb" "no")
9298 (const_int 8)
9299 (const_int 10))
9300 (if_then_else (eq_attr "is_thumb" "no")
9301 (const_int 8)
9302 (const_int 10))
9303 (if_then_else (eq_attr "is_thumb" "no")
9304 (const_int 8)
9305 (const_int 10))])]
8fa3ba89 9306)
9c08d1fa 9307
aea4c774 9308(define_insn "*cmp_ite1"
cffb2a26 9309 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 9310 (compare
9311 (if_then_else:SI
8fa3ba89 9312 (match_operator 4 "arm_comparison_operator"
2ff91fec 9313 [(match_operand:SI 0 "s_register_operand"
9314 "l,l,l,r,r,r,r,r,r")
9315 (match_operand:SI 1 "arm_add_operand"
9316 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8fa3ba89 9317 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9318 [(match_operand:SI 2 "s_register_operand"
9319 "l,r,r,l,l,r,r,r,r")
9320 (match_operand:SI 3 "arm_add_operand"
9321 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
aea4c774 9322 (const_int 1))
9323 (const_int 0)))]
2ff91fec 9324 "TARGET_32BIT"
9c08d1fa 9325 "*
9c08d1fa 9326 {
2ff91fec 9327 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9328 {
9329 {\"cmp\\t%0, %1\",
9330 \"cmp\\t%2, %3\"},
9331 {\"cmn\\t%0, #%n1\",
9332 \"cmp\\t%2, %3\"},
9333 {\"cmp\\t%0, %1\",
9334 \"cmn\\t%2, #%n3\"},
9335 {\"cmn\\t%0, #%n1\",
9336 \"cmn\\t%2, #%n3\"}
9337 };
9338 static const char * const cmp2[NUM_OF_COND_CMP][2] =
215b30b3 9339 {
2ff91fec 9340 {\"cmp%d4\\t%2, %3\",
9341 \"cmp%D5\\t%0, %1\"},
9342 {\"cmp%d4\\t%2, %3\",
9343 \"cmn%D5\\t%0, #%n1\"},
9344 {\"cmn%d4\\t%2, #%n3\",
9345 \"cmp%D5\\t%0, %1\"},
9346 {\"cmn%d4\\t%2, #%n3\",
9347 \"cmn%D5\\t%0, #%n1\"}
215b30b3 9348 };
2ff91fec 9349 static const char * const ite[2] =
9350 {
9351 \"it\\t%d4\",
9352 \"it\\t%D5\"
9353 };
9354 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9355 CMP_CMP, CMN_CMP, CMP_CMP,
9356 CMN_CMP, CMP_CMN, CMN_CMN};
215b30b3 9357 int swap =
9358 comparison_dominates_p (GET_CODE (operands[5]),
9359 reverse_condition (GET_CODE (operands[4])));
9360
2ff91fec 9361 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9362 if (TARGET_THUMB2) {
9363 output_asm_insn (ite[swap], operands);
9364 }
9365 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9366 return \"\";
215b30b3 9367 }"
8fa3ba89 9368 [(set_attr "conds" "set")
2ff91fec 9369 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9370 (set_attr_alternative "length"
9371 [(const_int 6)
9372 (const_int 8)
9373 (const_int 8)
9374 (const_int 8)
9375 (const_int 8)
9376 (if_then_else (eq_attr "is_thumb" "no")
9377 (const_int 8)
9378 (const_int 10))
9379 (if_then_else (eq_attr "is_thumb" "no")
9380 (const_int 8)
9381 (const_int 10))
9382 (if_then_else (eq_attr "is_thumb" "no")
9383 (const_int 8)
9384 (const_int 10))
9385 (if_then_else (eq_attr "is_thumb" "no")
9386 (const_int 8)
9387 (const_int 10))])]
8fa3ba89 9388)
9c08d1fa 9389
f6c53574 9390(define_insn "*cmp_and"
9391 [(set (match_operand 6 "dominant_cc_register" "")
9392 (compare
9393 (and:SI
9394 (match_operator 4 "arm_comparison_operator"
2ff91fec 9395 [(match_operand:SI 0 "s_register_operand"
9396 "l,l,l,r,r,r,r,r,r")
9397 (match_operand:SI 1 "arm_add_operand"
9398 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9399 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9400 [(match_operand:SI 2 "s_register_operand"
9401 "l,r,r,l,l,r,r,r,r")
9402 (match_operand:SI 3 "arm_add_operand"
9403 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9404 (const_int 0)))]
2ff91fec 9405 "TARGET_32BIT"
f6c53574 9406 "*
9407 {
2ff91fec 9408 static const char *const cmp1[NUM_OF_COND_CMP][2] =
f6c53574 9409 {
2ff91fec 9410 {\"cmp%d5\\t%0, %1\",
9411 \"cmp%d4\\t%2, %3\"},
9412 {\"cmn%d5\\t%0, #%n1\",
9413 \"cmp%d4\\t%2, %3\"},
9414 {\"cmp%d5\\t%0, %1\",
9415 \"cmn%d4\\t%2, #%n3\"},
9416 {\"cmn%d5\\t%0, #%n1\",
9417 \"cmn%d4\\t%2, #%n3\"}
f6c53574 9418 };
2ff91fec 9419 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9420 {
9421 {\"cmp\\t%2, %3\",
9422 \"cmp\\t%0, %1\"},
9423 {\"cmp\\t%2, %3\",
9424 \"cmn\\t%0, #%n1\"},
9425 {\"cmn\\t%2, #%n3\",
9426 \"cmp\\t%0, %1\"},
9427 {\"cmn\\t%2, #%n3\",
9428 \"cmn\\t%0, #%n1\"}
9429 };
9430 static const char *const ite[2] =
9431 {
9432 \"it\\t%d5\",
9433 \"it\\t%d4\"
9434 };
9435 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9436 CMP_CMP, CMN_CMP, CMP_CMP,
9437 CMN_CMP, CMP_CMN, CMN_CMN};
f6c53574 9438 int swap =
9439 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9440
2ff91fec 9441 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9442 if (TARGET_THUMB2) {
9443 output_asm_insn (ite[swap], operands);
9444 }
9445 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9446 return \"\";
f6c53574 9447 }"
9448 [(set_attr "conds" "set")
9449 (set_attr "predicable" "no")
2ff91fec 9450 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9451 (set_attr_alternative "length"
9452 [(const_int 6)
9453 (const_int 8)
9454 (const_int 8)
9455 (const_int 8)
9456 (const_int 8)
9457 (if_then_else (eq_attr "is_thumb" "no")
9458 (const_int 8)
9459 (const_int 10))
9460 (if_then_else (eq_attr "is_thumb" "no")
9461 (const_int 8)
9462 (const_int 10))
9463 (if_then_else (eq_attr "is_thumb" "no")
9464 (const_int 8)
9465 (const_int 10))
9466 (if_then_else (eq_attr "is_thumb" "no")
9467 (const_int 8)
9468 (const_int 10))])]
f6c53574 9469)
9470
9471(define_insn "*cmp_ior"
9472 [(set (match_operand 6 "dominant_cc_register" "")
9473 (compare
9474 (ior:SI
9475 (match_operator 4 "arm_comparison_operator"
2ff91fec 9476 [(match_operand:SI 0 "s_register_operand"
9477 "l,l,l,r,r,r,r,r,r")
9478 (match_operand:SI 1 "arm_add_operand"
9479 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
f6c53574 9480 (match_operator:SI 5 "arm_comparison_operator"
2ff91fec 9481 [(match_operand:SI 2 "s_register_operand"
9482 "l,r,r,l,l,r,r,r,r")
9483 (match_operand:SI 3 "arm_add_operand"
9484 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
f6c53574 9485 (const_int 0)))]
2ff91fec 9486 "TARGET_32BIT"
f6c53574 9487 "*
f6c53574 9488 {
2ff91fec 9489 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9490 {
9491 {\"cmp\\t%0, %1\",
9492 \"cmp\\t%2, %3\"},
9493 {\"cmn\\t%0, #%n1\",
9494 \"cmp\\t%2, %3\"},
9495 {\"cmp\\t%0, %1\",
9496 \"cmn\\t%2, #%n3\"},
9497 {\"cmn\\t%0, #%n1\",
9498 \"cmn\\t%2, #%n3\"}
9499 };
9500 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9501 {
9502 {\"cmp%D4\\t%2, %3\",
9503 \"cmp%D5\\t%0, %1\"},
9504 {\"cmp%D4\\t%2, %3\",
9505 \"cmn%D5\\t%0, #%n1\"},
9506 {\"cmn%D4\\t%2, #%n3\",
9507 \"cmp%D5\\t%0, %1\"},
9508 {\"cmn%D4\\t%2, #%n3\",
9509 \"cmn%D5\\t%0, #%n1\"}
9510 };
9511 static const char *const ite[2] =
9512 {
9513 \"it\\t%D4\",
9514 \"it\\t%D5\"
9515 };
9516 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9517 CMP_CMP, CMN_CMP, CMP_CMP,
9518 CMN_CMP, CMP_CMN, CMN_CMN};
9519 int swap =
9520 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9521
9522 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9523 if (TARGET_THUMB2) {
9524 output_asm_insn (ite[swap], operands);
9525 }
9526 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9527 return \"\";
9528 }
9529 "
f6c53574 9530 [(set_attr "conds" "set")
2ff91fec 9531 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9532 (set_attr_alternative "length"
9533 [(const_int 6)
9534 (const_int 8)
9535 (const_int 8)
9536 (const_int 8)
9537 (const_int 8)
9538 (if_then_else (eq_attr "is_thumb" "no")
9539 (const_int 8)
9540 (const_int 10))
9541 (if_then_else (eq_attr "is_thumb" "no")
9542 (const_int 8)
9543 (const_int 10))
9544 (if_then_else (eq_attr "is_thumb" "no")
9545 (const_int 8)
9546 (const_int 10))
9547 (if_then_else (eq_attr "is_thumb" "no")
9548 (const_int 8)
9549 (const_int 10))])]
f6c53574 9550)
9551
3c5afce6 9552(define_insn_and_split "*ior_scc_scc"
9553 [(set (match_operand:SI 0 "s_register_operand" "=r")
9554 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9555 [(match_operand:SI 1 "s_register_operand" "r")
9556 (match_operand:SI 2 "arm_add_operand" "rIL")])
9557 (match_operator:SI 6 "arm_comparison_operator"
9558 [(match_operand:SI 4 "s_register_operand" "r")
9559 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9560 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9561 "TARGET_32BIT
3c5afce6 9562 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9563 != CCmode)"
9564 "#"
2ff91fec 9565 "TARGET_32BIT && reload_completed"
3c5afce6 9566 [(set (match_dup 7)
9567 (compare
9568 (ior:SI
9569 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9570 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9571 (const_int 0)))
9572 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9573 "operands[7]
9574 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9575 DOM_CC_X_OR_Y),
601f584c 9576 CC_REGNUM);"
9577 [(set_attr "conds" "clob")
9578 (set_attr "length" "16")])
9579
9580; If the above pattern is followed by a CMP insn, then the compare is
9581; redundant, since we can rework the conditional instruction that follows.
9582(define_insn_and_split "*ior_scc_scc_cmp"
9583 [(set (match_operand 0 "dominant_cc_register" "")
9584 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9585 [(match_operand:SI 1 "s_register_operand" "r")
9586 (match_operand:SI 2 "arm_add_operand" "rIL")])
9587 (match_operator:SI 6 "arm_comparison_operator"
9588 [(match_operand:SI 4 "s_register_operand" "r")
9589 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9590 (const_int 0)))
9591 (set (match_operand:SI 7 "s_register_operand" "=r")
9592 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9593 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9594 "TARGET_32BIT"
601f584c 9595 "#"
2ff91fec 9596 "TARGET_32BIT && reload_completed"
601f584c 9597 [(set (match_dup 0)
9598 (compare
9599 (ior:SI
9600 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9601 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9602 (const_int 0)))
9603 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9604 ""
9605 [(set_attr "conds" "set")
9606 (set_attr "length" "16")])
3c5afce6 9607
9608(define_insn_and_split "*and_scc_scc"
9609 [(set (match_operand:SI 0 "s_register_operand" "=r")
9610 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9611 [(match_operand:SI 1 "s_register_operand" "r")
9612 (match_operand:SI 2 "arm_add_operand" "rIL")])
9613 (match_operator:SI 6 "arm_comparison_operator"
9614 [(match_operand:SI 4 "s_register_operand" "r")
9615 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9616 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9617 "TARGET_32BIT
3c5afce6 9618 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9619 != CCmode)"
9620 "#"
2ff91fec 9621 "TARGET_32BIT && reload_completed
601f584c 9622 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9623 != CCmode)"
3c5afce6 9624 [(set (match_dup 7)
9625 (compare
9626 (and:SI
9627 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9628 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9629 (const_int 0)))
9630 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9631 "operands[7]
9632 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9633 DOM_CC_X_AND_Y),
601f584c 9634 CC_REGNUM);"
9635 [(set_attr "conds" "clob")
9636 (set_attr "length" "16")])
9637
9638; If the above pattern is followed by a CMP insn, then the compare is
9639; redundant, since we can rework the conditional instruction that follows.
9640(define_insn_and_split "*and_scc_scc_cmp"
9641 [(set (match_operand 0 "dominant_cc_register" "")
9642 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9643 [(match_operand:SI 1 "s_register_operand" "r")
9644 (match_operand:SI 2 "arm_add_operand" "rIL")])
9645 (match_operator:SI 6 "arm_comparison_operator"
9646 [(match_operand:SI 4 "s_register_operand" "r")
9647 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9648 (const_int 0)))
9649 (set (match_operand:SI 7 "s_register_operand" "=r")
9650 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9651 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
2ff91fec 9652 "TARGET_32BIT"
601f584c 9653 "#"
2ff91fec 9654 "TARGET_32BIT && reload_completed"
601f584c 9655 [(set (match_dup 0)
9656 (compare
9657 (and:SI
9658 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9659 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9660 (const_int 0)))
9661 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9662 ""
9663 [(set_attr "conds" "set")
9664 (set_attr "length" "16")])
9665
9666;; If there is no dominance in the comparison, then we can still save an
9667;; instruction in the AND case, since we can know that the second compare
9668;; need only zero the value if false (if true, then the value is already
9669;; correct).
9670(define_insn_and_split "*and_scc_scc_nodom"
9671 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9672 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9673 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9674 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9675 (match_operator:SI 6 "arm_comparison_operator"
9676 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9677 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9678 (clobber (reg:CC CC_REGNUM))]
2ff91fec 9679 "TARGET_32BIT
601f584c 9680 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9681 == CCmode)"
9682 "#"
2ff91fec 9683 "TARGET_32BIT && reload_completed"
601f584c 9684 [(parallel [(set (match_dup 0)
9685 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9686 (clobber (reg:CC CC_REGNUM))])
9687 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9688 (set (match_dup 0)
9689 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9690 (match_dup 0)
9691 (const_int 0)))]
9692 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9693 operands[4], operands[5]),
9694 CC_REGNUM);
9695 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9696 operands[5]);"
9697 [(set_attr "conds" "clob")
9698 (set_attr "length" "20")])
3c5afce6 9699
3a0bdee0 9700(define_split
9701 [(set (reg:CC_NOOV CC_REGNUM)
9702 (compare:CC_NOOV (ior:SI
9703 (and:SI (match_operand:SI 0 "s_register_operand" "")
9704 (const_int 1))
b0694be0 9705 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9706 [(match_operand:SI 2 "s_register_operand" "")
9707 (match_operand:SI 3 "arm_add_operand" "")]))
9708 (const_int 0)))
9709 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9710 "TARGET_ARM"
9711 [(set (match_dup 4)
9712 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9713 (match_dup 0)))
9714 (set (reg:CC_NOOV CC_REGNUM)
9715 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9716 (const_int 0)))]
9717 "")
9718
9719(define_split
9720 [(set (reg:CC_NOOV CC_REGNUM)
9721 (compare:CC_NOOV (ior:SI
b0694be0 9722 (match_operator:SI 1 "arm_comparison_operator"
3a0bdee0 9723 [(match_operand:SI 2 "s_register_operand" "")
9724 (match_operand:SI 3 "arm_add_operand" "")])
9725 (and:SI (match_operand:SI 0 "s_register_operand" "")
9726 (const_int 1)))
9727 (const_int 0)))
9728 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9729 "TARGET_ARM"
9730 [(set (match_dup 4)
9731 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9732 (match_dup 0)))
9733 (set (reg:CC_NOOV CC_REGNUM)
9734 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9735 (const_int 0)))]
9736 "")
25f905c2 9737;; ??? The conditional patterns above need checking for Thumb-2 usefulness
3a0bdee0 9738
f7fbdd4a 9739(define_insn "*negscc"
9c08d1fa 9740 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9741 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 9742 [(match_operand:SI 1 "s_register_operand" "r")
9743 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 9744 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9745 "TARGET_ARM"
9c08d1fa 9746 "*
2ca2ec2e 9747 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
e2348bcb 9748 return \"mov\\t%0, %1, asr #31\";
9749
9c08d1fa 9750 if (GET_CODE (operands[3]) == NE)
e2348bcb 9751 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9752
e2348bcb 9753 output_asm_insn (\"cmp\\t%1, %2\", operands);
9754 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9755 return \"mvn%d3\\t%0, #0\";
215b30b3 9756 "
8fa3ba89 9757 [(set_attr "conds" "clob")
9758 (set_attr "length" "12")]
9759)
9c08d1fa 9760
9761(define_insn "movcond"
9762 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9763 (if_then_else:SI
8fa3ba89 9764 (match_operator 5 "arm_comparison_operator"
5565501b 9765 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9766 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9767 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9768 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 9769 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9770 "TARGET_ARM"
9c08d1fa 9771 "*
9772 if (GET_CODE (operands[5]) == LT
9773 && (operands[4] == const0_rtx))
9774 {
5565501b 9775 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9c08d1fa 9776 {
9c08d1fa 9777 if (operands[2] == const0_rtx)
e2348bcb 9778 return \"and\\t%0, %1, %3, asr #31\";
9779 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 9780 }
9781 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9782 {
9c08d1fa 9783 if (operands[1] == const0_rtx)
e2348bcb 9784 return \"bic\\t%0, %2, %3, asr #31\";
9785 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 9786 }
9787 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9788 are constants. */
9c08d1fa 9789 }
e2348bcb 9790
9c08d1fa 9791 if (GET_CODE (operands[5]) == GE
9792 && (operands[4] == const0_rtx))
9793 {
9794 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9795 {
9c08d1fa 9796 if (operands[2] == const0_rtx)
e2348bcb 9797 return \"bic\\t%0, %1, %3, asr #31\";
9798 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 9799 }
9800 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9801 {
9c08d1fa 9802 if (operands[1] == const0_rtx)
e2348bcb 9803 return \"and\\t%0, %2, %3, asr #31\";
9804 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 9805 }
9806 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 9807 are constants. */
9c08d1fa 9808 }
9809 if (GET_CODE (operands[4]) == CONST_INT
9810 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 9811 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 9812 else
e2348bcb 9813 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 9814 if (which_alternative != 0)
e2348bcb 9815 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 9816 if (which_alternative != 1)
e2348bcb 9817 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 9818 return \"\";
215b30b3 9819 "
8fa3ba89 9820 [(set_attr "conds" "clob")
9821 (set_attr "length" "8,8,12")]
9822)
9c08d1fa 9823
25f905c2 9824;; ??? The patterns below need checking for Thumb-2 usefulness.
9825
8a18b90c 9826(define_insn "*ifcompare_plus_move"
9827 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9828 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9829 [(match_operand:SI 4 "s_register_operand" "r,r")
9830 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9831 (plus:SI
9832 (match_operand:SI 2 "s_register_operand" "r,r")
9833 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 9834 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9835 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9836 "TARGET_ARM"
8a18b90c 9837 "#"
8fa3ba89 9838 [(set_attr "conds" "clob")
9839 (set_attr "length" "8,12")]
9840)
8a18b90c 9841
9842(define_insn "*if_plus_move"
129a2fe4 9843 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9844 (if_then_else:SI
8fa3ba89 9845 (match_operator 4 "arm_comparison_operator"
8a18b90c 9846 [(match_operand 5 "cc_register" "") (const_int 0)])
9847 (plus:SI
129a2fe4 9848 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9849 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9850 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 9851 "TARGET_ARM"
8a18b90c 9852 "@
9853 add%d4\\t%0, %2, %3
9854 sub%d4\\t%0, %2, #%n3
9855 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 9856 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 9857 [(set_attr "conds" "use")
9858 (set_attr "length" "4,4,8,8")
9859 (set_attr "type" "*,*,*,*")]
9860)
8a18b90c 9861
9862(define_insn "*ifcompare_move_plus"
5565501b 9863 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9864 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 9865 [(match_operand:SI 4 "s_register_operand" "r,r")
9866 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9867 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9868 (plus:SI
9869 (match_operand:SI 2 "s_register_operand" "r,r")
9870 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 9871 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9872 "TARGET_ARM"
8a18b90c 9873 "#"
8fa3ba89 9874 [(set_attr "conds" "clob")
9875 (set_attr "length" "8,12")]
9876)
8a18b90c 9877
9878(define_insn "*if_move_plus"
129a2fe4 9879 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 9880 (if_then_else:SI
8fa3ba89 9881 (match_operator 4 "arm_comparison_operator"
8a18b90c 9882 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 9883 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 9884 (plus:SI
129a2fe4 9885 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9886 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 9887 "TARGET_ARM"
8a18b90c 9888 "@
9889 add%D4\\t%0, %2, %3
9890 sub%D4\\t%0, %2, #%n3
9891 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 9892 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 9893 [(set_attr "conds" "use")
9894 (set_attr "length" "4,4,8,8")
9895 (set_attr "type" "*,*,*,*")]
9896)
8a18b90c 9897
9898(define_insn "*ifcompare_arith_arith"
9899 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9900 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 9901 [(match_operand:SI 5 "s_register_operand" "r")
9902 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 9903 (match_operator:SI 8 "shiftable_operator"
8a18b90c 9904 [(match_operand:SI 1 "s_register_operand" "r")
9905 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 9906 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9907 [(match_operand:SI 3 "s_register_operand" "r")
9908 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 9909 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9910 "TARGET_ARM"
8a18b90c 9911 "#"
8fa3ba89 9912 [(set_attr "conds" "clob")
9913 (set_attr "length" "12")]
9914)
9c08d1fa 9915
8a18b90c 9916(define_insn "*if_arith_arith"
9917 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 9918 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 9919 [(match_operand 8 "cc_register" "") (const_int 0)])
9920 (match_operator:SI 6 "shiftable_operator"
9921 [(match_operand:SI 1 "s_register_operand" "r")
9922 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9923 (match_operator:SI 7 "shiftable_operator"
9924 [(match_operand:SI 3 "s_register_operand" "r")
9925 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 9926 "TARGET_ARM"
8a18b90c 9927 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 9928 [(set_attr "conds" "use")
9929 (set_attr "length" "8")]
9930)
8a18b90c 9931
f7fbdd4a 9932(define_insn "*ifcompare_arith_move"
9c08d1fa 9933 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9934 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9935 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 9936 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 9937 (match_operator:SI 7 "shiftable_operator"
9938 [(match_operand:SI 4 "s_register_operand" "r,r")
9939 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 9940 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 9941 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9942 "TARGET_ARM"
9c08d1fa 9943 "*
9c08d1fa 9944 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 9945 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 9946 everything is in registers then we can do this in two instructions. */
9c08d1fa 9947 if (operands[3] == const0_rtx
9948 && GET_CODE (operands[7]) != AND
9949 && GET_CODE (operands[5]) == REG
9950 && GET_CODE (operands[1]) == REG
9951 && REGNO (operands[1]) == REGNO (operands[4])
9952 && REGNO (operands[4]) != REGNO (operands[0]))
9953 {
9954 if (GET_CODE (operands[6]) == LT)
40dbec34 9955 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9956 else if (GET_CODE (operands[6]) == GE)
40dbec34 9957 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 9958 }
9959 if (GET_CODE (operands[3]) == CONST_INT
9960 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 9961 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 9962 else
e2348bcb 9963 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 9964 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 9965 if (which_alternative != 0)
129a2fe4 9966 return \"mov%D6\\t%0, %1\";
9c08d1fa 9967 return \"\";
215b30b3 9968 "
8fa3ba89 9969 [(set_attr "conds" "clob")
9970 (set_attr "length" "8,12")]
9971)
9c08d1fa 9972
8a18b90c 9973(define_insn "*if_arith_move"
129a2fe4 9974 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9975 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 9976 [(match_operand 6 "cc_register" "") (const_int 0)])
9977 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9978 [(match_operand:SI 2 "s_register_operand" "r,r")
9979 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9980 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 9981 "TARGET_ARM"
8a18b90c 9982 "@
9983 %I5%d4\\t%0, %2, %3
129a2fe4 9984 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 9985 [(set_attr "conds" "use")
9986 (set_attr "length" "4,8")
9987 (set_attr "type" "*,*")]
9988)
8a18b90c 9989
f7fbdd4a 9990(define_insn "*ifcompare_move_arith"
9c08d1fa 9991 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9992 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 9993 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 9994 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 9995 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 9996 (match_operator:SI 7 "shiftable_operator"
9997 [(match_operand:SI 2 "s_register_operand" "r,r")
9998 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 9999 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10000 "TARGET_ARM"
9c08d1fa 10001 "*
9c08d1fa 10002 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 10003 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 10004 everything is in registers then we can do this in two instructions */
10005 if (operands[5] == const0_rtx
10006 && GET_CODE (operands[7]) != AND
10007 && GET_CODE (operands[3]) == REG
10008 && GET_CODE (operands[1]) == REG
10009 && REGNO (operands[1]) == REGNO (operands[2])
10010 && REGNO (operands[2]) != REGNO (operands[0]))
10011 {
10012 if (GET_CODE (operands[6]) == GE)
40dbec34 10013 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10014 else if (GET_CODE (operands[6]) == LT)
40dbec34 10015 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 10016 }
40dbec34 10017
9c08d1fa 10018 if (GET_CODE (operands[5]) == CONST_INT
10019 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 10020 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 10021 else
e2348bcb 10022 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 10023
9c08d1fa 10024 if (which_alternative != 0)
129a2fe4 10025 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 10026 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 10027 "
8fa3ba89 10028 [(set_attr "conds" "clob")
10029 (set_attr "length" "8,12")]
10030)
9c08d1fa 10031
8a18b90c 10032(define_insn "*if_move_arith"
129a2fe4 10033 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10034 (if_then_else:SI
8fa3ba89 10035 (match_operator 4 "arm_comparison_operator"
8a18b90c 10036 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 10037 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 10038 (match_operator:SI 5 "shiftable_operator"
129a2fe4 10039 [(match_operand:SI 2 "s_register_operand" "r,r")
10040 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 10041 "TARGET_ARM"
8a18b90c 10042 "@
10043 %I5%D4\\t%0, %2, %3
129a2fe4 10044 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 10045 [(set_attr "conds" "use")
10046 (set_attr "length" "4,8")
10047 (set_attr "type" "*,*")]
10048)
8a18b90c 10049
10050(define_insn "*ifcompare_move_not"
9c08d1fa 10051 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10052 (if_then_else:SI
8fa3ba89 10053 (match_operator 5 "arm_comparison_operator"
8a18b90c 10054 [(match_operand:SI 3 "s_register_operand" "r,r")
10055 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10056 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10057 (not:SI
10058 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10059 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10060 "TARGET_ARM"
8a18b90c 10061 "#"
8fa3ba89 10062 [(set_attr "conds" "clob")
10063 (set_attr "length" "8,12")]
10064)
9c08d1fa 10065
8a18b90c 10066(define_insn "*if_move_not"
10067 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10068 (if_then_else:SI
8fa3ba89 10069 (match_operator 4 "arm_comparison_operator"
8a18b90c 10070 [(match_operand 3 "cc_register" "") (const_int 0)])
10071 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10072 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10073 "TARGET_ARM"
8a18b90c 10074 "@
10075 mvn%D4\\t%0, %2
10076 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
10077 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 10078 [(set_attr "conds" "use")
d2a518d1 10079 (set_attr "insn" "mvn")
8fa3ba89 10080 (set_attr "length" "4,8,8")]
10081)
8a18b90c 10082
10083(define_insn "*ifcompare_not_move"
9c08d1fa 10084 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10085 (if_then_else:SI
8fa3ba89 10086 (match_operator 5 "arm_comparison_operator"
8a18b90c 10087 [(match_operand:SI 3 "s_register_operand" "r,r")
10088 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10089 (not:SI
10090 (match_operand:SI 2 "s_register_operand" "r,r"))
10091 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10092 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10093 "TARGET_ARM"
8a18b90c 10094 "#"
8fa3ba89 10095 [(set_attr "conds" "clob")
10096 (set_attr "length" "8,12")]
10097)
9c08d1fa 10098
8a18b90c 10099(define_insn "*if_not_move"
10100 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10101 (if_then_else:SI
8fa3ba89 10102 (match_operator 4 "arm_comparison_operator"
8a18b90c 10103 [(match_operand 3 "cc_register" "") (const_int 0)])
10104 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10105 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10106 "TARGET_ARM"
8a18b90c 10107 "@
10108 mvn%d4\\t%0, %2
10109 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
10110 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 10111 [(set_attr "conds" "use")
d2a518d1 10112 (set_attr "insn" "mvn")
8fa3ba89 10113 (set_attr "length" "4,8,8")]
10114)
8a18b90c 10115
10116(define_insn "*ifcompare_shift_move"
9c08d1fa 10117 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 10118 (if_then_else:SI
8fa3ba89 10119 (match_operator 6 "arm_comparison_operator"
8a18b90c 10120 [(match_operand:SI 4 "s_register_operand" "r,r")
10121 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10122 (match_operator:SI 7 "shift_operator"
10123 [(match_operand:SI 2 "s_register_operand" "r,r")
10124 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
10125 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10126 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10127 "TARGET_ARM"
9c08d1fa 10128 "#"
8fa3ba89 10129 [(set_attr "conds" "clob")
10130 (set_attr "length" "8,12")]
10131)
9c08d1fa 10132
8a18b90c 10133(define_insn "*if_shift_move"
10134 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10135 (if_then_else:SI
8fa3ba89 10136 (match_operator 5 "arm_comparison_operator"
8a18b90c 10137 [(match_operand 6 "cc_register" "") (const_int 0)])
10138 (match_operator:SI 4 "shift_operator"
10139 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10140 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
10141 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10142 "TARGET_ARM"
5565501b 10143 "@
8a18b90c 10144 mov%d5\\t%0, %2%S4
10145 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
10146 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 10147 [(set_attr "conds" "use")
331beb1a 10148 (set_attr "shift" "2")
a2cd141b 10149 (set_attr "length" "4,8,8")
d2a518d1 10150 (set_attr "insn" "mov")
a2cd141b 10151 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10152 (const_string "alu_shift")
10153 (const_string "alu_shift_reg")))]
8fa3ba89 10154)
5565501b 10155
8a18b90c 10156(define_insn "*ifcompare_move_shift"
10157 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10158 (if_then_else:SI
8fa3ba89 10159 (match_operator 6 "arm_comparison_operator"
8a18b90c 10160 [(match_operand:SI 4 "s_register_operand" "r,r")
10161 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10162 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 10163 (match_operator:SI 7 "shift_operator"
8a18b90c 10164 [(match_operand:SI 2 "s_register_operand" "r,r")
10165 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 10166 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10167 "TARGET_ARM"
8a18b90c 10168 "#"
8fa3ba89 10169 [(set_attr "conds" "clob")
10170 (set_attr "length" "8,12")]
10171)
5565501b 10172
8a18b90c 10173(define_insn "*if_move_shift"
10174 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 10175 (if_then_else:SI
8fa3ba89 10176 (match_operator 5 "arm_comparison_operator"
8a18b90c 10177 [(match_operand 6 "cc_register" "") (const_int 0)])
10178 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10179 (match_operator:SI 4 "shift_operator"
10180 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10181 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 10182 "TARGET_ARM"
5565501b 10183 "@
8a18b90c 10184 mov%D5\\t%0, %2%S4
10185 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10186 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 10187 [(set_attr "conds" "use")
331beb1a 10188 (set_attr "shift" "2")
a2cd141b 10189 (set_attr "length" "4,8,8")
d2a518d1 10190 (set_attr "insn" "mov")
a2cd141b 10191 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10192 (const_string "alu_shift")
10193 (const_string "alu_shift_reg")))]
8fa3ba89 10194)
9c08d1fa 10195
f7fbdd4a 10196(define_insn "*ifcompare_shift_shift"
8a18b90c 10197 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10198 (if_then_else:SI
8fa3ba89 10199 (match_operator 7 "arm_comparison_operator"
8a18b90c 10200 [(match_operand:SI 5 "s_register_operand" "r")
10201 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 10202 (match_operator:SI 8 "shift_operator"
8a18b90c 10203 [(match_operand:SI 1 "s_register_operand" "r")
10204 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 10205 (match_operator:SI 9 "shift_operator"
8a18b90c 10206 [(match_operand:SI 3 "s_register_operand" "r")
10207 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 10208 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10209 "TARGET_ARM"
8a18b90c 10210 "#"
8fa3ba89 10211 [(set_attr "conds" "clob")
10212 (set_attr "length" "12")]
10213)
9c08d1fa 10214
8a18b90c 10215(define_insn "*if_shift_shift"
10216 [(set (match_operand:SI 0 "s_register_operand" "=r")
10217 (if_then_else:SI
8fa3ba89 10218 (match_operator 5 "arm_comparison_operator"
8a18b90c 10219 [(match_operand 8 "cc_register" "") (const_int 0)])
10220 (match_operator:SI 6 "shift_operator"
10221 [(match_operand:SI 1 "s_register_operand" "r")
10222 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10223 (match_operator:SI 7 "shift_operator"
10224 [(match_operand:SI 3 "s_register_operand" "r")
10225 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 10226 "TARGET_ARM"
8a18b90c 10227 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 10228 [(set_attr "conds" "use")
331beb1a 10229 (set_attr "shift" "1")
a2cd141b 10230 (set_attr "length" "8")
d2a518d1 10231 (set_attr "insn" "mov")
a2cd141b 10232 (set (attr "type") (if_then_else
10233 (and (match_operand 2 "const_int_operand" "")
10234 (match_operand 4 "const_int_operand" ""))
10235 (const_string "alu_shift")
10236 (const_string "alu_shift_reg")))]
8fa3ba89 10237)
8a18b90c 10238
f7fbdd4a 10239(define_insn "*ifcompare_not_arith"
8a18b90c 10240 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10241 (if_then_else:SI
8fa3ba89 10242 (match_operator 6 "arm_comparison_operator"
8a18b90c 10243 [(match_operand:SI 4 "s_register_operand" "r")
10244 (match_operand:SI 5 "arm_add_operand" "rIL")])
10245 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 10246 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10247 [(match_operand:SI 2 "s_register_operand" "r")
10248 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 10249 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10250 "TARGET_ARM"
8a18b90c 10251 "#"
8fa3ba89 10252 [(set_attr "conds" "clob")
10253 (set_attr "length" "12")]
10254)
9c08d1fa 10255
8a18b90c 10256(define_insn "*if_not_arith"
10257 [(set (match_operand:SI 0 "s_register_operand" "=r")
10258 (if_then_else:SI
8fa3ba89 10259 (match_operator 5 "arm_comparison_operator"
8a18b90c 10260 [(match_operand 4 "cc_register" "") (const_int 0)])
10261 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10262 (match_operator:SI 6 "shiftable_operator"
10263 [(match_operand:SI 2 "s_register_operand" "r")
10264 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 10265 "TARGET_ARM"
8a18b90c 10266 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 10267 [(set_attr "conds" "use")
d2a518d1 10268 (set_attr "insn" "mvn")
8fa3ba89 10269 (set_attr "length" "8")]
10270)
8a18b90c 10271
10272(define_insn "*ifcompare_arith_not"
10273 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 10274 (if_then_else:SI
8fa3ba89 10275 (match_operator 6 "arm_comparison_operator"
8a18b90c 10276 [(match_operand:SI 4 "s_register_operand" "r")
10277 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 10278 (match_operator:SI 7 "shiftable_operator"
8a18b90c 10279 [(match_operand:SI 2 "s_register_operand" "r")
10280 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10281 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 10282 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10283 "TARGET_ARM"
8a18b90c 10284 "#"
8fa3ba89 10285 [(set_attr "conds" "clob")
10286 (set_attr "length" "12")]
10287)
9c08d1fa 10288
8a18b90c 10289(define_insn "*if_arith_not"
10290 [(set (match_operand:SI 0 "s_register_operand" "=r")
10291 (if_then_else:SI
8fa3ba89 10292 (match_operator 5 "arm_comparison_operator"
8a18b90c 10293 [(match_operand 4 "cc_register" "") (const_int 0)])
10294 (match_operator:SI 6 "shiftable_operator"
10295 [(match_operand:SI 2 "s_register_operand" "r")
10296 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10297 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 10298 "TARGET_ARM"
8a18b90c 10299 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 10300 [(set_attr "conds" "use")
d2a518d1 10301 (set_attr "insn" "mvn")
8fa3ba89 10302 (set_attr "length" "8")]
10303)
8a18b90c 10304
f7fbdd4a 10305(define_insn "*ifcompare_neg_move"
8a18b90c 10306 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10307 (if_then_else:SI
8fa3ba89 10308 (match_operator 5 "arm_comparison_operator"
8a18b90c 10309 [(match_operand:SI 3 "s_register_operand" "r,r")
10310 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10311 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10312 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 10313 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10314 "TARGET_ARM"
8a18b90c 10315 "#"
8fa3ba89 10316 [(set_attr "conds" "clob")
10317 (set_attr "length" "8,12")]
10318)
8a18b90c 10319
10320(define_insn "*if_neg_move"
10321 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10322 (if_then_else:SI
8fa3ba89 10323 (match_operator 4 "arm_comparison_operator"
8a18b90c 10324 [(match_operand 3 "cc_register" "") (const_int 0)])
10325 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10326 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 10327 "TARGET_ARM"
8a18b90c 10328 "@
10329 rsb%d4\\t%0, %2, #0
10330 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
10331 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 10332 [(set_attr "conds" "use")
10333 (set_attr "length" "4,8,8")]
10334)
9c08d1fa 10335
f7fbdd4a 10336(define_insn "*ifcompare_move_neg"
8a18b90c 10337 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 10338 (if_then_else:SI
8fa3ba89 10339 (match_operator 5 "arm_comparison_operator"
8a18b90c 10340 [(match_operand:SI 3 "s_register_operand" "r,r")
10341 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10342 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10343 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 10344 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10345 "TARGET_ARM"
8a18b90c 10346 "#"
8fa3ba89 10347 [(set_attr "conds" "clob")
10348 (set_attr "length" "8,12")]
10349)
8a18b90c 10350
10351(define_insn "*if_move_neg"
10352 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10353 (if_then_else:SI
8fa3ba89 10354 (match_operator 4 "arm_comparison_operator"
8a18b90c 10355 [(match_operand 3 "cc_register" "") (const_int 0)])
10356 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10357 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 10358 "TARGET_ARM"
8a18b90c 10359 "@
10360 rsb%D4\\t%0, %2, #0
10361 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
10362 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 10363 [(set_attr "conds" "use")
10364 (set_attr "length" "4,8,8")]
10365)
9c08d1fa 10366
f7fbdd4a 10367(define_insn "*arith_adjacentmem"
9c08d1fa 10368 [(set (match_operand:SI 0 "s_register_operand" "=r")
10369 (match_operator:SI 1 "shiftable_operator"
10370 [(match_operand:SI 2 "memory_operand" "m")
10371 (match_operand:SI 3 "memory_operand" "m")]))
10372 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 10373 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 10374 "*
215b30b3 10375 {
10376 rtx ldm[3];
10377 rtx arith[4];
94dee231 10378 rtx base_reg;
10379 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 10380
215b30b3 10381 if (REGNO (operands[0]) > REGNO (operands[4]))
10382 {
10383 ldm[1] = operands[4];
10384 ldm[2] = operands[0];
10385 }
10386 else
10387 {
10388 ldm[1] = operands[0];
10389 ldm[2] = operands[4];
10390 }
94dee231 10391
10392 base_reg = XEXP (operands[2], 0);
10393
10394 if (!REG_P (base_reg))
10395 {
10396 val1 = INTVAL (XEXP (base_reg, 1));
10397 base_reg = XEXP (base_reg, 0);
10398 }
10399
10400 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 10401 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 10402
215b30b3 10403 arith[0] = operands[0];
10404 arith[3] = operands[1];
94dee231 10405
215b30b3 10406 if (val1 < val2)
10407 {
10408 arith[1] = ldm[1];
10409 arith[2] = ldm[2];
10410 }
10411 else
10412 {
10413 arith[1] = ldm[2];
10414 arith[2] = ldm[1];
10415 }
94dee231 10416
10417 ldm[0] = base_reg;
10418 if (val1 !=0 && val2 != 0)
215b30b3 10419 {
cdb1295a 10420 rtx ops[3];
10421
94dee231 10422 if (val1 == 4 || val2 == 4)
10423 /* Other val must be 8, since we know they are adjacent and neither
10424 is zero. */
25f905c2 10425 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
cdb1295a 10426 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
94dee231 10427 {
94dee231 10428 ldm[0] = ops[0] = operands[4];
10429 ops[1] = base_reg;
10430 ops[2] = GEN_INT (val1);
10431 output_add_immediate (ops);
10432 if (val1 < val2)
25f905c2 10433 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
94dee231 10434 else
25f905c2 10435 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
94dee231 10436 }
cdb1295a 10437 else
10438 {
10439 /* Offset is out of range for a single add, so use two ldr. */
10440 ops[0] = ldm[1];
10441 ops[1] = base_reg;
10442 ops[2] = GEN_INT (val1);
10443 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10444 ops[0] = ldm[2];
10445 ops[2] = GEN_INT (val2);
10446 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10447 }
215b30b3 10448 }
94dee231 10449 else if (val1 != 0)
215b30b3 10450 {
215b30b3 10451 if (val1 < val2)
25f905c2 10452 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10453 else
25f905c2 10454 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10455 }
10456 else
10457 {
215b30b3 10458 if (val1 < val2)
25f905c2 10459 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
215b30b3 10460 else
25f905c2 10461 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
215b30b3 10462 }
10463 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10464 return \"\";
10465 }"
10466 [(set_attr "length" "12")
10467 (set_attr "predicable" "yes")
a2cd141b 10468 (set_attr "type" "load1")]
215b30b3 10469)
9c08d1fa 10470
9c08d1fa 10471; This pattern is never tried by combine, so do it as a peephole
10472
a0f94409 10473(define_peephole2
372575c7 10474 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10475 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 10476 (set (reg:CC CC_REGNUM)
aea4c774 10477 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 10478 "TARGET_ARM"
a0f94409 10479 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10480 (set (match_dup 0) (match_dup 1))])]
10481 ""
0d66636f 10482)
9c08d1fa 10483
9c08d1fa 10484(define_split
10485 [(set (match_operand:SI 0 "s_register_operand" "")
10486 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10487 (const_int 0))
8fa3ba89 10488 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 10489 [(match_operand:SI 3 "s_register_operand" "")
10490 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10491 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 10492 "TARGET_ARM"
9c08d1fa 10493 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10494 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10495 (match_dup 5)))]
215b30b3 10496 ""
10497)
9c08d1fa 10498
aea4c774 10499;; This split can be used because CC_Z mode implies that the following
10500;; branch will be an equality, or an unsigned inequality, so the sign
10501;; extension is not needed.
9c08d1fa 10502
aea4c774 10503(define_split
bd5b4116 10504 [(set (reg:CC_Z CC_REGNUM)
aea4c774 10505 (compare:CC_Z
10506 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 10507 (const_int 24))
aea4c774 10508 (match_operand 1 "const_int_operand" "")))
10509 (clobber (match_scratch:SI 2 ""))]
cffb2a26 10510 "TARGET_ARM
10511 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10512 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 10513 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 10514 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 10515 "
9c08d1fa 10516 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 10517 "
10518)
25f905c2 10519;; ??? Check the patterns above for Thumb-2 usefulness
9c08d1fa 10520
87b22bf7 10521(define_expand "prologue"
10522 [(clobber (const_int 0))]
cffb2a26 10523 "TARGET_EITHER"
25f905c2 10524 "if (TARGET_32BIT)
cffb2a26 10525 arm_expand_prologue ();
10526 else
25f905c2 10527 thumb1_expand_prologue ();
87b22bf7 10528 DONE;
cffb2a26 10529 "
10530)
87b22bf7 10531
56d27660 10532(define_expand "epilogue"
4c44712e 10533 [(clobber (const_int 0))]
cffb2a26 10534 "TARGET_EITHER"
56d27660 10535 "
18d50ae6 10536 if (crtl->calls_eh_return)
4c44712e 10537 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
25f905c2 10538 if (TARGET_THUMB1)
10539 thumb1_expand_epilogue ();
cffb2a26 10540 else if (USE_RETURN_INSN (FALSE))
56d27660 10541 {
10542 emit_jump_insn (gen_return ());
10543 DONE;
10544 }
cffb2a26 10545 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
1a860023 10546 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
cffb2a26 10547 DONE;
10548 "
10549)
56d27660 10550
7571d3f7 10551(define_insn "prologue_thumb1_interwork"
10552 [(unspec_volatile [(const_int 0)] VUNSPEC_THUMB1_INTERWORK)]
10553 "TARGET_THUMB1"
10554 "* return thumb1_output_interwork ();"
10555 [(set_attr "length" "8")]
10556)
10557
ef5651d0 10558;; Note - although unspec_volatile's USE all hard registers,
10559;; USEs are ignored after relaod has completed. Thus we need
10560;; to add an unspec of the link register to ensure that flow
10561;; does not think that it is unused by the sibcall branch that
10562;; will replace the standard function epilogue.
1c494086 10563(define_insn "sibcall_epilogue"
ef5651d0 10564 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10565 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
25f905c2 10566 "TARGET_32BIT"
1c494086 10567 "*
ffc9d00c 10568 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
5db468b7 10569 return output_return_instruction (const_true_rtx, FALSE, FALSE);
ffc9d00c 10570 return arm_output_epilogue (next_nonnote_insn (insn));
1c494086 10571 "
10572;; Length is absolute worst case
10573 [(set_attr "length" "44")
defc47cf 10574 (set_attr "type" "block")
10575 ;; We don't clobber the conditions, but the potential length of this
10576 ;; operation is sufficient to make conditionalizing the sequence
10577 ;; unlikely to be profitable.
10578 (set_attr "conds" "clob")]
1c494086 10579)
10580
cffb2a26 10581(define_insn "*epilogue_insns"
e1159bbe 10582 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 10583 "TARGET_EITHER"
56d27660 10584 "*
25f905c2 10585 if (TARGET_32BIT)
ffc9d00c 10586 return arm_output_epilogue (NULL);
25f905c2 10587 else /* TARGET_THUMB1 */
cffb2a26 10588 return thumb_unexpanded_epilogue ();
10589 "
215b30b3 10590 ; Length is absolute worst case
cffb2a26 10591 [(set_attr "length" "44")
defc47cf 10592 (set_attr "type" "block")
10593 ;; We don't clobber the conditions, but the potential length of this
10594 ;; operation is sufficient to make conditionalizing the sequence
10595 ;; unlikely to be profitable.
10596 (set_attr "conds" "clob")]
cffb2a26 10597)
10598
10599(define_expand "eh_epilogue"
7db9af5d 10600 [(use (match_operand:SI 0 "register_operand" ""))
10601 (use (match_operand:SI 1 "register_operand" ""))
10602 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10603 "TARGET_EITHER"
10604 "
215b30b3 10605 {
10606 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10607 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10608 {
10609 rtx ra = gen_rtx_REG (Pmode, 2);
10610
10611 emit_move_insn (ra, operands[2]);
10612 operands[2] = ra;
10613 }
5cf3595a 10614 /* This is a hack -- we may have crystalized the function type too
10615 early. */
10616 cfun->machine->func_type = 0;
215b30b3 10617 }"
10618)
56d27660 10619
9c08d1fa 10620;; This split is only used during output to reduce the number of patterns
10621;; that need assembler instructions adding to them. We allowed the setting
10622;; of the conditions to be implicit during rtl generation so that
10623;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10624;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10625;; up again here.
10626
25f905c2 10627;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10628;; conditional execution sufficient?
10629
9c08d1fa 10630(define_split
10631 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10632 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10633 [(match_operand 2 "" "") (match_operand 3 "" "")])
10634 (match_dup 0)
10635 (match_operand 4 "" "")))
bd5b4116 10636 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10637 "TARGET_ARM && reload_completed"
8fa3ba89 10638 [(set (match_dup 5) (match_dup 6))
10639 (cond_exec (match_dup 7)
10640 (set (match_dup 0) (match_dup 4)))]
10641 "
10642 {
10643 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10644 operands[2], operands[3]);
10645 enum rtx_code rc = GET_CODE (operands[1]);
10646
bd5b4116 10647 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10648 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10649 if (mode == CCFPmode || mode == CCFPEmode)
10650 rc = reverse_condition_maybe_unordered (rc);
10651 else
10652 rc = reverse_condition (rc);
10653
10654 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10655 }"
10656)
10657
10658(define_split
10659 [(set (match_operand:SI 0 "s_register_operand" "")
10660 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10661 [(match_operand 2 "" "") (match_operand 3 "" "")])
10662 (match_operand 4 "" "")
10663 (match_dup 0)))
bd5b4116 10664 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10665 "TARGET_ARM && reload_completed"
8fa3ba89 10666 [(set (match_dup 5) (match_dup 6))
10667 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10668 (set (match_dup 0) (match_dup 4)))]
10669 "
10670 {
10671 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10672 operands[2], operands[3]);
10673
bd5b4116 10674 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10675 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10676 }"
10677)
10678
10679(define_split
10680 [(set (match_operand:SI 0 "s_register_operand" "")
10681 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10682 [(match_operand 2 "" "") (match_operand 3 "" "")])
10683 (match_operand 4 "" "")
10684 (match_operand 5 "" "")))
bd5b4116 10685 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10686 "TARGET_ARM && reload_completed"
8fa3ba89 10687 [(set (match_dup 6) (match_dup 7))
10688 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10689 (set (match_dup 0) (match_dup 4)))
10690 (cond_exec (match_dup 8)
10691 (set (match_dup 0) (match_dup 5)))]
10692 "
10693 {
10694 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10695 operands[2], operands[3]);
10696 enum rtx_code rc = GET_CODE (operands[1]);
10697
bd5b4116 10698 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10699 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10700 if (mode == CCFPmode || mode == CCFPEmode)
10701 rc = reverse_condition_maybe_unordered (rc);
10702 else
10703 rc = reverse_condition (rc);
10704
10705 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10706 }"
10707)
10708
cffb2a26 10709(define_split
10710 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10711 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10712 [(match_operand:SI 2 "s_register_operand" "")
10713 (match_operand:SI 3 "arm_add_operand" "")])
10714 (match_operand:SI 4 "arm_rhs_operand" "")
10715 (not:SI
10716 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10717 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10718 "TARGET_ARM && reload_completed"
cffb2a26 10719 [(set (match_dup 6) (match_dup 7))
f6c53574 10720 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10721 (set (match_dup 0) (match_dup 4)))
10722 (cond_exec (match_dup 8)
10723 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10724 "
215b30b3 10725 {
10726 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10727 operands[2], operands[3]);
f6c53574 10728 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10729
bd5b4116 10730 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10731 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10732 if (mode == CCFPmode || mode == CCFPEmode)
10733 rc = reverse_condition_maybe_unordered (rc);
10734 else
10735 rc = reverse_condition (rc);
10736
10737 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10738 }"
10739)
cffb2a26 10740
10741(define_insn "*cond_move_not"
10742 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10743 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10744 [(match_operand 3 "cc_register" "") (const_int 0)])
10745 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10746 (not:SI
10747 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10748 "TARGET_ARM"
10749 "@
10750 mvn%D4\\t%0, %2
10751 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10752 [(set_attr "conds" "use")
d2a518d1 10753 (set_attr "insn" "mvn")
0d66636f 10754 (set_attr "length" "4,8")]
10755)
cffb2a26 10756
9c08d1fa 10757;; The next two patterns occur when an AND operation is followed by a
10758;; scc insn sequence
10759
f7fbdd4a 10760(define_insn "*sign_extract_onebit"
9c08d1fa 10761 [(set (match_operand:SI 0 "s_register_operand" "=r")
10762 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10763 (const_int 1)
ed750274 10764 (match_operand:SI 2 "const_int_operand" "n")))
10765 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10766 "TARGET_ARM"
9c08d1fa 10767 "*
0d66636f 10768 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10769 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10770 return \"mvnne\\t%0, #0\";
10771 "
10772 [(set_attr "conds" "clob")
10773 (set_attr "length" "8")]
10774)
9c08d1fa 10775
f7fbdd4a 10776(define_insn "*not_signextract_onebit"
9c08d1fa 10777 [(set (match_operand:SI 0 "s_register_operand" "=r")
10778 (not:SI
10779 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10780 (const_int 1)
ed750274 10781 (match_operand:SI 2 "const_int_operand" "n"))))
10782 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10783 "TARGET_ARM"
9c08d1fa 10784 "*
0d66636f 10785 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10786 output_asm_insn (\"tst\\t%1, %2\", operands);
10787 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10788 return \"movne\\t%0, #0\";
10789 "
10790 [(set_attr "conds" "clob")
10791 (set_attr "length" "12")]
10792)
25f905c2 10793;; ??? The above patterns need auditing for Thumb-2
87b22bf7 10794
0d66636f 10795;; Push multiple registers to the stack. Registers are in parallel (use ...)
10796;; expressions. For simplicity, the first register is also in the unspec
10797;; part.
08508cbf 10798;; To avoid the usage of GNU extension, the length attribute is computed
10799;; in a C function arm_attr_length_push_multi.
f7fbdd4a 10800(define_insn "*push_multi"
87b22bf7 10801 [(match_parallel 2 "multi_register_push"
7571d3f7 10802 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
3cc80a30 10803 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
e1159bbe 10804 UNSPEC_PUSH_MULT))])]
7571d3f7 10805 ""
87b22bf7 10806 "*
215b30b3 10807 {
10808 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10809
215b30b3 10810 /* For the StrongARM at least it is faster to
25f905c2 10811 use STR to store only a single register.
542d5028 10812 In Thumb mode always use push, and the assembler will pick
10813 something appropriate. */
25f905c2 10814 if (num_saves == 1 && TARGET_ARM)
61309563 10815 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
215b30b3 10816 else
10817 {
10818 int i;
10819 char pattern[100];
ed593f11 10820
25f905c2 10821 if (TARGET_ARM)
61309563 10822 strcpy (pattern, \"stm%(fd%)\\t%m0!, {%1\");
10823 else if (TARGET_THUMB2)
10824 strcpy (pattern, \"push%?\\t{%1\");
25f905c2 10825 else
10826 strcpy (pattern, \"push\\t{%1\");
215b30b3 10827
6079f055 10828 for (i = 1; i < num_saves; i++)
215b30b3 10829 {
10830 strcat (pattern, \", %|\");
10831 strcat (pattern,
10832 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10833 }
10834
10835 strcat (pattern, \"}\");
10836 output_asm_insn (pattern, operands);
10837 }
10838
10839 return \"\";
10840 }"
a6864a24 10841 [(set_attr "type" "store4")
10842 (set (attr "length")
08508cbf 10843 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
215b30b3 10844)
f7fbdd4a 10845
4c58c898 10846(define_insn "stack_tie"
10847 [(set (mem:BLK (scratch))
aaa37ad6 10848 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10849 (match_operand:SI 1 "s_register_operand" "rk")]
4c58c898 10850 UNSPEC_PRLG_STK))]
10851 ""
10852 ""
10853 [(set_attr "length" "0")]
10854)
10855
3398e91d 10856;; Similarly for the floating point registers
7b1d2fc4 10857(define_insn "*push_fp_multi"
10858 [(match_parallel 2 "multi_register_push"
10859 [(set (match_operand:BLK 0 "memory_operand" "=m")
3cc80a30 10860 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "")]
e1159bbe 10861 UNSPEC_PUSH_MULT))])]
25f905c2 10862 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
7b1d2fc4 10863 "*
215b30b3 10864 {
10865 char pattern[100];
7b1d2fc4 10866
877cdec9 10867 sprintf (pattern, \"sfm%%(fd%%)\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
215b30b3 10868 output_asm_insn (pattern, operands);
10869 return \"\";
10870 }"
013b9671 10871 [(set_attr "type" "f_fpa_store")]
215b30b3 10872)
7b1d2fc4 10873
f7fbdd4a 10874;; Special patterns for dealing with the constant pool
10875
cffb2a26 10876(define_insn "align_4"
e1159bbe 10877 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10878 "TARGET_EITHER"
f7fbdd4a 10879 "*
cffb2a26 10880 assemble_align (32);
f7fbdd4a 10881 return \"\";
cffb2a26 10882 "
10883)
f7fbdd4a 10884
755eb2b4 10885(define_insn "align_8"
10886 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10887 "TARGET_EITHER"
755eb2b4 10888 "*
10889 assemble_align (64);
10890 return \"\";
10891 "
10892)
10893
cffb2a26 10894(define_insn "consttable_end"
e1159bbe 10895 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10896 "TARGET_EITHER"
f7fbdd4a 10897 "*
cffb2a26 10898 making_const_table = FALSE;
f7fbdd4a 10899 return \"\";
cffb2a26 10900 "
10901)
f7fbdd4a 10902
cffb2a26 10903(define_insn "consttable_1"
e1159bbe 10904 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
25f905c2 10905 "TARGET_THUMB1"
f7fbdd4a 10906 "*
cffb2a26 10907 making_const_table = TRUE;
09d688ff 10908 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 10909 assemble_zeros (3);
f7fbdd4a 10910 return \"\";
cffb2a26 10911 "
10912 [(set_attr "length" "4")]
10913)
f7fbdd4a 10914
cffb2a26 10915(define_insn "consttable_2"
e1159bbe 10916 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
25f905c2 10917 "TARGET_THUMB1"
f7fbdd4a 10918 "*
cffb2a26 10919 making_const_table = TRUE;
9b8516be 10920 gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
09d688ff 10921 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 10922 assemble_zeros (2);
f7fbdd4a 10923 return \"\";
cffb2a26 10924 "
10925 [(set_attr "length" "4")]
10926)
10927
10928(define_insn "consttable_4"
e1159bbe 10929 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10930 "TARGET_EITHER"
10931 "*
10932 {
9b8516be 10933 rtx x = operands[0];
cffb2a26 10934 making_const_table = TRUE;
9b8516be 10935 switch (GET_MODE_CLASS (GET_MODE (x)))
cffb2a26 10936 {
10937 case MODE_FLOAT:
9b8516be 10938 if (GET_MODE (x) == HFmode)
10939 arm_emit_fp16_const (x);
10940 else
10941 {
10942 REAL_VALUE_TYPE r;
10943 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
10944 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
10945 }
10946 break;
cffb2a26 10947 default:
7b04c5d5 10948 /* XXX: Sometimes gcc does something really dumb and ends up with
10949 a HIGH in a constant pool entry, usually because it's trying to
10950 load into a VFP register. We know this will always be used in
10951 combination with a LO_SUM which ignores the high bits, so just
10952 strip off the HIGH. */
10953 if (GET_CODE (x) == HIGH)
10954 x = XEXP (x, 0);
9b8516be 10955 assemble_integer (x, 4, BITS_PER_WORD, 1);
10956 mark_symbol_refs_as_used (x);
cffb2a26 10957 break;
10958 }
10959 return \"\";
10960 }"
10961 [(set_attr "length" "4")]
10962)
10963
10964(define_insn "consttable_8"
e1159bbe 10965 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10966 "TARGET_EITHER"
10967 "*
10968 {
10969 making_const_table = TRUE;
10970 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10971 {
10972 case MODE_FLOAT:
10973 {
badfe841 10974 REAL_VALUE_TYPE r;
10975 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10976 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10977 break;
10978 }
10979 default:
09d688ff 10980 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10981 break;
10982 }
10983 return \"\";
10984 }"
10985 [(set_attr "length" "8")]
10986)
10987
d98a3884 10988(define_insn "consttable_16"
10989 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10990 "TARGET_EITHER"
10991 "*
10992 {
10993 making_const_table = TRUE;
10994 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10995 {
10996 case MODE_FLOAT:
10997 {
10998 REAL_VALUE_TYPE r;
10999 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
11000 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
11001 break;
11002 }
11003 default:
11004 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
11005 break;
11006 }
11007 return \"\";
11008 }"
11009 [(set_attr "length" "16")]
11010)
11011
cffb2a26 11012;; Miscellaneous Thumb patterns
11013
fd957ef3 11014(define_expand "tablejump"
7db9af5d 11015 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 11016 (use (label_ref (match_operand 1 "" "")))])]
25f905c2 11017 "TARGET_THUMB1"
fd957ef3 11018 "
11019 if (flag_pic)
11020 {
11021 /* Hopefully, CSE will eliminate this copy. */
11022 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
11023 rtx reg2 = gen_reg_rtx (SImode);
11024
11025 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
11026 operands[0] = reg2;
11027 }
11028 "
11029)
11030
f1039640 11031;; NB never uses BX.
25f905c2 11032(define_insn "*thumb1_tablejump"
cffb2a26 11033 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
11034 (use (label_ref (match_operand 1 "" "")))]
25f905c2 11035 "TARGET_THUMB1"
fd957ef3 11036 "mov\\t%|pc, %0"
cffb2a26 11037 [(set_attr "length" "2")]
11038)
0d66636f 11039
331beb1a 11040;; V5 Instructions,
11041
8f4be2be 11042(define_insn "clzsi2"
11043 [(set (match_operand:SI 0 "s_register_operand" "=r")
11044 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
25f905c2 11045 "TARGET_32BIT && arm_arch5"
ee7cbe0e 11046 "clz%?\\t%0, %1"
bcaec148 11047 [(set_attr "predicable" "yes")
11048 (set_attr "insn" "clz")])
331beb1a 11049
099ad98b 11050(define_insn "rbitsi2"
11051 [(set (match_operand:SI 0 "s_register_operand" "=r")
11052 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
11053 "TARGET_32BIT && arm_arch_thumb2"
11054 "rbit%?\\t%0, %1"
11055 [(set_attr "predicable" "yes")
11056 (set_attr "insn" "clz")])
11057
11058(define_expand "ctzsi2"
11059 [(set (match_operand:SI 0 "s_register_operand" "")
11060 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
11061 "TARGET_32BIT && arm_arch_thumb2"
11062 "
30191172 11063 {
11064 rtx tmp = gen_reg_rtx (SImode);
11065 emit_insn (gen_rbitsi2 (tmp, operands[1]));
11066 emit_insn (gen_clzsi2 (operands[0], tmp));
11067 }
099ad98b 11068 DONE;
11069 "
11070)
11071
e1159bbe 11072;; V5E instructions.
331beb1a 11073
11074(define_insn "prefetch"
f4e79814 11075 [(prefetch (match_operand:SI 0 "address_operand" "p")
11076 (match_operand:SI 1 "" "")
11077 (match_operand:SI 2 "" ""))]
25f905c2 11078 "TARGET_32BIT && arm_arch5e"
bcb7a8f6 11079 "pld\\t%a0")
331beb1a 11080
0d66636f 11081;; General predication pattern
11082
11083(define_cond_exec
11084 [(match_operator 0 "arm_comparison_operator"
11085 [(match_operand 1 "cc_register" "")
11086 (const_int 0)])]
25f905c2 11087 "TARGET_32BIT"
0d66636f 11088 ""
11089)
11090
063a05c7 11091(define_insn "prologue_use"
11092 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
11093 ""
11094 "%@ %0 needed for prologue"
02cfc9c9 11095 [(set_attr "length" "0")]
063a05c7 11096)
7db9af5d 11097
4c44712e 11098
11099;; Patterns for exception handling
11100
11101(define_expand "eh_return"
11102 [(use (match_operand 0 "general_operand" ""))]
11103 "TARGET_EITHER"
11104 "
11105 {
25f905c2 11106 if (TARGET_32BIT)
4c44712e 11107 emit_insn (gen_arm_eh_return (operands[0]));
11108 else
11109 emit_insn (gen_thumb_eh_return (operands[0]));
11110 DONE;
11111 }"
11112)
11113
11114;; We can't expand this before we know where the link register is stored.
11115(define_insn_and_split "arm_eh_return"
11116 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11117 VUNSPEC_EH_RETURN)
11118 (clobber (match_scratch:SI 1 "=&r"))]
11119 "TARGET_ARM"
11120 "#"
11121 "&& reload_completed"
11122 [(const_int 0)]
11123 "
11124 {
11125 arm_set_return_address (operands[0], operands[1]);
11126 DONE;
11127 }"
11128)
11129
11130(define_insn_and_split "thumb_eh_return"
11131 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
11132 VUNSPEC_EH_RETURN)
11133 (clobber (match_scratch:SI 1 "=&l"))]
25f905c2 11134 "TARGET_THUMB1"
4c44712e 11135 "#"
11136 "&& reload_completed"
11137 [(const_int 0)]
11138 "
11139 {
11140 thumb_set_return_address (operands[0], operands[1]);
11141 DONE;
11142 }"
11143)
11144
f655717d 11145\f
11146;; TLS support
11147
11148(define_insn "load_tp_hard"
11149 [(set (match_operand:SI 0 "register_operand" "=r")
11150 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11151 "TARGET_HARD_TP"
11152 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
11153 [(set_attr "predicable" "yes")]
11154)
11155
11156;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11157(define_insn "load_tp_soft"
11158 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11159 (clobber (reg:SI LR_REGNUM))
11160 (clobber (reg:SI IP_REGNUM))
11161 (clobber (reg:CC CC_REGNUM))]
11162 "TARGET_SOFT_TP"
11163 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
11164 [(set_attr "conds" "clob")]
11165)
11166
f41e4452 11167;; tls descriptor call
11168(define_insn "tlscall"
11169 [(set (reg:SI R0_REGNUM)
11170 (unspec:SI [(reg:SI R0_REGNUM)
11171 (match_operand:SI 0 "" "X")
11172 (match_operand 1 "" "")] UNSPEC_TLS))
11173 (clobber (reg:SI R1_REGNUM))
11174 (clobber (reg:SI LR_REGNUM))
11175 (clobber (reg:SI CC_REGNUM))]
11176 "TARGET_GNU2_TLS"
11177 {
11178 targetm.asm_out.internal_label (asm_out_file, "LPIC",
11179 INTVAL (operands[1]));
11180 return "bl\\t%c0(tlscall)";
11181 }
11182 [(set_attr "conds" "clob")
11183 (set_attr "length" "4")]
11184)
11185
11186;;
11187
aabe09ac 11188;; We only care about the lower 16 bits of the constant
11189;; being inserted into the upper 16 bits of the register.
eca5c984 11190(define_insn "*arm_movtas_ze"
11191 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
11192 (const_int 16)
11193 (const_int 16))
11194 (match_operand:SI 1 "const_int_operand" ""))]
181ab277 11195 "arm_arch_thumb2"
aabe09ac 11196 "movt%?\t%0, %L1"
eca5c984 11197 [(set_attr "predicable" "yes")
11198 (set_attr "length" "4")]
11199)
11200
c0fc3696 11201(define_insn "*arm_rev"
ff82f757 11202 [(set (match_operand:SI 0 "s_register_operand" "=r")
11203 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
c0fc3696 11204 "TARGET_32BIT && arm_arch6"
11205 "rev%?\t%0, %1"
11206 [(set_attr "predicable" "yes")
11207 (set_attr "length" "4")]
11208)
11209
11210(define_insn "*thumb1_rev"
11211 [(set (match_operand:SI 0 "s_register_operand" "=l")
11212 (bswap:SI (match_operand:SI 1 "s_register_operand" "l")))]
11213 "TARGET_THUMB1 && arm_arch6"
11214 "rev\t%0, %1"
11215 [(set_attr "length" "2")]
ff82f757 11216)
11217
11218(define_expand "arm_legacy_rev"
11219 [(set (match_operand:SI 2 "s_register_operand" "")
11220 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
11221 (const_int 16))
11222 (match_dup 1)))
11223 (set (match_dup 2)
11224 (lshiftrt:SI (match_dup 2)
11225 (const_int 8)))
11226 (set (match_operand:SI 3 "s_register_operand" "")
11227 (rotatert:SI (match_dup 1)
11228 (const_int 8)))
11229 (set (match_dup 2)
11230 (and:SI (match_dup 2)
11231 (const_int -65281)))
11232 (set (match_operand:SI 0 "s_register_operand" "")
11233 (xor:SI (match_dup 3)
11234 (match_dup 2)))]
11235 "TARGET_32BIT"
11236 ""
11237)
11238
11239;; Reuse temporaries to keep register pressure down.
11240(define_expand "thumb_legacy_rev"
11241 [(set (match_operand:SI 2 "s_register_operand" "")
11242 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
11243 (const_int 24)))
11244 (set (match_operand:SI 3 "s_register_operand" "")
11245 (lshiftrt:SI (match_dup 1)
11246 (const_int 24)))
11247 (set (match_dup 3)
11248 (ior:SI (match_dup 3)
11249 (match_dup 2)))
11250 (set (match_operand:SI 4 "s_register_operand" "")
11251 (const_int 16))
11252 (set (match_operand:SI 5 "s_register_operand" "")
11253 (rotatert:SI (match_dup 1)
11254 (match_dup 4)))
11255 (set (match_dup 2)
11256 (ashift:SI (match_dup 5)
11257 (const_int 24)))
11258 (set (match_dup 5)
11259 (lshiftrt:SI (match_dup 5)
11260 (const_int 24)))
11261 (set (match_dup 5)
11262 (ior:SI (match_dup 5)
11263 (match_dup 2)))
11264 (set (match_dup 5)
11265 (rotatert:SI (match_dup 5)
11266 (match_dup 4)))
11267 (set (match_operand:SI 0 "s_register_operand" "")
11268 (ior:SI (match_dup 5)
11269 (match_dup 3)))]
11270 "TARGET_THUMB"
11271 ""
11272)
11273
11274(define_expand "bswapsi2"
11275 [(set (match_operand:SI 0 "s_register_operand" "=r")
11276 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
8d1af482 11277"TARGET_EITHER && (arm_arch6 || !optimize_size)"
ff82f757 11278"
8d1af482 11279 if (!arm_arch6)
11280 {
11281 rtx op2 = gen_reg_rtx (SImode);
11282 rtx op3 = gen_reg_rtx (SImode);
ff82f757 11283
8d1af482 11284 if (TARGET_THUMB)
11285 {
11286 rtx op4 = gen_reg_rtx (SImode);
11287 rtx op5 = gen_reg_rtx (SImode);
ff82f757 11288
8d1af482 11289 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11290 op2, op3, op4, op5));
11291 }
11292 else
11293 {
11294 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11295 op2, op3));
11296 }
ff82f757 11297
8d1af482 11298 DONE;
11299 }
ff82f757 11300 "
11301)
11302
320ea44d 11303;; Load the load/store multiple patterns
11304(include "ldmstm.md")
7db9af5d 11305;; Load the FPA co-processor patterns
11306(include "fpa.md")
11307;; Load the Maverick co-processor patterns
11308(include "cirrus.md")
d98a3884 11309;; Vector bits common to IWMMXT and Neon
11310(include "vec-common.md")
755eb2b4 11311;; Load the Intel Wireless Multimedia Extension patterns
11312(include "iwmmxt.md")
a2cd141b 11313;; Load the VFP co-processor patterns
11314(include "vfp.md")
25f905c2 11315;; Thumb-2 patterns
11316(include "thumb2.md")
d98a3884 11317;; Neon patterns
11318(include "neon.md")
06df6b17 11319;; Synchronization Primitives
11320(include "sync.md")
bbbe4599 11321;; Fixed-point patterns
11322(include "arm-fixed.md")