]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
Update copyright years in gcc/
[thirdparty/gcc.git] / gcc / config / arm / arm.md
CommitLineData
b36ba79f 1;;- Machine description for ARM for GNU compiler
23a5b65a 2;; Copyright (C) 1991-2014 Free Software Foundation, Inc.
3a33f76f 3;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
7a0a1f09 4;; and Martin Simmons (@harleqn.co.uk).
b36ba79f 5;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
3a33f76f 6
4f448245 7;; This file is part of GCC.
3a33f76f 8
4f448245
NC
9;; GCC is free software; you can redistribute it and/or modify it
10;; under the terms of the GNU General Public License as published
2f83c7d6 11;; by the Free Software Foundation; either version 3, or (at your
4f448245 12;; option) any later version.
3a33f76f 13
4f448245
NC
14;; GCC is distributed in the hope that it will be useful, but WITHOUT
15;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17;; License for more details.
3a33f76f
RK
18
19;; You should have received a copy of the GNU General Public License
2f83c7d6
NC
20;; along with GCC; see the file COPYING3. If not see
21;; <http://www.gnu.org/licenses/>.
3a33f76f
RK
22
23;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
24
2385b218
GY
25;; Beware of splitting Thumb1 patterns that output multiple
26;; assembly instructions, in particular instruction such as SBC and
27;; ADC which consume flags. For example, in the pattern thumb_subdi3
28;; below, the output SUB implicitly sets the flags (assembled to SUBS)
29;; and then the Carry flag is used by SBC to compute the correct
30;; result. If we split thumb_subdi3 pattern into two separate RTL
31;; insns (using define_insn_and_split), the scheduler might place
32;; other RTL insns between SUB and SBC, possibly modifying the Carry
33;; flag used by SBC. This might happen because most Thumb1 patterns
34;; for flag-setting instructions do not have explicit RTL for setting
35;; or clobbering the flags. Instead, they have the attribute "conds"
36;; with value "set" or "clob". However, this attribute is not used to
37;; identify dependencies and therefore the scheduler might reorder
38;; these instruction. Currenly, this problem cannot happen because
39;; there are no separate Thumb1 patterns for individual instruction
40;; that consume flags (except conditional execution, which is treated
41;; differently). In particular there is no Thumb1 armv6-m pattern for
42;; sbc or adc.
43
ff9940b0 44\f
b15bca31
RE
45;;---------------------------------------------------------------------------
46;; Constants
47
0be8bd1a 48;; Register numbers -- All machine registers should be defined here
b15bca31 49(define_constants
0be8bd1a
RE
50 [(R0_REGNUM 0) ; First CORE register
51 (R1_REGNUM 1) ; Second CORE register
52 (IP_REGNUM 12) ; Scratch register
53 (SP_REGNUM 13) ; Stack pointer
54 (LR_REGNUM 14) ; Return address register
55 (PC_REGNUM 15) ; Program counter
56 (LAST_ARM_REGNUM 15) ;
57 (CC_REGNUM 100) ; Condition code pseudo register
58 (VFPCC_REGNUM 101) ; VFP Condition code pseudo register
b15bca31
RE
59 ]
60)
03f1640c
RE
61;; 3rd operand to select_dominance_cc_mode
62(define_constants
63 [(DOM_CC_X_AND_Y 0)
64 (DOM_CC_NX_OR_Y 1)
65 (DOM_CC_X_OR_Y 2)
66 ]
67)
990b31f7
JL
68;; conditional compare combination
69(define_constants
70 [(CMP_CMP 0)
71 (CMN_CMP 1)
72 (CMP_CMN 2)
73 (CMN_CMN 3)
74 (NUM_OF_COND_CMP 4)
75 ]
76)
b15bca31 77
3a33f76f 78\f
b15bca31 79;;---------------------------------------------------------------------------
ff9940b0
RE
80;; Attributes
81
7baa7c13
BS
82;; Processor type. This is created automatically from arm-cores.def.
83(include "arm-tune.md")
84
02231c13
TG
85;; Instruction classification types
86(include "types.md")
87
5895f793
RE
88; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
89; generating ARM code. This is used to control the length of some insn
90; patterns that share the same RTL in both ARM and Thumb code.
0616531f 91(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
d5b7b3ae 92
e4c6a07a
BS
93; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
94(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
95
906668bb
BS
96; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
97(define_attr "is_thumb1" "no,yes" (const (symbol_ref "thumb1_code")))
98
17a7fc37
KT
99; We use this attribute to disable alternatives that can produce 32-bit
100; instructions inside an IT-block in Thumb2 state. ARMv8 deprecates IT blocks
101; that contain 32-bit instructions.
102(define_attr "enabled_for_depr_it" "no,yes" (const_string "yes"))
103
104; This attribute is used to disable a predicated alternative when we have
105; arm_restrict_it.
106(define_attr "predicable_short_it" "no,yes" (const_string "yes"))
107
d19fb8e3
NC
108;; Operand number of an input operand that is shifted. Zero if the
109;; given instruction does not shift one of its input operands.
d19fb8e3
NC
110(define_attr "shift" "" (const_int 0))
111
dfaa6d72
RE
112; Floating Point Unit. If we only have floating point emulation, then there
113; is no point in scheduling the floating point insns. (Well, for best
114; performance we should try and group them together).
0be8bd1a 115(define_attr "fpu" "none,vfp"
29ad9694 116 (const (symbol_ref "arm_fpu_attr")))
dfaa6d72 117
17a7fc37
KT
118(define_attr "predicated" "yes,no" (const_string "no"))
119
a1dc0475 120; LENGTH of an instruction (in bytes)
029e79eb 121(define_attr "length" ""
18f0fe6b 122 (const_int 4))
ff9940b0 123
c29e2982
BS
124; The architecture which supports the instruction (or alternative).
125; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
126; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
127; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
128; arm_arch6. This attribute is used to compute attribute "enabled",
129; use type "any" to enable an alternative in all cases.
65074f54 130(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,neon_for_64bits,avoid_neon_for_64bits,iwmmxt,iwmmxt2"
c29e2982
BS
131 (const_string "any"))
132
133(define_attr "arch_enabled" "no,yes"
134 (cond [(eq_attr "arch" "any")
135 (const_string "yes")
136
137 (and (eq_attr "arch" "a")
b75b1be2 138 (match_test "TARGET_ARM"))
c29e2982
BS
139 (const_string "yes")
140
141 (and (eq_attr "arch" "t")
b75b1be2 142 (match_test "TARGET_THUMB"))
c29e2982
BS
143 (const_string "yes")
144
145 (and (eq_attr "arch" "t1")
b75b1be2 146 (match_test "TARGET_THUMB1"))
c29e2982
BS
147 (const_string "yes")
148
149 (and (eq_attr "arch" "t2")
b75b1be2 150 (match_test "TARGET_THUMB2"))
c29e2982
BS
151 (const_string "yes")
152
153 (and (eq_attr "arch" "32")
b75b1be2 154 (match_test "TARGET_32BIT"))
c29e2982
BS
155 (const_string "yes")
156
157 (and (eq_attr "arch" "v6")
b75b1be2 158 (match_test "TARGET_32BIT && arm_arch6"))
c29e2982
BS
159 (const_string "yes")
160
161 (and (eq_attr "arch" "nov6")
b75b1be2 162 (match_test "TARGET_32BIT && !arm_arch6"))
7baa7c13
BS
163 (const_string "yes")
164
65074f54
CL
165 (and (eq_attr "arch" "avoid_neon_for_64bits")
166 (match_test "TARGET_NEON")
167 (not (match_test "TARGET_PREFER_NEON_64BITS")))
7baa7c13
BS
168 (const_string "yes")
169
65074f54
CL
170 (and (eq_attr "arch" "neon_for_64bits")
171 (match_test "TARGET_NEON")
172 (match_test "TARGET_PREFER_NEON_64BITS"))
8fd03515
XQ
173 (const_string "yes")
174
175 (and (eq_attr "arch" "iwmmxt2")
176 (match_test "TARGET_REALLY_IWMMXT2"))
c29e2982 177 (const_string "yes")]
8fd03515 178
c29e2982
BS
179 (const_string "no")))
180
3f2dc806
AS
181(define_attr "opt" "any,speed,size"
182 (const_string "any"))
183
184(define_attr "opt_enabled" "no,yes"
185 (cond [(eq_attr "opt" "any")
186 (const_string "yes")
187
188 (and (eq_attr "opt" "speed")
189 (match_test "optimize_function_for_speed_p (cfun)"))
190 (const_string "yes")
191
192 (and (eq_attr "opt" "size")
193 (match_test "optimize_function_for_size_p (cfun)"))
194 (const_string "yes")]
195 (const_string "no")))
196
02231c13
TG
197(define_attr "use_literal_pool" "no,yes"
198 (cond [(and (eq_attr "type" "f_loads,f_loadd")
199 (match_test "CONSTANT_P (operands[1])"))
200 (const_string "yes")]
201 (const_string "no")))
202
c29e2982
BS
203; Allows an insn to disable certain alternatives for reasons other than
204; arch support.
205(define_attr "insn_enabled" "no,yes"
206 (const_string "yes"))
207
208; Enable all alternatives that are both arch_enabled and insn_enabled.
da787dec 209 (define_attr "enabled" "no,yes"
3f2dc806
AS
210 (cond [(eq_attr "insn_enabled" "no")
211 (const_string "no")
212
17a7fc37
KT
213 (and (eq_attr "predicable_short_it" "no")
214 (and (eq_attr "predicated" "yes")
215 (match_test "arm_restrict_it")))
216 (const_string "no")
217
218 (and (eq_attr "enabled_for_depr_it" "no")
219 (match_test "arm_restrict_it"))
220 (const_string "no")
221
02231c13
TG
222 (and (eq_attr "use_literal_pool" "yes")
223 (match_test "arm_disable_literal_pool"))
224 (const_string "no")
225
3f2dc806
AS
226 (eq_attr "arch_enabled" "no")
227 (const_string "no")
228
229 (eq_attr "opt_enabled" "no")
230 (const_string "no")]
231 (const_string "yes")))
c29e2982 232
949d79eb
RE
233; POOL_RANGE is how far away from a constant pool entry that this insn
234; can be placed. If the distance is zero, then this insn will never
235; reference the pool.
88f519b2
MGD
236; Note that for Thumb constant pools the PC value is rounded down to the
237; nearest multiple of four. Therefore, THUMB2_POOL_RANGE (and POOL_RANGE for
238; Thumb insns) should be set to <max_range> - 2.
d5b7b3ae 239; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
635a48fb 240; before its address. It is set to <max_range> - (8 + <data_size>).
0bd44ba2
BS
241(define_attr "arm_pool_range" "" (const_int 0))
242(define_attr "thumb2_pool_range" "" (const_int 0))
243(define_attr "arm_neg_pool_range" "" (const_int 0))
244(define_attr "thumb2_neg_pool_range" "" (const_int 0))
245
246(define_attr "pool_range" ""
247 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
248 (attr "arm_pool_range")))
249(define_attr "neg_pool_range" ""
250 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
251 (attr "arm_neg_pool_range")))
949d79eb 252
5895f793 253; An assembler sequence may clobber the condition codes without us knowing.
56fbb855
RE
254; If such an insn references the pool, then we have no way of knowing how,
255; so use the most conservative value for pool_range.
ff9940b0 256(define_asm_attributes
56fbb855
RE
257 [(set_attr "conds" "clob")
258 (set_attr "length" "4")
259 (set_attr "pool_range" "250")])
ff9940b0 260
f5a1b0d2 261; Load scheduling, set from the arm_ld_sched variable
c5387660 262; initialized by arm_option_override()
f5a1b0d2 263(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
fef37aaf 264
f7379e5e
JG
265; YES if the "type" attribute assigned to the insn denotes an
266; Advanced SIMD instruction, NO otherwise.
267(define_attr "is_neon_type" "yes,no"
268 (if_then_else (eq_attr "type"
269 "neon_add, neon_add_q, neon_add_widen, neon_add_long,\
270 neon_qadd, neon_qadd_q, neon_add_halve, neon_add_halve_q,\
271 neon_add_halve_narrow_q,\
272 neon_sub, neon_sub_q, neon_sub_widen, neon_sub_long, neon_qsub,\
273 neon_qsub_q, neon_sub_halve, neon_sub_halve_q,\
274 neon_sub_halve_narrow_q,\
275 neon_abs, neon_abs_q, neon_neg, neon_neg_q, neon_qneg,\
276 neon_qneg_q, neon_qabs, neon_qabs_q, neon_abd, neon_abd_q,\
277 neon_abd_long, neon_minmax, neon_minmax_q, neon_compare,\
278 neon_compare_q, neon_compare_zero, neon_compare_zero_q,\
279 neon_arith_acc, neon_arith_acc_q, neon_reduc_add,\
280 neon_reduc_add_q, neon_reduc_add_long, neon_reduc_add_acc,\
281 neon_reduc_add_acc_q, neon_reduc_minmax, neon_reduc_minmax_q,\
282 neon_logic, neon_logic_q, neon_tst, neon_tst_q,\
283 neon_shift_imm, neon_shift_imm_q, neon_shift_imm_narrow_q,\
284 neon_shift_imm_long, neon_shift_reg, neon_shift_reg_q,\
285 neon_shift_acc, neon_shift_acc_q, neon_sat_shift_imm,\
286 neon_sat_shift_imm_q, neon_sat_shift_imm_narrow_q,\
287 neon_sat_shift_reg, neon_sat_shift_reg_q,\
288 neon_ins, neon_ins_q, neon_move, neon_move_q, neon_move_narrow_q,\
289 neon_permute, neon_permute_q, neon_zip, neon_zip_q, neon_tbl1,\
290 neon_tbl1_q, neon_tbl2, neon_tbl2_q, neon_tbl3, neon_tbl3_q,\
291 neon_tbl4, neon_tbl4_q, neon_bsl, neon_bsl_q, neon_cls,\
292 neon_cls_q, neon_cnt, neon_cnt_q, neon_dup, neon_dup_q,\
293 neon_ext, neon_ext_q, neon_rbit, neon_rbit_q,\
294 neon_rev, neon_rev_q, neon_mul_b, neon_mul_b_q, neon_mul_h,\
295 neon_mul_h_q, neon_mul_s, neon_mul_s_q, neon_mul_b_long,\
021b5e6b 296 neon_mul_h_long, neon_mul_s_long, neon_mul_d_long, neon_mul_h_scalar,\
f7379e5e
JG
297 neon_mul_h_scalar_q, neon_mul_s_scalar, neon_mul_s_scalar_q,\
298 neon_mul_h_scalar_long, neon_mul_s_scalar_long, neon_sat_mul_b,\
299 neon_sat_mul_b_q, neon_sat_mul_h, neon_sat_mul_h_q,\
300 neon_sat_mul_s, neon_sat_mul_s_q, neon_sat_mul_b_long,\
301 neon_sat_mul_h_long, neon_sat_mul_s_long, neon_sat_mul_h_scalar,\
302 neon_sat_mul_h_scalar_q, neon_sat_mul_s_scalar,\
303 neon_sat_mul_s_scalar_q, neon_sat_mul_h_scalar_long,\
304 neon_sat_mul_s_scalar_long, neon_mla_b, neon_mla_b_q, neon_mla_h,\
305 neon_mla_h_q, neon_mla_s, neon_mla_s_q, neon_mla_b_long,\
306 neon_mla_h_long, neon_mla_s_long, neon_mla_h_scalar,\
307 neon_mla_h_scalar_q, neon_mla_s_scalar, neon_mla_s_scalar_q,\
308 neon_mla_h_scalar_long, neon_mla_s_scalar_long,\
309 neon_sat_mla_b_long, neon_sat_mla_h_long,\
310 neon_sat_mla_s_long, neon_sat_mla_h_scalar_long,\
311 neon_sat_mla_s_scalar_long,\
312 neon_to_gp, neon_to_gp_q, neon_from_gp, neon_from_gp_q,\
313 neon_ldr, neon_load1_1reg, neon_load1_1reg_q, neon_load1_2reg,\
314 neon_load1_2reg_q, neon_load1_3reg, neon_load1_3reg_q,\
315 neon_load1_4reg, neon_load1_4reg_q, neon_load1_all_lanes,\
316 neon_load1_all_lanes_q, neon_load1_one_lane, neon_load1_one_lane_q,\
317 neon_load2_2reg, neon_load2_2reg_q, neon_load2_4reg,\
318 neon_load2_4reg_q, neon_load2_all_lanes, neon_load2_all_lanes_q,\
319 neon_load2_one_lane, neon_load2_one_lane_q,\
320 neon_load3_3reg, neon_load3_3reg_q, neon_load3_all_lanes,\
321 neon_load3_all_lanes_q, neon_load3_one_lane, neon_load3_one_lane_q,\
322 neon_load4_4reg, neon_load4_4reg_q, neon_load4_all_lanes,\
323 neon_load4_all_lanes_q, neon_load4_one_lane, neon_load4_one_lane_q,\
324 neon_str, neon_store1_1reg, neon_store1_1reg_q, neon_store1_2reg,\
325 neon_store1_2reg_q, neon_store1_3reg, neon_store1_3reg_q,\
326 neon_store1_4reg, neon_store1_4reg_q, neon_store1_one_lane,\
327 neon_store1_one_lane_q, neon_store2_2reg, neon_store2_2reg_q,\
328 neon_store2_4reg, neon_store2_4reg_q, neon_store2_one_lane,\
329 neon_store2_one_lane_q, neon_store3_3reg, neon_store3_3reg_q,\
330 neon_store3_one_lane, neon_store3_one_lane_q, neon_store4_4reg,\
331 neon_store4_4reg_q, neon_store4_one_lane, neon_store4_one_lane_q,\
332 neon_fp_abd_s, neon_fp_abd_s_q, neon_fp_abd_d, neon_fp_abd_d_q,\
333 neon_fp_addsub_s, neon_fp_addsub_s_q, neon_fp_addsub_d,\
334 neon_fp_addsub_d_q, neon_fp_compare_s, neon_fp_compare_s_q,\
335 neon_fp_compare_d, neon_fp_compare_d_q, neon_fp_minmax_s,\
336 neon_fp_minmax_s_q, neon_fp_minmax_d, neon_fp_minmax_d_q,\
337 neon_fp_reduc_add_s, neon_fp_reduc_add_s_q, neon_fp_reduc_add_d,\
338 neon_fp_reduc_add_d_q, neon_fp_reduc_minmax_s,
339 neon_fp_reduc_minmax_s_q, neon_fp_reduc_minmax_d,\
340 neon_fp_reduc_minmax_d_q,\
341 neon_fp_cvt_narrow_s_q, neon_fp_cvt_narrow_d_q,\
342 neon_fp_cvt_widen_h, neon_fp_cvt_widen_s, neon_fp_to_int_s,\
343 neon_fp_to_int_s_q, neon_int_to_fp_s, neon_int_to_fp_s_q,\
344 neon_fp_round_s, neon_fp_round_s_q, neon_fp_recpe_s,\
345 neon_fp_recpe_s_q,\
346 neon_fp_recpe_d, neon_fp_recpe_d_q, neon_fp_recps_s,\
347 neon_fp_recps_s_q, neon_fp_recps_d, neon_fp_recps_d_q,\
348 neon_fp_recpx_s, neon_fp_recpx_s_q, neon_fp_recpx_d,\
349 neon_fp_recpx_d_q, neon_fp_rsqrte_s, neon_fp_rsqrte_s_q,\
350 neon_fp_rsqrte_d, neon_fp_rsqrte_d_q, neon_fp_rsqrts_s,\
351 neon_fp_rsqrts_s_q, neon_fp_rsqrts_d, neon_fp_rsqrts_d_q,\
352 neon_fp_mul_s, neon_fp_mul_s_q, neon_fp_mul_s_scalar,\
353 neon_fp_mul_s_scalar_q, neon_fp_mul_d, neon_fp_mul_d_q,\
354 neon_fp_mul_d_scalar_q, neon_fp_mla_s, neon_fp_mla_s_q,\
355 neon_fp_mla_s_scalar, neon_fp_mla_s_scalar_q, neon_fp_mla_d,\
356 neon_fp_mla_d_q, neon_fp_mla_d_scalar_q, neon_fp_sqrt_s,\
357 neon_fp_sqrt_s_q, neon_fp_sqrt_d, neon_fp_sqrt_d_q,\
021b5e6b
KT
358 neon_fp_div_s, neon_fp_div_s_q, neon_fp_div_d, neon_fp_div_d_q, crypto_aes,\
359 crypto_sha1_xor, crypto_sha1_fast, crypto_sha1_slow, crypto_sha256_fast,\
360 crypto_sha256_slow")
f7379e5e
JG
361 (const_string "yes")
362 (const_string "no")))
363
4cdb3ed4
RE
364; condition codes: this one is used by final_prescan_insn to speed up
365; conditionalizing instructions. It saves having to scan the rtl to see if
366; it uses or alters the condition codes.
5895f793 367;
4cdb3ed4 368; USE means that the condition codes are used by the insn in the process of
5895f793
RE
369; outputting code, this means (at present) that we can't use the insn in
370; inlined branches
371;
4cdb3ed4 372; SET means that the purpose of the insn is to set the condition codes in a
5895f793
RE
373; well defined manner.
374;
4cdb3ed4 375; CLOB means that the condition codes are altered in an undefined manner, if
5895f793
RE
376; they are altered at all
377;
e88290ac
MS
378; UNCONDITIONAL means the instruction can not be conditionally executed and
379; that the instruction does not use or alter the condition codes.
ecee559f 380;
e88290ac
MS
381; NOCOND means that the instruction does not use or alter the condition
382; codes but can be converted into a conditionally exectuted instruction.
4cdb3ed4 383
accbd151 384(define_attr "conds" "use,set,clob,unconditional,nocond"
906668bb
BS
385 (if_then_else
386 (ior (eq_attr "is_thumb1" "yes")
387 (eq_attr "type" "call"))
61f0ccff 388 (const_string "clob")
f7379e5e 389 (if_then_else (eq_attr "is_neon_type" "no")
003bb7f3
JG
390 (const_string "nocond")
391 (const_string "unconditional"))))
4cdb3ed4 392
5895f793
RE
393; Predicable means that the insn can be conditionally executed based on
394; an automatically added predicate (additional patterns are generated by
395; gen...). We default to 'no' because no Thumb patterns match this rule
396; and not all ARM patterns do.
cca0a211
RE
397(define_attr "predicable" "no,yes" (const_string "no"))
398
b36ba79f
RE
399; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
400; have one. Later ones, such as StrongARM, have write-back caches, so don't
9a9f7594 401; suffer blockages enough to warrant modelling this (and it can adversely
b36ba79f 402; affect the schedule).
abac3b49 403(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
b36ba79f 404
5895f793
RE
405; WRITE_CONFLICT implies that a read following an unrelated write is likely
406; to stall the processor. Used with model_wbuf above.
ff9940b0
RE
407(define_attr "write_conflict" "no,yes"
408 (if_then_else (eq_attr "type"
82981dc4 409 "block,call,load1")
ff9940b0
RE
410 (const_string "yes")
411 (const_string "no")))
412
5895f793
RE
413; Classify the insns into those that take one cycle and those that take more
414; than one on the main cpu execution unit.
4cdb3ed4
RE
415(define_attr "core_cycles" "single,multi"
416 (if_then_else (eq_attr "type"
6e4150e1
JG
417 "adc_imm, adc_reg, adcs_imm, adcs_reg, adr, alu_ext, alu_imm, alu_reg,\
418 alu_shift_imm, alu_shift_reg, alus_ext, alus_imm, alus_reg,\
419 alus_shift_imm, alus_shift_reg, bfm, csel, rev, logic_imm, logic_reg,\
420 logic_shift_imm, logic_shift_reg, logics_imm, logics_reg,\
421 logics_shift_imm, logics_shift_reg, extend, shift_imm, float, fcsel,\
31f8442b
SN
422 wmmx_wor, wmmx_wxor, wmmx_wand, wmmx_wandn, wmmx_wmov, wmmx_tmcrr,\
423 wmmx_tmrrc, wmmx_wldr, wmmx_wstr, wmmx_tmcr, wmmx_tmrc, wmmx_wadd,\
424 wmmx_wsub, wmmx_wmul, wmmx_wmac, wmmx_wavg2, wmmx_tinsr, wmmx_textrm,\
425 wmmx_wshufh, wmmx_wcmpeq, wmmx_wcmpgt, wmmx_wmax, wmmx_wmin, wmmx_wpack,\
426 wmmx_wunpckih, wmmx_wunpckil, wmmx_wunpckeh, wmmx_wunpckel, wmmx_wror,\
427 wmmx_wsra, wmmx_wsrl, wmmx_wsll, wmmx_wmadd, wmmx_tmia, wmmx_tmiaph,\
428 wmmx_tmiaxy, wmmx_tbcst, wmmx_tmovmsk, wmmx_wacc, wmmx_waligni,\
429 wmmx_walignr, wmmx_tandc, wmmx_textrc, wmmx_torc, wmmx_torvsc, wmmx_wsad,\
430 wmmx_wabs, wmmx_wabsdiff, wmmx_waddsubhx, wmmx_wsubaddhx, wmmx_wavg4,\
431 wmmx_wmulw, wmmx_wqmulm, wmmx_wqmulwm, wmmx_waddbhus, wmmx_wqmiaxy,\
432 wmmx_wmiaxy, wmmx_wmiawxy, wmmx_wmerge")
4cdb3ed4
RE
433 (const_string "single")
434 (const_string "multi")))
435
d5b7b3ae 436;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
5895f793 437;; distant label. Only applicable to Thumb code.
d5b7b3ae
RE
438(define_attr "far_jump" "yes,no" (const_string "no"))
439
9b901d50 440
5b3e6663
PB
441;; The number of machine instructions this pattern expands to.
442;; Used for Thumb-2 conditional execution.
443(define_attr "ce_count" "" (const_int 1))
444
79739965
KT
445;;---------------------------------------------------------------------------
446;; Unspecs
447
448(include "unspecs.md")
449
9b901d50 450;;---------------------------------------------------------------------------
3abcb3a7 451;; Mode iterators
9b901d50 452
ceddf62c 453(include "iterators.md")
953a18fb 454
9b901d50
RE
455;;---------------------------------------------------------------------------
456;; Predicates
457
a657c98a 458(include "predicates.md")
ce92b223 459(include "constraints.md")
a657c98a 460
9b66ebb1
PB
461;;---------------------------------------------------------------------------
462;; Pipeline descriptions
5895f793 463
51c69ddb
PB
464(define_attr "tune_cortexr4" "yes,no"
465 (const (if_then_else
572070ef 466 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
51c69ddb
PB
467 (const_string "yes")
468 (const_string "no"))))
469
9b66ebb1
PB
470;; True if the generic scheduling description should be used.
471
472(define_attr "generic_sched" "yes,no"
47d8f18d 473 (const (if_then_else
85591a5c 474 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa5,cortexa7,cortexa8,cortexa9,cortexa12,cortexa15,cortexa53,cortexm4,marvell_pj4")
47d8f18d 475 (eq_attr "tune_cortexr4" "yes"))
e648d85a
ILT
476 (const_string "no")
477 (const_string "yes"))))
478
75fe7b2f
RE
479(define_attr "generic_vfp" "yes,no"
480 (const (if_then_else
481 (and (eq_attr "fpu" "vfp")
c17ac06a 482 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa7,cortexa8,cortexa9,cortexa53,cortexm4,marvell_pj4")
51c69ddb 483 (eq_attr "tune_cortexr4" "no"))
75fe7b2f
RE
484 (const_string "yes")
485 (const_string "no"))))
486
8fd03515 487(include "marvell-f-iwmmxt.md")
9b66ebb1
PB
488(include "arm-generic.md")
489(include "arm926ejs.md")
75fe7b2f 490(include "arm1020e.md")
9b66ebb1
PB
491(include "arm1026ejs.md")
492(include "arm1136jfs.md")
c02a5ccb
SL
493(include "fa526.md")
494(include "fa606te.md")
495(include "fa626te.md")
496(include "fmp626.md")
497(include "fa726te.md")
d8099dd8 498(include "cortex-a5.md")
ffeffdcb 499(include "cortex-a7.md")
c956e102 500(include "cortex-a8.md")
7612f14d 501(include "cortex-a9.md")
ef578491 502(include "cortex-a15.md")
d8c69a92 503(include "cortex-a53.md")
bd4dc3cd 504(include "cortex-r4.md")
51c69ddb 505(include "cortex-r4f.md")
47d8f18d
JZ
506(include "cortex-m4.md")
507(include "cortex-m4-fpu.md")
3f4d9b98 508(include "vfp11.md")
df8de9b3 509(include "marvell-pj4.md")
103fc15d 510
ff9940b0 511\f
5895f793 512;;---------------------------------------------------------------------------
b15bca31
RE
513;; Insn patterns
514;;
bb6ae783 515;; Addition insns.
5895f793 516
ff9940b0
RE
517;; Note: For DImode insns, there is normally no reason why operands should
518;; not be in the same register, what we don't want is for something being
519;; written to partially overlap something that is an input.
520
d5b7b3ae
RE
521(define_expand "adddi3"
522 [(parallel
5895f793 523 [(set (match_operand:DI 0 "s_register_operand" "")
d5b7b3ae 524 (plus:DI (match_operand:DI 1 "s_register_operand" "")
44cd6810 525 (match_operand:DI 2 "arm_adddi_operand" "")))
48a08b9c 526 (clobber (reg:CC CC_REGNUM))])]
d5b7b3ae
RE
527 "TARGET_EITHER"
528 "
5b3e6663 529 if (TARGET_THUMB1)
d5b7b3ae 530 {
d435a4be 531 if (!REG_P (operands[1]))
6241ded1 532 operands[1] = force_reg (DImode, operands[1]);
d435a4be 533 if (!REG_P (operands[2]))
6241ded1 534 operands[2] = force_reg (DImode, operands[2]);
d5b7b3ae
RE
535 }
536 "
537)
538
5b3e6663 539(define_insn "*thumb1_adddi3"
d5b7b3ae
RE
540 [(set (match_operand:DI 0 "register_operand" "=l")
541 (plus:DI (match_operand:DI 1 "register_operand" "%0")
5895f793 542 (match_operand:DI 2 "register_operand" "l")))
48a08b9c 543 (clobber (reg:CC CC_REGNUM))
d5b7b3ae 544 ]
5b3e6663 545 "TARGET_THUMB1"
d5b7b3ae 546 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
594726e4
JG
547 [(set_attr "length" "4")
548 (set_attr "type" "multiple")]
d5b7b3ae
RE
549)
550
bb6ae783 551(define_insn_and_split "*arm_adddi3"
44cd6810
WG
552 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r,&r,&r")
553 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0, r, 0, r")
554 (match_operand:DI 2 "arm_adddi_operand" "r, 0, r, Dd, Dd")))
48a08b9c 555 (clobber (reg:CC CC_REGNUM))]
479f7546 556 "TARGET_32BIT && !TARGET_NEON"
3a8de233 557 "#"
bab53516
SL
558 "TARGET_32BIT && reload_completed
559 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
bb6ae783
RE
560 [(parallel [(set (reg:CC_C CC_REGNUM)
561 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
562 (match_dup 1)))
563 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
7ec6356e
BS
564 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
565 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
bb6ae783
RE
566 "
567 {
568 operands[3] = gen_highpart (SImode, operands[0]);
569 operands[0] = gen_lowpart (SImode, operands[0]);
570 operands[4] = gen_highpart (SImode, operands[1]);
571 operands[1] = gen_lowpart (SImode, operands[1]);
44cd6810 572 operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
bb6ae783
RE
573 operands[2] = gen_lowpart (SImode, operands[2]);
574 }"
d5b7b3ae 575 [(set_attr "conds" "clob")
594726e4
JG
576 (set_attr "length" "8")
577 (set_attr "type" "multiple")]
d5b7b3ae 578)
ff9940b0 579
bb6ae783 580(define_insn_and_split "*adddi_sesidi_di"
ff9940b0
RE
581 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
582 (plus:DI (sign_extend:DI
3dafc5c3 583 (match_operand:SI 2 "s_register_operand" "r,r"))
cfc25c74 584 (match_operand:DI 1 "s_register_operand" "0,r")))
48a08b9c 585 (clobber (reg:CC CC_REGNUM))]
479f7546 586 "TARGET_32BIT"
3a8de233 587 "#"
5b3e6663 588 "TARGET_32BIT && reload_completed"
bb6ae783
RE
589 [(parallel [(set (reg:CC_C CC_REGNUM)
590 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
591 (match_dup 1)))
592 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
7ec6356e 593 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
bb6ae783 594 (const_int 31))
7ec6356e
BS
595 (match_dup 4))
596 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
bb6ae783
RE
597 "
598 {
599 operands[3] = gen_highpart (SImode, operands[0]);
600 operands[0] = gen_lowpart (SImode, operands[0]);
601 operands[4] = gen_highpart (SImode, operands[1]);
602 operands[1] = gen_lowpart (SImode, operands[1]);
603 operands[2] = gen_lowpart (SImode, operands[2]);
604 }"
5895f793 605 [(set_attr "conds" "clob")
594726e4
JG
606 (set_attr "length" "8")
607 (set_attr "type" "multiple")]
5895f793 608)
ff9940b0 609
bb6ae783 610(define_insn_and_split "*adddi_zesidi_di"
ff9940b0
RE
611 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
612 (plus:DI (zero_extend:DI
3dafc5c3 613 (match_operand:SI 2 "s_register_operand" "r,r"))
cfc25c74 614 (match_operand:DI 1 "s_register_operand" "0,r")))
bb6ae783 615 (clobber (reg:CC CC_REGNUM))]
479f7546 616 "TARGET_32BIT"
3a8de233 617 "#"
5b3e6663 618 "TARGET_32BIT && reload_completed"
bb6ae783
RE
619 [(parallel [(set (reg:CC_C CC_REGNUM)
620 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
621 (match_dup 1)))
622 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
7ec6356e
BS
623 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
624 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
bb6ae783
RE
625 "
626 {
627 operands[3] = gen_highpart (SImode, operands[0]);
628 operands[0] = gen_lowpart (SImode, operands[0]);
629 operands[4] = gen_highpart (SImode, operands[1]);
630 operands[1] = gen_lowpart (SImode, operands[1]);
631 operands[2] = gen_lowpart (SImode, operands[2]);
632 }"
d5b7b3ae 633 [(set_attr "conds" "clob")
594726e4
JG
634 (set_attr "length" "8")
635 (set_attr "type" "multiple")]
d5b7b3ae 636)
3a33f76f 637
091426d3 638(define_expand "addsi3"
d5b7b3ae 639 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
640 (plus:SI (match_operand:SI 1 "s_register_operand" "")
641 (match_operand:SI 2 "reg_or_int_operand" "")))]
d5b7b3ae 642 "TARGET_EITHER"
091426d3 643 "
d435a4be 644 if (TARGET_32BIT && CONST_INT_P (operands[2]))
091426d3 645 {
a406f566
MM
646 arm_split_constant (PLUS, SImode, NULL_RTX,
647 INTVAL (operands[2]), operands[0], operands[1],
b3a13419 648 optimize && can_create_pseudo_p ());
091426d3
RE
649 DONE;
650 }
d5b7b3ae
RE
651 "
652)
091426d3 653
72ac76be 654; If there is a scratch available, this will be faster than synthesizing the
bb6ae783
RE
655; addition.
656(define_peephole2
657 [(match_scratch:SI 3 "r")
3053b100
RE
658 (set (match_operand:SI 0 "arm_general_register_operand" "")
659 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
d5b7b3ae 660 (match_operand:SI 2 "const_int_operand" "")))]
5b3e6663 661 "TARGET_32BIT &&
bb6ae783
RE
662 !(const_ok_for_arm (INTVAL (operands[2]))
663 || const_ok_for_arm (-INTVAL (operands[2])))
664 && const_ok_for_arm (~INTVAL (operands[2]))"
665 [(set (match_dup 3) (match_dup 2))
666 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
667 ""
668)
091426d3 669
e0079468
PB
670;; The r/r/k alternative is required when reloading the address
671;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
672;; put the duplicated register first, and not try the commutative version.
bb6ae783 673(define_insn_and_split "*arm_addsi3"
5e5f7673
KT
674 [(set (match_operand:SI 0 "s_register_operand" "=rk,l,l ,l ,r ,k ,r,r ,k ,r ,k,k,r ,k ,r")
675 (plus:SI (match_operand:SI 1 "s_register_operand" "%0 ,l,0 ,l ,rk,k ,r,rk,k ,rk,k,r,rk,k ,rk")
676 (match_operand:SI 2 "reg_or_int_operand" "rk ,l,Py,Pd,rI,rI,k,Pj,Pj,L ,L,L,PJ,PJ,?n")))]
5b3e6663 677 "TARGET_32BIT"
68df59d3 678 "@
b915718f 679 add%?\\t%0, %0, %2
68df59d3 680 add%?\\t%0, %1, %2
4870352d 681 add%?\\t%0, %1, %2
5e5f7673
KT
682 add%?\\t%0, %1, %2
683 add%?\\t%0, %1, %2
f5c630c3 684 add%?\\t%0, %1, %2
e0079468 685 add%?\\t%0, %2, %1
c2b640a7
AS
686 addw%?\\t%0, %1, %2
687 addw%?\\t%0, %1, %2
f5c630c3 688 sub%?\\t%0, %1, #%n2
091426d3 689 sub%?\\t%0, %1, #%n2
0f9926f3 690 sub%?\\t%0, %1, #%n2
c2b640a7
AS
691 subw%?\\t%0, %1, #%n2
692 subw%?\\t%0, %1, #%n2
091426d3 693 #"
e63d4106 694 "TARGET_32BIT
d435a4be 695 && CONST_INT_P (operands[2])
c2b640a7 696 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
e63d4106 697 && (reload_completed || !arm_eliminable_register (operands[1]))"
bb6ae783
RE
698 [(clobber (const_int 0))]
699 "
a406f566
MM
700 arm_split_constant (PLUS, SImode, curr_insn,
701 INTVAL (operands[2]), operands[0],
bb6ae783
RE
702 operands[1], 0);
703 DONE;
704 "
5e5f7673 705 [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4,4,4,4,16")
c2b640a7 706 (set_attr "predicable" "yes")
5e5f7673
KT
707 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no,no,no,no,no,no,no")
708 (set_attr "arch" "t2,t2,t2,t2,*,*,*,t2,t2,*,*,a,t2,t2,*")
148413a4 709 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6e4150e1
JG
710 (const_string "alu_imm")
711 (const_string "alu_reg")))
148413a4 712 ]
d5b7b3ae
RE
713)
714
81beb031 715(define_insn_and_split "*thumb1_addsi3"
16737e76
BS
716 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,k,l,l,l")
717 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,k,k,0,l,k")
718 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,M,O,Pa,Pb,Pc")))]
5b3e6663 719 "TARGET_THUMB1"
d5b7b3ae 720 "*
cca0a211 721 static const char * const asms[] =
d5b7b3ae
RE
722 {
723 \"add\\t%0, %0, %2\",
724 \"sub\\t%0, %0, #%n2\",
725 \"add\\t%0, %1, %2\",
726 \"add\\t%0, %0, %2\",
727 \"add\\t%0, %0, %2\",
728 \"add\\t%0, %1, %2\",
81beb031
RE
729 \"add\\t%0, %1, %2\",
730 \"#\",
16737e76 731 \"#\",
81beb031 732 \"#\"
d5b7b3ae
RE
733 };
734 if ((which_alternative == 2 || which_alternative == 6)
d435a4be 735 && CONST_INT_P (operands[2])
d5b7b3ae
RE
736 && INTVAL (operands[2]) < 0)
737 return \"sub\\t%0, %1, #%n2\";
738 return asms[which_alternative];
739 "
81beb031 740 "&& reload_completed && CONST_INT_P (operands[2])
16737e76
BS
741 && ((operands[1] != stack_pointer_rtx
742 && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255))
743 || (operands[1] == stack_pointer_rtx
744 && INTVAL (operands[2]) > 1020))"
81beb031
RE
745 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
746 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
747 {
748 HOST_WIDE_INT offset = INTVAL (operands[2]);
16737e76
BS
749 if (operands[1] == stack_pointer_rtx)
750 offset -= 1020;
751 else
752 {
753 if (offset > 255)
754 offset = 255;
755 else if (offset < -255)
756 offset = -255;
757 }
81beb031
RE
758 operands[3] = GEN_INT (offset);
759 operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
760 }
594726e4
JG
761 [(set_attr "length" "2,2,2,2,2,2,2,4,4,4")
762 (set_attr "type" "alus_imm,alus_imm,alus_reg,alus_reg,alus_reg,
763 alus_reg,alus_reg,multiple,multiple,multiple")]
d5b7b3ae
RE
764)
765
766;; Reloading and elimination of the frame pointer can
767;; sometimes cause this optimization to be missed.
bb6ae783 768(define_peephole2
3053b100 769 [(set (match_operand:SI 0 "arm_general_register_operand" "")
12249385 770 (match_operand:SI 1 "const_int_operand" ""))
d5b7b3ae 771 (set (match_dup 0)
3053b100 772 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
5b3e6663 773 "TARGET_THUMB1
d5b7b3ae
RE
774 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
775 && (INTVAL (operands[1]) & 3) == 0"
3053b100 776 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
bb6ae783 777 ""
d5b7b3ae 778)
3a33f76f 779
ce7b3761 780(define_insn "addsi3_compare0"
48a08b9c 781 [(set (reg:CC_NOOV CC_REGNUM)
68df59d3 782 (compare:CC_NOOV
148413a4
RR
783 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r,r")
784 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
68df59d3 785 (const_int 0)))
148413a4 786 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
ff9940b0 787 (plus:SI (match_dup 1) (match_dup 2)))]
dcd8b2ee 788 "TARGET_ARM"
68df59d3 789 "@
5b3e6663 790 add%.\\t%0, %1, %2
148413a4
RR
791 sub%.\\t%0, %1, #%n2
792 add%.\\t%0, %1, %2"
793 [(set_attr "conds" "set")
594726e4 794 (set_attr "type" "alus_imm,alus_imm,alus_reg")]
d5b7b3ae 795)
ff9940b0 796
589fe0fc 797(define_insn "*addsi3_compare0_scratch"
48a08b9c 798 [(set (reg:CC_NOOV CC_REGNUM)
589fe0fc 799 (compare:CC_NOOV
148413a4
RR
800 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r, r")
801 (match_operand:SI 1 "arm_add_operand" "I,L, r"))
589fe0fc 802 (const_int 0)))]
dcd8b2ee 803 "TARGET_ARM"
d5b7b3ae
RE
804 "@
805 cmn%?\\t%0, %1
148413a4
RR
806 cmp%?\\t%0, #%n1
807 cmn%?\\t%0, %1"
cc50a1e1 808 [(set_attr "conds" "set")
148413a4 809 (set_attr "predicable" "yes")
594726e4 810 (set_attr "type" "alus_imm,alus_imm,alus_reg")]
cca0a211 811)
d5b7b3ae 812
1ac3e311
RE
813(define_insn "*compare_negsi_si"
814 [(set (reg:CC_Z CC_REGNUM)
815 (compare:CC_Z
5e5f7673
KT
816 (neg:SI (match_operand:SI 0 "s_register_operand" "l,r"))
817 (match_operand:SI 1 "s_register_operand" "l,r")))]
5b3e6663 818 "TARGET_32BIT"
1ac3e311 819 "cmn%?\\t%1, %0"
cc50a1e1 820 [(set_attr "conds" "set")
5e5f7673
KT
821 (set_attr "predicable" "yes")
822 (set_attr "arch" "t2,*")
823 (set_attr "length" "2,4")
594726e4
JG
824 (set_attr "predicable_short_it" "yes,no")
825 (set_attr "type" "alus_reg")]
cca0a211 826)
589fe0fc 827
f9b9980e
RE
828;; This is the canonicalization of addsi3_compare0_for_combiner when the
829;; addend is a constant.
0480fff0 830(define_insn "cmpsi2_addneg"
f9b9980e
RE
831 [(set (reg:CC CC_REGNUM)
832 (compare:CC
833 (match_operand:SI 1 "s_register_operand" "r,r")
e6bfe8a2 834 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
f9b9980e
RE
835 (set (match_operand:SI 0 "s_register_operand" "=r,r")
836 (plus:SI (match_dup 1)
e6bfe8a2 837 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
5b3e6663 838 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
f9b9980e 839 "@
e6bfe8a2
RE
840 add%.\\t%0, %1, %3
841 sub%.\\t%0, %1, #%n3"
594726e4
JG
842 [(set_attr "conds" "set")
843 (set_attr "type" "alus_reg")]
f9b9980e
RE
844)
845
846;; Convert the sequence
847;; sub rd, rn, #1
848;; cmn rd, #1 (equivalent to cmp rd, #-1)
849;; bne dest
850;; into
851;; subs rd, rn, #1
852;; bcs dest ((unsigned)rn >= 1)
853;; similarly for the beq variant using bcc.
854;; This is a common looping idiom (while (n--))
855(define_peephole2
3053b100
RE
856 [(set (match_operand:SI 0 "arm_general_register_operand" "")
857 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
f9b9980e
RE
858 (const_int -1)))
859 (set (match_operand 2 "cc_register" "")
860 (compare (match_dup 0) (const_int -1)))
861 (set (pc)
862 (if_then_else (match_operator 3 "equality_operator"
863 [(match_dup 2) (const_int 0)])
864 (match_operand 4 "" "")
865 (match_operand 5 "" "")))]
5b3e6663 866 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
f9b9980e
RE
867 [(parallel[
868 (set (match_dup 2)
869 (compare:CC
870 (match_dup 1) (const_int 1)))
871 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
872 (set (pc)
873 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
874 (match_dup 4)
875 (match_dup 5)))]
876 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
877 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
878 ? GEU : LTU),
879 VOIDmode,
880 operands[2], const0_rtx);"
881)
882
a0b632ec
RE
883;; The next four insns work because they compare the result with one of
884;; the operands, and we know that the use of the condition code is
885;; either GEU or LTU, so we can use the carry flag from the addition
886;; instead of doing the compare a second time.
887(define_insn "*addsi3_compare_op1"
48a08b9c 888 [(set (reg:CC_C CC_REGNUM)
a0b632ec 889 (compare:CC_C
148413a4
RR
890 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
891 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
a0b632ec 892 (match_dup 1)))
148413a4 893 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
a0b632ec 894 (plus:SI (match_dup 1) (match_dup 2)))]
5b3e6663 895 "TARGET_32BIT"
a0b632ec 896 "@
5b3e6663 897 add%.\\t%0, %1, %2
148413a4
RR
898 sub%.\\t%0, %1, #%n2
899 add%.\\t%0, %1, %2"
900 [(set_attr "conds" "set")
6e4150e1 901 (set_attr "type" "alus_imm,alus_imm,alus_reg")]
cca0a211 902)
a0b632ec
RE
903
904(define_insn "*addsi3_compare_op2"
48a08b9c 905 [(set (reg:CC_C CC_REGNUM)
a0b632ec 906 (compare:CC_C
148413a4
RR
907 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
908 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
a0b632ec 909 (match_dup 2)))
148413a4 910 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
ff9940b0 911 (plus:SI (match_dup 1) (match_dup 2)))]
5b3e6663 912 "TARGET_32BIT"
68df59d3 913 "@
148413a4 914 add%.\\t%0, %1, %2
5b3e6663
PB
915 add%.\\t%0, %1, %2
916 sub%.\\t%0, %1, #%n2"
148413a4 917 [(set_attr "conds" "set")
6e4150e1 918 (set_attr "type" "alus_imm,alus_imm,alus_reg")]
cca0a211 919)
ff9940b0 920
a0b632ec 921(define_insn "*compare_addsi2_op0"
48a08b9c 922 [(set (reg:CC_C CC_REGNUM)
5e5f7673
KT
923 (compare:CC_C
924 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
925 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
926 (match_dup 0)))]
5b3e6663 927 "TARGET_32BIT"
a0b632ec 928 "@
5e5f7673
KT
929 cmp%?\\t%0, #%n1
930 cmn%?\\t%0, %1
a0b632ec 931 cmn%?\\t%0, %1
148413a4
RR
932 cmp%?\\t%0, #%n1
933 cmn%?\\t%0, %1"
cc50a1e1 934 [(set_attr "conds" "set")
148413a4 935 (set_attr "predicable" "yes")
5e5f7673
KT
936 (set_attr "arch" "t2,t2,*,*,*")
937 (set_attr "predicable_short_it" "yes,yes,no,no,no")
938 (set_attr "length" "2,2,4,4,4")
6e4150e1 939 (set_attr "type" "alus_imm,alus_reg,alus_imm,alus_imm,alus_reg")]
cca0a211 940)
a0b632ec
RE
941
942(define_insn "*compare_addsi2_op1"
48a08b9c 943 [(set (reg:CC_C CC_REGNUM)
5e5f7673
KT
944 (compare:CC_C
945 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
946 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
947 (match_dup 1)))]
5b3e6663 948 "TARGET_32BIT"
a0b632ec 949 "@
5e5f7673
KT
950 cmp%?\\t%0, #%n1
951 cmn%?\\t%0, %1
a0b632ec 952 cmn%?\\t%0, %1
148413a4
RR
953 cmp%?\\t%0, #%n1
954 cmn%?\\t%0, %1"
cc50a1e1 955 [(set_attr "conds" "set")
148413a4 956 (set_attr "predicable" "yes")
5e5f7673
KT
957 (set_attr "arch" "t2,t2,*,*,*")
958 (set_attr "predicable_short_it" "yes,yes,no,no,no")
959 (set_attr "length" "2,2,4,4,4")
6e4150e1 960 (set_attr "type" "alus_imm,alus_reg,alus_imm,alus_imm,alus_reg")]
5e5f7673 961 )
a0b632ec 962
7ec6356e 963(define_insn "*addsi3_carryin_<optab>"
5e5f7673
KT
964 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
965 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%l,r,r")
966 (match_operand:SI 2 "arm_not_operand" "0,rI,K"))
967 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
5b3e6663 968 "TARGET_32BIT"
44cd6810 969 "@
4870352d 970 adc%?\\t%0, %1, %2
44cd6810
WG
971 adc%?\\t%0, %1, %2
972 sbc%?\\t%0, %1, #%B2"
ceef6fd9 973 [(set_attr "conds" "use")
5e5f7673
KT
974 (set_attr "predicable" "yes")
975 (set_attr "arch" "t2,*,*")
976 (set_attr "length" "4")
594726e4
JG
977 (set_attr "predicable_short_it" "yes,no,no")
978 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
d5b7b3ae 979)
a0b632ec 980
7ec6356e 981(define_insn "*addsi3_carryin_alt2_<optab>"
5e5f7673
KT
982 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
983 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
984 (match_operand:SI 1 "s_register_operand" "%l,r,r"))
985 (match_operand:SI 2 "arm_rhs_operand" "l,rI,K")))]
5b3e6663 986 "TARGET_32BIT"
44cd6810 987 "@
4870352d 988 adc%?\\t%0, %1, %2
44cd6810
WG
989 adc%?\\t%0, %1, %2
990 sbc%?\\t%0, %1, #%B2"
ceef6fd9 991 [(set_attr "conds" "use")
5e5f7673
KT
992 (set_attr "predicable" "yes")
993 (set_attr "arch" "t2,*,*")
994 (set_attr "length" "4")
594726e4
JG
995 (set_attr "predicable_short_it" "yes,no,no")
996 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
cca0a211 997)
a0b632ec 998
7ec6356e 999(define_insn "*addsi3_carryin_shift_<optab>"
a0b632ec 1000 [(set (match_operand:SI 0 "s_register_operand" "=r")
7ec6356e
BS
1001 (plus:SI (plus:SI
1002 (match_operator:SI 2 "shift_operator"
1003 [(match_operand:SI 3 "s_register_operand" "r")
1004 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1005 (match_operand:SI 1 "s_register_operand" "r"))
1006 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
5b3e6663 1007 "TARGET_32BIT"
7ec6356e
BS
1008 "adc%?\\t%0, %1, %3%S2"
1009 [(set_attr "conds" "use")
ceef6fd9 1010 (set_attr "predicable" "yes")
5e5f7673 1011 (set_attr "predicable_short_it" "no")
7ec6356e 1012 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
6e4150e1
JG
1013 (const_string "alu_shift_imm")
1014 (const_string "alu_shift_reg")))]
d5b7b3ae 1015)
a0b632ec 1016
527e82c2
WG
1017(define_insn "*addsi3_carryin_clobercc_<optab>"
1018 [(set (match_operand:SI 0 "s_register_operand" "=r")
1019 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
1020 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1021 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
1022 (clobber (reg:CC CC_REGNUM))]
1023 "TARGET_32BIT"
1024 "adc%.\\t%0, %1, %2"
594726e4
JG
1025 [(set_attr "conds" "set")
1026 (set_attr "type" "adcs_reg")]
527e82c2
WG
1027)
1028
d633dd84
GY
1029(define_insn "*subsi3_carryin"
1030 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1031 (minus:SI (minus:SI (match_operand:SI 1 "reg_or_int_operand" "r,I")
1032 (match_operand:SI 2 "s_register_operand" "r,r"))
1033 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1034 "TARGET_32BIT"
1035 "@
1036 sbc%?\\t%0, %1, %2
1037 rsc%?\\t%0, %2, %1"
1038 [(set_attr "conds" "use")
1039 (set_attr "arch" "*,a")
5e5f7673 1040 (set_attr "predicable" "yes")
594726e4
JG
1041 (set_attr "predicable_short_it" "no")
1042 (set_attr "type" "adc_reg,adc_imm")]
d633dd84
GY
1043)
1044
1045(define_insn "*subsi3_carryin_const"
1046 [(set (match_operand:SI 0 "s_register_operand" "=r")
1047 (minus:SI (plus:SI (match_operand:SI 1 "reg_or_int_operand" "r")
1048 (match_operand:SI 2 "arm_not_operand" "K"))
1049 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1050 "TARGET_32BIT"
1051 "sbc\\t%0, %1, #%B2"
594726e4
JG
1052 [(set_attr "conds" "use")
1053 (set_attr "type" "adc_imm")]
d633dd84
GY
1054)
1055
1056(define_insn "*subsi3_carryin_compare"
1057 [(set (reg:CC CC_REGNUM)
1058 (compare:CC (match_operand:SI 1 "s_register_operand" "r")
1059 (match_operand:SI 2 "s_register_operand" "r")))
1060 (set (match_operand:SI 0 "s_register_operand" "=r")
1061 (minus:SI (minus:SI (match_dup 1)
1062 (match_dup 2))
1063 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1064 "TARGET_32BIT"
1065 "sbcs\\t%0, %1, %2"
594726e4
JG
1066 [(set_attr "conds" "set")
1067 (set_attr "type" "adcs_reg")]
d633dd84
GY
1068)
1069
1070(define_insn "*subsi3_carryin_compare_const"
1071 [(set (reg:CC CC_REGNUM)
1072 (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r")
1073 (match_operand:SI 2 "arm_not_operand" "K")))
1074 (set (match_operand:SI 0 "s_register_operand" "=r")
1075 (minus:SI (plus:SI (match_dup 1)
1076 (match_dup 2))
1077 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1078 "TARGET_32BIT"
1079 "sbcs\\t%0, %1, #%B2"
594726e4
JG
1080 [(set_attr "conds" "set")
1081 (set_attr "type" "adcs_imm")]
d633dd84
GY
1082)
1083
1084(define_insn "*subsi3_carryin_shift"
1085 [(set (match_operand:SI 0 "s_register_operand" "=r")
1086 (minus:SI (minus:SI
1087 (match_operand:SI 1 "s_register_operand" "r")
1088 (match_operator:SI 2 "shift_operator"
1089 [(match_operand:SI 3 "s_register_operand" "r")
1090 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
1091 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1092 "TARGET_32BIT"
1093 "sbc%?\\t%0, %1, %3%S2"
1094 [(set_attr "conds" "use")
1095 (set_attr "predicable" "yes")
1096 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
6e4150e1
JG
1097 (const_string "alu_shift_imm")
1098 (const_string "alu_shift_reg")))]
d633dd84
GY
1099)
1100
1101(define_insn "*rsbsi3_carryin_shift"
1102 [(set (match_operand:SI 0 "s_register_operand" "=r")
1103 (minus:SI (minus:SI
1104 (match_operator:SI 2 "shift_operator"
1105 [(match_operand:SI 3 "s_register_operand" "r")
1106 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1107 (match_operand:SI 1 "s_register_operand" "r"))
1108 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1109 "TARGET_ARM"
1110 "rsc%?\\t%0, %1, %3%S2"
1111 [(set_attr "conds" "use")
1112 (set_attr "predicable" "yes")
1113 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
6e4150e1
JG
1114 (const_string "alu_shift_imm")
1115 (const_string "alu_shift_reg")))]
d633dd84
GY
1116)
1117
de9315db
RE
1118; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
1119(define_split
1120 [(set (match_operand:SI 0 "s_register_operand" "")
1121 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1122 (match_operand:SI 2 "s_register_operand" ""))
1123 (const_int -1)))
1124 (clobber (match_operand:SI 3 "s_register_operand" ""))]
5b3e6663 1125 "TARGET_32BIT"
de9315db
RE
1126 [(set (match_dup 3) (match_dup 1))
1127 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1128 "
1129 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1130")
1131
37f74dcf
RE
1132(define_expand "addsf3"
1133 [(set (match_operand:SF 0 "s_register_operand" "")
1134 (plus:SF (match_operand:SF 1 "s_register_operand" "")
dae840fc 1135 (match_operand:SF 2 "s_register_operand" "")))]
5b3e6663 1136 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf 1137 "
37f74dcf
RE
1138")
1139
37f74dcf
RE
1140(define_expand "adddf3"
1141 [(set (match_operand:DF 0 "s_register_operand" "")
1142 (plus:DF (match_operand:DF 1 "s_register_operand" "")
dae840fc 1143 (match_operand:DF 2 "s_register_operand" "")))]
e0dc3601 1144 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
37f74dcf 1145 "
37f74dcf
RE
1146")
1147
d5b7b3ae
RE
1148(define_expand "subdi3"
1149 [(parallel
1150 [(set (match_operand:DI 0 "s_register_operand" "")
1151 (minus:DI (match_operand:DI 1 "s_register_operand" "")
1152 (match_operand:DI 2 "s_register_operand" "")))
48a08b9c 1153 (clobber (reg:CC CC_REGNUM))])]
d5b7b3ae
RE
1154 "TARGET_EITHER"
1155 "
5b3e6663 1156 if (TARGET_THUMB1)
d5b7b3ae 1157 {
d435a4be 1158 if (!REG_P (operands[1]))
61ed6392 1159 operands[1] = force_reg (DImode, operands[1]);
d435a4be 1160 if (!REG_P (operands[2]))
61ed6392 1161 operands[2] = force_reg (DImode, operands[2]);
d5b7b3ae
RE
1162 }
1163 "
1164)
1165
b0b49556 1166(define_insn_and_split "*arm_subdi3"
d5b7b3ae 1167 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
ff9940b0
RE
1168 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1169 (match_operand:DI 2 "s_register_operand" "r,0,0")))
48a08b9c 1170 (clobber (reg:CC CC_REGNUM))]
bab53516 1171 "TARGET_32BIT && !TARGET_NEON"
b0b49556
GY
1172 "#" ; "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
1173 "&& reload_completed"
1174 [(parallel [(set (reg:CC CC_REGNUM)
1175 (compare:CC (match_dup 1) (match_dup 2)))
1176 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1177 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1178 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1179 {
1180 operands[3] = gen_highpart (SImode, operands[0]);
1181 operands[0] = gen_lowpart (SImode, operands[0]);
1182 operands[4] = gen_highpart (SImode, operands[1]);
1183 operands[1] = gen_lowpart (SImode, operands[1]);
1184 operands[5] = gen_highpart (SImode, operands[2]);
1185 operands[2] = gen_lowpart (SImode, operands[2]);
1186 }
d5b7b3ae 1187 [(set_attr "conds" "clob")
594726e4
JG
1188 (set_attr "length" "8")
1189 (set_attr "type" "multiple")]
d5b7b3ae
RE
1190)
1191
1192(define_insn "*thumb_subdi3"
1193 [(set (match_operand:DI 0 "register_operand" "=l")
1194 (minus:DI (match_operand:DI 1 "register_operand" "0")
1195 (match_operand:DI 2 "register_operand" "l")))
48a08b9c 1196 (clobber (reg:CC CC_REGNUM))]
5b3e6663 1197 "TARGET_THUMB1"
d5b7b3ae 1198 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
594726e4
JG
1199 [(set_attr "length" "4")
1200 (set_attr "type" "multiple")]
d5b7b3ae 1201)
ff9940b0 1202
b0b49556 1203(define_insn_and_split "*subdi_di_zesidi"
d5b7b3ae 1204 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
cfc25c74 1205 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
ff9940b0 1206 (zero_extend:DI
d5b7b3ae 1207 (match_operand:SI 2 "s_register_operand" "r,r"))))
48a08b9c 1208 (clobber (reg:CC CC_REGNUM))]
5b3e6663 1209 "TARGET_32BIT"
b0b49556
GY
1210 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1211 "&& reload_completed"
1212 [(parallel [(set (reg:CC CC_REGNUM)
1213 (compare:CC (match_dup 1) (match_dup 2)))
1214 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1215 (set (match_dup 3) (minus:SI (plus:SI (match_dup 4) (match_dup 5))
1216 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1217 {
1218 operands[3] = gen_highpart (SImode, operands[0]);
1219 operands[0] = gen_lowpart (SImode, operands[0]);
1220 operands[4] = gen_highpart (SImode, operands[1]);
1221 operands[1] = gen_lowpart (SImode, operands[1]);
1222 operands[5] = GEN_INT (~0);
1223 }
d5b7b3ae 1224 [(set_attr "conds" "clob")
594726e4
JG
1225 (set_attr "length" "8")
1226 (set_attr "type" "multiple")]
d5b7b3ae 1227)
ff9940b0 1228
b0b49556 1229(define_insn_and_split "*subdi_di_sesidi"
d5b7b3ae 1230 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
cfc25c74 1231 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
ff9940b0 1232 (sign_extend:DI
d5b7b3ae 1233 (match_operand:SI 2 "s_register_operand" "r,r"))))
48a08b9c 1234 (clobber (reg:CC CC_REGNUM))]
5b3e6663 1235 "TARGET_32BIT"
b0b49556
GY
1236 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
1237 "&& reload_completed"
1238 [(parallel [(set (reg:CC CC_REGNUM)
1239 (compare:CC (match_dup 1) (match_dup 2)))
1240 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1241 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4)
1242 (ashiftrt:SI (match_dup 2)
1243 (const_int 31)))
1244 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1245 {
1246 operands[3] = gen_highpart (SImode, operands[0]);
1247 operands[0] = gen_lowpart (SImode, operands[0]);
1248 operands[4] = gen_highpart (SImode, operands[1]);
1249 operands[1] = gen_lowpart (SImode, operands[1]);
1250 }
d5b7b3ae 1251 [(set_attr "conds" "clob")
594726e4
JG
1252 (set_attr "length" "8")
1253 (set_attr "type" "multiple")]
d5b7b3ae 1254)
ff9940b0 1255
b0b49556 1256(define_insn_and_split "*subdi_zesidi_di"
d5b7b3ae 1257 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
ff9940b0 1258 (minus:DI (zero_extend:DI
d5b7b3ae 1259 (match_operand:SI 2 "s_register_operand" "r,r"))
cfc25c74 1260 (match_operand:DI 1 "s_register_operand" "0,r")))
48a08b9c 1261 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 1262 "TARGET_ARM"
b0b49556
GY
1263 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1264 ; is equivalent to:
1265 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, #0"
1266 "&& reload_completed"
1267 [(parallel [(set (reg:CC CC_REGNUM)
1268 (compare:CC (match_dup 2) (match_dup 1)))
1269 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1270 (set (match_dup 3) (minus:SI (minus:SI (const_int 0) (match_dup 4))
1271 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1272 {
1273 operands[3] = gen_highpart (SImode, operands[0]);
1274 operands[0] = gen_lowpart (SImode, operands[0]);
1275 operands[4] = gen_highpart (SImode, operands[1]);
1276 operands[1] = gen_lowpart (SImode, operands[1]);
1277 }
d5b7b3ae 1278 [(set_attr "conds" "clob")
594726e4
JG
1279 (set_attr "length" "8")
1280 (set_attr "type" "multiple")]
d5b7b3ae 1281)
ff9940b0 1282
b0b49556 1283(define_insn_and_split "*subdi_sesidi_di"
d5b7b3ae 1284 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
ff9940b0 1285 (minus:DI (sign_extend:DI
d5b7b3ae 1286 (match_operand:SI 2 "s_register_operand" "r,r"))
cfc25c74 1287 (match_operand:DI 1 "s_register_operand" "0,r")))
48a08b9c 1288 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 1289 "TARGET_ARM"
b0b49556
GY
1290 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1291 ; is equivalent to:
1292 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, %2, asr #31"
1293 "&& reload_completed"
1294 [(parallel [(set (reg:CC CC_REGNUM)
1295 (compare:CC (match_dup 2) (match_dup 1)))
1296 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1297 (set (match_dup 3) (minus:SI (minus:SI
1298 (ashiftrt:SI (match_dup 2)
1299 (const_int 31))
1300 (match_dup 4))
1301 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1302 {
1303 operands[3] = gen_highpart (SImode, operands[0]);
1304 operands[0] = gen_lowpart (SImode, operands[0]);
1305 operands[4] = gen_highpart (SImode, operands[1]);
1306 operands[1] = gen_lowpart (SImode, operands[1]);
1307 }
d5b7b3ae 1308 [(set_attr "conds" "clob")
594726e4
JG
1309 (set_attr "length" "8")
1310 (set_attr "type" "multiple")]
d5b7b3ae 1311)
ff9940b0 1312
b0b49556 1313(define_insn_and_split "*subdi_zesidi_zesidi"
d5b7b3ae 1314 [(set (match_operand:DI 0 "s_register_operand" "=r")
ff9940b0 1315 (minus:DI (zero_extend:DI
d5b7b3ae 1316 (match_operand:SI 1 "s_register_operand" "r"))
ff9940b0 1317 (zero_extend:DI
d5b7b3ae 1318 (match_operand:SI 2 "s_register_operand" "r"))))
48a08b9c 1319 (clobber (reg:CC CC_REGNUM))]
5b3e6663 1320 "TARGET_32BIT"
b0b49556
GY
1321 "#" ; "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1322 "&& reload_completed"
1323 [(parallel [(set (reg:CC CC_REGNUM)
1324 (compare:CC (match_dup 1) (match_dup 2)))
1325 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1326 (set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 1))
1327 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1328 {
1329 operands[3] = gen_highpart (SImode, operands[0]);
1330 operands[0] = gen_lowpart (SImode, operands[0]);
1331 }
d5b7b3ae 1332 [(set_attr "conds" "clob")
594726e4
JG
1333 (set_attr "length" "8")
1334 (set_attr "type" "multiple")]
d5b7b3ae 1335)
3a33f76f 1336
091426d3 1337(define_expand "subsi3"
d5b7b3ae 1338 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
1339 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1340 (match_operand:SI 2 "s_register_operand" "")))]
d5b7b3ae 1341 "TARGET_EITHER"
091426d3 1342 "
d435a4be 1343 if (CONST_INT_P (operands[1]))
091426d3 1344 {
5b3e6663 1345 if (TARGET_32BIT)
d5b7b3ae 1346 {
a406f566
MM
1347 arm_split_constant (MINUS, SImode, NULL_RTX,
1348 INTVAL (operands[1]), operands[0],
b3a13419 1349 operands[2], optimize && can_create_pseudo_p ());
d5b7b3ae
RE
1350 DONE;
1351 }
5b3e6663 1352 else /* TARGET_THUMB1 */
d5b7b3ae 1353 operands[1] = force_reg (SImode, operands[1]);
091426d3 1354 }
d5b7b3ae
RE
1355 "
1356)
091426d3 1357
906668bb 1358(define_insn "thumb1_subsi3_insn"
d5b7b3ae
RE
1359 [(set (match_operand:SI 0 "register_operand" "=l")
1360 (minus:SI (match_operand:SI 1 "register_operand" "l")
906668bb 1361 (match_operand:SI 2 "reg_or_int_operand" "lPd")))]
5b3e6663 1362 "TARGET_THUMB1"
d5b7b3ae 1363 "sub\\t%0, %1, %2"
906668bb 1364 [(set_attr "length" "2")
594726e4
JG
1365 (set_attr "conds" "set")
1366 (set_attr "type" "alus_reg")]
1367)
d5b7b3ae 1368
5b3e6663 1369; ??? Check Thumb-2 split length
bb6ae783 1370(define_insn_and_split "*arm_subsi3_insn"
5e5f7673
KT
1371 [(set (match_operand:SI 0 "s_register_operand" "=l,l ,l ,l ,r ,r,r,rk,r")
1372 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "l ,0 ,l ,Pz,rI,r,r,k ,?n")
1373 (match_operand:SI 2 "reg_or_int_operand" "l ,Py,Pd,l ,r ,I,r,r ,r")))]
5b3e6663 1374 "TARGET_32BIT"
0f447ef2 1375 "@
5e5f7673
KT
1376 sub%?\\t%0, %1, %2
1377 sub%?\\t%0, %2
1378 sub%?\\t%0, %1, %2
1379 rsb%?\\t%0, %2, %1
091426d3 1380 rsb%?\\t%0, %2, %1
f5c630c3 1381 sub%?\\t%0, %1, %2
7ec6356e 1382 sub%?\\t%0, %1, %2
148413a4 1383 sub%?\\t%0, %1, %2
091426d3 1384 #"
d435a4be 1385 "&& (CONST_INT_P (operands[1])
16340e86 1386 && !const_ok_for_arm (INTVAL (operands[1])))"
091426d3
RE
1387 [(clobber (const_int 0))]
1388 "
a406f566
MM
1389 arm_split_constant (MINUS, SImode, curr_insn,
1390 INTVAL (operands[1]), operands[0], operands[2], 0);
091426d3 1391 DONE;
d5b7b3ae 1392 "
5e5f7673
KT
1393 [(set_attr "length" "4,4,4,4,4,4,4,4,16")
1394 (set_attr "arch" "t2,t2,t2,t2,*,*,*,*,*")
148413a4 1395 (set_attr "predicable" "yes")
5e5f7673 1396 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no")
594726e4 1397 (set_attr "type" "alu_reg,alu_reg,alu_reg,alu_reg,alu_imm,alu_imm,alu_reg,alu_reg,multiple")]
bb6ae783
RE
1398)
1399
1400(define_peephole2
1401 [(match_scratch:SI 3 "r")
3053b100 1402 (set (match_operand:SI 0 "arm_general_register_operand" "")
bb6ae783 1403 (minus:SI (match_operand:SI 1 "const_int_operand" "")
3053b100 1404 (match_operand:SI 2 "arm_general_register_operand" "")))]
5b3e6663 1405 "TARGET_32BIT
bb6ae783
RE
1406 && !const_ok_for_arm (INTVAL (operands[1]))
1407 && const_ok_for_arm (~INTVAL (operands[1]))"
1408 [(set (match_dup 3) (match_dup 1))
1409 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1410 ""
d5b7b3ae 1411)
3a33f76f 1412
4cdb3ed4 1413(define_insn "*subsi3_compare0"
48a08b9c 1414 [(set (reg:CC_NOOV CC_REGNUM)
5895f793 1415 (compare:CC_NOOV
148413a4
RR
1416 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1417 (match_operand:SI 2 "arm_rhs_operand" "I,r,r"))
5895f793 1418 (const_int 0)))
148413a4 1419 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
ff9940b0 1420 (minus:SI (match_dup 1) (match_dup 2)))]
5b3e6663 1421 "TARGET_32BIT"
0f447ef2 1422 "@
148413a4 1423 sub%.\\t%0, %1, %2
5b3e6663
PB
1424 sub%.\\t%0, %1, %2
1425 rsb%.\\t%0, %2, %1"
148413a4 1426 [(set_attr "conds" "set")
6e4150e1 1427 (set_attr "type" "alus_imm,alus_reg,alus_reg")]
d5b7b3ae 1428)
ff9940b0 1429
0480fff0 1430(define_insn "subsi3_compare"
7ec6356e 1431 [(set (reg:CC CC_REGNUM)
148413a4
RR
1432 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1433 (match_operand:SI 2 "arm_rhs_operand" "I,r,r")))
1434 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
18e8200f
BS
1435 (minus:SI (match_dup 1) (match_dup 2)))]
1436 "TARGET_32BIT"
1437 "@
148413a4 1438 sub%.\\t%0, %1, %2
18e8200f
BS
1439 sub%.\\t%0, %1, %2
1440 rsb%.\\t%0, %2, %1"
148413a4 1441 [(set_attr "conds" "set")
6e4150e1 1442 (set_attr "type" "alus_imm,alus_reg,alus_reg")]
18e8200f
BS
1443)
1444
37f74dcf
RE
1445(define_expand "subsf3"
1446 [(set (match_operand:SF 0 "s_register_operand" "")
dae840fc
RE
1447 (minus:SF (match_operand:SF 1 "s_register_operand" "")
1448 (match_operand:SF 2 "s_register_operand" "")))]
5b3e6663 1449 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf 1450 "
37f74dcf
RE
1451")
1452
37f74dcf
RE
1453(define_expand "subdf3"
1454 [(set (match_operand:DF 0 "s_register_operand" "")
dae840fc
RE
1455 (minus:DF (match_operand:DF 1 "s_register_operand" "")
1456 (match_operand:DF 2 "s_register_operand" "")))]
e0dc3601 1457 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
37f74dcf 1458 "
37f74dcf
RE
1459")
1460
3a33f76f
RK
1461\f
1462;; Multiplication insns
1463
b2d3f886
RE
1464(define_expand "mulhi3"
1465 [(set (match_operand:HI 0 "s_register_operand" "")
1466 (mult:HI (match_operand:HI 1 "s_register_operand" "")
1467 (match_operand:HI 2 "s_register_operand" "")))]
1468 "TARGET_DSP_MULTIPLY"
1469 "
1470 {
1471 rtx result = gen_reg_rtx (SImode);
1472 emit_insn (gen_mulhisi3 (result, operands[1], operands[2]));
1473 emit_move_insn (operands[0], gen_lowpart (HImode, result));
1474 DONE;
1475 }"
1476)
1477
d5b7b3ae
RE
1478(define_expand "mulsi3"
1479 [(set (match_operand:SI 0 "s_register_operand" "")
1480 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1481 (match_operand:SI 1 "s_register_operand" "")))]
1482 "TARGET_EITHER"
1483 ""
1484)
1485
ff9940b0 1486;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
d5b7b3ae
RE
1487(define_insn "*arm_mulsi3"
1488 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
ff9940b0 1489 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
cfc25c74 1490 (match_operand:SI 1 "s_register_operand" "%0,r")))]
d6c397b0 1491 "TARGET_32BIT && !arm_arch6"
4cdb3ed4 1492 "mul%?\\t%0, %2, %1"
09485a08 1493 [(set_attr "type" "mul")
cca0a211 1494 (set_attr "predicable" "yes")]
d5b7b3ae
RE
1495)
1496
d6c397b0 1497(define_insn "*arm_mulsi3_v6"
31dfce10
KT
1498 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1499 (mult:SI (match_operand:SI 1 "s_register_operand" "0,l,r")
1500 (match_operand:SI 2 "s_register_operand" "l,0,r")))]
d6c397b0
PB
1501 "TARGET_32BIT && arm_arch6"
1502 "mul%?\\t%0, %1, %2"
09485a08 1503 [(set_attr "type" "mul")
31dfce10
KT
1504 (set_attr "predicable" "yes")
1505 (set_attr "arch" "t2,t2,*")
1506 (set_attr "length" "4")
1507 (set_attr "predicable_short_it" "yes,yes,no")]
d6c397b0
PB
1508)
1509
5895f793
RE
1510; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1511; 1 and 2; are the same, because reload will make operand 0 match
1512; operand 1 without realizing that this conflicts with operand 2. We fix
1513; this by adding another alternative to match this case, and then `reload'
1514; it ourselves. This alternative must come first.
d5b7b3ae
RE
1515(define_insn "*thumb_mulsi3"
1516 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1517 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1518 (match_operand:SI 2 "register_operand" "l,l,l")))]
d6c397b0 1519 "TARGET_THUMB1 && !arm_arch6"
d5b7b3ae
RE
1520 "*
1521 if (which_alternative < 2)
d08e2ccb 1522 return \"mov\\t%0, %1\;mul\\t%0, %2\";
d5b7b3ae 1523 else
d08e2ccb 1524 return \"mul\\t%0, %2\";
d5b7b3ae
RE
1525 "
1526 [(set_attr "length" "4,4,2")
09485a08 1527 (set_attr "type" "muls")]
d5b7b3ae 1528)
3a33f76f 1529
d6c397b0
PB
1530(define_insn "*thumb_mulsi3_v6"
1531 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
1532 (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1533 (match_operand:SI 2 "register_operand" "l,0,0")))]
1534 "TARGET_THUMB1 && arm_arch6"
1535 "@
81ad4ac0
JZ
1536 mul\\t%0, %2
1537 mul\\t%0, %1
d6c397b0
PB
1538 mul\\t%0, %1"
1539 [(set_attr "length" "2")
09485a08 1540 (set_attr "type" "muls")]
d6c397b0
PB
1541)
1542
4cdb3ed4 1543(define_insn "*mulsi3_compare0"
48a08b9c 1544 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
1545 (compare:CC_NOOV (mult:SI
1546 (match_operand:SI 2 "s_register_operand" "r,r")
cfc25c74 1547 (match_operand:SI 1 "s_register_operand" "%0,r"))
ff9940b0
RE
1548 (const_int 0)))
1549 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1550 (mult:SI (match_dup 2) (match_dup 1)))]
d6c397b0
PB
1551 "TARGET_ARM && !arm_arch6"
1552 "mul%.\\t%0, %2, %1"
1553 [(set_attr "conds" "set")
09485a08 1554 (set_attr "type" "muls")]
d6c397b0
PB
1555)
1556
1557(define_insn "*mulsi3_compare0_v6"
1558 [(set (reg:CC_NOOV CC_REGNUM)
1559 (compare:CC_NOOV (mult:SI
1560 (match_operand:SI 2 "s_register_operand" "r")
1561 (match_operand:SI 1 "s_register_operand" "r"))
1562 (const_int 0)))
1563 (set (match_operand:SI 0 "s_register_operand" "=r")
1564 (mult:SI (match_dup 2) (match_dup 1)))]
1565 "TARGET_ARM && arm_arch6 && optimize_size"
5b3e6663 1566 "mul%.\\t%0, %2, %1"
d5b7b3ae 1567 [(set_attr "conds" "set")
09485a08 1568 (set_attr "type" "muls")]
d5b7b3ae 1569)
ff9940b0 1570
4cdb3ed4 1571(define_insn "*mulsi_compare0_scratch"
48a08b9c 1572 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
1573 (compare:CC_NOOV (mult:SI
1574 (match_operand:SI 2 "s_register_operand" "r,r")
cfc25c74 1575 (match_operand:SI 1 "s_register_operand" "%0,r"))
ff9940b0
RE
1576 (const_int 0)))
1577 (clobber (match_scratch:SI 0 "=&r,&r"))]
d6c397b0
PB
1578 "TARGET_ARM && !arm_arch6"
1579 "mul%.\\t%0, %2, %1"
1580 [(set_attr "conds" "set")
09485a08 1581 (set_attr "type" "muls")]
d6c397b0
PB
1582)
1583
1584(define_insn "*mulsi_compare0_scratch_v6"
1585 [(set (reg:CC_NOOV CC_REGNUM)
1586 (compare:CC_NOOV (mult:SI
1587 (match_operand:SI 2 "s_register_operand" "r")
1588 (match_operand:SI 1 "s_register_operand" "r"))
1589 (const_int 0)))
1590 (clobber (match_scratch:SI 0 "=r"))]
1591 "TARGET_ARM && arm_arch6 && optimize_size"
5b3e6663 1592 "mul%.\\t%0, %2, %1"
d5b7b3ae 1593 [(set_attr "conds" "set")
09485a08 1594 (set_attr "type" "muls")]
d5b7b3ae 1595)
ff9940b0 1596
3a33f76f
RK
1597;; Unnamed templates to match MLA instruction.
1598
4cdb3ed4 1599(define_insn "*mulsi3addsi"
ff9940b0 1600 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
fd3f89a9 1601 (plus:SI
ff9940b0 1602 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
cfc25c74
RE
1603 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1604 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
d6c397b0
PB
1605 "TARGET_32BIT && !arm_arch6"
1606 "mla%?\\t%0, %2, %1, %3"
09485a08 1607 [(set_attr "type" "mla")
d6c397b0
PB
1608 (set_attr "predicable" "yes")]
1609)
1610
1611(define_insn "*mulsi3addsi_v6"
1612 [(set (match_operand:SI 0 "s_register_operand" "=r")
1613 (plus:SI
1614 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1615 (match_operand:SI 1 "s_register_operand" "r"))
1616 (match_operand:SI 3 "s_register_operand" "r")))]
1617 "TARGET_32BIT && arm_arch6"
4cdb3ed4 1618 "mla%?\\t%0, %2, %1, %3"
09485a08 1619 [(set_attr "type" "mla")
31dfce10
KT
1620 (set_attr "predicable" "yes")
1621 (set_attr "predicable_short_it" "no")]
cca0a211 1622)
3a33f76f 1623
4cdb3ed4 1624(define_insn "*mulsi3addsi_compare0"
48a08b9c 1625 [(set (reg:CC_NOOV CC_REGNUM)
5895f793
RE
1626 (compare:CC_NOOV
1627 (plus:SI (mult:SI
1628 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
cfc25c74
RE
1629 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1630 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
5895f793 1631 (const_int 0)))
ff9940b0
RE
1632 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1633 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1634 (match_dup 3)))]
d6c397b0
PB
1635 "TARGET_ARM && arm_arch6"
1636 "mla%.\\t%0, %2, %1, %3"
1637 [(set_attr "conds" "set")
09485a08 1638 (set_attr "type" "mlas")]
d6c397b0
PB
1639)
1640
1641(define_insn "*mulsi3addsi_compare0_v6"
1642 [(set (reg:CC_NOOV CC_REGNUM)
1643 (compare:CC_NOOV
1644 (plus:SI (mult:SI
1645 (match_operand:SI 2 "s_register_operand" "r")
1646 (match_operand:SI 1 "s_register_operand" "r"))
1647 (match_operand:SI 3 "s_register_operand" "r"))
1648 (const_int 0)))
1649 (set (match_operand:SI 0 "s_register_operand" "=r")
1650 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1651 (match_dup 3)))]
1652 "TARGET_ARM && arm_arch6 && optimize_size"
5b3e6663 1653 "mla%.\\t%0, %2, %1, %3"
cca0a211 1654 [(set_attr "conds" "set")
09485a08 1655 (set_attr "type" "mlas")]
cca0a211 1656)
ff9940b0 1657
4cdb3ed4 1658(define_insn "*mulsi3addsi_compare0_scratch"
48a08b9c 1659 [(set (reg:CC_NOOV CC_REGNUM)
5895f793
RE
1660 (compare:CC_NOOV
1661 (plus:SI (mult:SI
1662 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
cfc25c74 1663 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
5895f793
RE
1664 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1665 (const_int 0)))
ff9940b0 1666 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
d6c397b0
PB
1667 "TARGET_ARM && !arm_arch6"
1668 "mla%.\\t%0, %2, %1, %3"
1669 [(set_attr "conds" "set")
09485a08 1670 (set_attr "type" "mlas")]
d6c397b0
PB
1671)
1672
1673(define_insn "*mulsi3addsi_compare0_scratch_v6"
1674 [(set (reg:CC_NOOV CC_REGNUM)
1675 (compare:CC_NOOV
1676 (plus:SI (mult:SI
1677 (match_operand:SI 2 "s_register_operand" "r")
1678 (match_operand:SI 1 "s_register_operand" "r"))
1679 (match_operand:SI 3 "s_register_operand" "r"))
1680 (const_int 0)))
1681 (clobber (match_scratch:SI 0 "=r"))]
1682 "TARGET_ARM && arm_arch6 && optimize_size"
5b3e6663 1683 "mla%.\\t%0, %2, %1, %3"
d5b7b3ae 1684 [(set_attr "conds" "set")
09485a08 1685 (set_attr "type" "mlas")]
d5b7b3ae 1686)
4cdb3ed4 1687
26b53f80
PB
1688(define_insn "*mulsi3subsi"
1689 [(set (match_operand:SI 0 "s_register_operand" "=r")
1690 (minus:SI
1691 (match_operand:SI 3 "s_register_operand" "r")
1692 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1693 (match_operand:SI 1 "s_register_operand" "r"))))]
1694 "TARGET_32BIT && arm_arch_thumb2"
1695 "mls%?\\t%0, %2, %1, %3"
09485a08 1696 [(set_attr "type" "mla")
31dfce10
KT
1697 (set_attr "predicable" "yes")
1698 (set_attr "predicable_short_it" "no")]
26b53f80
PB
1699)
1700
810c4bf4
BS
1701(define_expand "maddsidi4"
1702 [(set (match_operand:DI 0 "s_register_operand" "")
1703 (plus: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 (match_operand:DI 3 "s_register_operand" "")))]
1708 "TARGET_32BIT && arm_arch3m"
1709 "")
9e3fc430
CP
1710
1711(define_insn "*mulsidi3adddi"
b082bfdb 1712 [(set (match_operand:DI 0 "s_register_operand" "=&r")
9e3fc430 1713 (plus:DI
5895f793 1714 (mult:DI
b082bfdb
RE
1715 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1716 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1717 (match_operand:DI 1 "s_register_operand" "0")))]
d6c397b0
PB
1718 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1719 "smlal%?\\t%Q0, %R0, %3, %2"
09485a08 1720 [(set_attr "type" "smlal")
d6c397b0
PB
1721 (set_attr "predicable" "yes")]
1722)
1723
1724(define_insn "*mulsidi3adddi_v6"
1725 [(set (match_operand:DI 0 "s_register_operand" "=r")
1726 (plus:DI
1727 (mult:DI
1728 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1729 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1730 (match_operand:DI 1 "s_register_operand" "0")))]
1731 "TARGET_32BIT && arm_arch6"
b082bfdb 1732 "smlal%?\\t%Q0, %R0, %3, %2"
09485a08 1733 [(set_attr "type" "smlal")
31dfce10
KT
1734 (set_attr "predicable" "yes")
1735 (set_attr "predicable_short_it" "no")]
cca0a211 1736)
9e3fc430 1737
fc7a6a0d
ZW
1738;; 32x32->64 widening multiply.
1739;; As with mulsi3, the only difference between the v3-5 and v6+
1740;; versions of these patterns is the requirement that the output not
1741;; overlap the inputs, but that still means we have to have a named
1742;; expander and two different starred insns.
1743
1744(define_expand "mulsidi3"
1745 [(set (match_operand:DI 0 "s_register_operand" "")
1746 (mult:DI
1747 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1748 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1749 "TARGET_32BIT && arm_arch3m"
1750 ""
1751)
1752
1753(define_insn "*mulsidi3_nov6"
4cdb3ed4 1754 [(set (match_operand:DI 0 "s_register_operand" "=&r")
5895f793
RE
1755 (mult:DI
1756 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1757 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
d6c397b0
PB
1758 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1759 "smull%?\\t%Q0, %R0, %1, %2"
09485a08 1760 [(set_attr "type" "smull")
d6c397b0
PB
1761 (set_attr "predicable" "yes")]
1762)
1763
fc7a6a0d 1764(define_insn "*mulsidi3_v6"
d6c397b0
PB
1765 [(set (match_operand:DI 0 "s_register_operand" "=r")
1766 (mult:DI
1767 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1768 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1769 "TARGET_32BIT && arm_arch6"
3dafc5c3 1770 "smull%?\\t%Q0, %R0, %1, %2"
09485a08 1771 [(set_attr "type" "smull")
31dfce10
KT
1772 (set_attr "predicable" "yes")
1773 (set_attr "predicable_short_it" "no")]
cca0a211 1774)
4cdb3ed4 1775
fc7a6a0d
ZW
1776(define_expand "umulsidi3"
1777 [(set (match_operand:DI 0 "s_register_operand" "")
1778 (mult:DI
1779 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1780 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1781 "TARGET_32BIT && arm_arch3m"
1782 ""
1783)
1784
1785(define_insn "*umulsidi3_nov6"
4cdb3ed4 1786 [(set (match_operand:DI 0 "s_register_operand" "=&r")
5895f793
RE
1787 (mult:DI
1788 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1789 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
d6c397b0
PB
1790 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1791 "umull%?\\t%Q0, %R0, %1, %2"
09485a08 1792 [(set_attr "type" "umull")
d6c397b0
PB
1793 (set_attr "predicable" "yes")]
1794)
1795
fc7a6a0d 1796(define_insn "*umulsidi3_v6"
d6c397b0
PB
1797 [(set (match_operand:DI 0 "s_register_operand" "=r")
1798 (mult:DI
1799 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1800 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1801 "TARGET_32BIT && arm_arch6"
3dafc5c3 1802 "umull%?\\t%Q0, %R0, %1, %2"
09485a08 1803 [(set_attr "type" "umull")
31dfce10
KT
1804 (set_attr "predicable" "yes")
1805 (set_attr "predicable_short_it" "no")]
cca0a211 1806)
3a33f76f 1807
810c4bf4
BS
1808(define_expand "umaddsidi4"
1809 [(set (match_operand:DI 0 "s_register_operand" "")
1810 (plus:DI
1811 (mult:DI
1812 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1813 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1814 (match_operand:DI 3 "s_register_operand" "")))]
1815 "TARGET_32BIT && arm_arch3m"
1816 "")
9e3fc430
CP
1817
1818(define_insn "*umulsidi3adddi"
a67ded0f 1819 [(set (match_operand:DI 0 "s_register_operand" "=&r")
9e3fc430 1820 (plus:DI
5895f793 1821 (mult:DI
b082bfdb
RE
1822 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1823 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1824 (match_operand:DI 1 "s_register_operand" "0")))]
d6c397b0
PB
1825 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1826 "umlal%?\\t%Q0, %R0, %3, %2"
09485a08 1827 [(set_attr "type" "umlal")
d6c397b0
PB
1828 (set_attr "predicable" "yes")]
1829)
1830
1831(define_insn "*umulsidi3adddi_v6"
1832 [(set (match_operand:DI 0 "s_register_operand" "=r")
1833 (plus:DI
1834 (mult:DI
1835 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1836 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1837 (match_operand:DI 1 "s_register_operand" "0")))]
1838 "TARGET_32BIT && arm_arch6"
b082bfdb 1839 "umlal%?\\t%Q0, %R0, %3, %2"
09485a08 1840 [(set_attr "type" "umlal")
31dfce10
KT
1841 (set_attr "predicable" "yes")
1842 (set_attr "predicable_short_it" "no")]
cca0a211 1843)
9e3fc430 1844
fc7a6a0d
ZW
1845(define_expand "smulsi3_highpart"
1846 [(parallel
1847 [(set (match_operand:SI 0 "s_register_operand" "")
1848 (truncate:SI
1849 (lshiftrt:DI
1850 (mult:DI
1851 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1852 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1853 (const_int 32))))
1854 (clobber (match_scratch:SI 3 ""))])]
1855 "TARGET_32BIT && arm_arch3m"
1856 ""
1857)
1858
1859(define_insn "*smulsi3_highpart_nov6"
7a0a1f09
RE
1860 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1861 (truncate:SI
1862 (lshiftrt:DI
5895f793 1863 (mult:DI
cfc25c74 1864 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
5895f793 1865 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
7a0a1f09
RE
1866 (const_int 32))))
1867 (clobber (match_scratch:SI 3 "=&r,&r"))]
d6c397b0
PB
1868 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1869 "smull%?\\t%3, %0, %2, %1"
09485a08 1870 [(set_attr "type" "smull")
d6c397b0
PB
1871 (set_attr "predicable" "yes")]
1872)
1873
fc7a6a0d 1874(define_insn "*smulsi3_highpart_v6"
d6c397b0
PB
1875 [(set (match_operand:SI 0 "s_register_operand" "=r")
1876 (truncate:SI
1877 (lshiftrt:DI
1878 (mult:DI
1879 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1880 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1881 (const_int 32))))
1882 (clobber (match_scratch:SI 3 "=r"))]
1883 "TARGET_32BIT && arm_arch6"
7a0a1f09 1884 "smull%?\\t%3, %0, %2, %1"
09485a08 1885 [(set_attr "type" "smull")
31dfce10
KT
1886 (set_attr "predicable" "yes")
1887 (set_attr "predicable_short_it" "no")]
d5b7b3ae 1888)
7a0a1f09 1889
fc7a6a0d
ZW
1890(define_expand "umulsi3_highpart"
1891 [(parallel
1892 [(set (match_operand:SI 0 "s_register_operand" "")
1893 (truncate:SI
1894 (lshiftrt:DI
1895 (mult:DI
1896 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1897 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1898 (const_int 32))))
1899 (clobber (match_scratch:SI 3 ""))])]
1900 "TARGET_32BIT && arm_arch3m"
1901 ""
1902)
1903
1904(define_insn "*umulsi3_highpart_nov6"
7a0a1f09
RE
1905 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1906 (truncate:SI
1907 (lshiftrt:DI
5895f793 1908 (mult:DI
cfc25c74 1909 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
5895f793 1910 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
7a0a1f09
RE
1911 (const_int 32))))
1912 (clobber (match_scratch:SI 3 "=&r,&r"))]
d6c397b0
PB
1913 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1914 "umull%?\\t%3, %0, %2, %1"
09485a08 1915 [(set_attr "type" "umull")
d6c397b0
PB
1916 (set_attr "predicable" "yes")]
1917)
1918
fc7a6a0d 1919(define_insn "*umulsi3_highpart_v6"
d6c397b0
PB
1920 [(set (match_operand:SI 0 "s_register_operand" "=r")
1921 (truncate:SI
1922 (lshiftrt:DI
1923 (mult:DI
1924 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1925 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1926 (const_int 32))))
1927 (clobber (match_scratch:SI 3 "=r"))]
1928 "TARGET_32BIT && arm_arch6"
7a0a1f09 1929 "umull%?\\t%3, %0, %2, %1"
09485a08 1930 [(set_attr "type" "umull")
31dfce10
KT
1931 (set_attr "predicable" "yes")
1932 (set_attr "predicable_short_it" "no")]
d5b7b3ae 1933)
7a0a1f09 1934
d19fb8e3
NC
1935(define_insn "mulhisi3"
1936 [(set (match_operand:SI 0 "s_register_operand" "=r")
1937 (mult:SI (sign_extend:SI
1938 (match_operand:HI 1 "s_register_operand" "%r"))
1939 (sign_extend:SI
1940 (match_operand:HI 2 "s_register_operand" "r"))))]
5b3e6663 1941 "TARGET_DSP_MULTIPLY"
859230d4 1942 "smulbb%?\\t%0, %1, %2"
09485a08 1943 [(set_attr "type" "smulxy")
b8c53e96
RE
1944 (set_attr "predicable" "yes")]
1945)
1946
1947(define_insn "*mulhisi3tb"
1948 [(set (match_operand:SI 0 "s_register_operand" "=r")
1949 (mult:SI (ashiftrt:SI
1950 (match_operand:SI 1 "s_register_operand" "r")
1951 (const_int 16))
1952 (sign_extend:SI
1953 (match_operand:HI 2 "s_register_operand" "r"))))]
5b3e6663 1954 "TARGET_DSP_MULTIPLY"
b8c53e96 1955 "smultb%?\\t%0, %1, %2"
09485a08 1956 [(set_attr "type" "smulxy")
31dfce10
KT
1957 (set_attr "predicable" "yes")
1958 (set_attr "predicable_short_it" "no")]
b8c53e96
RE
1959)
1960
1961(define_insn "*mulhisi3bt"
1962 [(set (match_operand:SI 0 "s_register_operand" "=r")
1963 (mult:SI (sign_extend:SI
1964 (match_operand:HI 1 "s_register_operand" "r"))
1965 (ashiftrt:SI
1966 (match_operand:SI 2 "s_register_operand" "r")
1967 (const_int 16))))]
5b3e6663 1968 "TARGET_DSP_MULTIPLY"
b8c53e96 1969 "smulbt%?\\t%0, %1, %2"
09485a08 1970 [(set_attr "type" "smulxy")
31dfce10
KT
1971 (set_attr "predicable" "yes")
1972 (set_attr "predicable_short_it" "no")]
b8c53e96
RE
1973)
1974
1975(define_insn "*mulhisi3tt"
1976 [(set (match_operand:SI 0 "s_register_operand" "=r")
1977 (mult:SI (ashiftrt:SI
1978 (match_operand:SI 1 "s_register_operand" "r")
1979 (const_int 16))
1980 (ashiftrt:SI
1981 (match_operand:SI 2 "s_register_operand" "r")
1982 (const_int 16))))]
5b3e6663 1983 "TARGET_DSP_MULTIPLY"
b8c53e96 1984 "smultt%?\\t%0, %1, %2"
09485a08 1985 [(set_attr "type" "smulxy")
31dfce10
KT
1986 (set_attr "predicable" "yes")
1987 (set_attr "predicable_short_it" "no")]
d19fb8e3
NC
1988)
1989
810c4bf4 1990(define_insn "maddhisi4"
d19fb8e3 1991 [(set (match_operand:SI 0 "s_register_operand" "=r")
cfd688ea
AS
1992 (plus:SI (mult:SI (sign_extend:SI
1993 (match_operand:HI 1 "s_register_operand" "r"))
d19fb8e3 1994 (sign_extend:SI
cfd688ea
AS
1995 (match_operand:HI 2 "s_register_operand" "r")))
1996 (match_operand:SI 3 "s_register_operand" "r")))]
5b3e6663 1997 "TARGET_DSP_MULTIPLY"
810c4bf4 1998 "smlabb%?\\t%0, %1, %2, %3"
09485a08 1999 [(set_attr "type" "smlaxy")
31dfce10
KT
2000 (set_attr "predicable" "yes")
2001 (set_attr "predicable_short_it" "no")]
d19fb8e3
NC
2002)
2003
f373314f
AS
2004;; Note: there is no maddhisi4ibt because this one is canonical form
2005(define_insn "*maddhisi4tb"
2006 [(set (match_operand:SI 0 "s_register_operand" "=r")
2007 (plus:SI (mult:SI (ashiftrt:SI
2008 (match_operand:SI 1 "s_register_operand" "r")
2009 (const_int 16))
2010 (sign_extend:SI
2011 (match_operand:HI 2 "s_register_operand" "r")))
2012 (match_operand:SI 3 "s_register_operand" "r")))]
2013 "TARGET_DSP_MULTIPLY"
2014 "smlatb%?\\t%0, %1, %2, %3"
09485a08 2015 [(set_attr "type" "smlaxy")
31dfce10
KT
2016 (set_attr "predicable" "yes")
2017 (set_attr "predicable_short_it" "no")]
f373314f
AS
2018)
2019
2020(define_insn "*maddhisi4tt"
2021 [(set (match_operand:SI 0 "s_register_operand" "=r")
2022 (plus:SI (mult:SI (ashiftrt:SI
2023 (match_operand:SI 1 "s_register_operand" "r")
2024 (const_int 16))
2025 (ashiftrt:SI
2026 (match_operand:SI 2 "s_register_operand" "r")
2027 (const_int 16)))
2028 (match_operand:SI 3 "s_register_operand" "r")))]
2029 "TARGET_DSP_MULTIPLY"
2030 "smlatt%?\\t%0, %1, %2, %3"
09485a08 2031 [(set_attr "type" "smlaxy")
31dfce10
KT
2032 (set_attr "predicable" "yes")
2033 (set_attr "predicable_short_it" "no")]
f373314f
AS
2034)
2035
5dfe80ba 2036(define_insn "maddhidi4"
d19fb8e3
NC
2037 [(set (match_operand:DI 0 "s_register_operand" "=r")
2038 (plus:DI
d19fb8e3 2039 (mult:DI (sign_extend:DI
31dfce10 2040 (match_operand:HI 1 "s_register_operand" "r"))
d19fb8e3 2041 (sign_extend:DI
cfd688ea
AS
2042 (match_operand:HI 2 "s_register_operand" "r")))
2043 (match_operand:DI 3 "s_register_operand" "0")))]
5b3e6663 2044 "TARGET_DSP_MULTIPLY"
810c4bf4 2045 "smlalbb%?\\t%Q0, %R0, %1, %2"
09485a08 2046 [(set_attr "type" "smlalxy")
31dfce10
KT
2047 (set_attr "predicable" "yes")
2048 (set_attr "predicable_short_it" "no")])
d19fb8e3 2049
f373314f
AS
2050;; Note: there is no maddhidi4ibt because this one is canonical form
2051(define_insn "*maddhidi4tb"
2052 [(set (match_operand:DI 0 "s_register_operand" "=r")
2053 (plus:DI
2054 (mult:DI (sign_extend:DI
2055 (ashiftrt:SI
2056 (match_operand:SI 1 "s_register_operand" "r")
2057 (const_int 16)))
2058 (sign_extend:DI
2059 (match_operand:HI 2 "s_register_operand" "r")))
2060 (match_operand:DI 3 "s_register_operand" "0")))]
2061 "TARGET_DSP_MULTIPLY"
2062 "smlaltb%?\\t%Q0, %R0, %1, %2"
09485a08 2063 [(set_attr "type" "smlalxy")
31dfce10
KT
2064 (set_attr "predicable" "yes")
2065 (set_attr "predicable_short_it" "no")])
f373314f
AS
2066
2067(define_insn "*maddhidi4tt"
2068 [(set (match_operand:DI 0 "s_register_operand" "=r")
2069 (plus:DI
2070 (mult:DI (sign_extend:DI
2071 (ashiftrt:SI
2072 (match_operand:SI 1 "s_register_operand" "r")
2073 (const_int 16)))
2074 (sign_extend:DI
2075 (ashiftrt:SI
2076 (match_operand:SI 2 "s_register_operand" "r")
2077 (const_int 16))))
2078 (match_operand:DI 3 "s_register_operand" "0")))]
2079 "TARGET_DSP_MULTIPLY"
2080 "smlaltt%?\\t%Q0, %R0, %1, %2"
09485a08 2081 [(set_attr "type" "smlalxy")
31dfce10
KT
2082 (set_attr "predicable" "yes")
2083 (set_attr "predicable_short_it" "no")])
f373314f 2084
37f74dcf
RE
2085(define_expand "mulsf3"
2086 [(set (match_operand:SF 0 "s_register_operand" "")
2087 (mult:SF (match_operand:SF 1 "s_register_operand" "")
dae840fc 2088 (match_operand:SF 2 "s_register_operand" "")))]
5b3e6663 2089 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf 2090 "
37f74dcf
RE
2091")
2092
37f74dcf
RE
2093(define_expand "muldf3"
2094 [(set (match_operand:DF 0 "s_register_operand" "")
2095 (mult:DF (match_operand:DF 1 "s_register_operand" "")
dae840fc 2096 (match_operand:DF 2 "s_register_operand" "")))]
e0dc3601 2097 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
37f74dcf 2098 "
37f74dcf 2099")
3a33f76f
RK
2100\f
2101;; Division insns
2102
82955615
RE
2103(define_expand "divsf3"
2104 [(set (match_operand:SF 0 "s_register_operand" "")
dae840fc
RE
2105 (div:SF (match_operand:SF 1 "s_register_operand" "")
2106 (match_operand:SF 2 "s_register_operand" "")))]
8fcd8c83 2107 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
82955615 2108 "")
ff9940b0 2109
82955615
RE
2110(define_expand "divdf3"
2111 [(set (match_operand:DF 0 "s_register_operand" "")
dae840fc
RE
2112 (div:DF (match_operand:DF 1 "s_register_operand" "")
2113 (match_operand:DF 2 "s_register_operand" "")))]
8fcd8c83 2114 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
82955615 2115 "")
3a33f76f
RK
2116\f
2117;; Boolean and,ior,xor insns
2118
6ab589e0
JL
2119;; Split up double word logical operations
2120
2121;; Split up simple DImode logical operations. Simply perform the logical
2122;; operation on the upper and lower halves of the registers.
2123(define_split
2124 [(set (match_operand:DI 0 "s_register_operand" "")
2125 (match_operator:DI 6 "logical_binary_operator"
2126 [(match_operand:DI 1 "s_register_operand" "")
2127 (match_operand:DI 2 "s_register_operand" "")]))]
5b3e6663 2128 "TARGET_32BIT && reload_completed
b3b7bbce 2129 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
5b3e6663 2130 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
6ab589e0
JL
2131 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2132 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
2133 "
5895f793
RE
2134 {
2135 operands[3] = gen_highpart (SImode, operands[0]);
2136 operands[0] = gen_lowpart (SImode, operands[0]);
2137 operands[4] = gen_highpart (SImode, operands[1]);
2138 operands[1] = gen_lowpart (SImode, operands[1]);
2139 operands[5] = gen_highpart (SImode, operands[2]);
2140 operands[2] = gen_lowpart (SImode, operands[2]);
2141 }"
2142)
6ab589e0 2143
6ab589e0
JL
2144(define_split
2145 [(set (match_operand:DI 0 "s_register_operand" "")
2146 (match_operator:DI 6 "logical_binary_operator"
2147 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2148 (match_operand:DI 1 "s_register_operand" "")]))]
5b3e6663 2149 "TARGET_32BIT && reload_completed"
6ab589e0
JL
2150 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2151 (set (match_dup 3) (match_op_dup:SI 6
2152 [(ashiftrt:SI (match_dup 2) (const_int 31))
2153 (match_dup 4)]))]
2154 "
5895f793
RE
2155 {
2156 operands[3] = gen_highpart (SImode, operands[0]);
2157 operands[0] = gen_lowpart (SImode, operands[0]);
2158 operands[4] = gen_highpart (SImode, operands[1]);
2159 operands[1] = gen_lowpart (SImode, operands[1]);
2160 operands[5] = gen_highpart (SImode, operands[2]);
2161 operands[2] = gen_lowpart (SImode, operands[2]);
2162 }"
2163)
6ab589e0 2164
6ab589e0
JL
2165;; The zero extend of operand 2 means we can just copy the high part of
2166;; operand1 into operand0.
2167(define_split
2168 [(set (match_operand:DI 0 "s_register_operand" "")
2169 (ior:DI
2170 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2171 (match_operand:DI 1 "s_register_operand" "")))]
5b3e6663 2172 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
6ab589e0
JL
2173 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
2174 (set (match_dup 3) (match_dup 4))]
2175 "
5895f793
RE
2176 {
2177 operands[4] = gen_highpart (SImode, operands[1]);
2178 operands[3] = gen_highpart (SImode, operands[0]);
2179 operands[0] = gen_lowpart (SImode, operands[0]);
2180 operands[1] = gen_lowpart (SImode, operands[1]);
2181 }"
2182)
6ab589e0
JL
2183
2184;; The zero extend of operand 2 means we can just copy the high part of
2185;; operand1 into operand0.
2186(define_split
2187 [(set (match_operand:DI 0 "s_register_operand" "")
2188 (xor:DI
2189 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2190 (match_operand:DI 1 "s_register_operand" "")))]
5b3e6663 2191 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
6ab589e0
JL
2192 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
2193 (set (match_dup 3) (match_dup 4))]
2194 "
5895f793
RE
2195 {
2196 operands[4] = gen_highpart (SImode, operands[1]);
2197 operands[3] = gen_highpart (SImode, operands[0]);
2198 operands[0] = gen_lowpart (SImode, operands[0]);
2199 operands[1] = gen_lowpart (SImode, operands[1]);
2200 }"
2201)
6ab589e0 2202
b3b7bbce
SL
2203(define_expand "anddi3"
2204 [(set (match_operand:DI 0 "s_register_operand" "")
2205 (and:DI (match_operand:DI 1 "s_register_operand" "")
2206 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
2207 "TARGET_32BIT"
2208 ""
2209)
2210
1c50eada 2211(define_insn_and_split "*anddi3_insn"
b31ddbdb
KT
2212 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
2213 (and:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
2214 (match_operand:DI 2 "arm_anddi_operand_neon" "w ,DL,r ,r ,De,De,w ,DL")))]
1c50eada
KT
2215 "TARGET_32BIT && !TARGET_IWMMXT"
2216{
2217 switch (which_alternative)
2218 {
b31ddbdb
KT
2219 case 0: /* fall through */
2220 case 6: return "vand\t%P0, %P1, %P2";
2221 case 1: /* fall through */
2222 case 7: return neon_output_logic_immediate ("vand", &operands[2],
2223 DImode, 1, VALID_NEON_QREG_MODE (DImode));
1c50eada 2224 case 2:
b31ddbdb
KT
2225 case 3:
2226 case 4:
1c50eada 2227 case 5: /* fall through */
b31ddbdb 2228 return "#";
1c50eada
KT
2229 default: gcc_unreachable ();
2230 }
2231}
b31ddbdb
KT
2232 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2233 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
1c50eada
KT
2234 [(set (match_dup 3) (match_dup 4))
2235 (set (match_dup 5) (match_dup 6))]
2236 "
2237 {
2238 operands[3] = gen_lowpart (SImode, operands[0]);
2239 operands[5] = gen_highpart (SImode, operands[0]);
2240
2241 operands[4] = simplify_gen_binary (AND, SImode,
2242 gen_lowpart (SImode, operands[1]),
2243 gen_lowpart (SImode, operands[2]));
2244 operands[6] = simplify_gen_binary (AND, SImode,
2245 gen_highpart (SImode, operands[1]),
2246 gen_highpart_mode (SImode, DImode, operands[2]));
2247
2248 }"
f7379e5e
JG
2249 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,\
2250 multiple,multiple,neon_logic,neon_logic")
b31ddbdb 2251 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,
1c50eada 2252 avoid_neon_for_64bits,avoid_neon_for_64bits")
b31ddbdb
KT
2253 (set_attr "length" "*,*,8,8,8,8,*,*")
2254 ]
5895f793 2255)
3a33f76f 2256
bb6ae783 2257(define_insn_and_split "*anddi_zesidi_di"
ff9940b0
RE
2258 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2259 (and:DI (zero_extend:DI
2260 (match_operand:SI 2 "s_register_operand" "r,r"))
cfc25c74 2261 (match_operand:DI 1 "s_register_operand" "0,r")))]
5b3e6663 2262 "TARGET_32BIT"
6ab589e0 2263 "#"
5b3e6663 2264 "TARGET_32BIT && reload_completed"
bb6ae783
RE
2265 ; The zero extend of operand 2 clears the high word of the output
2266 ; operand.
2267 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2268 (set (match_dup 3) (const_int 0))]
2269 "
2270 {
2271 operands[3] = gen_highpart (SImode, operands[0]);
2272 operands[0] = gen_lowpart (SImode, operands[0]);
2273 operands[1] = gen_lowpart (SImode, operands[1]);
2274 }"
594726e4
JG
2275 [(set_attr "length" "8")
2276 (set_attr "type" "multiple")]
5895f793 2277)
3a33f76f 2278
4cdb3ed4 2279(define_insn "*anddi_sesdi_di"
d5b7b3ae 2280 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
ff9940b0
RE
2281 (and:DI (sign_extend:DI
2282 (match_operand:SI 2 "s_register_operand" "r,r"))
cfc25c74 2283 (match_operand:DI 1 "s_register_operand" "0,r")))]
5b3e6663 2284 "TARGET_32BIT"
6ab589e0 2285 "#"
594726e4
JG
2286 [(set_attr "length" "8")
2287 (set_attr "type" "multiple")]
d5b7b3ae 2288)
3a33f76f 2289
091426d3 2290(define_expand "andsi3"
d5b7b3ae 2291 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
2292 (and:SI (match_operand:SI 1 "s_register_operand" "")
2293 (match_operand:SI 2 "reg_or_int_operand" "")))]
d5b7b3ae 2294 "TARGET_EITHER"
091426d3 2295 "
5b3e6663 2296 if (TARGET_32BIT)
091426d3 2297 {
d435a4be 2298 if (CONST_INT_P (operands[2]))
d5b7b3ae 2299 {
3565ffed
WG
2300 if (INTVAL (operands[2]) == 255 && arm_arch6)
2301 {
2302 operands[1] = convert_to_mode (QImode, operands[1], 1);
2303 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2304 operands[1]));
2305 }
2306 else
2307 arm_split_constant (AND, SImode, NULL_RTX,
2308 INTVAL (operands[2]), operands[0],
2309 operands[1],
2310 optimize && can_create_pseudo_p ());
d56993f2 2311
d5b7b3ae
RE
2312 DONE;
2313 }
091426d3 2314 }
5b3e6663 2315 else /* TARGET_THUMB1 */
d5b7b3ae 2316 {
d435a4be 2317 if (!CONST_INT_P (operands[2]))
582021ba
PB
2318 {
2319 rtx tmp = force_reg (SImode, operands[2]);
2320 if (rtx_equal_p (operands[0], operands[1]))
2321 operands[2] = tmp;
2322 else
2323 {
2324 operands[2] = operands[1];
2325 operands[1] = tmp;
2326 }
2327 }
d5b7b3ae
RE
2328 else
2329 {
2330 int i;
2331
5895f793 2332 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
d5b7b3ae 2333 {
5895f793
RE
2334 operands[2] = force_reg (SImode,
2335 GEN_INT (~INTVAL (operands[2])));
d5b7b3ae 2336
906668bb 2337 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
d5b7b3ae
RE
2338
2339 DONE;
2340 }
091426d3 2341
d5b7b3ae
RE
2342 for (i = 9; i <= 31; i++)
2343 {
2344 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2345 {
2346 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2347 const0_rtx));
2348 DONE;
2349 }
5895f793
RE
2350 else if ((((HOST_WIDE_INT) 1) << i) - 1
2351 == ~INTVAL (operands[2]))
d5b7b3ae
RE
2352 {
2353 rtx shift = GEN_INT (i);
2354 rtx reg = gen_reg_rtx (SImode);
2355
2356 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2357 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2358
2359 DONE;
2360 }
2361 }
2362
2363 operands[2] = force_reg (SImode, operands[2]);
2364 }
5895f793
RE
2365 }
2366 "
d5b7b3ae
RE
2367)
2368
5b3e6663 2369; ??? Check split length for Thumb-2
bb6ae783 2370(define_insn_and_split "*arm_andsi3_insn"
afc5e8a6
KT
2371 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2372 (and:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2373 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
5b3e6663 2374 "TARGET_32BIT"
68df59d3 2375 "@
afc5e8a6 2376 and%?\\t%0, %1, %2
68df59d3 2377 and%?\\t%0, %1, %2
091426d3 2378 bic%?\\t%0, %1, #%B2
148413a4 2379 and%?\\t%0, %1, %2
091426d3 2380 #"
5b3e6663 2381 "TARGET_32BIT
d435a4be 2382 && CONST_INT_P (operands[2])
bb6ae783
RE
2383 && !(const_ok_for_arm (INTVAL (operands[2]))
2384 || const_ok_for_arm (~INTVAL (operands[2])))"
2385 [(clobber (const_int 0))]
2386 "
a406f566
MM
2387 arm_split_constant (AND, SImode, curr_insn,
2388 INTVAL (operands[2]), operands[0], operands[1], 0);
bb6ae783
RE
2389 DONE;
2390 "
afc5e8a6 2391 [(set_attr "length" "4,4,4,4,16")
148413a4 2392 (set_attr "predicable" "yes")
afc5e8a6 2393 (set_attr "predicable_short_it" "no,yes,no,no,no")
6e4150e1 2394 (set_attr "type" "logic_imm,logic_imm,logic_reg,logic_reg,logic_imm")]
d5b7b3ae
RE
2395)
2396
5b3e6663 2397(define_insn "*thumb1_andsi3_insn"
d5b7b3ae
RE
2398 [(set (match_operand:SI 0 "register_operand" "=l")
2399 (and:SI (match_operand:SI 1 "register_operand" "%0")
2400 (match_operand:SI 2 "register_operand" "l")))]
5b3e6663 2401 "TARGET_THUMB1"
906668bb
BS
2402 "and\\t%0, %2"
2403 [(set_attr "length" "2")
6e4150e1 2404 (set_attr "type" "logic_imm")
906668bb 2405 (set_attr "conds" "set")])
091426d3 2406
4cdb3ed4 2407(define_insn "*andsi3_compare0"
48a08b9c 2408 [(set (reg:CC_NOOV CC_REGNUM)
68df59d3 2409 (compare:CC_NOOV
148413a4
RR
2410 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2411 (match_operand:SI 2 "arm_not_operand" "I,K,r"))
68df59d3 2412 (const_int 0)))
148413a4 2413 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
ff9940b0 2414 (and:SI (match_dup 1) (match_dup 2)))]
5b3e6663 2415 "TARGET_32BIT"
68df59d3 2416 "@
5b3e6663 2417 and%.\\t%0, %1, %2
148413a4
RR
2418 bic%.\\t%0, %1, #%B2
2419 and%.\\t%0, %1, %2"
2420 [(set_attr "conds" "set")
6e4150e1 2421 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
d5b7b3ae 2422)
ff9940b0 2423
4cdb3ed4 2424(define_insn "*andsi3_compare0_scratch"
48a08b9c 2425 [(set (reg:CC_NOOV CC_REGNUM)
68df59d3 2426 (compare:CC_NOOV
148413a4
RR
2427 (and:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
2428 (match_operand:SI 1 "arm_not_operand" "I,K,r"))
68df59d3 2429 (const_int 0)))
148413a4 2430 (clobber (match_scratch:SI 2 "=X,r,X"))]
5b3e6663 2431 "TARGET_32BIT"
68df59d3
RE
2432 "@
2433 tst%?\\t%0, %1
148413a4
RR
2434 bic%.\\t%2, %0, #%B1
2435 tst%?\\t%0, %1"
2436 [(set_attr "conds" "set")
6e4150e1 2437 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
cca0a211 2438)
ff9940b0 2439
4cdb3ed4 2440(define_insn "*zeroextractsi_compare0_scratch"
48a08b9c 2441 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
2442 (compare:CC_NOOV (zero_extract:SI
2443 (match_operand:SI 0 "s_register_operand" "r")
31dfce10 2444 (match_operand 1 "const_int_operand" "n")
0502226c 2445 (match_operand 2 "const_int_operand" "n"))
ff9940b0 2446 (const_int 0)))]
5b3e6663 2447 "TARGET_32BIT
d5b7b3ae
RE
2448 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2449 && INTVAL (operands[1]) > 0
2450 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2451 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
ff9940b0 2452 "*
d2ceebd1
RE
2453 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2454 << INTVAL (operands[2]));
c63165be 2455 output_asm_insn (\"tst%?\\t%0, %1\", operands);
0f447ef2 2456 return \"\";
cca0a211 2457 "
cc50a1e1 2458 [(set_attr "conds" "set")
148413a4 2459 (set_attr "predicable" "yes")
31dfce10 2460 (set_attr "predicable_short_it" "no")
6e4150e1 2461 (set_attr "type" "logics_imm")]
cca0a211 2462)
ff9940b0 2463
2a2789d8 2464(define_insn_and_split "*ne_zeroextractsi"
dfa08768
RE
2465 [(set (match_operand:SI 0 "s_register_operand" "=r")
2466 (ne:SI (zero_extract:SI
2467 (match_operand:SI 1 "s_register_operand" "r")
2468 (match_operand:SI 2 "const_int_operand" "n")
2469 (match_operand:SI 3 "const_int_operand" "n"))
872e50d3
RE
2470 (const_int 0)))
2471 (clobber (reg:CC CC_REGNUM))]
5b3e6663 2472 "TARGET_32BIT
d5b7b3ae
RE
2473 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2474 && INTVAL (operands[2]) > 0
2475 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2476 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2a2789d8 2477 "#"
5b3e6663 2478 "TARGET_32BIT
2a2789d8
RE
2479 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2480 && INTVAL (operands[2]) > 0
2481 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2482 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2483 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2484 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2485 (const_int 0)))
2486 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2487 (set (match_dup 0)
2488 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2489 (match_dup 0) (const_int 1)))]
2490 "
2491 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2492 << INTVAL (operands[3]));
2493 "
2494 [(set_attr "conds" "clob")
5b3e6663
PB
2495 (set (attr "length")
2496 (if_then_else (eq_attr "is_thumb" "yes")
2497 (const_int 12)
594726e4
JG
2498 (const_int 8)))
2499 (set_attr "type" "multiple")]
2a2789d8
RE
2500)
2501
2502(define_insn_and_split "*ne_zeroextractsi_shifted"
2503 [(set (match_operand:SI 0 "s_register_operand" "=r")
2504 (ne:SI (zero_extract:SI
2505 (match_operand:SI 1 "s_register_operand" "r")
2506 (match_operand:SI 2 "const_int_operand" "n")
2507 (const_int 0))
2508 (const_int 0)))
2509 (clobber (reg:CC CC_REGNUM))]
2510 "TARGET_ARM"
2511 "#"
2512 "TARGET_ARM"
2513 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2514 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2515 (const_int 0)))
2516 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2517 (set (match_dup 0)
2518 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2519 (match_dup 0) (const_int 1)))]
2520 "
2521 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2522 "
2523 [(set_attr "conds" "clob")
594726e4
JG
2524 (set_attr "length" "8")
2525 (set_attr "type" "multiple")]
2a2789d8
RE
2526)
2527
2528(define_insn_and_split "*ite_ne_zeroextractsi"
2529 [(set (match_operand:SI 0 "s_register_operand" "=r")
2530 (if_then_else:SI (ne (zero_extract:SI
2531 (match_operand:SI 1 "s_register_operand" "r")
2532 (match_operand:SI 2 "const_int_operand" "n")
2533 (match_operand:SI 3 "const_int_operand" "n"))
2534 (const_int 0))
2535 (match_operand:SI 4 "arm_not_operand" "rIK")
2536 (const_int 0)))
2537 (clobber (reg:CC CC_REGNUM))]
2538 "TARGET_ARM
2539 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2540 && INTVAL (operands[2]) > 0
2541 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
69260355
RE
2542 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2543 && !reg_overlap_mentioned_p (operands[0], operands[4])"
2a2789d8
RE
2544 "#"
2545 "TARGET_ARM
2546 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2547 && INTVAL (operands[2]) > 0
2548 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
69260355
RE
2549 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2550 && !reg_overlap_mentioned_p (operands[0], operands[4])"
2a2789d8
RE
2551 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2552 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2553 (const_int 0)))
2554 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2555 (set (match_dup 0)
2556 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2557 (match_dup 0) (match_dup 4)))]
2558 "
dfa08768 2559 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2a2789d8
RE
2560 << INTVAL (operands[3]));
2561 "
2562 [(set_attr "conds" "clob")
594726e4
JG
2563 (set_attr "length" "8")
2564 (set_attr "type" "multiple")]
2a2789d8
RE
2565)
2566
2567(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2568 [(set (match_operand:SI 0 "s_register_operand" "=r")
2569 (if_then_else:SI (ne (zero_extract:SI
2570 (match_operand:SI 1 "s_register_operand" "r")
2571 (match_operand:SI 2 "const_int_operand" "n")
2572 (const_int 0))
2573 (const_int 0))
2574 (match_operand:SI 3 "arm_not_operand" "rIK")
2575 (const_int 0)))
2576 (clobber (reg:CC CC_REGNUM))]
69260355 2577 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2a2789d8 2578 "#"
69260355 2579 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2a2789d8
RE
2580 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2581 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2582 (const_int 0)))
2583 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2584 (set (match_dup 0)
2585 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2586 (match_dup 0) (match_dup 3)))]
2587 "
2588 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
cca0a211
RE
2589 "
2590 [(set_attr "conds" "clob")
594726e4
JG
2591 (set_attr "length" "8")
2592 (set_attr "type" "multiple")]
5895f793 2593)
ff9940b0 2594
defc0463
RE
2595(define_split
2596 [(set (match_operand:SI 0 "s_register_operand" "")
2597 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2598 (match_operand:SI 2 "const_int_operand" "")
2599 (match_operand:SI 3 "const_int_operand" "")))
2600 (clobber (match_operand:SI 4 "s_register_operand" ""))]
5b3e6663 2601 "TARGET_THUMB1"
defc0463
RE
2602 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2603 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2604 "{
2605 HOST_WIDE_INT temp = INTVAL (operands[2]);
2606
2607 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2608 operands[3] = GEN_INT (32 - temp);
2609 }"
2610)
2611
5b3e6663 2612;; ??? Use Thumb-2 has bitfield insert/extract instructions.
da5cafa7
RE
2613(define_split
2614 [(set (match_operand:SI 0 "s_register_operand" "")
2615 (match_operator:SI 1 "shiftable_operator"
2616 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2617 (match_operand:SI 3 "const_int_operand" "")
2618 (match_operand:SI 4 "const_int_operand" ""))
2619 (match_operand:SI 5 "s_register_operand" "")]))
2620 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2621 "TARGET_ARM"
2622 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2623 (set (match_dup 0)
2624 (match_op_dup 1
2625 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2626 (match_dup 5)]))]
2627 "{
2628 HOST_WIDE_INT temp = INTVAL (operands[3]);
2629
2630 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2631 operands[4] = GEN_INT (32 - temp);
2632 }"
2633)
2634
defc0463
RE
2635(define_split
2636 [(set (match_operand:SI 0 "s_register_operand" "")
2637 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2638 (match_operand:SI 2 "const_int_operand" "")
2639 (match_operand:SI 3 "const_int_operand" "")))]
5b3e6663 2640 "TARGET_THUMB1"
defc0463
RE
2641 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2642 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2643 "{
2644 HOST_WIDE_INT temp = INTVAL (operands[2]);
2645
2646 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2647 operands[3] = GEN_INT (32 - temp);
2648 }"
2649)
2650
da5cafa7
RE
2651(define_split
2652 [(set (match_operand:SI 0 "s_register_operand" "")
2653 (match_operator:SI 1 "shiftable_operator"
2654 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2655 (match_operand:SI 3 "const_int_operand" "")
2656 (match_operand:SI 4 "const_int_operand" ""))
2657 (match_operand:SI 5 "s_register_operand" "")]))
2658 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2659 "TARGET_ARM"
2660 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2661 (set (match_dup 0)
2662 (match_op_dup 1
2663 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2664 (match_dup 5)]))]
2665 "{
2666 HOST_WIDE_INT temp = INTVAL (operands[3]);
2667
2668 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2669 operands[4] = GEN_INT (32 - temp);
2670 }"
2671)
2672
da959950
NC
2673;;; ??? This pattern is bogus. If operand3 has bits outside the range
2674;;; represented by the bitfield, then this will produce incorrect results.
2675;;; Somewhere, the value needs to be truncated. On targets like the m68k,
43a88a8c
KH
2676;;; which have a real bit-field insert instruction, the truncation happens
2677;;; in the bit-field insert instruction itself. Since arm does not have a
2678;;; bit-field insert instruction, we would have to emit code here to truncate
da959950
NC
2679;;; the value before we insert. This loses some of the advantage of having
2680;;; this insv pattern, so this pattern needs to be reevalutated.
2681
f54fd62e 2682(define_expand "insv"
86b60116
JB
2683 [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2684 (match_operand 1 "general_operand" "")
2685 (match_operand 2 "general_operand" ""))
2686 (match_operand 3 "reg_or_int_operand" ""))]
ef87d898 2687 "TARGET_ARM || arm_arch_thumb2"
f54fd62e 2688 "
5895f793
RE
2689 {
2690 int start_bit = INTVAL (operands[2]);
2691 int width = INTVAL (operands[1]);
2692 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2693 rtx target, subtarget;
2694
ef87d898
PB
2695 if (arm_arch_thumb2)
2696 {
86b60116
JB
2697 if (unaligned_access && MEM_P (operands[0])
2698 && s_register_operand (operands[3], GET_MODE (operands[3]))
2699 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
ef87d898 2700 {
86b60116
JB
2701 rtx base_addr;
2702
2703 if (BYTES_BIG_ENDIAN)
2704 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2705 - start_bit;
ef87d898 2706
86b60116 2707 if (width == 32)
ef87d898 2708 {
86b60116
JB
2709 base_addr = adjust_address (operands[0], SImode,
2710 start_bit / BITS_PER_UNIT);
2711 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
ef87d898 2712 }
86b60116
JB
2713 else
2714 {
2715 rtx tmp = gen_reg_rtx (HImode);
ef87d898 2716
86b60116
JB
2717 base_addr = adjust_address (operands[0], HImode,
2718 start_bit / BITS_PER_UNIT);
2719 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2720 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2721 }
2722 DONE;
ef87d898 2723 }
86b60116 2724 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
ef87d898 2725 {
86b60116 2726 bool use_bfi = TRUE;
ef87d898 2727
d435a4be 2728 if (CONST_INT_P (operands[3]))
86b60116
JB
2729 {
2730 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2731
2732 if (val == 0)
2733 {
2734 emit_insn (gen_insv_zero (operands[0], operands[1],
2735 operands[2]));
2736 DONE;
2737 }
2738
2739 /* See if the set can be done with a single orr instruction. */
2740 if (val == mask && const_ok_for_arm (val << start_bit))
2741 use_bfi = FALSE;
2742 }
2743
2744 if (use_bfi)
2745 {
d435a4be 2746 if (!REG_P (operands[3]))
86b60116
JB
2747 operands[3] = force_reg (SImode, operands[3]);
2748
2749 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2750 operands[3]));
2751 DONE;
2752 }
ef87d898 2753 }
86b60116
JB
2754 else
2755 FAIL;
ef87d898
PB
2756 }
2757
86b60116
JB
2758 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2759 FAIL;
2760
ee93c1c6 2761 target = copy_rtx (operands[0]);
5895f793
RE
2762 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2763 subreg as the final target. */
2764 if (GET_CODE (target) == SUBREG)
2765 {
2766 subtarget = gen_reg_rtx (SImode);
2767 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2768 < GET_MODE_SIZE (SImode))
2769 target = SUBREG_REG (target);
2770 }
2771 else
2772 subtarget = target;
f54fd62e 2773
d435a4be 2774 if (CONST_INT_P (operands[3]))
5895f793
RE
2775 {
2776 /* Since we are inserting a known constant, we may be able to
2777 reduce the number of bits that we have to clear so that
2778 the mask becomes simple. */
2779 /* ??? This code does not check to see if the new mask is actually
2780 simpler. It may not be. */
2781 rtx op1 = gen_reg_rtx (SImode);
2782 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2783 start of this pattern. */
2784 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2785 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2786
c2540bbb
DJ
2787 emit_insn (gen_andsi3 (op1, operands[0],
2788 gen_int_mode (~mask2, SImode)));
5895f793 2789 emit_insn (gen_iorsi3 (subtarget, op1,
b65e6318 2790 gen_int_mode (op3_value << start_bit, SImode)));
5895f793
RE
2791 }
2792 else if (start_bit == 0
2793 && !(const_ok_for_arm (mask)
2794 || const_ok_for_arm (~mask)))
2795 {
2796 /* A Trick, since we are setting the bottom bits in the word,
2797 we can shift operand[3] up, operand[0] down, OR them together
2798 and rotate the result back again. This takes 3 insns, and
093354e0 2799 the third might be mergeable into another op. */
5895f793
RE
2800 /* The shift up copes with the possibility that operand[3] is
2801 wider than the bitfield. */
2802 rtx op0 = gen_reg_rtx (SImode);
2803 rtx op1 = gen_reg_rtx (SImode);
2804
2805 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2806 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2807 emit_insn (gen_iorsi3 (op1, op1, op0));
2808 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2809 }
2810 else if ((width + start_bit == 32)
2811 && !(const_ok_for_arm (mask)
2812 || const_ok_for_arm (~mask)))
2813 {
2814 /* Similar trick, but slightly less efficient. */
f54fd62e 2815
5895f793
RE
2816 rtx op0 = gen_reg_rtx (SImode);
2817 rtx op1 = gen_reg_rtx (SImode);
f54fd62e 2818
5895f793
RE
2819 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2820 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2821 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2822 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2823 }
2824 else
2825 {
c2540bbb 2826 rtx op0 = gen_int_mode (mask, SImode);
5895f793
RE
2827 rtx op1 = gen_reg_rtx (SImode);
2828 rtx op2 = gen_reg_rtx (SImode);
f54fd62e 2829
5895f793
RE
2830 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2831 {
2832 rtx tmp = gen_reg_rtx (SImode);
f54fd62e 2833
5895f793
RE
2834 emit_insn (gen_movsi (tmp, op0));
2835 op0 = tmp;
2836 }
f54fd62e 2837
5895f793
RE
2838 /* Mask out any bits in operand[3] that are not needed. */
2839 emit_insn (gen_andsi3 (op1, operands[3], op0));
f54fd62e 2840
d435a4be 2841 if (CONST_INT_P (op0)
5895f793
RE
2842 && (const_ok_for_arm (mask << start_bit)
2843 || const_ok_for_arm (~(mask << start_bit))))
2844 {
c2540bbb 2845 op0 = gen_int_mode (~(mask << start_bit), SImode);
5895f793
RE
2846 emit_insn (gen_andsi3 (op2, operands[0], op0));
2847 }
2848 else
2849 {
d435a4be 2850 if (CONST_INT_P (op0))
5895f793
RE
2851 {
2852 rtx tmp = gen_reg_rtx (SImode);
f54fd62e 2853
5895f793
RE
2854 emit_insn (gen_movsi (tmp, op0));
2855 op0 = tmp;
2856 }
2857
2858 if (start_bit != 0)
2859 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
da959950 2860
5895f793
RE
2861 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2862 }
f54fd62e 2863
5895f793
RE
2864 if (start_bit != 0)
2865 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
f54fd62e 2866
5895f793
RE
2867 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2868 }
7a0a1f09 2869
5895f793
RE
2870 if (subtarget != target)
2871 {
2872 /* If TARGET is still a SUBREG, then it must be wider than a word,
2873 so we must be careful only to set the subword we were asked to. */
2874 if (GET_CODE (target) == SUBREG)
2875 emit_move_insn (target, subtarget);
2876 else
2877 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2878 }
f54fd62e 2879
5895f793
RE
2880 DONE;
2881 }"
2882)
f54fd62e 2883
ef87d898
PB
2884(define_insn "insv_zero"
2885 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2886 (match_operand:SI 1 "const_int_operand" "M")
2887 (match_operand:SI 2 "const_int_operand" "M"))
2888 (const_int 0))]
2889 "arm_arch_thumb2"
2890 "bfc%?\t%0, %2, %1"
2891 [(set_attr "length" "4")
31dfce10 2892 (set_attr "predicable" "yes")
6e4150e1
JG
2893 (set_attr "predicable_short_it" "no")
2894 (set_attr "type" "bfm")]
ef87d898
PB
2895)
2896
2897(define_insn "insv_t2"
2898 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2899 (match_operand:SI 1 "const_int_operand" "M")
2900 (match_operand:SI 2 "const_int_operand" "M"))
2901 (match_operand:SI 3 "s_register_operand" "r"))]
2902 "arm_arch_thumb2"
2903 "bfi%?\t%0, %3, %2, %1"
2904 [(set_attr "length" "4")
31dfce10 2905 (set_attr "predicable" "yes")
6e4150e1
JG
2906 (set_attr "predicable_short_it" "no")
2907 (set_attr "type" "bfm")]
ef87d898
PB
2908)
2909
5895f793 2910; constants for op 2 will never be given to these patterns.
bb6ae783 2911(define_insn_and_split "*anddi_notdi_di"
ff9940b0 2912 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
cfc25c74
RE
2913 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2914 (match_operand:DI 2 "s_register_operand" "r,0")))]
5b3e6663 2915 "TARGET_32BIT"
6ab589e0 2916 "#"
b3b7bbce
SL
2917 "TARGET_32BIT && reload_completed
2918 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2919 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
bb6ae783
RE
2920 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2921 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2922 "
2923 {
2924 operands[3] = gen_highpart (SImode, operands[0]);
2925 operands[0] = gen_lowpart (SImode, operands[0]);
2926 operands[4] = gen_highpart (SImode, operands[1]);
2927 operands[1] = gen_lowpart (SImode, operands[1]);
2928 operands[5] = gen_highpart (SImode, operands[2]);
2929 operands[2] = gen_lowpart (SImode, operands[2]);
2930 }"
cca0a211 2931 [(set_attr "length" "8")
594726e4
JG
2932 (set_attr "predicable" "yes")
2933 (set_attr "type" "multiple")]
cca0a211 2934)
31dfce10 2935
bb6ae783 2936(define_insn_and_split "*anddi_notzesidi_di"
ff9940b0
RE
2937 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2938 (and:DI (not:DI (zero_extend:DI
2939 (match_operand:SI 2 "s_register_operand" "r,r")))
0f447ef2 2940 (match_operand:DI 1 "s_register_operand" "0,?r")))]
5b3e6663 2941 "TARGET_32BIT"
0f447ef2 2942 "@
3dafc5c3 2943 bic%?\\t%Q0, %Q1, %2
6ab589e0 2944 #"
bb6ae783
RE
2945 ; (not (zero_extend ...)) allows us to just copy the high word from
2946 ; operand1 to operand0.
5b3e6663 2947 "TARGET_32BIT
bb6ae783
RE
2948 && reload_completed
2949 && operands[0] != operands[1]"
1dda7ee4 2950 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
bb6ae783
RE
2951 (set (match_dup 3) (match_dup 4))]
2952 "
2953 {
2954 operands[3] = gen_highpart (SImode, operands[0]);
2955 operands[0] = gen_lowpart (SImode, operands[0]);
2956 operands[4] = gen_highpart (SImode, operands[1]);
2957 operands[1] = gen_lowpart (SImode, operands[1]);
2958 }"
cca0a211 2959 [(set_attr "length" "4,8")
31dfce10 2960 (set_attr "predicable" "yes")
594726e4
JG
2961 (set_attr "predicable_short_it" "no")
2962 (set_attr "type" "multiple")]
cca0a211 2963)
31dfce10 2964
bb6ae783 2965(define_insn_and_split "*anddi_notsesidi_di"
ff9940b0
RE
2966 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2967 (and:DI (not:DI (sign_extend:DI
2968 (match_operand:SI 2 "s_register_operand" "r,r")))
1dda7ee4 2969 (match_operand:DI 1 "s_register_operand" "0,r")))]
5b3e6663 2970 "TARGET_32BIT"
6ab589e0 2971 "#"
5b3e6663 2972 "TARGET_32BIT && reload_completed"
1dda7ee4 2973 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
bb6ae783
RE
2974 (set (match_dup 3) (and:SI (not:SI
2975 (ashiftrt:SI (match_dup 2) (const_int 31)))
2976 (match_dup 4)))]
2977 "
2978 {
2979 operands[3] = gen_highpart (SImode, operands[0]);
2980 operands[0] = gen_lowpart (SImode, operands[0]);
2981 operands[4] = gen_highpart (SImode, operands[1]);
2982 operands[1] = gen_lowpart (SImode, operands[1]);
2983 }"
cca0a211 2984 [(set_attr "length" "8")
31dfce10 2985 (set_attr "predicable" "yes")
594726e4
JG
2986 (set_attr "predicable_short_it" "no")
2987 (set_attr "type" "multiple")]
cca0a211 2988)
31dfce10 2989
f54fd62e 2990(define_insn "andsi_notsi_si"
ff9940b0
RE
2991 [(set (match_operand:SI 0 "s_register_operand" "=r")
2992 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2993 (match_operand:SI 1 "s_register_operand" "r")))]
5b3e6663 2994 "TARGET_32BIT"
cca0a211 2995 "bic%?\\t%0, %1, %2"
31dfce10 2996 [(set_attr "predicable" "yes")
594726e4
JG
2997 (set_attr "predicable_short_it" "no")
2998 (set_attr "type" "logic_reg")]
cca0a211 2999)
3a33f76f 3000
906668bb 3001(define_insn "thumb1_bicsi3"
d5b7b3ae
RE
3002 [(set (match_operand:SI 0 "register_operand" "=l")
3003 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
3004 (match_operand:SI 2 "register_operand" "0")))]
5b3e6663 3005 "TARGET_THUMB1"
906668bb
BS
3006 "bic\\t%0, %1"
3007 [(set_attr "length" "2")
594726e4
JG
3008 (set_attr "conds" "set")
3009 (set_attr "type" "logics_reg")]
3010)
d5b7b3ae 3011
f54fd62e 3012(define_insn "andsi_not_shiftsi_si"
9b66ebb1
PB
3013 [(set (match_operand:SI 0 "s_register_operand" "=r")
3014 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
3015 [(match_operand:SI 2 "s_register_operand" "r")
3016 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
3017 (match_operand:SI 1 "s_register_operand" "r")))]
d5b7b3ae 3018 "TARGET_ARM"
b020fd92 3019 "bic%?\\t%0, %1, %2%S4"
ca68ea18 3020 [(set_attr "predicable" "yes")
d19fb8e3 3021 (set_attr "shift" "2")
9b66ebb1 3022 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6e4150e1
JG
3023 (const_string "logic_shift_imm")
3024 (const_string "logic_shift_reg")))]
b020fd92 3025)
f54fd62e 3026
4cdb3ed4 3027(define_insn "*andsi_notsi_si_compare0"
48a08b9c 3028 [(set (reg:CC_NOOV CC_REGNUM)
0f447ef2
RE
3029 (compare:CC_NOOV
3030 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3031 (match_operand:SI 1 "s_register_operand" "r"))
3032 (const_int 0)))
ff9940b0
RE
3033 (set (match_operand:SI 0 "s_register_operand" "=r")
3034 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
5b3e6663
PB
3035 "TARGET_32BIT"
3036 "bic%.\\t%0, %1, %2"
6e4150e1
JG
3037 [(set_attr "conds" "set")
3038 (set_attr "type" "logics_shift_reg")]
cca0a211 3039)
ff9940b0 3040
4cdb3ed4 3041(define_insn "*andsi_notsi_si_compare0_scratch"
48a08b9c 3042 [(set (reg:CC_NOOV CC_REGNUM)
0f447ef2
RE
3043 (compare:CC_NOOV
3044 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3045 (match_operand:SI 1 "s_register_operand" "r"))
3046 (const_int 0)))
ff9940b0 3047 (clobber (match_scratch:SI 0 "=r"))]
5b3e6663
PB
3048 "TARGET_32BIT"
3049 "bic%.\\t%0, %1, %2"
6e4150e1
JG
3050 [(set_attr "conds" "set")
3051 (set_attr "type" "logics_shift_reg")]
cca0a211 3052)
ff9940b0 3053
b3b7bbce
SL
3054(define_expand "iordi3"
3055 [(set (match_operand:DI 0 "s_register_operand" "")
3056 (ior:DI (match_operand:DI 1 "s_register_operand" "")
3057 (match_operand:DI 2 "neon_logic_op2" "")))]
3058 "TARGET_32BIT"
3059 ""
3060)
3061
b6af05a9
KT
3062(define_insn_and_split "*iordi3_insn"
3063 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
3064 (ior:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
33e49835 3065 (match_operand:DI 2 "arm_iordi_operand_neon" "w ,Dl,r ,r ,Df,Df,w ,Dl")))]
b6af05a9
KT
3066 "TARGET_32BIT && !TARGET_IWMMXT"
3067 {
3068 switch (which_alternative)
3069 {
3070 case 0: /* fall through */
3071 case 6: return "vorr\t%P0, %P1, %P2";
3072 case 1: /* fall through */
3073 case 7: return neon_output_logic_immediate ("vorr", &operands[2],
3074 DImode, 0, VALID_NEON_QREG_MODE (DImode));
3075 case 2:
3076 case 3:
3077 case 4:
3078 case 5:
3079 return "#";
3080 default: gcc_unreachable ();
3081 }
3082 }
3083 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3084 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3085 [(set (match_dup 3) (match_dup 4))
3086 (set (match_dup 5) (match_dup 6))]
3087 "
3088 {
3089 operands[3] = gen_lowpart (SImode, operands[0]);
3090 operands[5] = gen_highpart (SImode, operands[0]);
3091
3092 operands[4] = simplify_gen_binary (IOR, SImode,
3093 gen_lowpart (SImode, operands[1]),
3094 gen_lowpart (SImode, operands[2]));
3095 operands[6] = simplify_gen_binary (IOR, SImode,
3096 gen_highpart (SImode, operands[1]),
3097 gen_highpart_mode (SImode, DImode, operands[2]));
3098
3099 }"
f7379e5e
JG
3100 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,multiple,\
3101 multiple,neon_logic,neon_logic")
33e49835 3102 (set_attr "length" "*,*,8,8,8,8,*,*")
b6af05a9 3103 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")]
d5b7b3ae 3104)
ff9940b0 3105
4cdb3ed4 3106(define_insn "*iordi_zesidi_di"
ff9940b0
RE
3107 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3108 (ior:DI (zero_extend:DI
3109 (match_operand:SI 2 "s_register_operand" "r,r"))
0f447ef2 3110 (match_operand:DI 1 "s_register_operand" "0,?r")))]
5b3e6663 3111 "TARGET_32BIT"
0f447ef2 3112 "@
3dafc5c3 3113 orr%?\\t%Q0, %Q1, %2
6ab589e0 3114 #"
cca0a211 3115 [(set_attr "length" "4,8")
31dfce10 3116 (set_attr "predicable" "yes")
594726e4
JG
3117 (set_attr "predicable_short_it" "no")
3118 (set_attr "type" "logic_reg,multiple")]
d5b7b3ae 3119)
ff9940b0 3120
4cdb3ed4 3121(define_insn "*iordi_sesidi_di"
ff9940b0
RE
3122 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3123 (ior:DI (sign_extend:DI
3124 (match_operand:SI 2 "s_register_operand" "r,r"))
cfc25c74 3125 (match_operand:DI 1 "s_register_operand" "0,r")))]
5b3e6663 3126 "TARGET_32BIT"
6ab589e0 3127 "#"
cca0a211 3128 [(set_attr "length" "8")
594726e4
JG
3129 (set_attr "predicable" "yes")
3130 (set_attr "type" "multiple")]
d5b7b3ae 3131)
ff9940b0 3132
091426d3 3133(define_expand "iorsi3"
d5b7b3ae 3134 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
3135 (ior:SI (match_operand:SI 1 "s_register_operand" "")
3136 (match_operand:SI 2 "reg_or_int_operand" "")))]
d5b7b3ae 3137 "TARGET_EITHER"
091426d3 3138 "
d435a4be 3139 if (CONST_INT_P (operands[2]))
091426d3 3140 {
5b3e6663 3141 if (TARGET_32BIT)
d5b7b3ae 3142 {
a406f566
MM
3143 arm_split_constant (IOR, SImode, NULL_RTX,
3144 INTVAL (operands[2]), operands[0], operands[1],
b3a13419 3145 optimize && can_create_pseudo_p ());
d5b7b3ae
RE
3146 DONE;
3147 }
5b3e6663 3148 else /* TARGET_THUMB1 */
582021ba
PB
3149 {
3150 rtx tmp = force_reg (SImode, operands[2]);
3151 if (rtx_equal_p (operands[0], operands[1]))
3152 operands[2] = tmp;
3153 else
3154 {
3155 operands[2] = operands[1];
3156 operands[1] = tmp;
3157 }
3158 }
091426d3 3159 }
d5b7b3ae
RE
3160 "
3161)
091426d3 3162
c29e2982 3163(define_insn_and_split "*iorsi3_insn"
afc5e8a6
KT
3164 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
3165 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
3166 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
c29e2982 3167 "TARGET_32BIT"
091426d3 3168 "@
afc5e8a6 3169 orr%?\\t%0, %1, %2
091426d3 3170 orr%?\\t%0, %1, %2
c29e2982 3171 orn%?\\t%0, %1, #%B2
148413a4 3172 orr%?\\t%0, %1, %2
091426d3 3173 #"
c29e2982 3174 "TARGET_32BIT
d435a4be 3175 && CONST_INT_P (operands[2])
c29e2982
BS
3176 && !(const_ok_for_arm (INTVAL (operands[2]))
3177 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
bb6ae783 3178 [(clobber (const_int 0))]
c29e2982 3179{
afc5e8a6 3180 arm_split_constant (IOR, SImode, curr_insn,
a406f566 3181 INTVAL (operands[2]), operands[0], operands[1], 0);
bb6ae783 3182 DONE;
c29e2982 3183}
afc5e8a6
KT
3184 [(set_attr "length" "4,4,4,4,16")
3185 (set_attr "arch" "32,t2,t2,32,32")
148413a4 3186 (set_attr "predicable" "yes")
afc5e8a6 3187 (set_attr "predicable_short_it" "no,yes,no,no,no")
6e4150e1 3188 (set_attr "type" "logic_imm,logic_reg,logic_imm,logic_reg,logic_reg")]
148413a4 3189)
d5b7b3ae 3190
906668bb 3191(define_insn "*thumb1_iorsi3_insn"
d5b7b3ae
RE
3192 [(set (match_operand:SI 0 "register_operand" "=l")
3193 (ior:SI (match_operand:SI 1 "register_operand" "%0")
3194 (match_operand:SI 2 "register_operand" "l")))]
5b3e6663 3195 "TARGET_THUMB1"
906668bb
BS
3196 "orr\\t%0, %2"
3197 [(set_attr "length" "2")
594726e4
JG
3198 (set_attr "conds" "set")
3199 (set_attr "type" "logics_reg")])
ff9940b0 3200
bb6ae783
RE
3201(define_peephole2
3202 [(match_scratch:SI 3 "r")
3053b100
RE
3203 (set (match_operand:SI 0 "arm_general_register_operand" "")
3204 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
091426d3 3205 (match_operand:SI 2 "const_int_operand" "")))]
a7994a57 3206 "TARGET_ARM
bb6ae783
RE
3207 && !const_ok_for_arm (INTVAL (operands[2]))
3208 && const_ok_for_arm (~INTVAL (operands[2]))"
3209 [(set (match_dup 3) (match_dup 2))
3210 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
3211 ""
5895f793 3212)
bb6ae783 3213
4cdb3ed4 3214(define_insn "*iorsi3_compare0"
48a08b9c 3215 [(set (reg:CC_NOOV CC_REGNUM)
148413a4
RR
3216 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3217 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
ff9940b0 3218 (const_int 0)))
148413a4 3219 (set (match_operand:SI 0 "s_register_operand" "=r,r")
ff9940b0 3220 (ior:SI (match_dup 1) (match_dup 2)))]
5b3e6663
PB
3221 "TARGET_32BIT"
3222 "orr%.\\t%0, %1, %2"
148413a4 3223 [(set_attr "conds" "set")
6e4150e1 3224 (set_attr "type" "logics_imm,logics_reg")]
d5b7b3ae 3225)
ff9940b0 3226
4cdb3ed4 3227(define_insn "*iorsi3_compare0_scratch"
48a08b9c 3228 [(set (reg:CC_NOOV CC_REGNUM)
148413a4
RR
3229 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3230 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
ff9940b0 3231 (const_int 0)))
148413a4 3232 (clobber (match_scratch:SI 0 "=r,r"))]
5b3e6663
PB
3233 "TARGET_32BIT"
3234 "orr%.\\t%0, %1, %2"
148413a4 3235 [(set_attr "conds" "set")
6e4150e1 3236 (set_attr "type" "logics_imm,logics_reg")]
cca0a211 3237)
ff9940b0 3238
b3b7bbce
SL
3239(define_expand "xordi3"
3240 [(set (match_operand:DI 0 "s_register_operand" "")
3241 (xor:DI (match_operand:DI 1 "s_register_operand" "")
79678d04 3242 (match_operand:DI 2 "arm_xordi_operand" "")))]
b3b7bbce
SL
3243 "TARGET_32BIT"
3244 ""
3245)
3246
79678d04
KT
3247(define_insn_and_split "*xordi3_insn"
3248 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,&r,&r,?w")
3249 (xor:DI (match_operand:DI 1 "s_register_operand" "w ,%0,r ,0 ,r ,w")
3250 (match_operand:DI 2 "arm_xordi_operand" "w ,r ,r ,Dg,Dg,w")))]
3251 "TARGET_32BIT && !TARGET_IWMMXT"
3252{
3253 switch (which_alternative)
3254 {
3255 case 1:
3256 case 2:
3257 case 3:
3258 case 4: /* fall through */
3259 return "#";
3260 case 0: /* fall through */
3261 case 5: return "veor\t%P0, %P1, %P2";
3262 default: gcc_unreachable ();
3263 }
3264}
3265 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3266 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3267 [(set (match_dup 3) (match_dup 4))
3268 (set (match_dup 5) (match_dup 6))]
3269 "
3270 {
3271 operands[3] = gen_lowpart (SImode, operands[0]);
3272 operands[5] = gen_highpart (SImode, operands[0]);
3273
3274 operands[4] = simplify_gen_binary (XOR, SImode,
3275 gen_lowpart (SImode, operands[1]),
3276 gen_lowpart (SImode, operands[2]));
3277 operands[6] = simplify_gen_binary (XOR, SImode,
3278 gen_highpart (SImode, operands[1]),
3279 gen_highpart_mode (SImode, DImode, operands[2]));
3280
3281 }"
3282 [(set_attr "length" "*,8,8,8,8,*")
f7379e5e 3283 (set_attr "type" "neon_logic,multiple,multiple,multiple,multiple,neon_logic")
79678d04 3284 (set_attr "arch" "neon_for_64bits,*,*,*,*,avoid_neon_for_64bits")]
d5b7b3ae 3285)
ff9940b0 3286
4cdb3ed4 3287(define_insn "*xordi_zesidi_di"
ff9940b0
RE
3288 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3289 (xor:DI (zero_extend:DI
3290 (match_operand:SI 2 "s_register_operand" "r,r"))
0f447ef2 3291 (match_operand:DI 1 "s_register_operand" "0,?r")))]
5b3e6663 3292 "TARGET_32BIT"
0f447ef2 3293 "@
3dafc5c3 3294 eor%?\\t%Q0, %Q1, %2
6ab589e0 3295 #"
cca0a211 3296 [(set_attr "length" "4,8")
31dfce10 3297 (set_attr "predicable" "yes")
594726e4
JG
3298 (set_attr "predicable_short_it" "no")
3299 (set_attr "type" "logic_reg")]
d5b7b3ae 3300)
ff9940b0 3301
4cdb3ed4 3302(define_insn "*xordi_sesidi_di"
ff9940b0
RE
3303 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3304 (xor:DI (sign_extend:DI
3305 (match_operand:SI 2 "s_register_operand" "r,r"))
cfc25c74 3306 (match_operand:DI 1 "s_register_operand" "0,r")))]
5b3e6663 3307 "TARGET_32BIT"
6ab589e0 3308 "#"
cca0a211 3309 [(set_attr "length" "8")
594726e4
JG
3310 (set_attr "predicable" "yes")
3311 (set_attr "type" "multiple")]
d5b7b3ae 3312)
ff9940b0 3313
d5b7b3ae
RE
3314(define_expand "xorsi3"
3315 [(set (match_operand:SI 0 "s_register_operand" "")
3316 (xor:SI (match_operand:SI 1 "s_register_operand" "")
582021ba 3317 (match_operand:SI 2 "reg_or_int_operand" "")))]
d5b7b3ae 3318 "TARGET_EITHER"
d435a4be 3319 "if (CONST_INT_P (operands[2]))
582021ba
PB
3320 {
3321 if (TARGET_32BIT)
3322 {
3323 arm_split_constant (XOR, SImode, NULL_RTX,
3324 INTVAL (operands[2]), operands[0], operands[1],
3325 optimize && can_create_pseudo_p ());
3326 DONE;
3327 }
3328 else /* TARGET_THUMB1 */
3329 {
3330 rtx tmp = force_reg (SImode, operands[2]);
3331 if (rtx_equal_p (operands[0], operands[1]))
3332 operands[2] = tmp;
3333 else
3334 {
3335 operands[2] = operands[1];
3336 operands[1] = tmp;
3337 }
3338 }
3339 }"
d5b7b3ae
RE
3340)
3341
96e69fe2 3342(define_insn_and_split "*arm_xorsi3"
afc5e8a6
KT
3343 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r")
3344 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r")
3345 (match_operand:SI 2 "reg_or_int_operand" "I,l,r,?n")))]
5b3e6663 3346 "TARGET_32BIT"
96e69fe2 3347 "@
afc5e8a6 3348 eor%?\\t%0, %1, %2
148413a4 3349 eor%?\\t%0, %1, %2
96e69fe2
RH
3350 eor%?\\t%0, %1, %2
3351 #"
3352 "TARGET_32BIT
d435a4be 3353 && CONST_INT_P (operands[2])
96e69fe2
RH
3354 && !const_ok_for_arm (INTVAL (operands[2]))"
3355 [(clobber (const_int 0))]
3356{
3357 arm_split_constant (XOR, SImode, curr_insn,
3358 INTVAL (operands[2]), operands[0], operands[1], 0);
3359 DONE;
3360}
afc5e8a6 3361 [(set_attr "length" "4,4,4,16")
148413a4 3362 (set_attr "predicable" "yes")
afc5e8a6 3363 (set_attr "predicable_short_it" "no,yes,no,no")
594726e4 3364 (set_attr "type" "logic_imm,logic_reg,logic_reg,multiple")]
d5b7b3ae
RE
3365)
3366
906668bb 3367(define_insn "*thumb1_xorsi3_insn"
d5b7b3ae
RE
3368 [(set (match_operand:SI 0 "register_operand" "=l")
3369 (xor:SI (match_operand:SI 1 "register_operand" "%0")
3370 (match_operand:SI 2 "register_operand" "l")))]
5b3e6663 3371 "TARGET_THUMB1"
906668bb
BS
3372 "eor\\t%0, %2"
3373 [(set_attr "length" "2")
148413a4 3374 (set_attr "conds" "set")
6e4150e1 3375 (set_attr "type" "logics_reg")]
148413a4 3376)
ff9940b0 3377
4cdb3ed4 3378(define_insn "*xorsi3_compare0"
48a08b9c 3379 [(set (reg:CC_NOOV CC_REGNUM)
148413a4
RR
3380 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r,r")
3381 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
ff9940b0 3382 (const_int 0)))
148413a4 3383 (set (match_operand:SI 0 "s_register_operand" "=r,r")
ff9940b0 3384 (xor:SI (match_dup 1) (match_dup 2)))]
5b3e6663
PB
3385 "TARGET_32BIT"
3386 "eor%.\\t%0, %1, %2"
148413a4 3387 [(set_attr "conds" "set")
6e4150e1 3388 (set_attr "type" "logics_imm,logics_reg")]
cca0a211 3389)
ff9940b0 3390
4cdb3ed4 3391(define_insn "*xorsi3_compare0_scratch"
48a08b9c 3392 [(set (reg:CC_NOOV CC_REGNUM)
148413a4
RR
3393 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r,r")
3394 (match_operand:SI 1 "arm_rhs_operand" "I,r"))
ff9940b0 3395 (const_int 0)))]
5b3e6663 3396 "TARGET_32BIT"
c63165be 3397 "teq%?\\t%0, %1"
148413a4 3398 [(set_attr "conds" "set")
6e4150e1 3399 (set_attr "type" "logics_imm,logics_reg")]
d5b7b3ae 3400)
ff9940b0 3401
5895f793
RE
3402; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3403; (NOT D) we can sometimes merge the final NOT into one of the following
3404; insns.
ff9940b0
RE
3405
3406(define_split
12249385
RE
3407 [(set (match_operand:SI 0 "s_register_operand" "")
3408 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3409 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3410 (match_operand:SI 3 "arm_rhs_operand" "")))
3411 (clobber (match_operand:SI 4 "s_register_operand" ""))]
5b3e6663 3412 "TARGET_32BIT"
ff9940b0
RE
3413 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3414 (not:SI (match_dup 3))))
3415 (set (match_dup 0) (not:SI (match_dup 4)))]
3416 ""
3417)
3418
3f3bf1a8 3419(define_insn_and_split "*andsi_iorsi3_notsi"
ff9940b0 3420 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
cfc25c74 3421 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
ff9940b0
RE
3422 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3423 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
5b3e6663 3424 "TARGET_32BIT"
3f3bf1a8
GY
3425 "#" ; "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3426 "&& reload_completed"
3427 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
3428 (set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 0)))]
3429 ""
cca0a211 3430 [(set_attr "length" "8")
5b3e6663 3431 (set_attr "ce_count" "2")
31dfce10 3432 (set_attr "predicable" "yes")
594726e4
JG
3433 (set_attr "predicable_short_it" "no")
3434 (set_attr "type" "multiple")]
d5b7b3ae 3435)
ff9940b0 3436
5b3e6663
PB
3437; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3438; insns are available?
da5cafa7
RE
3439(define_split
3440 [(set (match_operand:SI 0 "s_register_operand" "")
3441 (match_operator:SI 1 "logical_binary_operator"
3442 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3443 (match_operand:SI 3 "const_int_operand" "")
3444 (match_operand:SI 4 "const_int_operand" ""))
3445 (match_operator:SI 9 "logical_binary_operator"
3446 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3447 (match_operand:SI 6 "const_int_operand" ""))
3448 (match_operand:SI 7 "s_register_operand" "")])]))
3449 (clobber (match_operand:SI 8 "s_register_operand" ""))]
5b3e6663 3450 "TARGET_32BIT
da5cafa7
RE
3451 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3452 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3453 [(set (match_dup 8)
3454 (match_op_dup 1
3455 [(ashift:SI (match_dup 2) (match_dup 4))
3456 (match_dup 5)]))
3457 (set (match_dup 0)
3458 (match_op_dup 1
3459 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3460 (match_dup 7)]))]
3461 "
3462 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3463")
3464
3465(define_split
3466 [(set (match_operand:SI 0 "s_register_operand" "")
3467 (match_operator:SI 1 "logical_binary_operator"
3468 [(match_operator:SI 9 "logical_binary_operator"
3469 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3470 (match_operand:SI 6 "const_int_operand" ""))
3471 (match_operand:SI 7 "s_register_operand" "")])
3472 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3473 (match_operand:SI 3 "const_int_operand" "")
3474 (match_operand:SI 4 "const_int_operand" ""))]))
3475 (clobber (match_operand:SI 8 "s_register_operand" ""))]
5b3e6663 3476 "TARGET_32BIT
da5cafa7
RE
3477 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3478 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3479 [(set (match_dup 8)
3480 (match_op_dup 1
3481 [(ashift:SI (match_dup 2) (match_dup 4))
3482 (match_dup 5)]))
3483 (set (match_dup 0)
3484 (match_op_dup 1
3485 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3486 (match_dup 7)]))]
3487 "
3488 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3489")
3490
3491(define_split
3492 [(set (match_operand:SI 0 "s_register_operand" "")
3493 (match_operator:SI 1 "logical_binary_operator"
3494 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3495 (match_operand:SI 3 "const_int_operand" "")
3496 (match_operand:SI 4 "const_int_operand" ""))
3497 (match_operator:SI 9 "logical_binary_operator"
3498 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3499 (match_operand:SI 6 "const_int_operand" ""))
3500 (match_operand:SI 7 "s_register_operand" "")])]))
3501 (clobber (match_operand:SI 8 "s_register_operand" ""))]
5b3e6663 3502 "TARGET_32BIT
da5cafa7
RE
3503 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3504 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3505 [(set (match_dup 8)
3506 (match_op_dup 1
3507 [(ashift:SI (match_dup 2) (match_dup 4))
3508 (match_dup 5)]))
3509 (set (match_dup 0)
3510 (match_op_dup 1
3511 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3512 (match_dup 7)]))]
3513 "
3514 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3515")
3516
3517(define_split
3518 [(set (match_operand:SI 0 "s_register_operand" "")
3519 (match_operator:SI 1 "logical_binary_operator"
3520 [(match_operator:SI 9 "logical_binary_operator"
3521 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3522 (match_operand:SI 6 "const_int_operand" ""))
3523 (match_operand:SI 7 "s_register_operand" "")])
3524 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3525 (match_operand:SI 3 "const_int_operand" "")
3526 (match_operand:SI 4 "const_int_operand" ""))]))
3527 (clobber (match_operand:SI 8 "s_register_operand" ""))]
5b3e6663 3528 "TARGET_32BIT
da5cafa7
RE
3529 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3530 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3531 [(set (match_dup 8)
3532 (match_op_dup 1
3533 [(ashift:SI (match_dup 2) (match_dup 4))
3534 (match_dup 5)]))
3535 (set (match_dup 0)
3536 (match_op_dup 1
3537 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3538 (match_dup 7)]))]
3539 "
3540 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3541")
ff9940b0
RE
3542\f
3543
3544;; Minimum and maximum insns
3545
0a484e3e
RE
3546(define_expand "smaxsi3"
3547 [(parallel [
3548 (set (match_operand:SI 0 "s_register_operand" "")
3549 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3550 (match_operand:SI 2 "arm_rhs_operand" "")))
3551 (clobber (reg:CC CC_REGNUM))])]
5b3e6663 3552 "TARGET_32BIT"
0a484e3e 3553 "
0cb381f0 3554 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
0a484e3e
RE
3555 {
3556 /* No need for a clobber of the condition code register here. */
3557 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3558 gen_rtx_SMAX (SImode, operands[1],
3559 operands[2])));
3560 DONE;
3561 }
3562")
3563
3564(define_insn "*smax_0"
3565 [(set (match_operand:SI 0 "s_register_operand" "=r")
3566 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3567 (const_int 0)))]
5b3e6663 3568 "TARGET_32BIT"
0a484e3e 3569 "bic%?\\t%0, %1, %1, asr #31"
31dfce10 3570 [(set_attr "predicable" "yes")
594726e4
JG
3571 (set_attr "predicable_short_it" "no")
3572 (set_attr "type" "logic_shift_reg")]
0a484e3e
RE
3573)
3574
0cb381f0
NP
3575(define_insn "*smax_m1"
3576 [(set (match_operand:SI 0 "s_register_operand" "=r")
3577 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3578 (const_int -1)))]
5b3e6663 3579 "TARGET_32BIT"
0cb381f0 3580 "orr%?\\t%0, %1, %1, asr #31"
31dfce10 3581 [(set_attr "predicable" "yes")
594726e4
JG
3582 (set_attr "predicable_short_it" "no")
3583 (set_attr "type" "logic_shift_reg")]
0cb381f0
NP
3584)
3585
75fe1cb5 3586(define_insn_and_split "*arm_smax_insn"
0a484e3e
RE
3587 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3588 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3589 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
48a08b9c 3590 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 3591 "TARGET_ARM"
75fe1cb5
GY
3592 "#"
3593 ; cmp\\t%1, %2\;movlt\\t%0, %2
3594 ; cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3595 "TARGET_ARM"
3596 [(set (reg:CC CC_REGNUM)
3597 (compare:CC (match_dup 1) (match_dup 2)))
3598 (set (match_dup 0)
3599 (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
3600 (match_dup 1)
3601 (match_dup 2)))]
3602 ""
d5b7b3ae 3603 [(set_attr "conds" "clob")
594726e4
JG
3604 (set_attr "length" "8,12")
3605 (set_attr "type" "multiple")]
d5b7b3ae 3606)
ff9940b0 3607
0a484e3e
RE
3608(define_expand "sminsi3"
3609 [(parallel [
3610 (set (match_operand:SI 0 "s_register_operand" "")
3611 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3612 (match_operand:SI 2 "arm_rhs_operand" "")))
3613 (clobber (reg:CC CC_REGNUM))])]
5b3e6663 3614 "TARGET_32BIT"
0a484e3e
RE
3615 "
3616 if (operands[2] == const0_rtx)
3617 {
3618 /* No need for a clobber of the condition code register here. */
3619 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3620 gen_rtx_SMIN (SImode, operands[1],
3621 operands[2])));
3622 DONE;
3623 }
3624")
3625
3626(define_insn "*smin_0"
3627 [(set (match_operand:SI 0 "s_register_operand" "=r")
3628 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3629 (const_int 0)))]
5b3e6663 3630 "TARGET_32BIT"
0a484e3e 3631 "and%?\\t%0, %1, %1, asr #31"
31dfce10 3632 [(set_attr "predicable" "yes")
594726e4
JG
3633 (set_attr "predicable_short_it" "no")
3634 (set_attr "type" "logic_shift_reg")]
0a484e3e
RE
3635)
3636
75fe1cb5 3637(define_insn_and_split "*arm_smin_insn"
0a484e3e
RE
3638 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3639 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3640 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
48a08b9c 3641 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 3642 "TARGET_ARM"
75fe1cb5
GY
3643 "#"
3644 ; cmp\\t%1, %2\;movge\\t%0, %2
3645 ; cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3646 "TARGET_ARM"
3647 [(set (reg:CC CC_REGNUM)
3648 (compare:CC (match_dup 1) (match_dup 2)))
3649 (set (match_dup 0)
3650 (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
3651 (match_dup 1)
3652 (match_dup 2)))]
3653 ""
cca0a211 3654 [(set_attr "conds" "clob")
594726e4
JG
3655 (set_attr "length" "8,12")
3656 (set_attr "type" "multiple,multiple")]
cca0a211 3657)
ff9940b0 3658
5b3e6663
PB
3659(define_expand "umaxsi3"
3660 [(parallel [
3661 (set (match_operand:SI 0 "s_register_operand" "")
3662 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3663 (match_operand:SI 2 "arm_rhs_operand" "")))
3664 (clobber (reg:CC CC_REGNUM))])]
3665 "TARGET_32BIT"
3666 ""
3667)
3668
75fe1cb5 3669(define_insn_and_split "*arm_umaxsi3"
ff9940b0
RE
3670 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3671 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3672 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
48a08b9c 3673 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 3674 "TARGET_ARM"
75fe1cb5
GY
3675 "#"
3676 ; cmp\\t%1, %2\;movcc\\t%0, %2
3677 ; cmp\\t%1, %2\;movcs\\t%0, %1
3678 ; cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3679 "TARGET_ARM"
3680 [(set (reg:CC CC_REGNUM)
3681 (compare:CC (match_dup 1) (match_dup 2)))
3682 (set (match_dup 0)
3683 (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
3684 (match_dup 1)
3685 (match_dup 2)))]
3686 ""
cca0a211 3687 [(set_attr "conds" "clob")
594726e4
JG
3688 (set_attr "length" "8,8,12")
3689 (set_attr "type" "store1")]
cca0a211 3690)
ff9940b0 3691
5b3e6663
PB
3692(define_expand "uminsi3"
3693 [(parallel [
3694 (set (match_operand:SI 0 "s_register_operand" "")
3695 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3696 (match_operand:SI 2 "arm_rhs_operand" "")))
3697 (clobber (reg:CC CC_REGNUM))])]
3698 "TARGET_32BIT"
3699 ""
3700)
3701
75fe1cb5 3702(define_insn_and_split "*arm_uminsi3"
ff9940b0
RE
3703 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3704 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3705 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
48a08b9c 3706 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 3707 "TARGET_ARM"
75fe1cb5
GY
3708 "#"
3709 ; cmp\\t%1, %2\;movcs\\t%0, %2
3710 ; cmp\\t%1, %2\;movcc\\t%0, %1
3711 ; cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3712 "TARGET_ARM"
3713 [(set (reg:CC CC_REGNUM)
3714 (compare:CC (match_dup 1) (match_dup 2)))
3715 (set (match_dup 0)
3716 (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
3717 (match_dup 1)
3718 (match_dup 2)))]
3719 ""
cca0a211 3720 [(set_attr "conds" "clob")
594726e4
JG
3721 (set_attr "length" "8,8,12")
3722 (set_attr "type" "store1")]
cca0a211 3723)
ff9940b0 3724
f54fd62e 3725(define_insn "*store_minmaxsi"
ff9940b0
RE
3726 [(set (match_operand:SI 0 "memory_operand" "=m")
3727 (match_operator:SI 3 "minmax_operator"
3728 [(match_operand:SI 1 "s_register_operand" "r")
3729 (match_operand:SI 2 "s_register_operand" "r")]))
48a08b9c 3730 (clobber (reg:CC CC_REGNUM))]
b2ddad83 3731 "TARGET_32BIT && optimize_function_for_size_p (cfun)"
ff9940b0 3732 "*
0f4c242b
KH
3733 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3734 operands[1], operands[2]);
0f447ef2 3735 output_asm_insn (\"cmp\\t%1, %2\", operands);
5b3e6663
PB
3736 if (TARGET_THUMB2)
3737 output_asm_insn (\"ite\t%d3\", operands);
0f447ef2
RE
3738 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3739 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3740 return \"\";
cca0a211
RE
3741 "
3742 [(set_attr "conds" "clob")
5b3e6663
PB
3743 (set (attr "length")
3744 (if_then_else (eq_attr "is_thumb" "yes")
3745 (const_int 14)
3746 (const_int 12)))
cca0a211
RE
3747 (set_attr "type" "store1")]
3748)
ff9940b0 3749
f54fd62e
RE
3750; Reject the frame pointer in operand[1], since reloading this after
3751; it has been eliminated can cause carnage.
4cdb3ed4 3752(define_insn "*minmax_arithsi"
ff9940b0
RE
3753 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3754 (match_operator:SI 4 "shiftable_operator"
3755 [(match_operator:SI 5 "minmax_operator"
3756 [(match_operand:SI 2 "s_register_operand" "r,r")
3757 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3758 (match_operand:SI 1 "s_register_operand" "0,?r")]))
48a08b9c 3759 (clobber (reg:CC CC_REGNUM))]
5e5f7673 3760 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && !arm_restrict_it"
ff9940b0 3761 "*
cca0a211
RE
3762 {
3763 enum rtx_code code = GET_CODE (operands[4]);
5b3e6663
PB
3764 bool need_else;
3765
3766 if (which_alternative != 0 || operands[3] != const0_rtx
100ed614 3767 || (code != PLUS && code != IOR && code != XOR))
5b3e6663
PB
3768 need_else = true;
3769 else
3770 need_else = false;
cca0a211 3771
0f4c242b
KH
3772 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3773 operands[2], operands[3]);
cca0a211 3774 output_asm_insn (\"cmp\\t%2, %3\", operands);
5b3e6663
PB
3775 if (TARGET_THUMB2)
3776 {
3777 if (need_else)
3778 output_asm_insn (\"ite\\t%d5\", operands);
3779 else
3780 output_asm_insn (\"it\\t%d5\", operands);
3781 }
cca0a211 3782 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
5b3e6663 3783 if (need_else)
cca0a211
RE
3784 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3785 return \"\";
5895f793 3786 }"
cca0a211 3787 [(set_attr "conds" "clob")
5b3e6663
PB
3788 (set (attr "length")
3789 (if_then_else (eq_attr "is_thumb" "yes")
3790 (const_int 14)
594726e4
JG
3791 (const_int 12)))
3792 (set_attr "type" "multiple")]
cca0a211 3793)
ff9940b0 3794
5017f1d2
KT
3795; Reject the frame pointer in operand[1], since reloading this after
3796; it has been eliminated can cause carnage.
3797(define_insn_and_split "*minmax_arithsi_non_canon"
5e5f7673 3798 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
5017f1d2 3799 (minus:SI
5e5f7673 3800 (match_operand:SI 1 "s_register_operand" "0,?Ts")
5017f1d2 3801 (match_operator:SI 4 "minmax_operator"
5e5f7673
KT
3802 [(match_operand:SI 2 "s_register_operand" "Ts,Ts")
3803 (match_operand:SI 3 "arm_rhs_operand" "TsI,TsI")])))
5017f1d2 3804 (clobber (reg:CC CC_REGNUM))]
5e5f7673
KT
3805 "TARGET_32BIT && !arm_eliminable_register (operands[1])
3806 && !(arm_restrict_it && CONST_INT_P (operands[3]))"
5017f1d2
KT
3807 "#"
3808 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && reload_completed"
3809 [(set (reg:CC CC_REGNUM)
3810 (compare:CC (match_dup 2) (match_dup 3)))
3811
3812 (cond_exec (match_op_dup 4 [(reg:CC CC_REGNUM) (const_int 0)])
3813 (set (match_dup 0)
3814 (minus:SI (match_dup 1)
3815 (match_dup 2))))
3816 (cond_exec (match_op_dup 5 [(reg:CC CC_REGNUM) (const_int 0)])
3817 (set (match_dup 0)
ce852f9c 3818 (match_dup 6)))]
5017f1d2
KT
3819 {
3820 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
3821 operands[2], operands[3]);
3822 enum rtx_code rc = minmax_code (operands[4]);
3823 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode,
3824 operands[2], operands[3]);
3825
3826 if (mode == CCFPmode || mode == CCFPEmode)
3827 rc = reverse_condition_maybe_unordered (rc);
3828 else
3829 rc = reverse_condition (rc);
3830 operands[5] = gen_rtx_fmt_ee (rc, SImode, operands[2], operands[3]);
ce852f9c
KT
3831 if (CONST_INT_P (operands[3]))
3832 operands[6] = plus_constant (SImode, operands[1], -INTVAL (operands[3]));
3833 else
3834 operands[6] = gen_rtx_MINUS (SImode, operands[1], operands[3]);
5017f1d2
KT
3835 }
3836 [(set_attr "conds" "clob")
3837 (set (attr "length")
3838 (if_then_else (eq_attr "is_thumb" "yes")
3839 (const_int 14)
594726e4
JG
3840 (const_int 12)))
3841 (set_attr "type" "multiple")]
5017f1d2
KT
3842)
3843
5d216c70
UW
3844(define_code_iterator SAT [smin smax])
3845(define_code_iterator SATrev [smin smax])
3846(define_code_attr SATlo [(smin "1") (smax "2")])
3847(define_code_attr SAThi [(smin "2") (smax "1")])
3848
3849(define_insn "*satsi_<SAT:code>"
3850 [(set (match_operand:SI 0 "s_register_operand" "=r")
3851 (SAT:SI (SATrev:SI (match_operand:SI 3 "s_register_operand" "r")
3852 (match_operand:SI 1 "const_int_operand" "i"))
3853 (match_operand:SI 2 "const_int_operand" "i")))]
3854 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3855 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3856{
3857 int mask;
3858 bool signed_sat;
3859 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3860 &mask, &signed_sat))
3861 gcc_unreachable ();
3862
3863 operands[1] = GEN_INT (mask);
3864 if (signed_sat)
3865 return "ssat%?\t%0, %1, %3";
3866 else
3867 return "usat%?\t%0, %1, %3";
3868}
5e5f7673 3869 [(set_attr "predicable" "yes")
594726e4
JG
3870 (set_attr "predicable_short_it" "no")
3871 (set_attr "type" "alus_imm")]
52fceb44 3872)
5d216c70
UW
3873
3874(define_insn "*satsi_<SAT:code>_shift"
3875 [(set (match_operand:SI 0 "s_register_operand" "=r")
3876 (SAT:SI (SATrev:SI (match_operator:SI 3 "sat_shift_operator"
3877 [(match_operand:SI 4 "s_register_operand" "r")
3878 (match_operand:SI 5 "const_int_operand" "i")])
3879 (match_operand:SI 1 "const_int_operand" "i"))
3880 (match_operand:SI 2 "const_int_operand" "i")))]
3881 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3882 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3883{
3884 int mask;
3885 bool signed_sat;
3886 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3887 &mask, &signed_sat))
3888 gcc_unreachable ();
3889
3890 operands[1] = GEN_INT (mask);
3891 if (signed_sat)
3892 return "ssat%?\t%0, %1, %4%S3";
3893 else
3894 return "usat%?\t%0, %1, %4%S3";
3895}
3896 [(set_attr "predicable" "yes")
5e5f7673 3897 (set_attr "predicable_short_it" "no")
5d216c70 3898 (set_attr "shift" "3")
6e4150e1 3899 (set_attr "type" "logic_shift_reg")])
3a33f76f
RK
3900\f
3901;; Shift and rotation insns
3902
9b66ebb1
PB
3903(define_expand "ashldi3"
3904 [(set (match_operand:DI 0 "s_register_operand" "")
3905 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
3f2dc806 3906 (match_operand:SI 2 "general_operand" "")))]
5b3e6663 3907 "TARGET_32BIT"
9b66ebb1 3908 "
3f2dc806
AS
3909 if (TARGET_NEON)
3910 {
3911 /* Delay the decision whether to use NEON or core-regs until
3912 register allocation. */
3913 emit_insn (gen_ashldi3_neon (operands[0], operands[1], operands[2]));
3914 DONE;
3915 }
3916 else
3917 {
3918 /* Only the NEON case can handle in-memory shift counts. */
3919 if (!reg_or_int_operand (operands[2], SImode))
3920 operands[2] = force_reg (SImode, operands[2]);
3921 }
3922
479f7546 3923 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
99aea943
AS
3924 ; /* No special preparation statements; expand pattern as above. */
3925 else
9b66ebb1 3926 {
99aea943
AS
3927 rtx scratch1, scratch2;
3928
3929 if (CONST_INT_P (operands[2])
3930 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
9b66ebb1
PB
3931 {
3932 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3933 DONE;
3934 }
99aea943
AS
3935
3936 /* Ideally we should use iwmmxt here if we could know that operands[1]
3937 ends up already living in an iwmmxt register. Otherwise it's
3938 cheaper to have the alternate code being generated than moving
3939 values to iwmmxt regs and back. */
3940
3941 /* If we're optimizing for size, we prefer the libgcc calls. */
3942 if (optimize_function_for_size_p (cfun))
3943 FAIL;
3944
3945 /* Expand operation using core-registers.
3946 'FAIL' would achieve the same thing, but this is a bit smarter. */
3947 scratch1 = gen_reg_rtx (SImode);
3948 scratch2 = gen_reg_rtx (SImode);
3949 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
3950 operands[2], scratch1, scratch2);
3951 DONE;
9b66ebb1 3952 }
9b66ebb1
PB
3953 "
3954)
3955
3a323a38 3956(define_insn "arm_ashldi3_1bit"
2cea21dd 3957 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
cfc25c74 3958 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
9b66ebb1
PB
3959 (const_int 1)))
3960 (clobber (reg:CC CC_REGNUM))]
5b3e6663 3961 "TARGET_32BIT"
3a323a38 3962 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
9b66ebb1 3963 [(set_attr "conds" "clob")
594726e4
JG
3964 (set_attr "length" "8")
3965 (set_attr "type" "multiple")]
9b66ebb1
PB
3966)
3967
091426d3 3968(define_expand "ashlsi3"
d5b7b3ae 3969 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
3970 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3971 (match_operand:SI 2 "arm_rhs_operand" "")))]
d5b7b3ae 3972 "TARGET_EITHER"
091426d3 3973 "
d435a4be 3974 if (CONST_INT_P (operands[2])
091426d3
RE
3975 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3976 {
3977 emit_insn (gen_movsi (operands[0], const0_rtx));
3978 DONE;
3979 }
d5b7b3ae
RE
3980 "
3981)
3982
5b3e6663 3983(define_insn "*thumb1_ashlsi3"
d5b7b3ae
RE
3984 [(set (match_operand:SI 0 "register_operand" "=l,l")
3985 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3986 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
5b3e6663 3987 "TARGET_THUMB1"
d5b7b3ae 3988 "lsl\\t%0, %1, %2"
906668bb 3989 [(set_attr "length" "2")
6e4150e1 3990 (set_attr "type" "shift_imm,shift_reg")
906668bb 3991 (set_attr "conds" "set")])
3a33f76f 3992
9b66ebb1
PB
3993(define_expand "ashrdi3"
3994 [(set (match_operand:DI 0 "s_register_operand" "")
3995 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3996 (match_operand:SI 2 "reg_or_int_operand" "")))]
5b3e6663 3997 "TARGET_32BIT"
9b66ebb1 3998 "
3f2dc806
AS
3999 if (TARGET_NEON)
4000 {
4001 /* Delay the decision whether to use NEON or core-regs until
4002 register allocation. */
4003 emit_insn (gen_ashrdi3_neon (operands[0], operands[1], operands[2]));
4004 DONE;
4005 }
4006
479f7546 4007 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
99aea943
AS
4008 ; /* No special preparation statements; expand pattern as above. */
4009 else
9b66ebb1 4010 {
99aea943
AS
4011 rtx scratch1, scratch2;
4012
4013 if (CONST_INT_P (operands[2])
4014 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
9b66ebb1
PB
4015 {
4016 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
4017 DONE;
4018 }
99aea943
AS
4019
4020 /* Ideally we should use iwmmxt here if we could know that operands[1]
4021 ends up already living in an iwmmxt register. Otherwise it's
4022 cheaper to have the alternate code being generated than moving
4023 values to iwmmxt regs and back. */
4024
4025 /* If we're optimizing for size, we prefer the libgcc calls. */
4026 if (optimize_function_for_size_p (cfun))
4027 FAIL;
4028
4029 /* Expand operation using core-registers.
4030 'FAIL' would achieve the same thing, but this is a bit smarter. */
4031 scratch1 = gen_reg_rtx (SImode);
4032 scratch2 = gen_reg_rtx (SImode);
4033 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
4034 operands[2], scratch1, scratch2);
4035 DONE;
9b66ebb1 4036 }
9b66ebb1
PB
4037 "
4038)
4039
3a323a38 4040(define_insn "arm_ashrdi3_1bit"
2cea21dd 4041 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
cfc25c74 4042 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
9b66ebb1
PB
4043 (const_int 1)))
4044 (clobber (reg:CC CC_REGNUM))]
5b3e6663 4045 "TARGET_32BIT"
3a323a38 4046 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
9b66ebb1 4047 [(set_attr "conds" "clob")
594726e4
JG
4048 (set_attr "length" "8")
4049 (set_attr "type" "multiple")]
9b66ebb1
PB
4050)
4051
091426d3 4052(define_expand "ashrsi3"
d5b7b3ae 4053 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
4054 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
4055 (match_operand:SI 2 "arm_rhs_operand" "")))]
d5b7b3ae 4056 "TARGET_EITHER"
091426d3 4057 "
d435a4be 4058 if (CONST_INT_P (operands[2])
091426d3
RE
4059 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
4060 operands[2] = GEN_INT (31);
d5b7b3ae
RE
4061 "
4062)
4063
5b3e6663 4064(define_insn "*thumb1_ashrsi3"
d5b7b3ae
RE
4065 [(set (match_operand:SI 0 "register_operand" "=l,l")
4066 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
4067 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
5b3e6663 4068 "TARGET_THUMB1"
d5b7b3ae 4069 "asr\\t%0, %1, %2"
906668bb 4070 [(set_attr "length" "2")
6e4150e1 4071 (set_attr "type" "shift_imm,shift_reg")
906668bb 4072 (set_attr "conds" "set")])
3a33f76f 4073
9b66ebb1
PB
4074(define_expand "lshrdi3"
4075 [(set (match_operand:DI 0 "s_register_operand" "")
4076 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
4077 (match_operand:SI 2 "reg_or_int_operand" "")))]
5b3e6663 4078 "TARGET_32BIT"
9b66ebb1 4079 "
3f2dc806
AS
4080 if (TARGET_NEON)
4081 {
4082 /* Delay the decision whether to use NEON or core-regs until
4083 register allocation. */
4084 emit_insn (gen_lshrdi3_neon (operands[0], operands[1], operands[2]));
4085 DONE;
4086 }
4087
479f7546 4088 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
99aea943
AS
4089 ; /* No special preparation statements; expand pattern as above. */
4090 else
9b66ebb1 4091 {
99aea943
AS
4092 rtx scratch1, scratch2;
4093
4094 if (CONST_INT_P (operands[2])
4095 && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
9b66ebb1
PB
4096 {
4097 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
4098 DONE;
4099 }
99aea943
AS
4100
4101 /* Ideally we should use iwmmxt here if we could know that operands[1]
4102 ends up already living in an iwmmxt register. Otherwise it's
4103 cheaper to have the alternate code being generated than moving
4104 values to iwmmxt regs and back. */
4105
4106 /* If we're optimizing for size, we prefer the libgcc calls. */
4107 if (optimize_function_for_size_p (cfun))
4108 FAIL;
4109
4110 /* Expand operation using core-registers.
4111 'FAIL' would achieve the same thing, but this is a bit smarter. */
4112 scratch1 = gen_reg_rtx (SImode);
4113 scratch2 = gen_reg_rtx (SImode);
4114 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
4115 operands[2], scratch1, scratch2);
4116 DONE;
9b66ebb1 4117 }
9b66ebb1
PB
4118 "
4119)
4120
3a323a38 4121(define_insn "arm_lshrdi3_1bit"
2cea21dd 4122 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
cfc25c74 4123 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
9b66ebb1
PB
4124 (const_int 1)))
4125 (clobber (reg:CC CC_REGNUM))]
5b3e6663 4126 "TARGET_32BIT"
3a323a38 4127 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
9b66ebb1 4128 [(set_attr "conds" "clob")
594726e4
JG
4129 (set_attr "length" "8")
4130 (set_attr "type" "multiple")]
9b66ebb1
PB
4131)
4132
091426d3 4133(define_expand "lshrsi3"
d5b7b3ae 4134 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
4135 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
4136 (match_operand:SI 2 "arm_rhs_operand" "")))]
d5b7b3ae 4137 "TARGET_EITHER"
091426d3 4138 "
d435a4be 4139 if (CONST_INT_P (operands[2])
091426d3
RE
4140 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
4141 {
4142 emit_insn (gen_movsi (operands[0], const0_rtx));
4143 DONE;
4144 }
d5b7b3ae
RE
4145 "
4146)
4147
5b3e6663 4148(define_insn "*thumb1_lshrsi3"
d5b7b3ae
RE
4149 [(set (match_operand:SI 0 "register_operand" "=l,l")
4150 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
4151 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
5b3e6663 4152 "TARGET_THUMB1"
d5b7b3ae 4153 "lsr\\t%0, %1, %2"
906668bb 4154 [(set_attr "length" "2")
6e4150e1 4155 (set_attr "type" "shift_imm,shift_reg")
906668bb 4156 (set_attr "conds" "set")])
3a33f76f 4157
091426d3 4158(define_expand "rotlsi3"
d5b7b3ae 4159 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
4160 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
4161 (match_operand:SI 2 "reg_or_int_operand" "")))]
5b3e6663 4162 "TARGET_32BIT"
091426d3 4163 "
d435a4be 4164 if (CONST_INT_P (operands[2]))
091426d3
RE
4165 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
4166 else
3a33f76f 4167 {
091426d3
RE
4168 rtx reg = gen_reg_rtx (SImode);
4169 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
4170 operands[2] = reg;
3a33f76f 4171 }
d5b7b3ae
RE
4172 "
4173)
ff9940b0 4174
091426d3 4175(define_expand "rotrsi3"
d5b7b3ae 4176 [(set (match_operand:SI 0 "s_register_operand" "")
091426d3
RE
4177 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
4178 (match_operand:SI 2 "arm_rhs_operand" "")))]
d5b7b3ae 4179 "TARGET_EITHER"
091426d3 4180 "
5b3e6663 4181 if (TARGET_32BIT)
d5b7b3ae 4182 {
d435a4be 4183 if (CONST_INT_P (operands[2])
d5b7b3ae
RE
4184 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
4185 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
4186 }
5b3e6663 4187 else /* TARGET_THUMB1 */
d5b7b3ae 4188 {
d435a4be 4189 if (CONST_INT_P (operands [2]))
d5b7b3ae
RE
4190 operands [2] = force_reg (SImode, operands[2]);
4191 }
4192 "
4193)
091426d3 4194
5b3e6663 4195(define_insn "*thumb1_rotrsi3"
d5b7b3ae
RE
4196 [(set (match_operand:SI 0 "register_operand" "=l")
4197 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
4198 (match_operand:SI 2 "register_operand" "l")))]
5b3e6663 4199 "TARGET_THUMB1"
d5b7b3ae 4200 "ror\\t%0, %0, %2"
006bd006
SN
4201 [(set_attr "type" "shift_reg")
4202 (set_attr "length" "2")]
d5b7b3ae
RE
4203)
4204
4205(define_insn "*arm_shiftsi3"
df45c0cc 4206 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r")
d5b7b3ae 4207 (match_operator:SI 3 "shift_operator"
df45c0cc
KT
4208 [(match_operand:SI 1 "s_register_operand" "0,l,r,r")
4209 (match_operand:SI 2 "reg_or_int_operand" "l,M,M,r")]))]
5b3e6663
PB
4210 "TARGET_32BIT"
4211 "* return arm_output_shift(operands, 0);"
ca68ea18 4212 [(set_attr "predicable" "yes")
df45c0cc
KT
4213 (set_attr "arch" "t2,t2,*,*")
4214 (set_attr "predicable_short_it" "yes,yes,no,no")
5e5f7673 4215 (set_attr "length" "4")
d19fb8e3 4216 (set_attr "shift" "1")
df45c0cc 4217 (set_attr "type" "alu_shift_reg,alu_shift_imm,alu_shift_imm,alu_shift_reg")]
b020fd92 4218)
091426d3 4219
4cdb3ed4 4220(define_insn "*shiftsi3_compare0"
48a08b9c 4221 [(set (reg:CC_NOOV CC_REGNUM)
091426d3 4222 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
006bd006
SN
4223 [(match_operand:SI 1 "s_register_operand" "r,r")
4224 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
ff9940b0 4225 (const_int 0)))
006bd006 4226 (set (match_operand:SI 0 "s_register_operand" "=r,r")
091426d3 4227 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
5b3e6663
PB
4228 "TARGET_32BIT"
4229 "* return arm_output_shift(operands, 1);"
ca68ea18 4230 [(set_attr "conds" "set")
d19fb8e3 4231 (set_attr "shift" "1")
6e4150e1 4232 (set_attr "type" "alus_shift_imm,alus_shift_reg")]
cca0a211 4233)
ff9940b0 4234
4cdb3ed4 4235(define_insn "*shiftsi3_compare0_scratch"
48a08b9c 4236 [(set (reg:CC_NOOV CC_REGNUM)
091426d3 4237 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
006bd006
SN
4238 [(match_operand:SI 1 "s_register_operand" "r,r")
4239 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
ff9940b0 4240 (const_int 0)))
006bd006 4241 (clobber (match_scratch:SI 0 "=r,r"))]
5b3e6663
PB
4242 "TARGET_32BIT"
4243 "* return arm_output_shift(operands, 1);"
ca68ea18 4244 [(set_attr "conds" "set")
006bd006 4245 (set_attr "shift" "1")
6e4150e1 4246 (set_attr "type" "shift_imm,shift_reg")]
cca0a211 4247)
ff9940b0 4248
c29e2982
BS
4249(define_insn "*not_shiftsi"
4250 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
091426d3 4251 (not:SI (match_operator:SI 3 "shift_operator"
c29e2982
BS
4252 [(match_operand:SI 1 "s_register_operand" "r,r")
4253 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
4254 "TARGET_32BIT"
b020fd92 4255 "mvn%?\\t%0, %1%S3"
ca68ea18 4256 [(set_attr "predicable" "yes")
31dfce10 4257 (set_attr "predicable_short_it" "no")
d19fb8e3 4258 (set_attr "shift" "1")
c29e2982 4259 (set_attr "arch" "32,a")
859abddd 4260 (set_attr "type" "mvn_shift,mvn_shift_reg")])
ff9940b0 4261
c29e2982 4262(define_insn "*not_shiftsi_compare0"
48a08b9c 4263 [(set (reg:CC_NOOV CC_REGNUM)
c29e2982
BS
4264 (compare:CC_NOOV
4265 (not:SI (match_operator:SI 3 "shift_operator"
4266 [(match_operand:SI 1 "s_register_operand" "r,r")
4267 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4268 (const_int 0)))
4269 (set (match_operand:SI 0 "s_register_operand" "=r,r")
091426d3 4270 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
c29e2982 4271 "TARGET_32BIT"
5b3e6663 4272 "mvn%.\\t%0, %1%S3"
ca68ea18 4273 [(set_attr "conds" "set")
d19fb8e3 4274 (set_attr "shift" "1")
c29e2982 4275 (set_attr "arch" "32,a")
859abddd 4276 (set_attr "type" "mvn_shift,mvn_shift_reg")])
ff9940b0 4277
c29e2982 4278(define_insn "*not_shiftsi_compare0_scratch"
48a08b9c 4279 [(set (reg:CC_NOOV CC_REGNUM)
c29e2982
BS
4280 (compare:CC_NOOV
4281 (not:SI (match_operator:SI 3 "shift_operator"
4282 [(match_operand:SI 1 "s_register_operand" "r,r")
4283 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4284 (const_int 0)))
4285 (clobber (match_scratch:SI 0 "=r,r"))]
4286 "TARGET_32BIT"
5b3e6663 4287 "mvn%.\\t%0, %1%S3"
ca68ea18 4288 [(set_attr "conds" "set")
d19fb8e3 4289 (set_attr "shift" "1")
c29e2982 4290 (set_attr "arch" "32,a")
859abddd 4291 (set_attr "type" "mvn_shift,mvn_shift_reg")])
ff9940b0 4292
d5b7b3ae
RE
4293;; We don't really have extzv, but defining this using shifts helps
4294;; to reduce register pressure later on.
4295
4296(define_expand "extzv"
86b60116
JB
4297 [(set (match_operand 0 "s_register_operand" "")
4298 (zero_extract (match_operand 1 "nonimmediate_operand" "")
4299 (match_operand 2 "const_int_operand" "")
4300 (match_operand 3 "const_int_operand" "")))]
ef87d898 4301 "TARGET_THUMB1 || arm_arch_thumb2"
d5b7b3ae
RE
4302 "
4303 {
4304 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
4305 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
4306
ef87d898
PB
4307 if (arm_arch_thumb2)
4308 {
86b60116
JB
4309 HOST_WIDE_INT width = INTVAL (operands[2]);
4310 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4311
4312 if (unaligned_access && MEM_P (operands[1])
4313 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
4314 {
4315 rtx base_addr;
4316
4317 if (BYTES_BIG_ENDIAN)
4318 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
4319 - bitpos;
4320
4321 if (width == 32)
4322 {
4323 base_addr = adjust_address (operands[1], SImode,
4324 bitpos / BITS_PER_UNIT);
4325 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4326 }
4327 else
4328 {
4329 rtx dest = operands[0];
4330 rtx tmp = gen_reg_rtx (SImode);
4331
4332 /* We may get a paradoxical subreg here. Strip it off. */
4333 if (GET_CODE (dest) == SUBREG
4334 && GET_MODE (dest) == SImode
4335 && GET_MODE (SUBREG_REG (dest)) == HImode)
4336 dest = SUBREG_REG (dest);
4337
4338 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4339 FAIL;
4340
4341 base_addr = adjust_address (operands[1], HImode,
4342 bitpos / BITS_PER_UNIT);
4343 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
4344 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4345 }
4346 DONE;
4347 }
4348 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
4349 {
4350 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
4351 operands[3]));
4352 DONE;
4353 }
4354 else
4355 FAIL;
ef87d898 4356 }
86b60116
JB
4357
4358 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4359 FAIL;
ef87d898 4360
d5b7b3ae
RE
4361 operands[3] = GEN_INT (rshift);
4362
4363 if (lshift == 0)
4364 {
4365 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
4366 DONE;
4367 }
4368
86b60116
JB
4369 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
4370 operands[3], gen_reg_rtx (SImode)));
4371 DONE;
5895f793 4372 }"
d5b7b3ae
RE
4373)
4374
86b60116
JB
4375;; Helper for extzv, for the Thumb-1 register-shifts case.
4376
4377(define_expand "extzv_t1"
4378 [(set (match_operand:SI 4 "s_register_operand" "")
4379 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
4380 (match_operand:SI 2 "const_int_operand" "")))
4381 (set (match_operand:SI 0 "s_register_operand" "")
4382 (lshiftrt:SI (match_dup 4)
4383 (match_operand:SI 3 "const_int_operand" "")))]
4384 "TARGET_THUMB1"
4385 "")
4386
4387(define_expand "extv"
4388 [(set (match_operand 0 "s_register_operand" "")
4389 (sign_extract (match_operand 1 "nonimmediate_operand" "")
4390 (match_operand 2 "const_int_operand" "")
4391 (match_operand 3 "const_int_operand" "")))]
4392 "arm_arch_thumb2"
4393{
4394 HOST_WIDE_INT width = INTVAL (operands[2]);
4395 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4396
4397 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
4398 && (bitpos % BITS_PER_UNIT) == 0)
4399 {
4400 rtx base_addr;
4401
4402 if (BYTES_BIG_ENDIAN)
4403 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
4404
4405 if (width == 32)
4406 {
4407 base_addr = adjust_address (operands[1], SImode,
4408 bitpos / BITS_PER_UNIT);
4409 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4410 }
4411 else
4412 {
4413 rtx dest = operands[0];
4414 rtx tmp = gen_reg_rtx (SImode);
4415
4416 /* We may get a paradoxical subreg here. Strip it off. */
4417 if (GET_CODE (dest) == SUBREG
4418 && GET_MODE (dest) == SImode
4419 && GET_MODE (SUBREG_REG (dest)) == HImode)
4420 dest = SUBREG_REG (dest);
4421
4422 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4423 FAIL;
4424
4425 base_addr = adjust_address (operands[1], HImode,
4426 bitpos / BITS_PER_UNIT);
4427 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
4428 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4429 }
4430
4431 DONE;
4432 }
4433 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4434 FAIL;
4435 else if (GET_MODE (operands[0]) == SImode
4436 && GET_MODE (operands[1]) == SImode)
4437 {
4438 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
4439 operands[3]));
4440 DONE;
4441 }
4442
4443 FAIL;
4444})
4445
4446; Helper to expand register forms of extv with the proper modes.
4447
4448(define_expand "extv_regsi"
4449 [(set (match_operand:SI 0 "s_register_operand" "")
4450 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
4451 (match_operand 2 "const_int_operand" "")
4452 (match_operand 3 "const_int_operand" "")))]
4453 ""
4454{
4455})
4456
4457; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
4458
4459(define_insn "unaligned_loadsi"
4460 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4461 (unspec:SI [(match_operand:SI 1 "memory_operand" "Uw,m")]
4462 UNSPEC_UNALIGNED_LOAD))]
4463 "unaligned_access && TARGET_32BIT"
4464 "ldr%?\t%0, %1\t@ unaligned"
4465 [(set_attr "arch" "t2,any")
4466 (set_attr "length" "2,4")
4467 (set_attr "predicable" "yes")
31dfce10 4468 (set_attr "predicable_short_it" "yes,no")
86b60116
JB
4469 (set_attr "type" "load1")])
4470
4471(define_insn "unaligned_loadhis"
4472 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4473 (sign_extend:SI
4474 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4475 UNSPEC_UNALIGNED_LOAD)))]
4476 "unaligned_access && TARGET_32BIT"
4477 "ldr%(sh%)\t%0, %1\t@ unaligned"
4478 [(set_attr "arch" "t2,any")
4479 (set_attr "length" "2,4")
4480 (set_attr "predicable" "yes")
31dfce10 4481 (set_attr "predicable_short_it" "yes,no")
86b60116
JB
4482 (set_attr "type" "load_byte")])
4483
4484(define_insn "unaligned_loadhiu"
4485 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4486 (zero_extend:SI
4487 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4488 UNSPEC_UNALIGNED_LOAD)))]
4489 "unaligned_access && TARGET_32BIT"
4490 "ldr%(h%)\t%0, %1\t@ unaligned"
4491 [(set_attr "arch" "t2,any")
4492 (set_attr "length" "2,4")
4493 (set_attr "predicable" "yes")
31dfce10 4494 (set_attr "predicable_short_it" "yes,no")
86b60116
JB
4495 (set_attr "type" "load_byte")])
4496
4497(define_insn "unaligned_storesi"
4498 [(set (match_operand:SI 0 "memory_operand" "=Uw,m")
4499 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,r")]
4500 UNSPEC_UNALIGNED_STORE))]
4501 "unaligned_access && TARGET_32BIT"
4502 "str%?\t%1, %0\t@ unaligned"
4503 [(set_attr "arch" "t2,any")
4504 (set_attr "length" "2,4")
4505 (set_attr "predicable" "yes")
31dfce10 4506 (set_attr "predicable_short_it" "yes,no")
86b60116
JB
4507 (set_attr "type" "store1")])
4508
4509(define_insn "unaligned_storehi"
4510 [(set (match_operand:HI 0 "memory_operand" "=Uw,m")
4511 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
4512 UNSPEC_UNALIGNED_STORE))]
4513 "unaligned_access && TARGET_32BIT"
4514 "str%(h%)\t%1, %0\t@ unaligned"
4515 [(set_attr "arch" "t2,any")
4516 (set_attr "length" "2,4")
4517 (set_attr "predicable" "yes")
31dfce10 4518 (set_attr "predicable_short_it" "yes,no")
86b60116
JB
4519 (set_attr "type" "store1")])
4520
798d3d04
GY
4521;; Unaligned double-word load and store.
4522;; Split after reload into two unaligned single-word accesses.
4523;; It prevents lower_subreg from splitting some other aligned
4524;; double-word accesses too early. Used for internal memcpy.
4525
4526(define_insn_and_split "unaligned_loaddi"
4527 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4528 (unspec:DI [(match_operand:DI 1 "memory_operand" "o,o")]
4529 UNSPEC_UNALIGNED_LOAD))]
4530 "unaligned_access && TARGET_32BIT"
4531 "#"
4532 "&& reload_completed"
4533 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_UNALIGNED_LOAD))
4534 (set (match_dup 2) (unspec:SI [(match_dup 3)] UNSPEC_UNALIGNED_LOAD))]
4535 {
4536 operands[2] = gen_highpart (SImode, operands[0]);
4537 operands[0] = gen_lowpart (SImode, operands[0]);
4538 operands[3] = gen_highpart (SImode, operands[1]);
4539 operands[1] = gen_lowpart (SImode, operands[1]);
4540
4541 /* If the first destination register overlaps with the base address,
4542 swap the order in which the loads are emitted. */
4543 if (reg_overlap_mentioned_p (operands[0], operands[1]))
4544 {
4545 rtx tmp = operands[1];
4546 operands[1] = operands[3];
4547 operands[3] = tmp;
4548 tmp = operands[0];
4549 operands[0] = operands[2];
4550 operands[2] = tmp;
4551 }
4552 }
4553 [(set_attr "arch" "t2,any")
4554 (set_attr "length" "4,8")
4555 (set_attr "predicable" "yes")
4556 (set_attr "type" "load2")])
4557
4558(define_insn_and_split "unaligned_storedi"
4559 [(set (match_operand:DI 0 "memory_operand" "=o,o")
4560 (unspec:DI [(match_operand:DI 1 "s_register_operand" "l,r")]
4561 UNSPEC_UNALIGNED_STORE))]
4562 "unaligned_access && TARGET_32BIT"
4563 "#"
4564 "&& reload_completed"
4565 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_UNALIGNED_STORE))
4566 (set (match_dup 2) (unspec:SI [(match_dup 3)] UNSPEC_UNALIGNED_STORE))]
4567 {
4568 operands[2] = gen_highpart (SImode, operands[0]);
4569 operands[0] = gen_lowpart (SImode, operands[0]);
4570 operands[3] = gen_highpart (SImode, operands[1]);
4571 operands[1] = gen_lowpart (SImode, operands[1]);
4572 }
4573 [(set_attr "arch" "t2,any")
4574 (set_attr "length" "4,8")
4575 (set_attr "predicable" "yes")
4576 (set_attr "type" "store2")])
4577
4578
86b60116 4579(define_insn "*extv_reg"
ef87d898
PB
4580 [(set (match_operand:SI 0 "s_register_operand" "=r")
4581 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
4582 (match_operand:SI 2 "const_int_operand" "M")
4583 (match_operand:SI 3 "const_int_operand" "M")))]
4584 "arm_arch_thumb2"
4585 "sbfx%?\t%0, %1, %3, %2"
4586 [(set_attr "length" "4")
31dfce10 4587 (set_attr "predicable" "yes")
6e4150e1
JG
4588 (set_attr "predicable_short_it" "no")
4589 (set_attr "type" "bfm")]
ef87d898
PB
4590)
4591
4592(define_insn "extzv_t2"
4593 [(set (match_operand:SI 0 "s_register_operand" "=r")
4594 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
4595 (match_operand:SI 2 "const_int_operand" "M")
4596 (match_operand:SI 3 "const_int_operand" "M")))]
4597 "arm_arch_thumb2"
4598 "ubfx%?\t%0, %1, %3, %2"
4599 [(set_attr "length" "4")
31dfce10 4600 (set_attr "predicable" "yes")
6e4150e1
JG
4601 (set_attr "predicable_short_it" "no")
4602 (set_attr "type" "bfm")]
ef87d898
PB
4603)
4604
572070ef
PB
4605
4606;; Division instructions
4607(define_insn "divsi3"
4608 [(set (match_operand:SI 0 "s_register_operand" "=r")
4609 (div:SI (match_operand:SI 1 "s_register_operand" "r")
4610 (match_operand:SI 2 "s_register_operand" "r")))]
4611 "TARGET_IDIV"
4612 "sdiv%?\t%0, %1, %2"
4613 [(set_attr "predicable" "yes")
31dfce10 4614 (set_attr "predicable_short_it" "no")
09485a08 4615 (set_attr "type" "sdiv")]
572070ef
PB
4616)
4617
4618(define_insn "udivsi3"
4619 [(set (match_operand:SI 0 "s_register_operand" "=r")
4620 (udiv:SI (match_operand:SI 1 "s_register_operand" "r")
4621 (match_operand:SI 2 "s_register_operand" "r")))]
4622 "TARGET_IDIV"
4623 "udiv%?\t%0, %1, %2"
4624 [(set_attr "predicable" "yes")
31dfce10 4625 (set_attr "predicable_short_it" "no")
09485a08 4626 (set_attr "type" "udiv")]
572070ef
PB
4627)
4628
3a33f76f
RK
4629\f
4630;; Unary arithmetic insns
4631
d5b7b3ae
RE
4632(define_expand "negdi2"
4633 [(parallel
9e315505
RE
4634 [(set (match_operand:DI 0 "s_register_operand" "")
4635 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
48a08b9c 4636 (clobber (reg:CC CC_REGNUM))])]
d5b7b3ae 4637 "TARGET_EITHER"
b8fb55d1
AS
4638 {
4639 if (TARGET_NEON)
4640 {
4641 emit_insn (gen_negdi2_neon (operands[0], operands[1]));
4642 DONE;
4643 }
4644 }
d5b7b3ae
RE
4645)
4646
4647;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
cfc25c74 4648;; The first alternative allows the common case of a *full* overlap.
3f3bf1a8 4649(define_insn_and_split "*arm_negdi2"
ae59e00d 4650 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
cfc25c74 4651 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
48a08b9c 4652 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 4653 "TARGET_ARM"
3f3bf1a8
GY
4654 "#" ; "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
4655 "&& reload_completed"
4656 [(parallel [(set (reg:CC CC_REGNUM)
4657 (compare:CC (const_int 0) (match_dup 1)))
4658 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4659 (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
4660 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4661 {
4662 operands[2] = gen_highpart (SImode, operands[0]);
4663 operands[0] = gen_lowpart (SImode, operands[0]);
4664 operands[3] = gen_highpart (SImode, operands[1]);
4665 operands[1] = gen_lowpart (SImode, operands[1]);
4666 }
d5b7b3ae 4667 [(set_attr "conds" "clob")
594726e4
JG
4668 (set_attr "length" "8")
4669 (set_attr "type" "multiple")]
d5b7b3ae 4670)
3a33f76f 4671
5b3e6663 4672(define_insn "*thumb1_negdi2"
9e315505
RE
4673 [(set (match_operand:DI 0 "register_operand" "=&l")
4674 (neg:DI (match_operand:DI 1 "register_operand" "l")))
48a08b9c 4675 (clobber (reg:CC CC_REGNUM))]
5b3e6663 4676 "TARGET_THUMB1"
d5b7b3ae 4677 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
594726e4
JG
4678 [(set_attr "length" "6")
4679 (set_attr "type" "multiple")]
d5b7b3ae
RE
4680)
4681
4682(define_expand "negsi2"
4683 [(set (match_operand:SI 0 "s_register_operand" "")
4684 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
4685 "TARGET_EITHER"
3a33f76f 4686 ""
d5b7b3ae
RE
4687)
4688
4689(define_insn "*arm_negsi2"
31dfce10
KT
4690 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4691 (neg:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
5b3e6663 4692 "TARGET_32BIT"
d5b7b3ae 4693 "rsb%?\\t%0, %1, #0"
31dfce10
KT
4694 [(set_attr "predicable" "yes")
4695 (set_attr "predicable_short_it" "yes,no")
4696 (set_attr "arch" "t2,*")
594726e4
JG
4697 (set_attr "length" "4")
4698 (set_attr "type" "alu_reg")]
d5b7b3ae
RE
4699)
4700
5b3e6663 4701(define_insn "*thumb1_negsi2"
d5b7b3ae
RE
4702 [(set (match_operand:SI 0 "register_operand" "=l")
4703 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
5b3e6663 4704 "TARGET_THUMB1"
d5b7b3ae 4705 "neg\\t%0, %1"
594726e4
JG
4706 [(set_attr "length" "2")
4707 (set_attr "type" "alu_imm")]
d5b7b3ae 4708)
3a33f76f 4709
37f74dcf
RE
4710(define_expand "negsf2"
4711 [(set (match_operand:SF 0 "s_register_operand" "")
4712 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
8fcd8c83 4713 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
37f74dcf
RE
4714 ""
4715)
4716
4717(define_expand "negdf2"
4718 [(set (match_operand:DF 0 "s_register_operand" "")
4719 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
8fcd8c83 4720 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
37f74dcf
RE
4721 "")
4722
a866fa46
KT
4723(define_insn_and_split "*zextendsidi_negsi"
4724 [(set (match_operand:DI 0 "s_register_operand" "=r")
4725 (zero_extend:DI (neg:SI (match_operand:SI 1 "s_register_operand" "r"))))]
4726 "TARGET_32BIT"
4727 "#"
4728 ""
4729 [(set (match_dup 2)
4730 (neg:SI (match_dup 1)))
4731 (set (match_dup 3)
4732 (const_int 0))]
4733 {
4734 operands[2] = gen_lowpart (SImode, operands[0]);
4735 operands[3] = gen_highpart (SImode, operands[0]);
4736 }
4737 [(set_attr "length" "8")
4738 (set_attr "type" "multiple")]
4739)
4740
045e472c
GY
4741;; Negate an extended 32-bit value.
4742(define_insn_and_split "*negdi_extendsidi"
8f1c326d
RE
4743 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4744 (neg:DI (sign_extend:DI
4745 (match_operand:SI 1 "s_register_operand" "l,r"))))
045e472c
GY
4746 (clobber (reg:CC CC_REGNUM))]
4747 "TARGET_32BIT"
8f1c326d 4748 "#"
045e472c
GY
4749 "&& reload_completed"
4750 [(const_int 0)]
4751 {
8f1c326d
RE
4752 rtx low = gen_lowpart (SImode, operands[0]);
4753 rtx high = gen_highpart (SImode, operands[0]);
4754
4755 if (reg_overlap_mentioned_p (low, operands[1]))
4756 {
4757 /* Input overlaps the low word of the output. Use:
4758 asr Rhi, Rin, #31
4759 rsbs Rlo, Rin, #0
4760 rsc Rhi, Rhi, #0 (thumb2: sbc Rhi, Rhi, Rhi, lsl #1). */
4761 rtx cc_reg = gen_rtx_REG (CC_Cmode, CC_REGNUM);
4762
4763 emit_insn (gen_rtx_SET (VOIDmode, high,
4764 gen_rtx_ASHIFTRT (SImode, operands[1],
4765 GEN_INT (31))));
4766
4767 emit_insn (gen_subsi3_compare (low, const0_rtx, operands[1]));
4768 if (TARGET_ARM)
4769 emit_insn (gen_rtx_SET (VOIDmode, high,
4770 gen_rtx_MINUS (SImode,
4771 gen_rtx_MINUS (SImode,
4772 const0_rtx,
4773 high),
4774 gen_rtx_LTU (SImode,
4775 cc_reg,
4776 const0_rtx))));
4777 else
4778 {
4779 rtx two_x = gen_rtx_ASHIFT (SImode, high, GEN_INT (1));
4780 emit_insn (gen_rtx_SET (VOIDmode, high,
4781 gen_rtx_MINUS (SImode,
4782 gen_rtx_MINUS (SImode,
4783 high,
4784 two_x),
4785 gen_rtx_LTU (SImode,
4786 cc_reg,
4787 const0_rtx))));
4788 }
4789 }
4790 else
4791 {
4792 /* No overlap, or overlap on high word. Use:
4793 rsb Rlo, Rin, #0
4794 bic Rhi, Rlo, Rin
4795 asr Rhi, Rhi, #31
4796 Flags not needed for this sequence. */
4797 emit_insn (gen_rtx_SET (VOIDmode, low,
4798 gen_rtx_NEG (SImode, operands[1])));
4799 emit_insn (gen_rtx_SET (VOIDmode, high,
4800 gen_rtx_AND (SImode,
4801 gen_rtx_NOT (SImode, operands[1]),
4802 low)));
4803 emit_insn (gen_rtx_SET (VOIDmode, high,
4804 gen_rtx_ASHIFTRT (SImode, high,
4805 GEN_INT (31))));
4806 }
4807 DONE;
045e472c 4808 }
8f1c326d
RE
4809 [(set_attr "length" "12")
4810 (set_attr "arch" "t2,*")
594726e4 4811 (set_attr "type" "multiple")]
045e472c
GY
4812)
4813
4814(define_insn_and_split "*negdi_zero_extendsidi"
4815 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4816 (neg:DI (zero_extend:DI (match_operand:SI 1 "s_register_operand" "0,r"))))
4817 (clobber (reg:CC CC_REGNUM))]
4818 "TARGET_32BIT"
4819 "#" ; "rsbs\\t%Q0, %1, #0\;sbc\\t%R0,%R0,%R0"
4820 ;; Don't care what register is input to sbc,
4821 ;; since we just just need to propagate the carry.
4822 "&& reload_completed"
4823 [(parallel [(set (reg:CC CC_REGNUM)
4824 (compare:CC (const_int 0) (match_dup 1)))
4825 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4826 (set (match_dup 2) (minus:SI (minus:SI (match_dup 2) (match_dup 2))
4827 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4828 {
4829 operands[2] = gen_highpart (SImode, operands[0]);
4830 operands[0] = gen_lowpart (SImode, operands[0]);
4831 }
4832 [(set_attr "conds" "clob")
594726e4
JG
4833 (set_attr "length" "8")
4834 (set_attr "type" "multiple")] ;; length in thumb is 4
045e472c
GY
4835)
4836
ff9940b0
RE
4837;; abssi2 doesn't really clobber the condition codes if a different register
4838;; is being set. To keep things simple, assume during rtl manipulations that
4839;; it does, but tell the final scan operator the truth. Similarly for
4840;; (neg (abs...))
4841
37f74dcf
RE
4842(define_expand "abssi2"
4843 [(parallel
4844 [(set (match_operand:SI 0 "s_register_operand" "")
4845 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
ecaf6f07
RE
4846 (clobber (match_dup 2))])]
4847 "TARGET_EITHER"
4848 "
5b3e6663 4849 if (TARGET_THUMB1)
ecaf6f07
RE
4850 operands[2] = gen_rtx_SCRATCH (SImode);
4851 else
4852 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4853")
37f74dcf 4854
3f3bf1a8 4855(define_insn_and_split "*arm_abssi2"
ecaf6f07 4856 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
ff9940b0 4857 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
48a08b9c 4858 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 4859 "TARGET_ARM"
3f3bf1a8
GY
4860 "#"
4861 "&& reload_completed"
4862 [(const_int 0)]
4863 {
4864 /* if (which_alternative == 0) */
4865 if (REGNO(operands[0]) == REGNO(operands[1]))
4866 {
4867 /* Emit the pattern:
4868 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
4869 [(set (reg:CC CC_REGNUM)
4870 (compare:CC (match_dup 0) (const_int 0)))
4871 (cond_exec (lt:CC (reg:CC CC_REGNUM) (const_int 0))
4872 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1))))]
4873 */
4874 emit_insn (gen_rtx_SET (VOIDmode,
4875 gen_rtx_REG (CCmode, CC_REGNUM),
4876 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4877 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4878 (gen_rtx_LT (SImode,
4879 gen_rtx_REG (CCmode, CC_REGNUM),
4880 const0_rtx)),
4881 (gen_rtx_SET (VOIDmode,
4882 operands[0],
4883 (gen_rtx_MINUS (SImode,
4884 const0_rtx,
4885 operands[1]))))));
4886 DONE;
4887 }
4888 else
4889 {
4890 /* Emit the pattern:
4891 alt1: eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
4892 [(set (match_dup 0)
4893 (xor:SI (match_dup 1)
4894 (ashiftrt:SI (match_dup 1) (const_int 31))))
4895 (set (match_dup 0)
4896 (minus:SI (match_dup 0)
4897 (ashiftrt:SI (match_dup 1) (const_int 31))))]
4898 */
4899 emit_insn (gen_rtx_SET (VOIDmode,
4900 operands[0],
4901 gen_rtx_XOR (SImode,
4902 gen_rtx_ASHIFTRT (SImode,
4903 operands[1],
4904 GEN_INT (31)),
4905 operands[1])));
4906 emit_insn (gen_rtx_SET (VOIDmode,
4907 operands[0],
4908 gen_rtx_MINUS (SImode,
4909 operands[0],
4910 gen_rtx_ASHIFTRT (SImode,
4911 operands[1],
4912 GEN_INT (31)))));
4913 DONE;
4914 }
4915 }
d5b7b3ae 4916 [(set_attr "conds" "clob,*")
d19fb8e3 4917 (set_attr "shift" "1")
099f2693 4918 (set_attr "predicable" "no, yes")
594726e4
JG
4919 (set_attr "length" "8")
4920 (set_attr "type" "multiple")]
d5b7b3ae 4921)
ff9940b0 4922
5b3e6663 4923(define_insn_and_split "*thumb1_abssi2"
ecaf6f07
RE
4924 [(set (match_operand:SI 0 "s_register_operand" "=l")
4925 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
4926 (clobber (match_scratch:SI 2 "=&l"))]
5b3e6663 4927 "TARGET_THUMB1"
ecaf6f07 4928 "#"
5b3e6663 4929 "TARGET_THUMB1 && reload_completed"
ecaf6f07
RE
4930 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
4931 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
4932 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
4933 ""
594726e4
JG
4934 [(set_attr "length" "6")
4935 (set_attr "type" "multiple")]
ecaf6f07
RE
4936)
4937
3f3bf1a8 4938(define_insn_and_split "*arm_neg_abssi2"
ff9940b0
RE
4939 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4940 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
48a08b9c 4941 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 4942 "TARGET_ARM"
3f3bf1a8
GY
4943 "#"
4944 "&& reload_completed"
4945 [(const_int 0)]
4946 {
4947 /* if (which_alternative == 0) */
4948 if (REGNO (operands[0]) == REGNO (operands[1]))
4949 {
4950 /* Emit the pattern:
4951 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
4952 */
4953 emit_insn (gen_rtx_SET (VOIDmode,
4954 gen_rtx_REG (CCmode, CC_REGNUM),
4955 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4956 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4957 gen_rtx_GT (SImode,
4958 gen_rtx_REG (CCmode, CC_REGNUM),
4959 const0_rtx),
4960 gen_rtx_SET (VOIDmode,
4961 operands[0],
4962 (gen_rtx_MINUS (SImode,
4963 const0_rtx,
4964 operands[1])))));
4965 }
4966 else
4967 {
4968 /* Emit the pattern:
4969 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
4970 */
4971 emit_insn (gen_rtx_SET (VOIDmode,
4972 operands[0],
4973 gen_rtx_XOR (SImode,
4974 gen_rtx_ASHIFTRT (SImode,
4975 operands[1],
4976 GEN_INT (31)),
4977 operands[1])));
4978 emit_insn (gen_rtx_SET (VOIDmode,
4979 operands[0],
4980 gen_rtx_MINUS (SImode,
4981 gen_rtx_ASHIFTRT (SImode,
4982 operands[1],
4983 GEN_INT (31)),
4984 operands[0])));
4985 }
4986 DONE;
4987 }
d5b7b3ae 4988 [(set_attr "conds" "clob,*")
d19fb8e3 4989 (set_attr "shift" "1")
099f2693 4990 (set_attr "predicable" "no, yes")
594726e4
JG
4991 (set_attr "length" "8")
4992 (set_attr "type" "multiple")]
d5b7b3ae 4993)
3a33f76f 4994
5b3e6663 4995(define_insn_and_split "*thumb1_neg_abssi2"
ecaf6f07
RE
4996 [(set (match_operand:SI 0 "s_register_operand" "=l")
4997 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
4998 (clobber (match_scratch:SI 2 "=&l"))]
5b3e6663 4999 "TARGET_THUMB1"
ecaf6f07 5000 "#"
5b3e6663 5001 "TARGET_THUMB1 && reload_completed"
ecaf6f07
RE
5002 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
5003 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
5004 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
5005 ""
594726e4
JG
5006 [(set_attr "length" "6")
5007 (set_attr "type" "multiple")]
ecaf6f07
RE
5008)
5009
37f74dcf
RE
5010(define_expand "abssf2"
5011 [(set (match_operand:SF 0 "s_register_operand" "")
5012 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
5b3e6663 5013 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf
RE
5014 "")
5015
37f74dcf
RE
5016(define_expand "absdf2"
5017 [(set (match_operand:DF 0 "s_register_operand" "")
5018 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
e0dc3601 5019 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
37f74dcf
RE
5020 "")
5021
82955615
RE
5022(define_expand "sqrtsf2"
5023 [(set (match_operand:SF 0 "s_register_operand" "")
5024 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
8fcd8c83 5025 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
82955615 5026 "")
ff9940b0 5027
82955615
RE
5028(define_expand "sqrtdf2"
5029 [(set (match_operand:DF 0 "s_register_operand" "")
5030 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
8fcd8c83 5031 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
82955615 5032 "")
ff9940b0 5033
bb6ae783 5034(define_insn_and_split "one_cmpldi2"
14f986ed
AS
5035 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,?w")
5036 (not:DI (match_operand:DI 1 "s_register_operand" " w, 0, r, w")))]
5b3e6663 5037 "TARGET_32BIT"
14f986ed
AS
5038 "@
5039 vmvn\t%P0, %P1
5040 #
5041 #
5042 vmvn\t%P0, %P1"
5043 "TARGET_32BIT && reload_completed
5044 && arm_general_register_operand (operands[0], DImode)"
bb6ae783
RE
5045 [(set (match_dup 0) (not:SI (match_dup 1)))
5046 (set (match_dup 2) (not:SI (match_dup 3)))]
5047 "
5048 {
5049 operands[2] = gen_highpart (SImode, operands[0]);
5050 operands[0] = gen_lowpart (SImode, operands[0]);
5051 operands[3] = gen_highpart (SImode, operands[1]);
5052 operands[1] = gen_lowpart (SImode, operands[1]);
5053 }"
14f986ed
AS
5054 [(set_attr "length" "*,8,8,*")
5055 (set_attr "predicable" "no,yes,yes,no")
f7379e5e 5056 (set_attr "type" "neon_move,multiple,multiple,neon_move")
65074f54 5057 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")]
d5b7b3ae 5058)
3a33f76f 5059
d5b7b3ae
RE
5060(define_expand "one_cmplsi2"
5061 [(set (match_operand:SI 0 "s_register_operand" "")
5062 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
5063 "TARGET_EITHER"
3a33f76f 5064 ""
d5b7b3ae
RE
5065)
5066
5067(define_insn "*arm_one_cmplsi2"
31dfce10
KT
5068 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
5069 (not:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
5b3e6663 5070 "TARGET_32BIT"
d5b7b3ae 5071 "mvn%?\\t%0, %1"
f8045c41 5072 [(set_attr "predicable" "yes")
31dfce10
KT
5073 (set_attr "predicable_short_it" "yes,no")
5074 (set_attr "arch" "t2,*")
5075 (set_attr "length" "4")
859abddd 5076 (set_attr "type" "mvn_reg")]
d5b7b3ae
RE
5077)
5078
5b3e6663 5079(define_insn "*thumb1_one_cmplsi2"
d5b7b3ae
RE
5080 [(set (match_operand:SI 0 "register_operand" "=l")
5081 (not:SI (match_operand:SI 1 "register_operand" "l")))]
5b3e6663 5082 "TARGET_THUMB1"
d5b7b3ae 5083 "mvn\\t%0, %1"
f8045c41 5084 [(set_attr "length" "2")
859abddd 5085 (set_attr "type" "mvn_reg")]
d5b7b3ae 5086)
ff9940b0 5087
4cdb3ed4 5088(define_insn "*notsi_compare0"
48a08b9c 5089 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
5090 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5091 (const_int 0)))
5092 (set (match_operand:SI 0 "s_register_operand" "=r")
5093 (not:SI (match_dup 1)))]
5b3e6663
PB
5094 "TARGET_32BIT"
5095 "mvn%.\\t%0, %1"
f8045c41 5096 [(set_attr "conds" "set")
859abddd 5097 (set_attr "type" "mvn_reg")]
d5b7b3ae 5098)
ff9940b0 5099
4cdb3ed4 5100(define_insn "*notsi_compare0_scratch"
48a08b9c 5101 [(set (reg:CC_NOOV CC_REGNUM)
ff9940b0
RE
5102 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5103 (const_int 0)))
5104 (clobber (match_scratch:SI 0 "=r"))]
5b3e6663
PB
5105 "TARGET_32BIT"
5106 "mvn%.\\t%0, %1"
f8045c41 5107 [(set_attr "conds" "set")
859abddd 5108 (set_attr "type" "mvn_reg")]
d5b7b3ae 5109)
3a33f76f
RK
5110\f
5111;; Fixed <--> Floating conversion insns
5112
0fd8c3ad
SL
5113(define_expand "floatsihf2"
5114 [(set (match_operand:HF 0 "general_operand" "")
5115 (float:HF (match_operand:SI 1 "general_operand" "")))]
5116 "TARGET_EITHER"
5117 "
5118 {
5119 rtx op1 = gen_reg_rtx (SFmode);
5120 expand_float (op1, operands[1], 0);
5121 op1 = convert_to_mode (HFmode, op1, 0);
5122 emit_move_insn (operands[0], op1);
5123 DONE;
5124 }"
5125)
5126
5127(define_expand "floatdihf2"
5128 [(set (match_operand:HF 0 "general_operand" "")
5129 (float:HF (match_operand:DI 1 "general_operand" "")))]
5130 "TARGET_EITHER"
5131 "
5132 {
5133 rtx op1 = gen_reg_rtx (SFmode);
5134 expand_float (op1, operands[1], 0);
5135 op1 = convert_to_mode (HFmode, op1, 0);
5136 emit_move_insn (operands[0], op1);
5137 DONE;
5138 }"
5139)
5140
37f74dcf
RE
5141(define_expand "floatsisf2"
5142 [(set (match_operand:SF 0 "s_register_operand" "")
5143 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
5b3e6663 5144 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf 5145 "
37f74dcf
RE
5146")
5147
37f74dcf
RE
5148(define_expand "floatsidf2"
5149 [(set (match_operand:DF 0 "s_register_operand" "")
5150 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
e0dc3601 5151 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
37f74dcf 5152 "
37f74dcf
RE
5153")
5154
0fd8c3ad
SL
5155(define_expand "fix_trunchfsi2"
5156 [(set (match_operand:SI 0 "general_operand" "")
5157 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
5158 "TARGET_EITHER"
5159 "
5160 {
5161 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
5162 expand_fix (operands[0], op1, 0);
5163 DONE;
5164 }"
5165)
5166
5167(define_expand "fix_trunchfdi2"
5168 [(set (match_operand:DI 0 "general_operand" "")
5169 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
5170 "TARGET_EITHER"
5171 "
5172 {
5173 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
5174 expand_fix (operands[0], op1, 0);
5175 DONE;
5176 }"
5177)
5178
37f74dcf
RE
5179(define_expand "fix_truncsfsi2"
5180 [(set (match_operand:SI 0 "s_register_operand" "")
17136dde 5181 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
5b3e6663 5182 "TARGET_32BIT && TARGET_HARD_FLOAT"
37f74dcf 5183 "
37f74dcf
RE
5184")
5185
37f74dcf
RE
5186(define_expand "fix_truncdfsi2"
5187 [(set (match_operand:SI 0 "s_register_operand" "")
17136dde 5188 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
e0dc3601 5189 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
37f74dcf 5190 "
37f74dcf
RE
5191")
5192
3a7a2719 5193;; Truncation insns
3a33f76f 5194
37f74dcf
RE
5195(define_expand "truncdfsf2"
5196 [(set (match_operand:SF 0 "s_register_operand" "")
5197 (float_truncate:SF
5198 (match_operand:DF 1 "s_register_operand" "")))]
e0dc3601 5199 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
37f74dcf
RE
5200 ""
5201)
0fd8c3ad
SL
5202
5203/* DFmode -> HFmode conversions have to go through SFmode. */
5204(define_expand "truncdfhf2"
5205 [(set (match_operand:HF 0 "general_operand" "")
5206 (float_truncate:HF
5207 (match_operand:DF 1 "general_operand" "")))]
5208 "TARGET_EITHER"
5209 "
5210 {
5211 rtx op1;
5212 op1 = convert_to_mode (SFmode, operands[1], 0);
5213 op1 = convert_to_mode (HFmode, op1, 0);
5214 emit_move_insn (operands[0], op1);
5215 DONE;
5216 }"
5217)
3a33f76f 5218\f
ff9940b0 5219;; Zero and sign extension instructions.
3a33f76f 5220
da0a441d 5221(define_insn "zero_extend<mode>di2"
e0237780 5222 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,w")
8d4f1548
RR
5223 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
5224 "<qhs_zextenddi_cstr>")))]
da0a441d
BS
5225 "TARGET_32BIT <qhs_zextenddi_cond>"
5226 "#"
e0237780 5227 [(set_attr "length" "8,4,8,8")
65074f54 5228 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")
da0a441d 5229 (set_attr "ce_count" "2")
5393d83e
JG
5230 (set_attr "predicable" "yes")
5231 (set_attr "type" "multiple,mov_reg,multiple,multiple")]
5b3e6663
PB
5232)
5233
da0a441d 5234(define_insn "extend<mode>di2"
e0237780 5235 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,?r,w")
c9cdcaa5
BS
5236 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
5237 "<qhs_extenddi_cstr>")))]
da0a441d
BS
5238 "TARGET_32BIT <qhs_sextenddi_cond>"
5239 "#"
e0237780 5240 [(set_attr "length" "8,4,8,8,8")
da0a441d
BS
5241 (set_attr "ce_count" "2")
5242 (set_attr "shift" "1")
cdbf870f 5243 (set_attr "predicable" "yes")
594726e4
JG
5244 (set_attr "arch" "neon_for_64bits,*,a,t,avoid_neon_for_64bits")
5245 (set_attr "type" "multiple,mov_reg,multiple,multiple,multiple")]
cca0a211 5246)
ff9940b0 5247
da0a441d
BS
5248;; Splits for all extensions to DImode
5249(define_split
5250 [(set (match_operand:DI 0 "s_register_operand" "")
5251 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
e0237780 5252 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
da0a441d
BS
5253 [(set (match_dup 0) (match_dup 1))]
5254{
da0a441d
BS
5255 rtx lo_part = gen_lowpart (SImode, operands[0]);
5256 enum machine_mode src_mode = GET_MODE (operands[1]);
5257
5258 if (REG_P (operands[0])
5259 && !reg_overlap_mentioned_p (operands[0], operands[1]))
5260 emit_clobber (operands[0]);
5261 if (!REG_P (lo_part) || src_mode != SImode
5262 || !rtx_equal_p (lo_part, operands[1]))
5263 {
5264 if (src_mode == SImode)
5265 emit_move_insn (lo_part, operands[1]);
5266 else
5267 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
5268 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
5269 operands[1] = lo_part;
5270 }
5271 operands[0] = gen_highpart (SImode, operands[0]);
5272 operands[1] = const0_rtx;
5273})
ff9940b0 5274
da0a441d 5275(define_split
5b3e6663 5276 [(set (match_operand:DI 0 "s_register_operand" "")
da0a441d 5277 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
e0237780 5278 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
da0a441d
BS
5279 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
5280{
5281 rtx lo_part = gen_lowpart (SImode, operands[0]);
5282 enum machine_mode src_mode = GET_MODE (operands[1]);
5b3e6663 5283
da0a441d
BS
5284 if (REG_P (operands[0])
5285 && !reg_overlap_mentioned_p (operands[0], operands[1]))
5286 emit_clobber (operands[0]);
5287
5288 if (!REG_P (lo_part) || src_mode != SImode
5289 || !rtx_equal_p (lo_part, operands[1]))
5290 {
5291 if (src_mode == SImode)
5292 emit_move_insn (lo_part, operands[1]);
5293 else
5294 emit_insn (gen_rtx_SET (VOIDmode, lo_part,
5295 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
5296 operands[1] = lo_part;
5297 }
5298 operands[0] = gen_highpart (SImode, operands[0]);
5299})
ff9940b0
RE
5300
5301(define_expand "zero_extendhisi2"
e4c6a07a
BS
5302 [(set (match_operand:SI 0 "s_register_operand" "")
5303 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
d5b7b3ae 5304 "TARGET_EITHER"
e4c6a07a
BS
5305{
5306 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
4cdb3ed4 5307 {
e4c6a07a
BS
5308 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
5309 DONE;
988337ca 5310 }
e4c6a07a
BS
5311 if (!arm_arch6 && !MEM_P (operands[1]))
5312 {
5313 rtx t = gen_lowpart (SImode, operands[1]);
5314 rtx tmp = gen_reg_rtx (SImode);
5315 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5316 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
5317 DONE;
5318 }
5319})
ff9940b0 5320
e4c6a07a 5321(define_split
5acb7dec
CLT
5322 [(set (match_operand:SI 0 "s_register_operand" "")
5323 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
e4c6a07a
BS
5324 "!TARGET_THUMB2 && !arm_arch6"
5325 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5326 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
5327{
5328 operands[2] = gen_lowpart (SImode, operands[1]);
5329})
5330
5331(define_insn "*thumb1_zero_extendhisi2"
9b66ebb1
PB
5332 [(set (match_operand:SI 0 "register_operand" "=l,l")
5333 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
e4c6a07a 5334 "TARGET_THUMB1"
da0a441d 5335{
9b66ebb1
PB
5336 rtx mem;
5337
e4c6a07a 5338 if (which_alternative == 0 && arm_arch6)
da0a441d 5339 return "uxth\t%0, %1";
e4c6a07a 5340 if (which_alternative == 0)
da0a441d 5341 return "#";
9b66ebb1
PB
5342
5343 mem = XEXP (operands[1], 0);
5344
5345 if (GET_CODE (mem) == CONST)
5346 mem = XEXP (mem, 0);
5347
9b66ebb1
PB
5348 if (GET_CODE (mem) == PLUS)
5349 {
5350 rtx a = XEXP (mem, 0);
9b66ebb1
PB
5351
5352 /* This can happen due to bugs in reload. */
d435a4be 5353 if (REG_P (a) && REGNO (a) == SP_REGNUM)
9b66ebb1
PB
5354 {
5355 rtx ops[2];
5356 ops[0] = operands[0];
5357 ops[1] = a;
5358
da0a441d 5359 output_asm_insn ("mov\t%0, %1", ops);
9b66ebb1
PB
5360
5361 XEXP (mem, 0) = operands[0];
5362 }
9b66ebb1
PB
5363 }
5364
da0a441d
BS
5365 return "ldrh\t%0, %1";
5366}
e4c6a07a
BS
5367 [(set_attr_alternative "length"
5368 [(if_then_else (eq_attr "is_arch6" "yes")
5369 (const_int 2) (const_int 4))
5370 (const_int 4)])
006bd006 5371 (set_attr "type" "extend,load_byte")]
9b66ebb1
PB
5372)
5373
d5b7b3ae 5374(define_insn "*arm_zero_extendhisi2"
e4c6a07a
BS
5375 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5376 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
9b66ebb1 5377 "TARGET_ARM && arm_arch4 && !arm_arch6"
e4c6a07a
BS
5378 "@
5379 #
5380 ldr%(h%)\\t%0, %1"
6e4150e1 5381 [(set_attr "type" "alu_shift_reg,load_byte")
da0a441d 5382 (set_attr "predicable" "yes")]
d5b7b3ae 5383)
4cdb3ed4 5384
9b66ebb1
PB
5385(define_insn "*arm_zero_extendhisi2_v6"
5386 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5387 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
5388 "TARGET_ARM && arm_arch6"
5389 "@
5390 uxth%?\\t%0, %1
5b3e6663 5391 ldr%(h%)\\t%0, %1"
148413a4 5392 [(set_attr "predicable" "yes")
006bd006 5393 (set_attr "type" "extend,load_byte")]
9b66ebb1
PB
5394)
5395
5396(define_insn "*arm_zero_extendhisi2addsi"
5397 [(set (match_operand:SI 0 "s_register_operand" "=r")
5398 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5399 (match_operand:SI 2 "s_register_operand" "r")))]
5b3e6663 5400 "TARGET_INT_SIMD"
9b66ebb1 5401 "uxtah%?\\t%0, %2, %1"
6e4150e1 5402 [(set_attr "type" "alu_shift_reg")
31dfce10
KT
5403 (set_attr "predicable" "yes")
5404 (set_attr "predicable_short_it" "no")]
9b66ebb1
PB
5405)
5406
091426d3 5407(define_expand "zero_extendqisi2"
d5b7b3ae
RE
5408 [(set (match_operand:SI 0 "s_register_operand" "")
5409 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
5410 "TARGET_EITHER"
e4c6a07a 5411{
d435a4be 5412 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
091426d3 5413 {
e4c6a07a
BS
5414 emit_insn (gen_andsi3 (operands[0],
5415 gen_lowpart (SImode, operands[1]),
5416 GEN_INT (255)));
5417 DONE;
5418 }
5419 if (!arm_arch6 && !MEM_P (operands[1]))
5420 {
5421 rtx t = gen_lowpart (SImode, operands[1]);
5422 rtx tmp = gen_reg_rtx (SImode);
5423 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5424 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
5425 DONE;
5426 }
5427})
d5b7b3ae 5428
e4c6a07a 5429(define_split
5acb7dec
CLT
5430 [(set (match_operand:SI 0 "s_register_operand" "")
5431 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
e4c6a07a
BS
5432 "!arm_arch6"
5433 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5434 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
5435{
5436 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5437 if (TARGET_ARM)
5438 {
5439 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
091426d3
RE
5440 DONE;
5441 }
e4c6a07a 5442})
ff9940b0 5443
5b3e6663 5444(define_insn "*thumb1_zero_extendqisi2"
e4c6a07a
BS
5445 [(set (match_operand:SI 0 "register_operand" "=l,l")
5446 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
5b3e6663 5447 "TARGET_THUMB1 && !arm_arch6"
e4c6a07a
BS
5448 "@
5449 #
5450 ldrb\\t%0, %1"
5451 [(set_attr "length" "4,2")
6e4150e1 5452 (set_attr "type" "alu_shift_reg,load_byte")
e4c6a07a 5453 (set_attr "pool_range" "*,32")]
d5b7b3ae
RE
5454)
5455
5b3e6663 5456(define_insn "*thumb1_zero_extendqisi2_v6"
9b66ebb1
PB
5457 [(set (match_operand:SI 0 "register_operand" "=l,l")
5458 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
5b3e6663 5459 "TARGET_THUMB1 && arm_arch6"
9b66ebb1
PB
5460 "@
5461 uxtb\\t%0, %1
5462 ldrb\\t%0, %1"
da0a441d 5463 [(set_attr "length" "2")
006bd006 5464 (set_attr "type" "extend,load_byte")]
9b66ebb1
PB
5465)
5466
d5b7b3ae 5467(define_insn "*arm_zero_extendqisi2"
e4c6a07a
BS
5468 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5469 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
9b66ebb1 5470 "TARGET_ARM && !arm_arch6"
e4c6a07a
BS
5471 "@
5472 #
5473 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
5474 [(set_attr "length" "8,4")
6e4150e1 5475 (set_attr "type" "alu_shift_reg,load_byte")
da0a441d 5476 (set_attr "predicable" "yes")]
d5b7b3ae 5477)
091426d3 5478
9b66ebb1
PB
5479(define_insn "*arm_zero_extendqisi2_v6"
5480 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5481 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
5482 "TARGET_ARM && arm_arch6"
5483 "@
5b3e6663
PB
5484 uxtb%(%)\\t%0, %1
5485 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
006bd006 5486 [(set_attr "type" "extend,load_byte")
da0a441d 5487 (set_attr "predicable" "yes")]
9b66ebb1
PB
5488)
5489
5490(define_insn "*arm_zero_extendqisi2addsi"
5491 [(set (match_operand:SI 0 "s_register_operand" "=r")
5492 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5493 (match_operand:SI 2 "s_register_operand" "r")))]
5b3e6663 5494 "TARGET_INT_SIMD"
9b66ebb1
PB
5495 "uxtab%?\\t%0, %2, %1"
5496 [(set_attr "predicable" "yes")
31dfce10 5497 (set_attr "predicable_short_it" "no")
6e4150e1 5498 (set_attr "type" "alu_shift_reg")]
9b66ebb1
PB
5499)
5500
091426d3
RE
5501(define_split
5502 [(set (match_operand:SI 0 "s_register_operand" "")
5503 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
5504 (clobber (match_operand:SI 2 "s_register_operand" ""))]
d435a4be 5505 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
091426d3
RE
5506 [(set (match_dup 2) (match_dup 1))
5507 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
d5b7b3ae
RE
5508 ""
5509)
ff9940b0 5510
174ddc67
RS
5511(define_split
5512 [(set (match_operand:SI 0 "s_register_operand" "")
5513 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
5514 (clobber (match_operand:SI 2 "s_register_operand" ""))]
d435a4be 5515 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
174ddc67
RS
5516 [(set (match_dup 2) (match_dup 1))
5517 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
5518 ""
5519)
5520
fa01135d
RE
5521
5522(define_split
5523 [(set (match_operand:SI 0 "s_register_operand" "")
5524 (ior_xor:SI (and:SI (ashift:SI
5525 (match_operand:SI 1 "s_register_operand" "")
5526 (match_operand:SI 2 "const_int_operand" ""))
5527 (match_operand:SI 3 "const_int_operand" ""))
5528 (zero_extend:SI
5529 (match_operator 5 "subreg_lowpart_operator"
5530 [(match_operand:SI 4 "s_register_operand" "")]))))]
5531 "TARGET_32BIT
6d53a79f 5532 && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
fa01135d
RE
5533 == (GET_MODE_MASK (GET_MODE (operands[5]))
5534 & (GET_MODE_MASK (GET_MODE (operands[5]))
5535 << (INTVAL (operands[2])))))"
5536 [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
5537 (match_dup 4)))
5538 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
5539 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
5540)
5541
4cdb3ed4 5542(define_insn "*compareqi_eq0"
48a08b9c 5543 [(set (reg:CC_Z CC_REGNUM)
0502226c 5544 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
091426d3 5545 (const_int 0)))]
5b3e6663 5546 "TARGET_32BIT"
cc50a1e1
RH
5547 "tst%?\\t%0, #255"
5548 [(set_attr "conds" "set")
31dfce10 5549 (set_attr "predicable" "yes")
594726e4
JG
5550 (set_attr "predicable_short_it" "no")
5551 (set_attr "type" "logic_imm")]
d5b7b3ae 5552)
3a33f76f 5553
3a33f76f 5554(define_expand "extendhisi2"
e4c6a07a
BS
5555 [(set (match_operand:SI 0 "s_register_operand" "")
5556 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
d5b7b3ae 5557 "TARGET_EITHER"
e4c6a07a
BS
5558{
5559 if (TARGET_THUMB1)
5560 {
5561 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
5562 DONE;
5563 }
5564 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
5565 {
5566 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
5567 DONE;
5568 }
e6d29d15 5569
e4c6a07a
BS
5570 if (!arm_arch6 && !MEM_P (operands[1]))
5571 {
5572 rtx t = gen_lowpart (SImode, operands[1]);
5573 rtx tmp = gen_reg_rtx (SImode);
5574 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5575 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
5576 DONE;
5577 }
5578})
d5b7b3ae 5579
e4c6a07a
BS
5580(define_split
5581 [(parallel
5582 [(set (match_operand:SI 0 "register_operand" "")
5583 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
5584 (clobber (match_scratch:SI 2 ""))])]
5585 "!arm_arch6"
5586 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5587 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5588{
5589 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5590})
988337ca 5591
9b66ebb1
PB
5592;; We used to have an early-clobber on the scratch register here.
5593;; However, there's a bug somewhere in reload which means that this
5594;; can be partially ignored during spill allocation if the memory
e6d29d15 5595;; address also needs reloading; this causes us to die later on when
9b66ebb1
PB
5596;; we try to verify the operands. Fortunately, we don't really need
5597;; the early-clobber: we can always use operand 0 if operand 2
5598;; overlaps the address.
e4c6a07a 5599(define_insn "thumb1_extendhisi2"
9b66ebb1
PB
5600 [(set (match_operand:SI 0 "register_operand" "=l,l")
5601 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
5602 (clobber (match_scratch:SI 2 "=X,l"))]
e4c6a07a 5603 "TARGET_THUMB1"
9b66ebb1
PB
5604 "*
5605 {
5606 rtx ops[4];
5607 rtx mem;
5608
e4c6a07a
BS
5609 if (which_alternative == 0 && !arm_arch6)
5610 return \"#\";
9b66ebb1
PB
5611 if (which_alternative == 0)
5612 return \"sxth\\t%0, %1\";
5613
5614 mem = XEXP (operands[1], 0);
5615
5616 /* This code used to try to use 'V', and fix the address only if it was
5617 offsettable, but this fails for e.g. REG+48 because 48 is outside the
5618 range of QImode offsets, and offsettable_address_p does a QImode
5619 address check. */
5620
5621 if (GET_CODE (mem) == CONST)
5622 mem = XEXP (mem, 0);
5623
5624 if (GET_CODE (mem) == LABEL_REF)
5625 return \"ldr\\t%0, %1\";
5626
5627 if (GET_CODE (mem) == PLUS)
5628 {
5629 rtx a = XEXP (mem, 0);
5630 rtx b = XEXP (mem, 1);
5631
5632 if (GET_CODE (a) == LABEL_REF
d435a4be 5633 && CONST_INT_P (b))
9b66ebb1
PB
5634 return \"ldr\\t%0, %1\";
5635
d435a4be 5636 if (REG_P (b))
9b66ebb1
PB
5637 return \"ldrsh\\t%0, %1\";
5638
5639 ops[1] = a;
5640 ops[2] = b;
5641 }
5642 else
5643 {
5644 ops[1] = mem;
5645 ops[2] = const0_rtx;
5646 }
5647
d435a4be 5648 gcc_assert (REG_P (ops[1]));
9b66ebb1
PB
5649
5650 ops[0] = operands[0];
5651 if (reg_mentioned_p (operands[2], ops[1]))
5652 ops[3] = ops[0];
5653 else
5654 ops[3] = operands[2];
5655 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
5656 return \"\";
5657 }"
e4c6a07a
BS
5658 [(set_attr_alternative "length"
5659 [(if_then_else (eq_attr "is_arch6" "yes")
5660 (const_int 2) (const_int 4))
5661 (const_int 4)])
006bd006 5662 (set_attr "type" "extend,load_byte")
88f519b2 5663 (set_attr "pool_range" "*,1018")]
9b66ebb1
PB
5664)
5665
5b3e6663 5666;; This pattern will only be used when ldsh is not available
988337ca 5667(define_expand "extendhisi2_mem"
34757369 5668 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
988337ca 5669 (set (match_dup 3)
34757369 5670 (zero_extend:SI (match_dup 7)))
988337ca
RE
5671 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
5672 (set (match_operand:SI 0 "" "")
5673 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
d5b7b3ae 5674 "TARGET_ARM"
988337ca 5675 "
5895f793
RE
5676 {
5677 rtx mem1, mem2;
5678 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5679
31fa16b6 5680 mem1 = change_address (operands[1], QImode, addr);
0a81f074
RS
5681 mem2 = change_address (operands[1], QImode,
5682 plus_constant (Pmode, addr, 1));
5895f793
RE
5683 operands[0] = gen_lowpart (SImode, operands[0]);
5684 operands[1] = mem1;
5685 operands[2] = gen_reg_rtx (SImode);
5686 operands[3] = gen_reg_rtx (SImode);
5687 operands[6] = gen_reg_rtx (SImode);
5688 operands[7] = mem2;
988337ca 5689
5895f793
RE
5690 if (BYTES_BIG_ENDIAN)
5691 {
5692 operands[4] = operands[2];
5693 operands[5] = operands[3];
5694 }
5695 else
5696 {
5697 operands[4] = operands[3];
5698 operands[5] = operands[2];
5699 }
5700 }"
5701)
3a33f76f 5702
e4c6a07a
BS
5703(define_split
5704 [(set (match_operand:SI 0 "register_operand" "")
5705 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
5706 "!arm_arch6"
5707 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5708 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5709{
5710 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5711})
5712
9b66ebb1 5713(define_insn "*arm_extendhisi2"
e4c6a07a
BS
5714 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5715 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
9b66ebb1 5716 "TARGET_ARM && arm_arch4 && !arm_arch6"
e4c6a07a
BS
5717 "@
5718 #
5719 ldr%(sh%)\\t%0, %1"
5720 [(set_attr "length" "8,4")
6e4150e1 5721 (set_attr "type" "alu_shift_reg,load_byte")
cca0a211 5722 (set_attr "predicable" "yes")
e4c6a07a
BS
5723 (set_attr "pool_range" "*,256")
5724 (set_attr "neg_pool_range" "*,244")]
d5b7b3ae 5725)
4cdb3ed4 5726
5b3e6663 5727;; ??? Check Thumb-2 pool range
9b66ebb1
PB
5728(define_insn "*arm_extendhisi2_v6"
5729 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5730 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
5b3e6663 5731 "TARGET_32BIT && arm_arch6"
9b66ebb1
PB
5732 "@
5733 sxth%?\\t%0, %1
5b3e6663 5734 ldr%(sh%)\\t%0, %1"
006bd006 5735 [(set_attr "type" "extend,load_byte")
9b66ebb1 5736 (set_attr "predicable" "yes")
31dfce10 5737 (set_attr "predicable_short_it" "no")
9b66ebb1
PB
5738 (set_attr "pool_range" "*,256")
5739 (set_attr "neg_pool_range" "*,244")]
5740)
5741
5742(define_insn "*arm_extendhisi2addsi"
5743 [(set (match_operand:SI 0 "s_register_operand" "=r")
5744 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5745 (match_operand:SI 2 "s_register_operand" "r")))]
5b3e6663 5746 "TARGET_INT_SIMD"
9b66ebb1 5747 "sxtah%?\\t%0, %2, %1"
594726e4 5748 [(set_attr "type" "alu_shift_reg")]
9b66ebb1
PB
5749)
5750
fd3f89a9
TG
5751(define_expand "extendqihi2"
5752 [(set (match_dup 2)
01577df7 5753 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
fd3f89a9 5754 (const_int 24)))
ff9940b0 5755 (set (match_operand:HI 0 "s_register_operand" "")
fd3f89a9
TG
5756 (ashiftrt:SI (match_dup 2)
5757 (const_int 24)))]
d5b7b3ae 5758 "TARGET_ARM"
fd3f89a9 5759 "
5895f793 5760 {
d435a4be 5761 if (arm_arch4 && MEM_P (operands[1]))
5895f793
RE
5762 {
5763 emit_insn (gen_rtx_SET (VOIDmode,
5764 operands[0],
5765 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
5766 DONE;
5767 }
5768 if (!s_register_operand (operands[1], QImode))
5769 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5770 operands[0] = gen_lowpart (SImode, operands[0]);
5771 operands[1] = gen_lowpart (SImode, operands[1]);
5772 operands[2] = gen_reg_rtx (SImode);
5773 }"
5774)
4cdb3ed4 5775
5b3e6663 5776(define_insn "*arm_extendqihi_insn"
1e1ab407 5777 [(set (match_operand:HI 0 "s_register_operand" "=r")
01577df7 5778 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
d5b7b3ae 5779 "TARGET_ARM && arm_arch4"
5b3e6663 5780 "ldr%(sb%)\\t%0, %1"
9b66ebb1 5781 [(set_attr "type" "load_byte")
cca0a211 5782 (set_attr "predicable" "yes")
d5b7b3ae
RE
5783 (set_attr "pool_range" "256")
5784 (set_attr "neg_pool_range" "244")]
5785)
4d818c85 5786
3a33f76f 5787(define_expand "extendqisi2"
e4c6a07a
BS
5788 [(set (match_operand:SI 0 "s_register_operand" "")
5789 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
d5b7b3ae 5790 "TARGET_EITHER"
e4c6a07a
BS
5791{
5792 if (!arm_arch4 && MEM_P (operands[1]))
5793 operands[1] = copy_to_mode_reg (QImode, operands[1]);
9b66ebb1 5794
e4c6a07a
BS
5795 if (!arm_arch6 && !MEM_P (operands[1]))
5796 {
5797 rtx t = gen_lowpart (SImode, operands[1]);
5798 rtx tmp = gen_reg_rtx (SImode);
5799 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5800 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
5801 DONE;
5802 }
5803})
9b66ebb1 5804
e4c6a07a
BS
5805(define_split
5806 [(set (match_operand:SI 0 "register_operand" "")
5807 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5808 "!arm_arch6"
5809 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5810 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5811{
5812 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5813})
4cdb3ed4 5814
9b66ebb1 5815(define_insn "*arm_extendqisi"
e4c6a07a
BS
5816 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5817 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
9b66ebb1 5818 "TARGET_ARM && arm_arch4 && !arm_arch6"
e4c6a07a
BS
5819 "@
5820 #
5821 ldr%(sb%)\\t%0, %1"
5822 [(set_attr "length" "8,4")
6e4150e1 5823 (set_attr "type" "alu_shift_reg,load_byte")
cca0a211 5824 (set_attr "predicable" "yes")
e4c6a07a
BS
5825 (set_attr "pool_range" "*,256")
5826 (set_attr "neg_pool_range" "*,244")]
d5b7b3ae 5827)
4d818c85 5828
9b66ebb1
PB
5829(define_insn "*arm_extendqisi_v6"
5830 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
01577df7
RE
5831 (sign_extend:SI
5832 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
9b66ebb1 5833 "TARGET_ARM && arm_arch6"
1e1ab407
RE
5834 "@
5835 sxtb%?\\t%0, %1
5b3e6663 5836 ldr%(sb%)\\t%0, %1"
006bd006 5837 [(set_attr "type" "extend,load_byte")
9b66ebb1 5838 (set_attr "predicable" "yes")
9b66ebb1
PB
5839 (set_attr "pool_range" "*,256")
5840 (set_attr "neg_pool_range" "*,244")]
5841)
5842
5843(define_insn "*arm_extendqisi2addsi"
5844 [(set (match_operand:SI 0 "s_register_operand" "=r")
5845 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5846 (match_operand:SI 2 "s_register_operand" "r")))]
5b3e6663 5847 "TARGET_INT_SIMD"
9b66ebb1 5848 "sxtab%?\\t%0, %2, %1"
6e4150e1 5849 [(set_attr "type" "alu_shift_reg")
31dfce10
KT
5850 (set_attr "predicable" "yes")
5851 (set_attr "predicable_short_it" "no")]
9b66ebb1
PB
5852)
5853
e4c6a07a
BS
5854(define_split
5855 [(set (match_operand:SI 0 "register_operand" "")
5856 (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))]
5857 "TARGET_THUMB1 && reload_completed"
5858 [(set (match_dup 0) (match_dup 2))
5859 (set (match_dup 0) (sign_extend:SI (match_dup 3)))]
5860{
5861 rtx addr = XEXP (operands[1], 0);
d5b7b3ae 5862
e4c6a07a
BS
5863 if (GET_CODE (addr) == CONST)
5864 addr = XEXP (addr, 0);
d5b7b3ae 5865
e4c6a07a
BS
5866 if (GET_CODE (addr) == PLUS
5867 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
5868 /* No split necessary. */
5869 FAIL;
5870
5871 if (GET_CODE (addr) == PLUS
5872 && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1)))
5873 FAIL;
5874
5875 if (reg_overlap_mentioned_p (operands[0], addr))
5876 {
5877 rtx t = gen_lowpart (QImode, operands[0]);
5878 emit_move_insn (t, operands[1]);
5879 emit_insn (gen_thumb1_extendqisi2 (operands[0], t));
5880 DONE;
5881 }
5882
5883 if (REG_P (addr))
5884 {
5885 addr = gen_rtx_PLUS (Pmode, addr, operands[0]);
5886 operands[2] = const0_rtx;
5887 }
5888 else if (GET_CODE (addr) != PLUS)
5889 FAIL;
5890 else if (REG_P (XEXP (addr, 0)))
5891 {
5892 operands[2] = XEXP (addr, 1);
5893 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]);
5894 }
5895 else
5896 {
5897 operands[2] = XEXP (addr, 0);
5898 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]);
5899 }
d5b7b3ae 5900
e4c6a07a
BS
5901 operands[3] = change_address (operands[1], QImode, addr);
5902})
5903
1744c800
BS
5904(define_peephole2
5905 [(set (match_operand:SI 0 "register_operand" "")
5906 (plus:SI (match_dup 0) (match_operand 1 "const_int_operand")))
5907 (set (match_operand:SI 2 "register_operand" "") (const_int 0))
5908 (set (match_operand:SI 3 "register_operand" "")
5909 (sign_extend:SI (match_operand:QI 4 "memory_operand" "")))]
5910 "TARGET_THUMB1
5911 && GET_CODE (XEXP (operands[4], 0)) == PLUS
5912 && rtx_equal_p (operands[0], XEXP (XEXP (operands[4], 0), 0))
5913 && rtx_equal_p (operands[2], XEXP (XEXP (operands[4], 0), 1))
5914 && (peep2_reg_dead_p (3, operands[0])
5915 || rtx_equal_p (operands[0], operands[3]))
5916 && (peep2_reg_dead_p (3, operands[2])
5917 || rtx_equal_p (operands[2], operands[3]))"
5918 [(set (match_dup 2) (match_dup 1))
5919 (set (match_dup 3) (sign_extend:SI (match_dup 4)))]
5920{
5921 rtx addr = gen_rtx_PLUS (Pmode, operands[0], operands[2]);
5922 operands[4] = change_address (operands[4], QImode, addr);
5923})
5924
e4c6a07a 5925(define_insn "thumb1_extendqisi2"
9b66ebb1
PB
5926 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
5927 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
e4c6a07a
BS
5928 "TARGET_THUMB1"
5929{
5930 rtx addr;
9b66ebb1 5931
e4c6a07a
BS
5932 if (which_alternative == 0 && arm_arch6)
5933 return "sxtb\\t%0, %1";
5934 if (which_alternative == 0)
5935 return "#";
9b66ebb1 5936
e4c6a07a
BS
5937 addr = XEXP (operands[1], 0);
5938 if (GET_CODE (addr) == PLUS
5939 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
5940 return "ldrsb\\t%0, %1";
9b66ebb1 5941
e4c6a07a
BS
5942 return "#";
5943}
5944 [(set_attr_alternative "length"
5945 [(if_then_else (eq_attr "is_arch6" "yes")
5946 (const_int 2) (const_int 4))
5947 (const_int 2)
5948 (if_then_else (eq_attr "is_arch6" "yes")
5949 (const_int 4) (const_int 6))])
006bd006 5950 (set_attr "type" "extend,load_byte,load_byte")]
9b66ebb1
PB
5951)
5952
1e3af7f6
NC
5953(define_expand "extendsfdf2"
5954 [(set (match_operand:DF 0 "s_register_operand" "")
5955 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
e0dc3601 5956 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1e3af7f6
NC
5957 ""
5958)
0fd8c3ad
SL
5959
5960/* HFmode -> DFmode conversions have to go through SFmode. */
5961(define_expand "extendhfdf2"
5962 [(set (match_operand:DF 0 "general_operand" "")
5963 (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
5964 "TARGET_EITHER"
5965 "
5966 {
5967 rtx op1;
5968 op1 = convert_to_mode (SFmode, operands[1], 0);
5969 op1 = convert_to_mode (DFmode, op1, 0);
5970 emit_insn (gen_movdf (operands[0], op1));
5971 DONE;
5972 }"
5973)
3a33f76f
RK
5974\f
5975;; Move insns (including loads and stores)
5976
5977;; XXX Just some ideas about movti.
ff9940b0
RE
5978;; I don't think these are a good idea on the arm, there just aren't enough
5979;; registers
3a33f76f 5980;;(define_expand "loadti"
ff9940b0 5981;; [(set (match_operand:TI 0 "s_register_operand" "")
3a33f76f
RK
5982;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
5983;; "" "")
5984
5985;;(define_expand "storeti"
5986;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
ff9940b0 5987;; (match_operand:TI 1 "s_register_operand" ""))]
3a33f76f
RK
5988;; "" "")
5989
5990;;(define_expand "movti"
5991;; [(set (match_operand:TI 0 "general_operand" "")
5992;; (match_operand:TI 1 "general_operand" ""))]
5993;; ""
5994;; "
5995;;{
5996;; rtx insn;
5997;;
d435a4be 5998;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
3a33f76f 5999;; operands[1] = copy_to_reg (operands[1]);
d435a4be 6000;; if (MEM_P (operands[0]))
3a33f76f 6001;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
d435a4be 6002;; else if (MEM_P (operands[1]))
3a33f76f
RK
6003;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
6004;; else
6005;; FAIL;
6006;;
6007;; emit_insn (insn);
6008;; DONE;
6009;;}")
6010
05713b80 6011;; Recognize garbage generated above.
3a33f76f
RK
6012
6013;;(define_insn ""
6014;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
6015;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
6016;; ""
6017;; "*
6018;; {
6019;; register mem = (which_alternative < 3);
cca0a211 6020;; register const char *template;
3a33f76f
RK
6021;;
6022;; operands[mem] = XEXP (operands[mem], 0);
6023;; switch (which_alternative)
6024;; {
6025;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
6026;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
6027;; case 2: template = \"ldmia\\t%1, %M0\"; break;
6028;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
6029;; case 4: template = \"stmia\\t%0!, %M1\"; break;
6030;; case 5: template = \"stmia\\t%0, %M1\"; break;
6031;; }
0f447ef2
RE
6032;; output_asm_insn (template, operands);
6033;; return \"\";
3a33f76f
RK
6034;; }")
6035
d5b7b3ae
RE
6036(define_expand "movdi"
6037 [(set (match_operand:DI 0 "general_operand" "")
6038 (match_operand:DI 1 "general_operand" ""))]
6039 "TARGET_EITHER"
6040 "
b3a13419 6041 if (can_create_pseudo_p ())
d5b7b3ae 6042 {
d435a4be 6043 if (!REG_P (operands[0]))
d5b6e637 6044 operands[1] = force_reg (DImode, operands[1]);
d5b7b3ae
RE
6045 }
6046 "
6047)
3a33f76f 6048
d5b7b3ae 6049(define_insn "*arm_movdi"
4542a38a
GY
6050 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, q, m")
6051 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,q"))]
0bd44ba2 6052 "TARGET_32BIT
479f7546 6053 && !(TARGET_HARD_FLOAT && TARGET_VFP)
d5b6e637
PB
6054 && !TARGET_IWMMXT
6055 && ( register_operand (operands[0], DImode)
6056 || register_operand (operands[1], DImode))"
3a33f76f 6057 "*
9b901d50
RE
6058 switch (which_alternative)
6059 {
6060 case 0:
6061 case 1:
6062 case 2:
6063 return \"#\";
6064 default:
3598da80 6065 return output_move_double (operands, true, NULL);
9b901d50 6066 }
d5b7b3ae 6067 "
2075b05d 6068 [(set_attr "length" "8,12,16,8,8")
594726e4 6069 (set_attr "type" "multiple,multiple,multiple,load2,store2")
0bd44ba2 6070 (set_attr "arm_pool_range" "*,*,*,1020,*")
635a48fb 6071 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
88f519b2 6072 (set_attr "thumb2_pool_range" "*,*,*,4094,*")
0bd44ba2 6073 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
d5b7b3ae
RE
6074)
6075
9b901d50
RE
6076(define_split
6077 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
6078 (match_operand:ANY64 1 "const_double_operand" ""))]
5b3e6663 6079 "TARGET_32BIT
9b901d50
RE
6080 && reload_completed
6081 && (arm_const_double_inline_cost (operands[1])
02231c13 6082 <= arm_max_const_double_inline_cost ())"
9b901d50
RE
6083 [(const_int 0)]
6084 "
6085 arm_split_constant (SET, SImode, curr_insn,
6086 INTVAL (gen_lowpart (SImode, operands[1])),
6087 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
6088 arm_split_constant (SET, SImode, curr_insn,
6089 INTVAL (gen_highpart_mode (SImode,
6090 GET_MODE (operands[0]),
6091 operands[1])),
6092 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
6093 DONE;
6094 "
6095)
6096
b4a58f80
RE
6097; If optimizing for size, or if we have load delay slots, then
6098; we want to split the constant into two separate operations.
6099; In both cases this may split a trivial part into a single data op
6100; leaving a single complex constant to load. We can also get longer
6101; offsets in a LDR which means we get better chances of sharing the pool
6102; entries. Finally, we can normally do a better job of scheduling
6103; LDR instructions than we can with LDM.
6104; This pattern will only match if the one above did not.
6105(define_split
6106 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
6107 (match_operand:ANY64 1 "const_double_operand" ""))]
6108 "TARGET_ARM && reload_completed
6109 && arm_const_double_by_parts (operands[1])"
6110 [(set (match_dup 0) (match_dup 1))
6111 (set (match_dup 2) (match_dup 3))]
6112 "
6113 operands[2] = gen_highpart (SImode, operands[0]);
6114 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
6115 operands[1]);
6116 operands[0] = gen_lowpart (SImode, operands[0]);
6117 operands[1] = gen_lowpart (SImode, operands[1]);
6118 "
6119)
6120
9b901d50
RE
6121(define_split
6122 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
6123 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
6124 "TARGET_EITHER && reload_completed"
6125 [(set (match_dup 0) (match_dup 1))
6126 (set (match_dup 2) (match_dup 3))]
6127 "
6128 operands[2] = gen_highpart (SImode, operands[0]);
6129 operands[3] = gen_highpart (SImode, operands[1]);
6130 operands[0] = gen_lowpart (SImode, operands[0]);
6131 operands[1] = gen_lowpart (SImode, operands[1]);
6132
6133 /* Handle a partial overlap. */
6134 if (rtx_equal_p (operands[0], operands[3]))
6135 {
6136 rtx tmp0 = operands[0];
6137 rtx tmp1 = operands[1];
6138
6139 operands[0] = operands[2];
6140 operands[1] = operands[3];
6141 operands[2] = tmp0;
6142 operands[3] = tmp1;
6143 }
6144 "
6145)
6146
fdd695fd
PB
6147;; We can't actually do base+index doubleword loads if the index and
6148;; destination overlap. Split here so that we at least have chance to
6149;; schedule.
6150(define_split
6151 [(set (match_operand:DI 0 "s_register_operand" "")
6152 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
6153 (match_operand:SI 2 "s_register_operand" ""))))]
6154 "TARGET_LDRD
6155 && reg_overlap_mentioned_p (operands[0], operands[1])
6156 && reg_overlap_mentioned_p (operands[0], operands[2])"
6157 [(set (match_dup 4)
6158 (plus:SI (match_dup 1)
6159 (match_dup 2)))
6160 (set (match_dup 0)
6161 (mem:DI (match_dup 4)))]
6162 "
6163 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
6164 "
6165)
6166
d5b7b3ae
RE
6167;;; ??? This should have alternatives for constants.
6168;;; ??? This was originally identical to the movdf_insn pattern.
6169;;; ??? The 'i' constraint looks funny, but it should always be replaced by
6170;;; thumb_reorg with a memory reference.
5b3e6663 6171(define_insn "*thumb1_movdi_insn"
5895f793
RE
6172 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
6173 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
5b3e6663 6174 "TARGET_THUMB1
d5b7b3ae
RE
6175 && ( register_operand (operands[0], DImode)
6176 || register_operand (operands[1], DImode))"
6177 "*
6178 {
6179 switch (which_alternative)
6180 {
6181 default:
6182 case 0:
6183 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6184 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6185 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6186 case 1:
6187 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
6188 case 2:
6189 operands[1] = GEN_INT (- INTVAL (operands[1]));
6190 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
6191 case 3:
6192 return \"ldmia\\t%1, {%0, %H0}\";
6193 case 4:
6194 return \"stmia\\t%0, {%1, %H1}\";
6195 case 5:
6196 return thumb_load_double_from_address (operands);
6197 case 6:
f1c25d3b 6198 operands[2] = gen_rtx_MEM (SImode,
0a81f074 6199 plus_constant (Pmode, XEXP (operands[0], 0), 4));
d5b7b3ae
RE
6200 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6201 return \"\";
6202 case 7:
6203 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6204 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6205 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6206 }
6207 }"
6208 [(set_attr "length" "4,4,6,2,2,6,4,4")
9ea187a5 6209 (set_attr "type" "multiple,multiple,multiple,load2,store2,load2,store2,multiple")
88f519b2 6210 (set_attr "pool_range" "*,*,*,*,*,1018,*,*")]
d5b7b3ae 6211)
3a33f76f 6212
ff9940b0
RE
6213(define_expand "movsi"
6214 [(set (match_operand:SI 0 "general_operand" "")
6215 (match_operand:SI 1 "general_operand" ""))]
d5b7b3ae 6216 "TARGET_EITHER"
ff9940b0 6217 "
2c3de459 6218 {
8426b956
RS
6219 rtx base, offset, tmp;
6220
5b3e6663 6221 if (TARGET_32BIT)
ff9940b0 6222 {
d6b4baa4 6223 /* Everything except mem = const or mem = mem can be done easily. */
d435a4be 6224 if (MEM_P (operands[0]))
d5b7b3ae 6225 operands[1] = force_reg (SImode, operands[1]);
9b66ebb1 6226 if (arm_general_register_operand (operands[0], SImode)
d435a4be 6227 && CONST_INT_P (operands[1])
d5b7b3ae
RE
6228 && !(const_ok_for_arm (INTVAL (operands[1]))
6229 || const_ok_for_arm (~INTVAL (operands[1]))))
6230 {
a406f566
MM
6231 arm_split_constant (SET, SImode, NULL_RTX,
6232 INTVAL (operands[1]), operands[0], NULL_RTX,
b3a13419 6233 optimize && can_create_pseudo_p ());
d5b7b3ae
RE
6234 DONE;
6235 }
6236 }
5b3e6663 6237 else /* TARGET_THUMB1... */
d5b7b3ae 6238 {
b3a13419 6239 if (can_create_pseudo_p ())
d5b7b3ae 6240 {
d435a4be 6241 if (!REG_P (operands[0]))
d5b7b3ae
RE
6242 operands[1] = force_reg (SImode, operands[1]);
6243 }
ff9940b0 6244 }
d3585b76 6245
8426b956
RS
6246 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
6247 {
6248 split_const (operands[1], &base, &offset);
6249 if (GET_CODE (base) == SYMBOL_REF
6250 && !offset_within_block_p (base, INTVAL (offset)))
6251 {
08a576fb 6252 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
8426b956
RS
6253 emit_move_insn (tmp, base);
6254 emit_insn (gen_addsi3 (operands[0], tmp, offset));
6255 DONE;
6256 }
6257 }
6258
d3585b76
DJ
6259 /* Recognize the case where operand[1] is a reference to thread-local
6260 data and load its address to a register. */
6261 if (arm_tls_referenced_p (operands[1]))
6262 {
6263 rtx tmp = operands[1];
6264 rtx addend = NULL;
6265
6266 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
6267 {
6268 addend = XEXP (XEXP (tmp, 0), 1);
6269 tmp = XEXP (XEXP (tmp, 0), 0);
6270 }
6271
6272 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
6273 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
6274
b3a13419
ILT
6275 tmp = legitimize_tls_address (tmp,
6276 !can_create_pseudo_p () ? operands[0] : 0);
d3585b76
DJ
6277 if (addend)
6278 {
6279 tmp = gen_rtx_PLUS (SImode, tmp, addend);
6280 tmp = force_operand (tmp, operands[0]);
6281 }
6282 operands[1] = tmp;
6283 }
6284 else if (flag_pic
6285 && (CONSTANT_P (operands[1])
6286 || symbol_mentioned_p (operands[1])
6287 || label_mentioned_p (operands[1])))
6288 operands[1] = legitimize_pic_address (operands[1], SImode,
b3a13419
ILT
6289 (!can_create_pseudo_p ()
6290 ? operands[0]
6291 : 0));
2c3de459 6292 }
5895f793
RE
6293 "
6294)
ff9940b0 6295
571191af
PB
6296;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
6297;; LO_SUM adds in the high bits. Fortunately these are opaque operations
6298;; so this does not matter.
6299(define_insn "*arm_movt"
6300 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
6301 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
6302 (match_operand:SI 2 "general_operand" "i")))]
cce470f9 6303 "arm_arch_thumb2"
571191af
PB
6304 "movt%?\t%0, #:upper16:%c2"
6305 [(set_attr "predicable" "yes")
31dfce10 6306 (set_attr "predicable_short_it" "no")
594726e4
JG
6307 (set_attr "length" "4")
6308 (set_attr "type" "mov_imm")]
571191af
PB
6309)
6310
d5b7b3ae 6311(define_insn "*arm_movsi_insn"
f5c630c3 6312 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
d58bc084 6313 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
5a9335ef 6314 "TARGET_ARM && ! TARGET_IWMMXT
9b66ebb1 6315 && !(TARGET_HARD_FLOAT && TARGET_VFP)
d5b7b3ae
RE
6316 && ( register_operand (operands[0], SImode)
6317 || register_operand (operands[1], SImode))"
4cdb3ed4 6318 "@
f5c630c3 6319 mov%?\\t%0, %1
4cdb3ed4
RE
6320 mov%?\\t%0, %1
6321 mvn%?\\t%0, #%B1
5b3e6663 6322 movw%?\\t%0, %1
4cdb3ed4
RE
6323 ldr%?\\t%0, %1
6324 str%?\\t%1, %0"
859abddd 6325 [(set_attr "type" "mov_reg,mov_imm,mvn_imm,mov_imm,load1,store1")
cca0a211 6326 (set_attr "predicable" "yes")
f5c630c3
PB
6327 (set_attr "pool_range" "*,*,*,*,4096,*")
6328 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
d5b7b3ae 6329)
091426d3
RE
6330
6331(define_split
9b66ebb1 6332 [(set (match_operand:SI 0 "arm_general_register_operand" "")
091426d3 6333 (match_operand:SI 1 "const_int_operand" ""))]
5b3e6663 6334 "TARGET_32BIT
5895f793
RE
6335 && (!(const_ok_for_arm (INTVAL (operands[1]))
6336 || const_ok_for_arm (~INTVAL (operands[1]))))"
091426d3
RE
6337 [(clobber (const_int 0))]
6338 "
a406f566
MM
6339 arm_split_constant (SET, SImode, NULL_RTX,
6340 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
091426d3 6341 DONE;
5895f793
RE
6342 "
6343)
ff9940b0 6344
02231c13
TG
6345;; A normal way to do (symbol + offset) requires three instructions at least
6346;; (depends on how big the offset is) as below:
6347;; movw r0, #:lower16:g
6348;; movw r0, #:upper16:g
6349;; adds r0, #4
6350;;
6351;; A better way would be:
6352;; movw r0, #:lower16:g+4
6353;; movw r0, #:upper16:g+4
6354;;
6355;; The limitation of this way is that the length of offset should be a 16-bit
6356;; signed value, because current assembler only supports REL type relocation for
6357;; such case. If the more powerful RELA type is supported in future, we should
6358;; update this pattern to go with better way.
6359(define_split
6360 [(set (match_operand:SI 0 "arm_general_register_operand" "")
6361 (const:SI (plus:SI (match_operand:SI 1 "general_operand" "")
6362 (match_operand:SI 2 "const_int_operand" ""))))]
6363 "TARGET_THUMB2
6364 && arm_disable_literal_pool
6365 && reload_completed
6366 && GET_CODE (operands[1]) == SYMBOL_REF"
6367 [(clobber (const_int 0))]
6368 "
6369 int offset = INTVAL (operands[2]);
6370
6371 if (offset < -0x8000 || offset > 0x7fff)
6372 {
6373 arm_emit_movpair (operands[0], operands[1]);
6374 emit_insn (gen_rtx_SET (SImode, operands[0],
6375 gen_rtx_PLUS (SImode, operands[0], operands[2])));
6376 }
6377 else
6378 {
6379 rtx op = gen_rtx_CONST (SImode,
6380 gen_rtx_PLUS (SImode, operands[1], operands[2]));
6381 arm_emit_movpair (operands[0], op);
6382 }
6383 "
6384)
6385
2f011375
JB
6386;; Split symbol_refs at the later stage (after cprop), instead of generating
6387;; movt/movw pair directly at expand. Otherwise corresponding high_sum
6388;; and lo_sum would be merged back into memory load at cprop. However,
6389;; if the default is to prefer movt/movw rather than a load from the constant
6390;; pool, the performance is better.
6391(define_split
6392 [(set (match_operand:SI 0 "arm_general_register_operand" "")
6393 (match_operand:SI 1 "general_operand" ""))]
6394 "TARGET_32BIT
6395 && TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
6396 && !flag_pic && !target_word_relocations
6397 && !arm_tls_referenced_p (operands[1])"
6398 [(clobber (const_int 0))]
6399{
6400 arm_emit_movpair (operands[0], operands[1]);
6401 DONE;
6402})
6403
5b3e6663 6404(define_insn "*thumb1_movsi_insn"
565d018d
JB
6405 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*l*h*k")
6406 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*l*h*k"))]
5b3e6663 6407 "TARGET_THUMB1
d5b7b3ae
RE
6408 && ( register_operand (operands[0], SImode)
6409 || register_operand (operands[1], SImode))"
6410 "@
6411 mov %0, %1
6412 mov %0, %1
6413 #
6414 #
6415 ldmia\\t%1, {%0}
6416 stmia\\t%0, {%1}
6417 ldr\\t%0, %1
6418 str\\t%1, %0
6419 mov\\t%0, %1"
6420 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
594726e4 6421 (set_attr "type" "mov_reg,mov_imm,multiple,multiple,load1,store1,load1,store1,mov_reg")
88f519b2 6422 (set_attr "pool_range" "*,*,*,*,*,*,1018,*,*")
906668bb 6423 (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")])
d5b7b3ae
RE
6424
6425(define_split
6426 [(set (match_operand:SI 0 "register_operand" "")
6427 (match_operand:SI 1 "const_int_operand" ""))]
5b3e6663 6428 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
3393e880
MK
6429 [(set (match_dup 2) (match_dup 1))
6430 (set (match_dup 0) (neg:SI (match_dup 2)))]
6431 "
6432 {
6433 operands[1] = GEN_INT (- INTVAL (operands[1]));
6434 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
6435 }"
d5b7b3ae
RE
6436)
6437
6438(define_split
6439 [(set (match_operand:SI 0 "register_operand" "")
6440 (match_operand:SI 1 "const_int_operand" ""))]
5b3e6663 6441 "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
3393e880
MK
6442 [(set (match_dup 2) (match_dup 1))
6443 (set (match_dup 0) (ashift:SI (match_dup 2) (match_dup 3)))]
d5b7b3ae
RE
6444 "
6445 {
ce41c38b 6446 unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
d5b7b3ae
RE
6447 unsigned HOST_WIDE_INT mask = 0xff;
6448 int i;
6449
6450 for (i = 0; i < 25; i++)
6451 if ((val & (mask << i)) == val)
6452 break;
6453
3393e880 6454 /* Don't split if the shift is zero. */
d5b7b3ae
RE
6455 if (i == 0)
6456 FAIL;
6457
6458 operands[1] = GEN_INT (val >> i);
3393e880
MK
6459 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
6460 operands[3] = GEN_INT (i);
d5b7b3ae
RE
6461 }"
6462)
6463
572a49c8
JY
6464;; For thumb1 split imm move [256-510] into mov [1-255] and add #255
6465(define_split
6466 [(set (match_operand:SI 0 "register_operand" "")
6467 (match_operand:SI 1 "const_int_operand" ""))]
6468 "TARGET_THUMB1 && satisfies_constraint_Pe (operands[1])"
6469 [(set (match_dup 2) (match_dup 1))
6470 (set (match_dup 0) (plus:SI (match_dup 2) (match_dup 3)))]
6471 "
6472 {
6473 operands[1] = GEN_INT (INTVAL (operands[1]) - 255);
6474 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
6475 operands[3] = GEN_INT (255);
6476 }"
6477)
6478
f12c5ef3
RE
6479;; When generating pic, we need to load the symbol offset into a register.
6480;; So that the optimizer does not confuse this with a normal symbol load
6481;; we use an unspec. The offset will be loaded from a constant pool entry,
6482;; since that is the only type of relocation we can use.
6483
d37c3c62
MK
6484;; Wrap calculation of the whole PIC address in a single pattern for the
6485;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
6486;; a PIC address involves two loads from memory, so we want to CSE it
6487;; as often as possible.
6488;; This pattern will be split into one of the pic_load_addr_* patterns
6489;; and a move after GCSE optimizations.
6490;;
6491;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
6492(define_expand "calculate_pic_address"
6493 [(set (match_operand:SI 0 "register_operand" "")
6494 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
6495 (unspec:SI [(match_operand:SI 2 "" "")]
6496 UNSPEC_PIC_SYM))))]
6497 "flag_pic"
6498)
6499
6500;; Split calculate_pic_address into pic_load_addr_* and a move.
6501(define_split
6502 [(set (match_operand:SI 0 "register_operand" "")
6503 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
6504 (unspec:SI [(match_operand:SI 2 "" "")]
6505 UNSPEC_PIC_SYM))))]
6506 "flag_pic"
6507 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
6508 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
6509 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
6510)
6511
f06129ea
RR
6512;; operand1 is the memory address to go into
6513;; pic_load_addr_32bit.
6514;; operand2 is the PIC label to be emitted
6515;; from pic_add_dot_plus_eight.
6516;; We do this to allow hoisting of the entire insn.
6517(define_insn_and_split "pic_load_addr_unified"
6518 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
6519 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
6520 (match_operand:SI 2 "" "")]
6521 UNSPEC_PIC_UNIFIED))]
6522 "flag_pic"
6523 "#"
6524 "&& reload_completed"
6525 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
6526 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
6527 (match_dup 2)] UNSPEC_PIC_BASE))]
6528 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
6529 [(set_attr "type" "load1,load1,load1")
88f519b2 6530 (set_attr "pool_range" "4096,4094,1022")
f06129ea
RR
6531 (set_attr "neg_pool_range" "4084,0,0")
6532 (set_attr "arch" "a,t2,t1")
6533 (set_attr "length" "8,6,4")]
6534)
6535
f12c5ef3
RE
6536;; The rather odd constraints on the following are to force reload to leave
6537;; the insn alone, and to force the minipool generation pass to then move
6538;; the GOT symbol to memory.
fef37aaf 6539
87d05b44 6540(define_insn "pic_load_addr_32bit"
fef37aaf 6541 [(set (match_operand:SI 0 "s_register_operand" "=r")
b15bca31 6542 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
87d05b44 6543 "TARGET_32BIT && flag_pic"
f12c5ef3 6544 "ldr%?\\t%0, %1"
9b66ebb1 6545 [(set_attr "type" "load1")
88f519b2
MGD
6546 (set (attr "pool_range")
6547 (if_then_else (eq_attr "is_thumb" "no")
6548 (const_int 4096)
6549 (const_int 4094)))
87d05b44
RE
6550 (set (attr "neg_pool_range")
6551 (if_then_else (eq_attr "is_thumb" "no")
6552 (const_int 4084)
6553 (const_int 0)))]
4bec9f7d
NC
6554)
6555
5b3e6663 6556(define_insn "pic_load_addr_thumb1"
4bec9f7d 6557 [(set (match_operand:SI 0 "s_register_operand" "=l")
b15bca31 6558 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5b3e6663 6559 "TARGET_THUMB1 && flag_pic"
4bec9f7d 6560 "ldr\\t%0, %1"
9b66ebb1 6561 [(set_attr "type" "load1")
88f519b2 6562 (set (attr "pool_range") (const_int 1018))]
d5b7b3ae 6563)
fef37aaf 6564
d5b7b3ae 6565(define_insn "pic_add_dot_plus_four"
6137ba90 6566 [(set (match_operand:SI 0 "register_operand" "=r")
f9bd1a89
RS
6567 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
6568 (const_int 4)
10ae7c7b
DJ
6569 (match_operand 2 "" "")]
6570 UNSPEC_PIC_BASE))]
87d05b44 6571 "TARGET_THUMB"
d5b7b3ae 6572 "*
f16fe45f
DJ
6573 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6574 INTVAL (operands[2]));
d5b7b3ae
RE
6575 return \"add\\t%0, %|pc\";
6576 "
594726e4
JG
6577 [(set_attr "length" "2")
6578 (set_attr "type" "alu_reg")]
d5b7b3ae 6579)
fef37aaf
RE
6580
6581(define_insn "pic_add_dot_plus_eight"
6137ba90 6582 [(set (match_operand:SI 0 "register_operand" "=r")
f9bd1a89
RS
6583 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
6584 (const_int 8)
10ae7c7b
DJ
6585 (match_operand 2 "" "")]
6586 UNSPEC_PIC_BASE))]
d3585b76 6587 "TARGET_ARM"
dfa08768 6588 "*
f16fe45f
DJ
6589 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6590 INTVAL (operands[2]));
6137ba90 6591 return \"add%?\\t%0, %|pc, %1\";
d5b7b3ae 6592 "
594726e4
JG
6593 [(set_attr "predicable" "yes")
6594 (set_attr "type" "alu_reg")]
d5b7b3ae 6595)
fef37aaf 6596
d3585b76 6597(define_insn "tls_load_dot_plus_eight"
0f727c82 6598 [(set (match_operand:SI 0 "register_operand" "=r")
f9bd1a89
RS
6599 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
6600 (const_int 8)
10ae7c7b
DJ
6601 (match_operand 2 "" "")]
6602 UNSPEC_PIC_BASE)))]
d3585b76
DJ
6603 "TARGET_ARM"
6604 "*
f16fe45f
DJ
6605 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6606 INTVAL (operands[2]));
d3585b76
DJ
6607 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
6608 "
594726e4
JG
6609 [(set_attr "predicable" "yes")
6610 (set_attr "type" "load1")]
d3585b76
DJ
6611)
6612
6613;; PIC references to local variables can generate pic_add_dot_plus_eight
6614;; followed by a load. These sequences can be crunched down to
6615;; tls_load_dot_plus_eight by a peephole.
6616
6617(define_peephole2
f9bd1a89
RS
6618 [(set (match_operand:SI 0 "register_operand" "")
6619 (unspec:SI [(match_operand:SI 3 "register_operand" "")
6620 (const_int 8)
6621 (match_operand 1 "" "")]
6622 UNSPEC_PIC_BASE))
8ea2d689
JJ
6623 (set (match_operand:SI 2 "arm_general_register_operand" "")
6624 (mem:SI (match_dup 0)))]
d3585b76 6625 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
f9bd1a89
RS
6626 [(set (match_dup 2)
6627 (mem:SI (unspec:SI [(match_dup 3)
6628 (const_int 8)
6629 (match_dup 1)]
6630 UNSPEC_PIC_BASE)))]
d3585b76
DJ
6631 ""
6632)
6633
9403b7f7
RS
6634(define_insn "pic_offset_arm"
6635 [(set (match_operand:SI 0 "register_operand" "=r")
6636 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
6637 (unspec:SI [(match_operand:SI 2 "" "X")]
6638 UNSPEC_PIC_OFFSET))))]
6639 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
6640 "ldr%?\\t%0, [%1,%2]"
6641 [(set_attr "type" "load1")]
6642)
6643
c1163e75
PB
6644(define_expand "builtin_setjmp_receiver"
6645 [(label_ref (match_operand 0 "" ""))]
6646 "flag_pic"
6647 "
6648{
fe013435
PB
6649 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
6650 register. */
020a4035
RE
6651 if (arm_pic_register != INVALID_REGNUM)
6652 arm_load_pic_register (1UL << 3);
c1163e75
PB
6653 DONE;
6654}")
6655
ff9940b0
RE
6656;; If copying one reg to another we can set the condition codes according to
6657;; its value. Such a move is common after a return from subroutine and the
6658;; result is being tested against zero.
6659
4cdb3ed4 6660(define_insn "*movsi_compare0"
48a08b9c 6661 [(set (reg:CC CC_REGNUM)
d5b7b3ae
RE
6662 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
6663 (const_int 0)))
6664 (set (match_operand:SI 0 "s_register_operand" "=r,r")
6665 (match_dup 1))]
5b3e6663 6666 "TARGET_32BIT"
0f447ef2 6667 "@
c63165be 6668 cmp%?\\t%0, #0
5b3e6663 6669 sub%.\\t%0, %1, #0"
148413a4 6670 [(set_attr "conds" "set")
6e4150e1 6671 (set_attr "type" "alus_imm,alus_imm")]
d5b7b3ae 6672)
3a33f76f 6673
3a33f76f
RK
6674;; Subroutine to store a half word from a register into memory.
6675;; Operand 0 is the source register (HImode)
fd3f89a9 6676;; Operand 1 is the destination address in a register (SImode)
3a33f76f 6677
ff9940b0 6678;; In both this routine and the next, we must be careful not to spill
ddd5a7c1 6679;; a memory address of reg+large_const into a separate PLUS insn, since this
ff9940b0
RE
6680;; can generate unrecognizable rtl.
6681
3a33f76f 6682(define_expand "storehi"
fd3f89a9 6683 [;; store the low byte
7a0a1f09 6684 (set (match_operand 1 "" "") (match_dup 3))
3a33f76f 6685 ;; extract the high byte
fd3f89a9
TG
6686 (set (match_dup 2)
6687 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
3a33f76f 6688 ;; store the high byte
c9389e79 6689 (set (match_dup 4) (match_dup 5))]
d5b7b3ae 6690 "TARGET_ARM"
3a33f76f 6691 "
5895f793 6692 {
792760b9
RK
6693 rtx op1 = operands[1];
6694 rtx addr = XEXP (op1, 0);
5895f793
RE
6695 enum rtx_code code = GET_CODE (addr);
6696
d435a4be 6697 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
5895f793 6698 || code == MINUS)
792760b9 6699 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
5895f793 6700
792760b9 6701 operands[4] = adjust_address (op1, QImode, 1);
f4ef873c 6702 operands[1] = adjust_address (operands[1], QImode, 0);
5895f793
RE
6703 operands[3] = gen_lowpart (QImode, operands[0]);
6704 operands[0] = gen_lowpart (SImode, operands[0]);
c9389e79
RE
6705 operands[2] = gen_reg_rtx (SImode);
6706 operands[5] = gen_lowpart (QImode, operands[2]);
5895f793
RE
6707 }"
6708)
3a33f76f 6709
fe241a29 6710(define_expand "storehi_bigend"
7a0a1f09 6711 [(set (match_dup 4) (match_dup 3))
fe241a29
RE
6712 (set (match_dup 2)
6713 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
c9389e79 6714 (set (match_operand 1 "" "") (match_dup 5))]
d5b7b3ae 6715 "TARGET_ARM"
3a33f76f 6716 "
5895f793 6717 {
792760b9
RK
6718 rtx op1 = operands[1];
6719 rtx addr = XEXP (op1, 0);
5895f793
RE
6720 enum rtx_code code = GET_CODE (addr);
6721
d435a4be 6722 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
5895f793 6723 || code == MINUS)
792760b9 6724 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
5895f793 6725
792760b9 6726 operands[4] = adjust_address (op1, QImode, 1);
f4ef873c 6727 operands[1] = adjust_address (operands[1], QImode, 0);
5895f793
RE
6728 operands[3] = gen_lowpart (QImode, operands[0]);
6729 operands[0] = gen_lowpart (SImode, operands[0]);
6730 operands[2] = gen_reg_rtx (SImode);
c9389e79 6731 operands[5] = gen_lowpart (QImode, operands[2]);
5895f793
RE
6732 }"
6733)
fe241a29
RE
6734
6735;; Subroutine to store a half word integer constant into memory.
6736(define_expand "storeinthi"
7a0a1f09 6737 [(set (match_operand 0 "" "")
c9389e79 6738 (match_operand 1 "" ""))
5d5603e2 6739 (set (match_dup 3) (match_dup 2))]
d5b7b3ae 6740 "TARGET_ARM"
fe241a29 6741 "
5895f793
RE
6742 {
6743 HOST_WIDE_INT value = INTVAL (operands[1]);
6744 rtx addr = XEXP (operands[0], 0);
792760b9 6745 rtx op0 = operands[0];
5895f793 6746 enum rtx_code code = GET_CODE (addr);
fe241a29 6747
d435a4be 6748 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
5895f793 6749 || code == MINUS)
792760b9 6750 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
fe241a29 6751
5895f793
RE
6752 operands[1] = gen_reg_rtx (SImode);
6753 if (BYTES_BIG_ENDIAN)
6754 {
6755 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
6756 if ((value & 255) == ((value >> 8) & 255))
6757 operands[2] = operands[1];
6758 else
6759 {
6760 operands[2] = gen_reg_rtx (SImode);
6761 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
6762 }
6763 }
6764 else
6765 {
6766 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
6767 if ((value & 255) == ((value >> 8) & 255))
6768 operands[2] = operands[1];
6769 else
6770 {
6771 operands[2] = gen_reg_rtx (SImode);
6772 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
6773 }
6774 }
fe241a29 6775
792760b9 6776 operands[3] = adjust_address (op0, QImode, 1);
f4ef873c 6777 operands[0] = adjust_address (operands[0], QImode, 0);
5d5603e2 6778 operands[2] = gen_lowpart (QImode, operands[2]);
c9389e79 6779 operands[1] = gen_lowpart (QImode, operands[1]);
5895f793
RE
6780 }"
6781)
3a33f76f 6782
4cdb3ed4
RE
6783(define_expand "storehi_single_op"
6784 [(set (match_operand:HI 0 "memory_operand" "")
6785 (match_operand:HI 1 "general_operand" ""))]
5b3e6663 6786 "TARGET_32BIT && arm_arch4"
4cdb3ed4 6787 "
5895f793 6788 if (!s_register_operand (operands[1], HImode))
4cdb3ed4 6789 operands[1] = copy_to_mode_reg (HImode, operands[1]);
5895f793
RE
6790 "
6791)
4cdb3ed4 6792
3a33f76f
RK
6793(define_expand "movhi"
6794 [(set (match_operand:HI 0 "general_operand" "")
fd3f89a9 6795 (match_operand:HI 1 "general_operand" ""))]
d5b7b3ae 6796 "TARGET_EITHER"
3a33f76f 6797 "
d5b7b3ae 6798 if (TARGET_ARM)
3a33f76f 6799 {
b3a13419 6800 if (can_create_pseudo_p ())
d5b7b3ae 6801 {
d435a4be 6802 if (MEM_P (operands[0]))
3a33f76f 6803 {
d5b7b3ae
RE
6804 if (arm_arch4)
6805 {
6806 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
6807 DONE;
6808 }
d435a4be 6809 if (CONST_INT_P (operands[1]))
d5b7b3ae 6810 emit_insn (gen_storeinthi (operands[0], operands[1]));
fe241a29 6811 else
d5b7b3ae 6812 {
d435a4be 6813 if (MEM_P (operands[1]))
d5b7b3ae
RE
6814 operands[1] = force_reg (HImode, operands[1]);
6815 if (BYTES_BIG_ENDIAN)
6816 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
6817 else
6818 emit_insn (gen_storehi (operands[1], operands[0]));
6819 }
6820 DONE;
3a33f76f 6821 }
d5b7b3ae 6822 /* Sign extend a constant, and keep it in an SImode reg. */
d435a4be 6823 else if (CONST_INT_P (operands[1]))
ff9940b0 6824 {
d5b7b3ae
RE
6825 rtx reg = gen_reg_rtx (SImode);
6826 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6827
6828 /* If the constant is already valid, leave it alone. */
5895f793 6829 if (!const_ok_for_arm (val))
d5b7b3ae
RE
6830 {
6831 /* If setting all the top bits will make the constant
6832 loadable in a single instruction, then set them.
6833 Otherwise, sign extend the number. */
6834
5895f793 6835 if (const_ok_for_arm (~(val | ~0xffff)))
d5b7b3ae
RE
6836 val |= ~0xffff;
6837 else if (val & 0x8000)
6838 val |= ~0xffff;
6839 }
6840
6841 emit_insn (gen_movsi (reg, GEN_INT (val)));
5d5603e2 6842 operands[1] = gen_lowpart (HImode, reg);
ff9940b0 6843 }
b3a13419 6844 else if (arm_arch4 && optimize && can_create_pseudo_p ()
d435a4be 6845 && MEM_P (operands[1]))
b41caf7c
RE
6846 {
6847 rtx reg = gen_reg_rtx (SImode);
6848
6849 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6850 operands[1] = gen_lowpart (HImode, reg);
6851 }
5895f793 6852 else if (!arm_arch4)
4cdb3ed4 6853 {
d435a4be 6854 if (MEM_P (operands[1]))
d5b7b3ae 6855 {
61f0ccff
RE
6856 rtx base;
6857 rtx offset = const0_rtx;
6858 rtx reg = gen_reg_rtx (SImode);
6859
d435a4be 6860 if ((REG_P (base = XEXP (operands[1], 0))
61f0ccff 6861 || (GET_CODE (base) == PLUS
d435a4be 6862 && (CONST_INT_P (offset = XEXP (base, 1)))
61f0ccff 6863 && ((INTVAL(offset) & 1) != 1)
d435a4be 6864 && REG_P (base = XEXP (base, 0))))
61f0ccff 6865 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
0502226c 6866 {
0a2aaacc 6867 rtx new_rtx;
61f0ccff 6868
0a2aaacc
KG
6869 new_rtx = widen_memory_access (operands[1], SImode,
6870 ((INTVAL (offset) & ~3)
6871 - INTVAL (offset)));
6872 emit_insn (gen_movsi (reg, new_rtx));
61f0ccff
RE
6873 if (((INTVAL (offset) & 2) != 0)
6874 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
6875 {
6876 rtx reg2 = gen_reg_rtx (SImode);
6877
6878 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
6879 reg = reg2;
6880 }
0502226c 6881 }
61f0ccff
RE
6882 else
6883 emit_insn (gen_movhi_bytes (reg, operands[1]));
6884
6885 operands[1] = gen_lowpart (HImode, reg);
d5b7b3ae
RE
6886 }
6887 }
6888 }
d6b4baa4 6889 /* Handle loading a large integer during reload. */
d435a4be 6890 else if (CONST_INT_P (operands[1])
5895f793
RE
6891 && !const_ok_for_arm (INTVAL (operands[1]))
6892 && !const_ok_for_arm (~INTVAL (operands[1])))
d5b7b3ae
RE
6893 {
6894 /* Writing a constant to memory needs a scratch, which should
6895 be handled with SECONDARY_RELOADs. */
d435a4be 6896 gcc_assert (REG_P (operands[0]));
d5b7b3ae
RE
6897
6898 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6899 emit_insn (gen_movsi (operands[0], operands[1]));
6900 DONE;
6901 }
6902 }
5b3e6663
PB
6903 else if (TARGET_THUMB2)
6904 {
6905 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
b3a13419 6906 if (can_create_pseudo_p ())
5b3e6663 6907 {
d435a4be 6908 if (!REG_P (operands[0]))
5b3e6663
PB
6909 operands[1] = force_reg (HImode, operands[1]);
6910 /* Zero extend a constant, and keep it in an SImode reg. */
d435a4be 6911 else if (CONST_INT_P (operands[1]))
5b3e6663
PB
6912 {
6913 rtx reg = gen_reg_rtx (SImode);
6914 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6915
6916 emit_insn (gen_movsi (reg, GEN_INT (val)));
6917 operands[1] = gen_lowpart (HImode, reg);
6918 }
6919 }
6920 }
6921 else /* TARGET_THUMB1 */
d5b7b3ae 6922 {
b3a13419 6923 if (can_create_pseudo_p ())
d5b7b3ae 6924 {
d435a4be 6925 if (CONST_INT_P (operands[1]))
78a5d727
RE
6926 {
6927 rtx reg = gen_reg_rtx (SImode);
6928
6929 emit_insn (gen_movsi (reg, operands[1]));
6930 operands[1] = gen_lowpart (HImode, reg);
6931 }
d5b7b3ae
RE
6932
6933 /* ??? We shouldn't really get invalid addresses here, but this can
5895f793 6934 happen if we are passed a SP (never OK for HImode/QImode) or
331d9186
PB
6935 virtual register (also rejected as illegitimate for HImode/QImode)
6936 relative address. */
d5b7b3ae
RE
6937 /* ??? This should perhaps be fixed elsewhere, for instance, in
6938 fixup_stack_1, by checking for other kinds of invalid addresses,
6939 e.g. a bare reference to a virtual register. This may confuse the
6940 alpha though, which must handle this case differently. */
d435a4be 6941 if (MEM_P (operands[0])
5895f793
RE
6942 && !memory_address_p (GET_MODE (operands[0]),
6943 XEXP (operands[0], 0)))
792760b9
RK
6944 operands[0]
6945 = replace_equiv_address (operands[0],
6946 copy_to_reg (XEXP (operands[0], 0)));
d5b7b3ae 6947
d435a4be 6948 if (MEM_P (operands[1])
5895f793
RE
6949 && !memory_address_p (GET_MODE (operands[1]),
6950 XEXP (operands[1], 0)))
792760b9
RK
6951 operands[1]
6952 = replace_equiv_address (operands[1],
6953 copy_to_reg (XEXP (operands[1], 0)));
78a5d727 6954
d435a4be 6955 if (MEM_P (operands[1]) && optimize > 0)
78a5d727
RE
6956 {
6957 rtx reg = gen_reg_rtx (SImode);
6958
6959 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6960 operands[1] = gen_lowpart (HImode, reg);
6961 }
6962
d435a4be 6963 if (MEM_P (operands[0]))
78a5d727 6964 operands[1] = force_reg (HImode, operands[1]);
d5b7b3ae 6965 }
d435a4be 6966 else if (CONST_INT_P (operands[1])
ce92b223 6967 && !satisfies_constraint_I (operands[1]))
d5b7b3ae 6968 {
78a5d727
RE
6969 /* Handle loading a large integer during reload. */
6970
d5b7b3ae
RE
6971 /* Writing a constant to memory needs a scratch, which should
6972 be handled with SECONDARY_RELOADs. */
d435a4be 6973 gcc_assert (REG_P (operands[0]));
d5b7b3ae 6974
f1c25d3b 6975 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
d5b7b3ae
RE
6976 emit_insn (gen_movsi (operands[0], operands[1]));
6977 DONE;
6978 }
3a33f76f 6979 }
d5b7b3ae
RE
6980 "
6981)
6982
5b3e6663 6983(define_insn "*thumb1_movhi_insn"
f954388e
RE
6984 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
6985 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
5b3e6663 6986 "TARGET_THUMB1
d5b7b3ae
RE
6987 && ( register_operand (operands[0], HImode)
6988 || register_operand (operands[1], HImode))"
6989 "*
6990 switch (which_alternative)
f57b1ad3 6991 {
d5b7b3ae
RE
6992 case 0: return \"add %0, %1, #0\";
6993 case 2: return \"strh %1, %0\";
6994 case 3: return \"mov %0, %1\";
6995 case 4: return \"mov %0, %1\";
6996 case 5: return \"mov %0, %1\";
e6d29d15 6997 default: gcc_unreachable ();
d5b7b3ae
RE
6998 case 1:
6999 /* The stack pointer can end up being taken as an index register.
7000 Catch this case here and deal with it. */
7001 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
d435a4be 7002 && REG_P (XEXP (XEXP (operands[1], 0), 0))
d5b7b3ae
RE
7003 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
7004 {
7005 rtx ops[2];
7006 ops[0] = operands[0];
7007 ops[1] = XEXP (XEXP (operands[1], 0), 0);
7008
7009 output_asm_insn (\"mov %0, %1\", ops);
7010
7011 XEXP (XEXP (operands[1], 0), 0) = operands[0];
7012
7013 }
7014 return \"ldrh %0, %1\";
7015 }"
7016 [(set_attr "length" "2,4,2,2,2,2")
594726e4 7017 (set_attr "type" "alus_imm,load1,store1,mov_reg,mov_reg,mov_imm")
906668bb 7018 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
f57b1ad3 7019
3a33f76f 7020
988337ca 7021(define_expand "movhi_bytes"
34757369 7022 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
988337ca 7023 (set (match_dup 3)
34757369 7024 (zero_extend:SI (match_dup 6)))
988337ca
RE
7025 (set (match_operand:SI 0 "" "")
7026 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
d5b7b3ae 7027 "TARGET_ARM"
988337ca 7028 "
5895f793
RE
7029 {
7030 rtx mem1, mem2;
7031 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
7032
31fa16b6 7033 mem1 = change_address (operands[1], QImode, addr);
0a81f074
RS
7034 mem2 = change_address (operands[1], QImode,
7035 plus_constant (Pmode, addr, 1));
5895f793
RE
7036 operands[0] = gen_lowpart (SImode, operands[0]);
7037 operands[1] = mem1;
7038 operands[2] = gen_reg_rtx (SImode);
7039 operands[3] = gen_reg_rtx (SImode);
7040 operands[6] = mem2;
988337ca 7041
5895f793
RE
7042 if (BYTES_BIG_ENDIAN)
7043 {
7044 operands[4] = operands[2];
7045 operands[5] = operands[3];
7046 }
7047 else
7048 {
7049 operands[4] = operands[3];
7050 operands[5] = operands[2];
7051 }
7052 }"
7053)
988337ca 7054
fe241a29
RE
7055(define_expand "movhi_bigend"
7056 [(set (match_dup 2)
7057 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
7058 (const_int 16)))
7059 (set (match_dup 3)
7060 (ashiftrt:SI (match_dup 2) (const_int 16)))
7061 (set (match_operand:HI 0 "s_register_operand" "")
c9389e79 7062 (match_dup 4))]
d5b7b3ae 7063 "TARGET_ARM"
fe241a29
RE
7064 "
7065 operands[2] = gen_reg_rtx (SImode);
7066 operands[3] = gen_reg_rtx (SImode);
c9389e79 7067 operands[4] = gen_lowpart (HImode, operands[3]);
5895f793
RE
7068 "
7069)
3a33f76f 7070
05713b80 7071;; Pattern to recognize insn generated default case above
4cdb3ed4 7072(define_insn "*movhi_insn_arch4"
0bd44ba2 7073 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
6fe471c8 7074 (match_operand:HI 1 "general_operand" "rI,K,r,mi"))]
d5b7b3ae
RE
7075 "TARGET_ARM
7076 && arm_arch4
6fe471c8
RE
7077 && (register_operand (operands[0], HImode)
7078 || register_operand (operands[1], HImode))"
4cdb3ed4
RE
7079 "@
7080 mov%?\\t%0, %1\\t%@ movhi
7081 mvn%?\\t%0, #%B1\\t%@ movhi
5b3e6663
PB
7082 str%(h%)\\t%1, %0\\t%@ movhi
7083 ldr%(h%)\\t%0, %1\\t%@ movhi"
148413a4 7084 [(set_attr "predicable" "yes")
d5b7b3ae 7085 (set_attr "pool_range" "*,*,*,256")
148413a4
RR
7086 (set_attr "neg_pool_range" "*,*,*,244")
7087 (set_attr_alternative "type"
7088 [(if_then_else (match_operand 1 "const_int_operand" "")
859abddd
SN
7089 (const_string "mov_imm" )
7090 (const_string "mov_reg"))
7091 (const_string "mvn_imm")
148413a4
RR
7092 (const_string "store1")
7093 (const_string "load1")])]
d5b7b3ae 7094)
4cdb3ed4 7095
4cdb3ed4 7096(define_insn "*movhi_bytes"
148413a4
RR
7097 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
7098 (match_operand:HI 1 "arm_rhs_operand" "I,r,K"))]
61f0ccff 7099 "TARGET_ARM"
988337ca 7100 "@
148413a4 7101 mov%?\\t%0, %1\\t%@ movhi
988337ca 7102 mov%?\\t%0, %1\\t%@ movhi
cca0a211 7103 mvn%?\\t%0, #%B1\\t%@ movhi"
f8045c41 7104 [(set_attr "predicable" "yes")
859abddd 7105 (set_attr "type" "mov_imm,mov_reg,mvn_imm")]
cca0a211 7106)
988337ca 7107
2591db65
RE
7108(define_expand "thumb_movhi_clobber"
7109 [(set (match_operand:HI 0 "memory_operand" "")
7110 (match_operand:HI 1 "register_operand" ""))
7111 (clobber (match_operand:DI 2 "register_operand" ""))]
5b3e6663 7112 "TARGET_THUMB1"
2591db65
RE
7113 "
7114 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
7115 && REGNO (operands[1]) <= LAST_LO_REGNUM)
7116 {
7117 emit_insn (gen_movhi (operands[0], operands[1]));
7118 DONE;
7119 }
7120 /* XXX Fixme, need to handle other cases here as well. */
7121 gcc_unreachable ();
7122 "
d5b7b3ae
RE
7123)
7124
f9cc092a
RE
7125;; We use a DImode scratch because we may occasionally need an additional
7126;; temporary if the address isn't offsettable -- push_reload doesn't seem
7127;; to take any notice of the "o" constraints on reload_memory_operand operand.
c1d5bfb9 7128(define_expand "reload_outhi"
d5b7b3ae 7129 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
5895f793
RE
7130 (match_operand:HI 1 "s_register_operand" "r")
7131 (match_operand:DI 2 "s_register_operand" "=&l")])]
d5b7b3ae
RE
7132 "TARGET_EITHER"
7133 "if (TARGET_ARM)
7134 arm_reload_out_hi (operands);
7135 else
7136 thumb_reload_out_hi (operands);
c1d5bfb9 7137 DONE;
d5b7b3ae
RE
7138 "
7139)
c1d5bfb9 7140
988337ca
RE
7141(define_expand "reload_inhi"
7142 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
d5b7b3ae 7143 (match_operand:HI 1 "arm_reload_memory_operand" "o")
f9cc092a 7144 (match_operand:DI 2 "s_register_operand" "=&r")])]
61f0ccff 7145 "TARGET_EITHER"
988337ca 7146 "
d5b7b3ae
RE
7147 if (TARGET_ARM)
7148 arm_reload_in_hi (operands);
7149 else
7150 thumb_reload_out_hi (operands);
988337ca
RE
7151 DONE;
7152")
7153
ff9940b0
RE
7154(define_expand "movqi"
7155 [(set (match_operand:QI 0 "general_operand" "")
7156 (match_operand:QI 1 "general_operand" ""))]
d5b7b3ae 7157 "TARGET_EITHER"
ff9940b0 7158 "
78a5d727 7159 /* Everything except mem = const or mem = mem can be done easily */
b41caf7c 7160
b3a13419 7161 if (can_create_pseudo_p ())
d5b7b3ae 7162 {
d435a4be 7163 if (CONST_INT_P (operands[1]))
78a5d727
RE
7164 {
7165 rtx reg = gen_reg_rtx (SImode);
7166
953a18fb
RE
7167 /* For thumb we want an unsigned immediate, then we are more likely
7168 to be able to use a movs insn. */
7169 if (TARGET_THUMB)
7170 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
7171
78a5d727
RE
7172 emit_insn (gen_movsi (reg, operands[1]));
7173 operands[1] = gen_lowpart (QImode, reg);
7174 }
d5b7b3ae 7175
78a5d727
RE
7176 if (TARGET_THUMB)
7177 {
d5b7b3ae 7178 /* ??? We shouldn't really get invalid addresses here, but this can
5895f793 7179 happen if we are passed a SP (never OK for HImode/QImode) or
331d9186
PB
7180 virtual register (also rejected as illegitimate for HImode/QImode)
7181 relative address. */
d5b7b3ae
RE
7182 /* ??? This should perhaps be fixed elsewhere, for instance, in
7183 fixup_stack_1, by checking for other kinds of invalid addresses,
7184 e.g. a bare reference to a virtual register. This may confuse the
7185 alpha though, which must handle this case differently. */
d435a4be 7186 if (MEM_P (operands[0])
5895f793 7187 && !memory_address_p (GET_MODE (operands[0]),
d5b7b3ae 7188 XEXP (operands[0], 0)))
792760b9
RK
7189 operands[0]
7190 = replace_equiv_address (operands[0],
7191 copy_to_reg (XEXP (operands[0], 0)));
d435a4be 7192 if (MEM_P (operands[1])
5895f793 7193 && !memory_address_p (GET_MODE (operands[1]),
d5b7b3ae 7194 XEXP (operands[1], 0)))
792760b9
RK
7195 operands[1]
7196 = replace_equiv_address (operands[1],
7197 copy_to_reg (XEXP (operands[1], 0)));
78a5d727
RE
7198 }
7199
d435a4be 7200 if (MEM_P (operands[1]) && optimize > 0)
78a5d727
RE
7201 {
7202 rtx reg = gen_reg_rtx (SImode);
7203
7204 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
7205 operands[1] = gen_lowpart (QImode, reg);
7206 }
7207
d435a4be 7208 if (MEM_P (operands[0]))
78a5d727
RE
7209 operands[1] = force_reg (QImode, operands[1]);
7210 }
7211 else if (TARGET_THUMB
d435a4be 7212 && CONST_INT_P (operands[1])
ce92b223 7213 && !satisfies_constraint_I (operands[1]))
78a5d727 7214 {
d6b4baa4 7215 /* Handle loading a large integer during reload. */
d5b7b3ae 7216
78a5d727
RE
7217 /* Writing a constant to memory needs a scratch, which should
7218 be handled with SECONDARY_RELOADs. */
d435a4be 7219 gcc_assert (REG_P (operands[0]));
78a5d727
RE
7220
7221 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
7222 emit_insn (gen_movsi (operands[0], operands[1]));
7223 DONE;
d5b7b3ae
RE
7224 }
7225 "
7226)
3a33f76f 7227
d5b7b3ae 7228(define_insn "*arm_movqi_insn"
956a95a5
KT
7229 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,r,l,Uu,r,m")
7230 (match_operand:QI 1 "general_operand" "r,r,I,Py,K,Uu,l,m,r"))]
5b3e6663 7231 "TARGET_32BIT
d5b7b3ae
RE
7232 && ( register_operand (operands[0], QImode)
7233 || register_operand (operands[1], QImode))"
68df59d3 7234 "@
956a95a5
KT
7235 mov%?\\t%0, %1
7236 mov%?\\t%0, %1
148413a4 7237 mov%?\\t%0, %1
68df59d3
RE
7238 mov%?\\t%0, %1
7239 mvn%?\\t%0, #%B1
5b3e6663 7240 ldr%(b%)\\t%0, %1
363ee90e
WG
7241 str%(b%)\\t%1, %0
7242 ldr%(b%)\\t%0, %1
5b3e6663 7243 str%(b%)\\t%1, %0"
859abddd 7244 [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load1,store1,load1,store1")
363ee90e 7245 (set_attr "predicable" "yes")
956a95a5
KT
7246 (set_attr "predicable_short_it" "yes,yes,yes,no,no,no,no,no,no")
7247 (set_attr "arch" "t2,any,any,t2,any,t2,t2,any,any")
7248 (set_attr "length" "2,4,4,2,4,2,2,4,4")]
d5b7b3ae
RE
7249)
7250
5b3e6663 7251(define_insn "*thumb1_movqi_insn"
d5b7b3ae 7252 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5895f793 7253 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
5b3e6663 7254 "TARGET_THUMB1
d5b7b3ae
RE
7255 && ( register_operand (operands[0], QImode)
7256 || register_operand (operands[1], QImode))"
7257 "@
7258 add\\t%0, %1, #0
7259 ldrb\\t%0, %1
7260 strb\\t%1, %0
7261 mov\\t%0, %1
7262 mov\\t%0, %1
7263 mov\\t%0, %1"
7264 [(set_attr "length" "2")
6e4150e1 7265 (set_attr "type" "alu_imm,load1,store1,mov_reg,mov_imm,mov_imm")
906668bb
BS
7266 (set_attr "pool_range" "*,32,*,*,*,*")
7267 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
3a33f76f 7268
0fd8c3ad
SL
7269;; HFmode moves
7270(define_expand "movhf"
7271 [(set (match_operand:HF 0 "general_operand" "")
7272 (match_operand:HF 1 "general_operand" ""))]
7273 "TARGET_EITHER"
7274 "
7275 if (TARGET_32BIT)
7276 {
d435a4be 7277 if (MEM_P (operands[0]))
0fd8c3ad
SL
7278 operands[1] = force_reg (HFmode, operands[1]);
7279 }
7280 else /* TARGET_THUMB1 */
7281 {
7282 if (can_create_pseudo_p ())
7283 {
d435a4be 7284 if (!REG_P (operands[0]))
0fd8c3ad
SL
7285 operands[1] = force_reg (HFmode, operands[1]);
7286 }
7287 }
7288 "
7289)
7290
7291(define_insn "*arm32_movhf"
7292 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
7293 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
5e5f7673 7294 "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16) && !arm_restrict_it
0fd8c3ad
SL
7295 && ( s_register_operand (operands[0], HFmode)
7296 || s_register_operand (operands[1], HFmode))"
7297 "*
7298 switch (which_alternative)
7299 {
7300 case 0: /* ARM register from memory */
7301 return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
7302 case 1: /* memory from ARM register */
7303 return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
7304 case 2: /* ARM register from ARM register */
7305 return \"mov%?\\t%0, %1\\t%@ __fp16\";
7306 case 3: /* ARM register from constant */
7307 {
7308 REAL_VALUE_TYPE r;
7309 long bits;
7310 rtx ops[4];
7311
7312 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
7313 bits = real_to_target (NULL, &r, HFmode);
7314 ops[0] = operands[0];
7315 ops[1] = GEN_INT (bits);
7316 ops[2] = GEN_INT (bits & 0xff00);
7317 ops[3] = GEN_INT (bits & 0x00ff);
7318
7319 if (arm_arch_thumb2)
7320 output_asm_insn (\"movw%?\\t%0, %1\", ops);
7321 else
7322 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
7323 return \"\";
7324 }
7325 default:
7326 gcc_unreachable ();
7327 }
7328 "
7329 [(set_attr "conds" "unconditional")
9ea187a5 7330 (set_attr "type" "load1,store1,mov_reg,multiple")
0fd8c3ad 7331 (set_attr "length" "4,4,4,8")
f8045c41 7332 (set_attr "predicable" "yes")]
0fd8c3ad
SL
7333)
7334
7335(define_insn "*thumb1_movhf"
7336 [(set (match_operand:HF 0 "nonimmediate_operand" "=l,l,m,*r,*h")
7337 (match_operand:HF 1 "general_operand" "l,mF,l,*h,*r"))]
7338 "TARGET_THUMB1
7339 && ( s_register_operand (operands[0], HFmode)
7340 || s_register_operand (operands[1], HFmode))"
7341 "*
7342 switch (which_alternative)
7343 {
7344 case 1:
7345 {
7346 rtx addr;
d435a4be 7347 gcc_assert (MEM_P (operands[1]));
0fd8c3ad
SL
7348 addr = XEXP (operands[1], 0);
7349 if (GET_CODE (addr) == LABEL_REF
7350 || (GET_CODE (addr) == CONST
7351 && GET_CODE (XEXP (addr, 0)) == PLUS
7352 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
d435a4be 7353 && CONST_INT_P (XEXP (XEXP (addr, 0), 1))))
0fd8c3ad
SL
7354 {
7355 /* Constant pool entry. */
7356 return \"ldr\\t%0, %1\";
7357 }
7358 return \"ldrh\\t%0, %1\";
7359 }
7360 case 2: return \"strh\\t%1, %0\";
7361 default: return \"mov\\t%0, %1\";
7362 }
7363 "
7364 [(set_attr "length" "2")
859abddd 7365 (set_attr "type" "mov_reg,load1,store1,mov_reg,mov_reg")
88f519b2 7366 (set_attr "pool_range" "*,1018,*,*,*")
906668bb 7367 (set_attr "conds" "clob,nocond,nocond,nocond,nocond")])
0fd8c3ad 7368
091426d3
RE
7369(define_expand "movsf"
7370 [(set (match_operand:SF 0 "general_operand" "")
7371 (match_operand:SF 1 "general_operand" ""))]
d5b7b3ae 7372 "TARGET_EITHER"
091426d3 7373 "
5b3e6663 7374 if (TARGET_32BIT)
d5b7b3ae 7375 {
d435a4be 7376 if (MEM_P (operands[0]))
d5b7b3ae
RE
7377 operands[1] = force_reg (SFmode, operands[1]);
7378 }
5b3e6663 7379 else /* TARGET_THUMB1 */
d5b7b3ae 7380 {
b3a13419 7381 if (can_create_pseudo_p ())
d5b7b3ae 7382 {
d435a4be 7383 if (!REG_P (operands[0]))
d5b7b3ae
RE
7384 operands[1] = force_reg (SFmode, operands[1]);
7385 }
7386 }
7387 "
7388)
7389
f7657ed3
RE
7390;; Transform a floating-point move of a constant into a core register into
7391;; an SImode operation.
d5b7b3ae 7392(define_split
f7657ed3 7393 [(set (match_operand:SF 0 "arm_general_register_operand" "")
d5b7b3ae 7394 (match_operand:SF 1 "immediate_operand" ""))]
07422036 7395 "TARGET_EITHER
d5b7b3ae 7396 && reload_completed
d435a4be 7397 && CONST_DOUBLE_P (operands[1])"
d5b7b3ae
RE
7398 [(set (match_dup 2) (match_dup 3))]
7399 "
7400 operands[2] = gen_lowpart (SImode, operands[0]);
7401 operands[3] = gen_lowpart (SImode, operands[1]);
7402 if (operands[2] == 0 || operands[3] == 0)
7403 FAIL;
5895f793
RE
7404 "
7405)
091426d3 7406
d5b7b3ae
RE
7407(define_insn "*arm_movsf_soft_insn"
7408 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
7409 (match_operand:SF 1 "general_operand" "r,mE,r"))]
0bd44ba2 7410 "TARGET_32BIT
d5b7b3ae 7411 && TARGET_SOFT_FLOAT
d435a4be 7412 && (!MEM_P (operands[0])
5895f793 7413 || register_operand (operands[1], SFmode))"
39c0ef95
DE
7414 "@
7415 mov%?\\t%0, %1
7416 ldr%?\\t%0, %1\\t%@ float
7417 str%?\\t%1, %0\\t%@ float"
0bd44ba2 7418 [(set_attr "predicable" "yes")
5e5f7673 7419 (set_attr "predicable_short_it" "no")
859abddd 7420 (set_attr "type" "mov_reg,load1,store1")
88f519b2
MGD
7421 (set_attr "arm_pool_range" "*,4096,*")
7422 (set_attr "thumb2_pool_range" "*,4094,*")
0bd44ba2
BS
7423 (set_attr "arm_neg_pool_range" "*,4084,*")
7424 (set_attr "thumb2_neg_pool_range" "*,0,*")]
d5b7b3ae
RE
7425)
7426
7427;;; ??? This should have alternatives for constants.
5b3e6663 7428(define_insn "*thumb1_movsf_insn"
5895f793
RE
7429 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
7430 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
5b3e6663 7431 "TARGET_THUMB1
d5b7b3ae
RE
7432 && ( register_operand (operands[0], SFmode)
7433 || register_operand (operands[1], SFmode))"
7434 "@
7435 add\\t%0, %1, #0
7436 ldmia\\t%1, {%0}
7437 stmia\\t%0, {%1}
7438 ldr\\t%0, %1
7439 str\\t%1, %0
7440 mov\\t%0, %1
7441 mov\\t%0, %1"
7442 [(set_attr "length" "2")
594726e4 7443 (set_attr "type" "alus_imm,load1,store1,load1,store1,mov_reg,mov_reg")
88f519b2 7444 (set_attr "pool_range" "*,*,*,1018,*,*,*")
906668bb 7445 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,nocond,nocond")]
d5b7b3ae 7446)
39c0ef95 7447
ff9940b0 7448(define_expand "movdf"
091426d3
RE
7449 [(set (match_operand:DF 0 "general_operand" "")
7450 (match_operand:DF 1 "general_operand" ""))]
d5b7b3ae 7451 "TARGET_EITHER"
ff9940b0 7452 "
5b3e6663 7453 if (TARGET_32BIT)
d5b7b3ae 7454 {
d435a4be 7455 if (MEM_P (operands[0]))
d5b7b3ae
RE
7456 operands[1] = force_reg (DFmode, operands[1]);
7457 }
7458 else /* TARGET_THUMB */
7459 {
b3a13419 7460 if (can_create_pseudo_p ())
d5b7b3ae 7461 {
d435a4be 7462 if (!REG_P (operands[0]))
d5b7b3ae
RE
7463 operands[1] = force_reg (DFmode, operands[1]);
7464 }
7465 }
7466 "
7467)
3a33f76f 7468
ff9940b0
RE
7469;; Reloading a df mode value stored in integer regs to memory can require a
7470;; scratch reg.
7471(define_expand "reload_outdf"
d5b7b3ae 7472 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
091426d3
RE
7473 (match_operand:DF 1 "s_register_operand" "r")
7474 (match_operand:SI 2 "s_register_operand" "=&r")]
06eb52ca 7475 "TARGET_THUMB2"
091426d3 7476 "
5895f793
RE
7477 {
7478 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
4cdb3ed4 7479
5895f793
RE
7480 if (code == REG)
7481 operands[2] = XEXP (operands[0], 0);
7482 else if (code == POST_INC || code == PRE_DEC)
7483 {
7484 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7485 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
7486 emit_insn (gen_movdi (operands[0], operands[1]));
7487 DONE;
7488 }
7489 else if (code == PRE_INC)
7490 {
7491 rtx reg = XEXP (XEXP (operands[0], 0), 0);
4cdb3ed4 7492
5895f793
RE
7493 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
7494 operands[2] = reg;
7495 }
7496 else if (code == POST_DEC)
7497 operands[2] = XEXP (XEXP (operands[0], 0), 0);
7498 else
7499 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
7500 XEXP (XEXP (operands[0], 0), 1)));
4cdb3ed4 7501
31fa16b6
RE
7502 emit_insn (gen_rtx_SET (VOIDmode,
7503 replace_equiv_address (operands[0], operands[2]),
5895f793 7504 operands[1]));
4cdb3ed4 7505
5895f793
RE
7506 if (code == POST_DEC)
7507 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
7508
7509 DONE;
7510 }"
7511)
ff9940b0 7512
39c0ef95 7513(define_insn "*movdf_soft_insn"
4542a38a
GY
7514 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,q,m")
7515 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,q"))]
0bd44ba2 7516 "TARGET_32BIT && TARGET_SOFT_FLOAT
d5b6e637
PB
7517 && ( register_operand (operands[0], DFmode)
7518 || register_operand (operands[1], DFmode))"
9b901d50
RE
7519 "*
7520 switch (which_alternative)
7521 {
7522 case 0:
7523 case 1:
7524 case 2:
7525 return \"#\";
7526 default:
3598da80 7527 return output_move_double (operands, true, NULL);
9b901d50
RE
7528 }
7529 "
2075b05d 7530 [(set_attr "length" "8,12,16,8,8")
594726e4 7531 (set_attr "type" "multiple,multiple,multiple,load2,store2")
88f519b2
MGD
7532 (set_attr "arm_pool_range" "*,*,*,1020,*")
7533 (set_attr "thumb2_pool_range" "*,*,*,1018,*")
635a48fb 7534 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
0bd44ba2 7535 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
d5b7b3ae
RE
7536)
7537
7538;;; ??? This should have alternatives for constants.
7539;;; ??? This was originally identical to the movdi_insn pattern.
7540;;; ??? The 'F' constraint looks funny, but it should always be replaced by
7541;;; thumb_reorg with a memory reference.
7542(define_insn "*thumb_movdf_insn"
5895f793
RE
7543 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
7544 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
5b3e6663 7545 "TARGET_THUMB1
d5b7b3ae
RE
7546 && ( register_operand (operands[0], DFmode)
7547 || register_operand (operands[1], DFmode))"
7548 "*
7549 switch (which_alternative)
7550 {
7551 default:
7552 case 0:
7553 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
7554 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
7555 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
7556 case 1:
7557 return \"ldmia\\t%1, {%0, %H0}\";
7558 case 2:
7559 return \"stmia\\t%0, {%1, %H1}\";
7560 case 3:
7561 return thumb_load_double_from_address (operands);
7562 case 4:
f1c25d3b 7563 operands[2] = gen_rtx_MEM (SImode,
0a81f074
RS
7564 plus_constant (Pmode,
7565 XEXP (operands[0], 0), 4));
d5b7b3ae
RE
7566 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
7567 return \"\";
7568 case 5:
7569 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
7570 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
7571 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
7572 }
7573 "
7574 [(set_attr "length" "4,2,2,6,4,4")
9ea187a5 7575 (set_attr "type" "multiple,load2,store2,load2,store2,multiple")
88f519b2 7576 (set_attr "pool_range" "*,*,*,1018,*,*")]
d5b7b3ae 7577)
3a33f76f 7578\f
3a33f76f 7579
ff9940b0
RE
7580;; load- and store-multiple insns
7581;; The arm can load/store any set of registers, provided that they are in
37119410 7582;; ascending order, but these expanders assume a contiguous set.
3a33f76f 7583
ff9940b0
RE
7584(define_expand "load_multiple"
7585 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
7586 (match_operand:SI 1 "" ""))
7587 (use (match_operand:SI 2 "" ""))])]
5b3e6663 7588 "TARGET_32BIT"
50ed9cea
RH
7589{
7590 HOST_WIDE_INT offset = 0;
7591
48a08b9c 7592 /* Support only fixed point registers. */
d435a4be 7593 if (!CONST_INT_P (operands[2])
ff9940b0
RE
7594 || INTVAL (operands[2]) > 14
7595 || INTVAL (operands[2]) < 2
d435a4be
KT
7596 || !MEM_P (operands[1])
7597 || !REG_P (operands[0])
48a08b9c
NC
7598 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
7599 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
ff9940b0
RE
7600 FAIL;
7601
7602 operands[3]
37119410
BS
7603 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
7604 INTVAL (operands[2]),
7a0a1f09 7605 force_reg (SImode, XEXP (operands[1], 0)),
37119410 7606 FALSE, operands[1], &offset);
50ed9cea 7607})
3a33f76f 7608
ff9940b0
RE
7609(define_expand "store_multiple"
7610 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
7611 (match_operand:SI 1 "" ""))
7612 (use (match_operand:SI 2 "" ""))])]
5b3e6663 7613 "TARGET_32BIT"
50ed9cea
RH
7614{
7615 HOST_WIDE_INT offset = 0;
7616
d6b4baa4 7617 /* Support only fixed point registers. */
d435a4be 7618 if (!CONST_INT_P (operands[2])
ff9940b0
RE
7619 || INTVAL (operands[2]) > 14
7620 || INTVAL (operands[2]) < 2
d435a4be
KT
7621 || !REG_P (operands[1])
7622 || !MEM_P (operands[0])
48a08b9c
NC
7623 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
7624 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
ff9940b0
RE
7625 FAIL;
7626
7627 operands[3]
37119410
BS
7628 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
7629 INTVAL (operands[2]),
7a0a1f09 7630 force_reg (SImode, XEXP (operands[0], 0)),
37119410 7631 FALSE, operands[0], &offset);
50ed9cea 7632})
3a33f76f 7633
ff9940b0
RE
7634
7635;; Move a block of memory if it is word aligned and MORE than 2 words long.
7636;; We could let this apply for blocks of less than this, but it clobbers so
7637;; many registers that there is then probably a better way.
7638
70128ad9 7639(define_expand "movmemqi"
0bdece8a
RE
7640 [(match_operand:BLK 0 "general_operand" "")
7641 (match_operand:BLK 1 "general_operand" "")
7642 (match_operand:SI 2 "const_int_operand" "")
7643 (match_operand:SI 3 "const_int_operand" "")]
798d3d04 7644 ""
ff9940b0 7645 "
5b3e6663 7646 if (TARGET_32BIT)
d5b7b3ae 7647 {
798d3d04
GY
7648 if (TARGET_LDRD && current_tune->prefer_ldrd_strd
7649 && !optimize_function_for_size_p (cfun))
7650 {
7651 if (gen_movmem_ldrd_strd (operands))
7652 DONE;
7653 FAIL;
7654 }
7655
70128ad9 7656 if (arm_gen_movmemqi (operands))
d5b7b3ae
RE
7657 DONE;
7658 FAIL;
7659 }
5b3e6663 7660 else /* TARGET_THUMB1 */
d5b7b3ae
RE
7661 {
7662 if ( INTVAL (operands[3]) != 4
7663 || INTVAL (operands[2]) > 48)
7664 FAIL;
7665
70128ad9 7666 thumb_expand_movmemqi (operands);
d5b7b3ae
RE
7667 DONE;
7668 }
7669 "
7670)
7671
d6c5a763 7672;; Thumb block-move insns
d5b7b3ae
RE
7673
7674(define_insn "movmem12b"
ca356f3a
RE
7675 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
7676 (mem:SI (match_operand:SI 3 "register_operand" "1")))
7677 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
7678 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
7679 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
7680 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
7681 (set (match_operand:SI 0 "register_operand" "=l")
7682 (plus:SI (match_dup 2) (const_int 12)))
7683 (set (match_operand:SI 1 "register_operand" "=l")
7684 (plus:SI (match_dup 3) (const_int 12)))
7685 (clobber (match_scratch:SI 4 "=&l"))
7686 (clobber (match_scratch:SI 5 "=&l"))
7687 (clobber (match_scratch:SI 6 "=&l"))]
5b3e6663 7688 "TARGET_THUMB1"
d5b7b3ae
RE
7689 "* return thumb_output_move_mem_multiple (3, operands);"
7690 [(set_attr "length" "4")
5895f793
RE
7691 ; This isn't entirely accurate... It loads as well, but in terms of
7692 ; scheduling the following insn it is better to consider it as a store
d5b7b3ae
RE
7693 (set_attr "type" "store3")]
7694)
7695
7696(define_insn "movmem8b"
ca356f3a
RE
7697 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
7698 (mem:SI (match_operand:SI 3 "register_operand" "1")))
7699 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
7700 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
7701 (set (match_operand:SI 0 "register_operand" "=l")
7702 (plus:SI (match_dup 2) (const_int 8)))
7703 (set (match_operand:SI 1 "register_operand" "=l")
7704 (plus:SI (match_dup 3) (const_int 8)))
7705 (clobber (match_scratch:SI 4 "=&l"))
7706 (clobber (match_scratch:SI 5 "=&l"))]
5b3e6663 7707 "TARGET_THUMB1"
d5b7b3ae
RE
7708 "* return thumb_output_move_mem_multiple (2, operands);"
7709 [(set_attr "length" "4")
5895f793
RE
7710 ; This isn't entirely accurate... It loads as well, but in terms of
7711 ; scheduling the following insn it is better to consider it as a store
d5b7b3ae
RE
7712 (set_attr "type" "store2")]
7713)
7714
ff9940b0 7715\f
3a33f76f 7716
6c98269c 7717;; Compare & branch insns
9a9f7594 7718;; The range calculations are based as follows:
6c98269c
RE
7719;; For forward branches, the address calculation returns the address of
7720;; the next instruction. This is 2 beyond the branch instruction.
7721;; For backward branches, the address calculation returns the address of
7722;; the first instruction in this pattern (cmp). This is 2 before the branch
7723;; instruction for the shortest sequence, and 4 before the branch instruction
7724;; if we have to jump around an unconditional branch.
7725;; To the basic branch range the PC offset must be added (this is +4).
7726;; So for forward branches we have
7727;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
7728;; And for backward branches we have
7729;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
7730;;
7731;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
7732;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
d5b7b3ae 7733
c769a35d
RE
7734(define_expand "cbranchsi4"
7735 [(set (pc) (if_then_else
aa0b3f8f 7736 (match_operator 0 "expandable_comparison_operator"
c769a35d
RE
7737 [(match_operand:SI 1 "s_register_operand" "")
7738 (match_operand:SI 2 "nonmemory_operand" "")])
7739 (label_ref (match_operand 3 "" ""))
7740 (pc)))]
95ffee1f 7741 "TARGET_EITHER"
c769a35d 7742 "
f90b7a5a
PB
7743 if (!TARGET_THUMB1)
7744 {
95ffee1f
RR
7745 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
7746 FAIL;
f90b7a5a
PB
7747 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7748 operands[3]));
7749 DONE;
7750 }
5b3e6663 7751 if (thumb1_cmpneg_operand (operands[2], SImode))
c769a35d
RE
7752 {
7753 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
7754 operands[3], operands[0]));
7755 DONE;
7756 }
5b3e6663 7757 if (!thumb1_cmp_operand (operands[2], SImode))
c769a35d
RE
7758 operands[2] = force_reg (SImode, operands[2]);
7759 ")
7760
f0c6475a
BS
7761;; A pattern to recognize a special situation and optimize for it.
7762;; On the thumb, zero-extension from memory is preferrable to sign-extension
7763;; due to the available addressing modes. Hence, convert a signed comparison
7764;; with zero into an unsigned comparison with 127 if possible.
7765(define_expand "cbranchqi4"
7766 [(set (pc) (if_then_else
7767 (match_operator 0 "lt_ge_comparison_operator"
7768 [(match_operand:QI 1 "memory_operand" "")
7769 (match_operand:QI 2 "const0_operand" "")])
7770 (label_ref (match_operand 3 "" ""))
7771 (pc)))]
7772 "TARGET_THUMB1"
7773{
95da5cf9 7774 rtx xops[4];
f0c6475a
BS
7775 xops[1] = gen_reg_rtx (SImode);
7776 emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
7777 xops[2] = GEN_INT (127);
7778 xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
7779 VOIDmode, xops[1], xops[2]);
7780 xops[3] = operands[3];
7781 emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
7782 DONE;
7783})
7784
f90b7a5a
PB
7785(define_expand "cbranchsf4"
7786 [(set (pc) (if_then_else
aa0b3f8f 7787 (match_operator 0 "expandable_comparison_operator"
f90b7a5a
PB
7788 [(match_operand:SF 1 "s_register_operand" "")
7789 (match_operand:SF 2 "arm_float_compare_operand" "")])
7790 (label_ref (match_operand 3 "" ""))
7791 (pc)))]
7792 "TARGET_32BIT && TARGET_HARD_FLOAT"
7793 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7794 operands[3])); DONE;"
7795)
7796
7797(define_expand "cbranchdf4"
7798 [(set (pc) (if_then_else
aa0b3f8f 7799 (match_operator 0 "expandable_comparison_operator"
f90b7a5a
PB
7800 [(match_operand:DF 1 "s_register_operand" "")
7801 (match_operand:DF 2 "arm_float_compare_operand" "")])
7802 (label_ref (match_operand 3 "" ""))
7803 (pc)))]
e0dc3601 7804 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
f90b7a5a
PB
7805 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7806 operands[3])); DONE;"
7807)
7808
f90b7a5a
PB
7809(define_expand "cbranchdi4"
7810 [(set (pc) (if_then_else
aa0b3f8f 7811 (match_operator 0 "expandable_comparison_operator"
a70418fc 7812 [(match_operand:DI 1 "s_register_operand" "")
73160ba9 7813 (match_operand:DI 2 "cmpdi_operand" "")])
f90b7a5a
PB
7814 (label_ref (match_operand 3 "" ""))
7815 (pc)))]
73160ba9
DJ
7816 "TARGET_32BIT"
7817 "{
d435a4be 7818 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
95ffee1f
RR
7819 FAIL;
7820 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
73160ba9
DJ
7821 operands[3]));
7822 DONE;
7823 }"
f90b7a5a
PB
7824)
7825
6ea007e4 7826(define_insn "cbranchsi4_insn"
c769a35d
RE
7827 [(set (pc) (if_then_else
7828 (match_operator 0 "arm_comparison_operator"
906668bb 7829 [(match_operand:SI 1 "s_register_operand" "l,l*h")
5b3e6663 7830 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
c769a35d
RE
7831 (label_ref (match_operand 3 "" ""))
7832 (pc)))]
5b3e6663 7833 "TARGET_THUMB1"
906668bb
BS
7834{
7835 rtx t = cfun->machine->thumb1_cc_insn;
7836 if (t != NULL_RTX)
6ea007e4 7837 {
906668bb
BS
7838 if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
7839 || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2]))
7840 t = NULL_RTX;
7841 if (cfun->machine->thumb1_cc_mode == CC_NOOVmode)
7842 {
7843 if (!noov_comparison_operator (operands[0], VOIDmode))
7844 t = NULL_RTX;
7845 }
7846 else if (cfun->machine->thumb1_cc_mode != CCmode)
6ea007e4
BS
7847 t = NULL_RTX;
7848 }
6ea007e4 7849 if (t == NULL_RTX)
906668bb
BS
7850 {
7851 output_asm_insn ("cmp\t%1, %2", operands);
7852 cfun->machine->thumb1_cc_insn = insn;
7853 cfun->machine->thumb1_cc_op0 = operands[1];
7854 cfun->machine->thumb1_cc_op1 = operands[2];
7855 cfun->machine->thumb1_cc_mode = CCmode;
7856 }
7857 else
7858 /* Ensure we emit the right type of condition code on the jump. */
7859 XEXP (operands[0], 0) = gen_rtx_REG (cfun->machine->thumb1_cc_mode,
7860 CC_REGNUM);
c769a35d 7861
d5b7b3ae
RE
7862 switch (get_attr_length (insn))
7863 {
7864 case 4: return \"b%d0\\t%l3\";
7865 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7866 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7867 }
906668bb 7868}
d5b7b3ae
RE
7869 [(set (attr "far_jump")
7870 (if_then_else
7871 (eq_attr "length" "8")
7872 (const_string "yes")
7873 (const_string "no")))
7874 (set (attr "length")
7875 (if_then_else
7876 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7877 (le (minus (match_dup 3) (pc)) (const_int 256)))
7878 (const_int 4)
7879 (if_then_else
7880 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6c98269c 7881 (le (minus (match_dup 3) (pc)) (const_int 2048)))
d5b7b3ae 7882 (const_int 6)
594726e4
JG
7883 (const_int 8))))
7884 (set_attr "type" "multiple")]
d5b7b3ae
RE
7885)
7886
c769a35d
RE
7887(define_insn "cbranchsi4_scratch"
7888 [(set (pc) (if_then_else
7889 (match_operator 4 "arm_comparison_operator"
7890 [(match_operand:SI 1 "s_register_operand" "l,0")
5b3e6663 7891 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
c769a35d
RE
7892 (label_ref (match_operand 3 "" ""))
7893 (pc)))
7894 (clobber (match_scratch:SI 0 "=l,l"))]
5b3e6663 7895 "TARGET_THUMB1"
c769a35d
RE
7896 "*
7897 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
7898
7899 switch (get_attr_length (insn))
7900 {
7901 case 4: return \"b%d4\\t%l3\";
7902 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7903 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7904 }
7905 "
7906 [(set (attr "far_jump")
7907 (if_then_else
7908 (eq_attr "length" "8")
7909 (const_string "yes")
7910 (const_string "no")))
7911 (set (attr "length")
7912 (if_then_else
7913 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7914 (le (minus (match_dup 3) (pc)) (const_int 256)))
7915 (const_int 4)
7916 (if_then_else
7917 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7918 (le (minus (match_dup 3) (pc)) (const_int 2048)))
7919 (const_int 6)
594726e4
JG
7920 (const_int 8))))
7921 (set_attr "type" "multiple")]
c769a35d 7922)
57f5eef0 7923
d5b7b3ae
RE
7924(define_insn "*negated_cbranchsi4"
7925 [(set (pc)
7926 (if_then_else
1ac3e311 7927 (match_operator 0 "equality_operator"
c769a35d
RE
7928 [(match_operand:SI 1 "s_register_operand" "l")
7929 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
7930 (label_ref (match_operand 3 "" ""))
5895f793 7931 (pc)))]
5b3e6663 7932 "TARGET_THUMB1"
d5b7b3ae
RE
7933 "*
7934 output_asm_insn (\"cmn\\t%1, %2\", operands);
7935 switch (get_attr_length (insn))
7936 {
7937 case 4: return \"b%d0\\t%l3\";
7938 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7939 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7940 }
7941 "
7942 [(set (attr "far_jump")
7943 (if_then_else
7944 (eq_attr "length" "8")
7945 (const_string "yes")
7946 (const_string "no")))
7947 (set (attr "length")
7948 (if_then_else
7949 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6c98269c 7950 (le (minus (match_dup 3) (pc)) (const_int 256)))
d5b7b3ae
RE
7951 (const_int 4)
7952 (if_then_else
6c98269c
RE
7953 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7954 (le (minus (match_dup 3) (pc)) (const_int 2048)))
d5b7b3ae 7955 (const_int 6)
594726e4
JG
7956 (const_int 8))))
7957 (set_attr "type" "multiple")]
d5b7b3ae
RE
7958)
7959
defc0463
RE
7960(define_insn "*tbit_cbranch"
7961 [(set (pc)
7962 (if_then_else
7963 (match_operator 0 "equality_operator"
7964 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
7965 (const_int 1)
7966 (match_operand:SI 2 "const_int_operand" "i"))
7967 (const_int 0)])
7968 (label_ref (match_operand 3 "" ""))
7969 (pc)))
7970 (clobber (match_scratch:SI 4 "=l"))]
5b3e6663 7971 "TARGET_THUMB1"
defc0463
RE
7972 "*
7973 {
7974 rtx op[3];
7975 op[0] = operands[4];
7976 op[1] = operands[1];
7977 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
7978
f9fa4363
RE
7979 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
7980 switch (get_attr_length (insn))
7981 {
7982 case 4: return \"b%d0\\t%l3\";
7983 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7984 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7985 }
7986 }"
7987 [(set (attr "far_jump")
7988 (if_then_else
7989 (eq_attr "length" "8")
7990 (const_string "yes")
7991 (const_string "no")))
7992 (set (attr "length")
7993 (if_then_else
7994 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7995 (le (minus (match_dup 3) (pc)) (const_int 256)))
7996 (const_int 4)
7997 (if_then_else
7998 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7999 (le (minus (match_dup 3) (pc)) (const_int 2048)))
8000 (const_int 6)
594726e4
JG
8001 (const_int 8))))
8002 (set_attr "type" "multiple")]
f9fa4363
RE
8003)
8004
8005(define_insn "*tlobits_cbranch"
8006 [(set (pc)
8007 (if_then_else
8008 (match_operator 0 "equality_operator"
8009 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
8010 (match_operand:SI 2 "const_int_operand" "i")
8011 (const_int 0))
8012 (const_int 0)])
8013 (label_ref (match_operand 3 "" ""))
8014 (pc)))
8015 (clobber (match_scratch:SI 4 "=l"))]
5b3e6663 8016 "TARGET_THUMB1"
f9fa4363
RE
8017 "*
8018 {
8019 rtx op[3];
8020 op[0] = operands[4];
8021 op[1] = operands[1];
8022 op[2] = GEN_INT (32 - INTVAL (operands[2]));
8023
defc0463
RE
8024 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
8025 switch (get_attr_length (insn))
8026 {
8027 case 4: return \"b%d0\\t%l3\";
8028 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
8029 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
8030 }
8031 }"
8032 [(set (attr "far_jump")
8033 (if_then_else
8034 (eq_attr "length" "8")
8035 (const_string "yes")
8036 (const_string "no")))
8037 (set (attr "length")
8038 (if_then_else
8039 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
8040 (le (minus (match_dup 3) (pc)) (const_int 256)))
8041 (const_int 4)
8042 (if_then_else
8043 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
8044 (le (minus (match_dup 3) (pc)) (const_int 2048)))
8045 (const_int 6)
594726e4
JG
8046 (const_int 8))))
8047 (set_attr "type" "multiple")]
defc0463 8048)
906668bb 8049
c769a35d 8050(define_insn "*tstsi3_cbranch"
defc0463
RE
8051 [(set (pc)
8052 (if_then_else
c769a35d
RE
8053 (match_operator 3 "equality_operator"
8054 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
8055 (match_operand:SI 1 "s_register_operand" "l"))
defc0463 8056 (const_int 0)])
c769a35d
RE
8057 (label_ref (match_operand 2 "" ""))
8058 (pc)))]
5b3e6663 8059 "TARGET_THUMB1"
defc0463
RE
8060 "*
8061 {
c769a35d 8062 output_asm_insn (\"tst\\t%0, %1\", operands);
defc0463
RE
8063 switch (get_attr_length (insn))
8064 {
c769a35d
RE
8065 case 4: return \"b%d3\\t%l2\";
8066 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
8067 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
defc0463
RE
8068 }
8069 }"
8070 [(set (attr "far_jump")
8071 (if_then_else
8072 (eq_attr "length" "8")
8073 (const_string "yes")
8074 (const_string "no")))
8075 (set (attr "length")
8076 (if_then_else
c769a35d
RE
8077 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
8078 (le (minus (match_dup 2) (pc)) (const_int 256)))
defc0463
RE
8079 (const_int 4)
8080 (if_then_else
c769a35d
RE
8081 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
8082 (le (minus (match_dup 2) (pc)) (const_int 2048)))
defc0463 8083 (const_int 6)
594726e4
JG
8084 (const_int 8))))
8085 (set_attr "type" "multiple")]
defc0463
RE
8086)
8087
f9b9980e
RE
8088(define_insn "*cbranchne_decr1"
8089 [(set (pc)
8090 (if_then_else (match_operator 3 "equality_operator"
8091 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
8092 (const_int 0)])
8093 (label_ref (match_operand 4 "" ""))
8094 (pc)))
c769a35d 8095 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
f9b9980e
RE
8096 (plus:SI (match_dup 2) (const_int -1)))
8097 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5b3e6663 8098 "TARGET_THUMB1"
f9b9980e
RE
8099 "*
8100 {
8101 rtx cond[2];
8102 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
8103 ? GEU : LTU),
defc0463 8104 VOIDmode, operands[2], const1_rtx);
f9b9980e
RE
8105 cond[1] = operands[4];
8106
8107 if (which_alternative == 0)
8108 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
8109 else if (which_alternative == 1)
8110 {
8111 /* We must provide an alternative for a hi reg because reload
8112 cannot handle output reloads on a jump instruction, but we
8113 can't subtract into that. Fortunately a mov from lo to hi
8114 does not clobber the condition codes. */
8115 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
8116 output_asm_insn (\"mov\\t%0, %1\", operands);
8117 }
8118 else
8119 {
8120 /* Similarly, but the target is memory. */
8121 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
8122 output_asm_insn (\"str\\t%1, %0\", operands);
8123 }
8124
8125 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
8126 {
8127 case 4:
91de08c3 8128 output_asm_insn (\"b%d0\\t%l1\", cond);
f9b9980e
RE
8129 return \"\";
8130 case 6:
91de08c3 8131 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
f9b9980e
RE
8132 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
8133 default:
91de08c3 8134 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
f9b9980e
RE
8135 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
8136 }
8137 }
8138 "
8139 [(set (attr "far_jump")
8140 (if_then_else
8141 (ior (and (eq (symbol_ref ("which_alternative"))
8142 (const_int 0))
8143 (eq_attr "length" "8"))
8144 (eq_attr "length" "10"))
8145 (const_string "yes")
8146 (const_string "no")))
8147 (set_attr_alternative "length"
8148 [
8149 ;; Alternative 0
8150 (if_then_else
8151 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
8152 (le (minus (match_dup 4) (pc)) (const_int 256)))
8153 (const_int 4)
8154 (if_then_else
8155 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
8156 (le (minus (match_dup 4) (pc)) (const_int 2048)))
8157 (const_int 6)
8158 (const_int 8)))
8159 ;; Alternative 1
8160 (if_then_else
8161 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
8162 (le (minus (match_dup 4) (pc)) (const_int 256)))
8163 (const_int 6)
8164 (if_then_else
8165 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
8166 (le (minus (match_dup 4) (pc)) (const_int 2048)))
8167 (const_int 8)
8168 (const_int 10)))
8169 ;; Alternative 2
8170 (if_then_else
8171 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
8172 (le (minus (match_dup 4) (pc)) (const_int 256)))
8173 (const_int 6)
8174 (if_then_else
8175 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
8176 (le (minus (match_dup 4) (pc)) (const_int 2048)))
8177 (const_int 8)
8178 (const_int 10)))
8179 ;; Alternative 3
8180 (if_then_else
8181 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
8182 (le (minus (match_dup 4) (pc)) (const_int 256)))
8183 (const_int 6)
8184 (if_then_else
8185 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
8186 (le (minus (match_dup 4) (pc)) (const_int 2048)))
8187 (const_int 8)
594726e4
JG
8188 (const_int 10)))])
8189 (set_attr "type" "multiple")]
f9b9980e 8190)
d5b7b3ae 8191
defc0463
RE
8192(define_insn "*addsi3_cbranch"
8193 [(set (pc)
8194 (if_then_else
accbd151 8195 (match_operator 4 "arm_comparison_operator"
defc0463 8196 [(plus:SI
0879e7b3
BS
8197 (match_operand:SI 2 "s_register_operand" "%0,l,*l,1,1,1")
8198 (match_operand:SI 3 "reg_or_int_operand" "IJ,lL,*l,lIJ,lIJ,lIJ"))
defc0463
RE
8199 (const_int 0)])
8200 (label_ref (match_operand 5 "" ""))
8201 (pc)))
c769a35d
RE
8202 (set
8203 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
8204 (plus:SI (match_dup 2) (match_dup 3)))
3302cfa1 8205 (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
5b3e6663 8206 "TARGET_THUMB1
defc0463
RE
8207 && (GET_CODE (operands[4]) == EQ
8208 || GET_CODE (operands[4]) == NE
8209 || GET_CODE (operands[4]) == GE
8210 || GET_CODE (operands[4]) == LT)"
8211 "*
8212 {
8213 rtx cond[3];
8214
3302cfa1 8215 cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
defc0463
RE
8216 cond[1] = operands[2];
8217 cond[2] = operands[3];
8218
d435a4be 8219 if (CONST_INT_P (cond[2]) && INTVAL (cond[2]) < 0)
defc0463
RE
8220 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
8221 else
8222 output_asm_insn (\"add\\t%0, %1, %2\", cond);
8223
3302cfa1 8224 if (which_alternative >= 2
defc0463
RE
8225 && which_alternative < 4)
8226 output_asm_insn (\"mov\\t%0, %1\", operands);
8227 else if (which_alternative >= 4)
8228 output_asm_insn (\"str\\t%1, %0\", operands);
8229
95da5cf9 8230 switch (get_attr_length (insn) - ((which_alternative >= 2) ? 2 : 0))
defc0463
RE
8231 {
8232 case 4:
8233 return \"b%d4\\t%l5\";
8234 case 6:
8235 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
8236 default:
8237 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
8238 }
8239 }
8240 "
8241 [(set (attr "far_jump")
8242 (if_then_else
8243 (ior (and (lt (symbol_ref ("which_alternative"))
95da5cf9 8244 (const_int 2))
defc0463
RE
8245 (eq_attr "length" "8"))
8246 (eq_attr "length" "10"))
8247 (const_string "yes")
8248 (const_string "no")))
8249 (set (attr "length")
8250 (if_then_else
8251 (lt (symbol_ref ("which_alternative"))
95da5cf9 8252 (const_int 2))
defc0463
RE
8253 (if_then_else
8254 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
8255 (le (minus (match_dup 5) (pc)) (const_int 256)))
8256 (const_int 4)
8257 (if_then_else
8258 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
8259 (le (minus (match_dup 5) (pc)) (const_int 2048)))
8260 (const_int 6)
8261 (const_int 8)))
8262 (if_then_else
8263 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
8264 (le (minus (match_dup 5) (pc)) (const_int 256)))
8265 (const_int 6)
8266 (if_then_else
8267 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
8268 (le (minus (match_dup 5) (pc)) (const_int 2048)))
8269 (const_int 8)
594726e4
JG
8270 (const_int 10)))))
8271 (set_attr "type" "multiple")]
defc0463
RE
8272)
8273
8274(define_insn "*addsi3_cbranch_scratch"
8275 [(set (pc)
8276 (if_then_else
accbd151 8277 (match_operator 3 "arm_comparison_operator"
defc0463
RE
8278 [(plus:SI
8279 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
b49e92fe 8280 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
defc0463
RE
8281 (const_int 0)])
8282 (label_ref (match_operand 4 "" ""))
8283 (pc)))
8284 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
5b3e6663 8285 "TARGET_THUMB1
defc0463
RE
8286 && (GET_CODE (operands[3]) == EQ
8287 || GET_CODE (operands[3]) == NE
8288 || GET_CODE (operands[3]) == GE
8289 || GET_CODE (operands[3]) == LT)"
8290 "*
8291 {
8292 switch (which_alternative)
8293 {
8294 case 0:
8295 output_asm_insn (\"cmp\t%1, #%n2\", operands);
8296 break;
8297 case 1:
8298 output_asm_insn (\"cmn\t%1, %2\", operands);
8299 break;
108a579c 8300 case 2:
b49e92fe
PB
8301 if (INTVAL (operands[2]) < 0)
8302 output_asm_insn (\"sub\t%0, %1, %2\", operands);
8303 else
8304 output_asm_insn (\"add\t%0, %1, %2\", operands);
defc0463 8305 break;
108a579c 8306 case 3:
b49e92fe
PB
8307 if (INTVAL (operands[2]) < 0)
8308 output_asm_insn (\"sub\t%0, %0, %2\", operands);
8309 else
8310 output_asm_insn (\"add\t%0, %0, %2\", operands);
defc0463
RE
8311 break;
8312 }
8313
8314 switch (get_attr_length (insn))
8315 {
8316 case 4:
8317 return \"b%d3\\t%l4\";
8318 case 6:
8319 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
8320 default:
8321 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
8322 }
8323 }
8324 "
8325 [(set (attr "far_jump")
8326 (if_then_else
8327 (eq_attr "length" "8")
8328 (const_string "yes")
8329 (const_string "no")))
8330 (set (attr "length")
8331 (if_then_else
8332 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
8333 (le (minus (match_dup 4) (pc)) (const_int 256)))
8334 (const_int 4)
8335 (if_then_else
8336 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
8337 (le (minus (match_dup 4) (pc)) (const_int 2048)))
8338 (const_int 6)
594726e4
JG
8339 (const_int 8))))
8340 (set_attr "type" "multiple")]
defc0463
RE
8341)
8342
defc0463 8343
ff9940b0
RE
8344;; Comparison and test insns
8345
d5b7b3ae 8346(define_insn "*arm_cmpsi_insn"
48a08b9c 8347 [(set (reg:CC CC_REGNUM)
86eb4bd7
KT
8348 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r,r")
8349 (match_operand:SI 1 "arm_add_operand" "Py,r,r,I,L")))]
5b3e6663 8350 "TARGET_32BIT"
68df59d3 8351 "@
4925d0d5
WG
8352 cmp%?\\t%0, %1
8353 cmp%?\\t%0, %1
589fe0fc 8354 cmp%?\\t%0, %1
86eb4bd7 8355 cmp%?\\t%0, %1
589fe0fc 8356 cmn%?\\t%0, #%n1"
4925d0d5 8357 [(set_attr "conds" "set")
86eb4bd7
KT
8358 (set_attr "arch" "t2,t2,any,any,any")
8359 (set_attr "length" "2,2,4,4,4")
148413a4 8360 (set_attr "predicable" "yes")
86eb4bd7
KT
8361 (set_attr "predicable_short_it" "yes,yes,yes,no,no")
8362 (set_attr "type" "alus_imm,alus_reg,alus_reg,alus_imm,alus_imm")]
d5b7b3ae 8363)
3a33f76f 8364
c29e2982 8365(define_insn "*cmpsi_shiftsi"
48a08b9c 8366 [(set (reg:CC CC_REGNUM)
6e4150e1 8367 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r,r")
d5b7b3ae 8368 (match_operator:SI 3 "shift_operator"
6e4150e1
JG
8369 [(match_operand:SI 1 "s_register_operand" "r,r,r")
8370 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])))]
c29e2982 8371 "TARGET_32BIT"
86eb4bd7 8372 "cmp\\t%0, %1%S3"
ca68ea18 8373 [(set_attr "conds" "set")
d19fb8e3 8374 (set_attr "shift" "1")
6e4150e1
JG
8375 (set_attr "arch" "32,a,a")
8376 (set_attr "type" "alus_shift_imm,alu_shift_reg,alus_shift_imm")])
3a33f76f 8377
c29e2982 8378(define_insn "*cmpsi_shiftsi_swp"
48a08b9c 8379 [(set (reg:CC_SWP CC_REGNUM)
589fe0fc 8380 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6e4150e1
JG
8381 [(match_operand:SI 1 "s_register_operand" "r,r,r")
8382 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])
8383 (match_operand:SI 0 "s_register_operand" "r,r,r")))]
c29e2982 8384 "TARGET_32BIT"
589fe0fc 8385 "cmp%?\\t%0, %1%S3"
ca68ea18 8386 [(set_attr "conds" "set")
d19fb8e3 8387 (set_attr "shift" "1")
6e4150e1
JG
8388 (set_attr "arch" "32,a,a")
8389 (set_attr "type" "alus_shift_imm,alu_shift_reg,alus_shift_imm")])
3a33f76f 8390
5b3e6663 8391(define_insn "*arm_cmpsi_negshiftsi_si"
1ac3e311
RE
8392 [(set (reg:CC_Z CC_REGNUM)
8393 (compare:CC_Z
8394 (neg:SI (match_operator:SI 1 "shift_operator"
8395 [(match_operand:SI 2 "s_register_operand" "r")
8396 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
8397 (match_operand:SI 0 "s_register_operand" "r")))]
d5b7b3ae 8398 "TARGET_ARM"
1ac3e311 8399 "cmn%?\\t%0, %2%S1"
ca68ea18 8400 [(set_attr "conds" "set")
1ac3e311 8401 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6e4150e1
JG
8402 (const_string "alus_shift_imm")
8403 (const_string "alus_shift_reg")))
cc50a1e1 8404 (set_attr "predicable" "yes")]
cca0a211 8405)
3a33f76f 8406
73160ba9
DJ
8407;; DImode comparisons. The generic code generates branches that
8408;; if-conversion can not reduce to a conditional compare, so we do
8409;; that directly.
8410
3f3bf1a8 8411(define_insn_and_split "*arm_cmpdi_insn"
73160ba9
DJ
8412 [(set (reg:CC_NCV CC_REGNUM)
8413 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
8414 (match_operand:DI 1 "arm_di_operand" "rDi")))
8415 (clobber (match_scratch:SI 2 "=r"))]
479f7546 8416 "TARGET_32BIT"
3f3bf1a8
GY
8417 "#" ; "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
8418 "&& reload_completed"
8419 [(set (reg:CC CC_REGNUM)
8420 (compare:CC (match_dup 0) (match_dup 1)))
8421 (parallel [(set (reg:CC CC_REGNUM)
8422 (compare:CC (match_dup 3) (match_dup 4)))
8423 (set (match_dup 2)
8424 (minus:SI (match_dup 5)
8425 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])]
8426 {
8427 operands[3] = gen_highpart (SImode, operands[0]);
8428 operands[0] = gen_lowpart (SImode, operands[0]);
8429 if (CONST_INT_P (operands[1]))
8430 {
8431 operands[4] = GEN_INT (~INTVAL (gen_highpart_mode (SImode,
8432 DImode,
8433 operands[1])));
8434 operands[5] = gen_rtx_PLUS (SImode, operands[3], operands[4]);
8435 }
8436 else
8437 {
8438 operands[4] = gen_highpart (SImode, operands[1]);
8439 operands[5] = gen_rtx_MINUS (SImode, operands[3], operands[4]);
8440 }
8441 operands[1] = gen_lowpart (SImode, operands[1]);
8442 operands[2] = gen_lowpart (SImode, operands[2]);
8443 }
73160ba9 8444 [(set_attr "conds" "set")
594726e4
JG
8445 (set_attr "length" "8")
8446 (set_attr "type" "multiple")]
73160ba9
DJ
8447)
8448
3f3bf1a8 8449(define_insn_and_split "*arm_cmpdi_unsigned"
73160ba9 8450 [(set (reg:CC_CZ CC_REGNUM)
5e5f7673
KT
8451 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "l,r,r")
8452 (match_operand:DI 1 "arm_di_operand" "Py,r,rDi")))]
8453
6cb2b964 8454 "TARGET_32BIT"
3f3bf1a8
GY
8455 "#" ; "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
8456 "&& reload_completed"
8457 [(set (reg:CC CC_REGNUM)
8458 (compare:CC (match_dup 2) (match_dup 3)))
8459 (cond_exec (eq:SI (reg:CC CC_REGNUM) (const_int 0))
8460 (set (reg:CC CC_REGNUM)
8461 (compare:CC (match_dup 0) (match_dup 1))))]
8462 {
8463 operands[2] = gen_highpart (SImode, operands[0]);
8464 operands[0] = gen_lowpart (SImode, operands[0]);
8465 if (CONST_INT_P (operands[1]))
8466 operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
8467 else
8468 operands[3] = gen_highpart (SImode, operands[1]);
8469 operands[1] = gen_lowpart (SImode, operands[1]);
8470 }
73160ba9 8471 [(set_attr "conds" "set")
5e5f7673
KT
8472 (set_attr "enabled_for_depr_it" "yes,yes,no")
8473 (set_attr "arch" "t2,t2,*")
594726e4
JG
8474 (set_attr "length" "6,6,8")
8475 (set_attr "type" "multiple")]
73160ba9
DJ
8476)
8477
8478(define_insn "*arm_cmpdi_zero"
8479 [(set (reg:CC_Z CC_REGNUM)
8480 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
8481 (const_int 0)))
8482 (clobber (match_scratch:SI 1 "=r"))]
8483 "TARGET_32BIT"
8484 "orr%.\\t%1, %Q0, %R0"
594726e4
JG
8485 [(set_attr "conds" "set")
8486 (set_attr "type" "logics_reg")]
73160ba9
DJ
8487)
8488
8489(define_insn "*thumb_cmpdi_zero"
8490 [(set (reg:CC_Z CC_REGNUM)
8491 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
8492 (const_int 0)))
8493 (clobber (match_scratch:SI 1 "=l"))]
8494 "TARGET_THUMB1"
8495 "orr\\t%1, %Q0, %R0"
8496 [(set_attr "conds" "set")
594726e4
JG
8497 (set_attr "length" "2")
8498 (set_attr "type" "logics_reg")]
73160ba9
DJ
8499)
8500
ff9940b0
RE
8501; This insn allows redundant compares to be removed by cse, nothing should
8502; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
8503; is deleted later on. The match_dup will match the mode here, so that
8504; mode changes of the condition codes aren't lost by this even though we don't
8505; specify what they are.
8506
f54fd62e 8507(define_insn "*deleted_compare"
ff9940b0 8508 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5b3e6663 8509 "TARGET_32BIT"
c63165be 8510 "\\t%@ deleted compare"
d5b7b3ae 8511 [(set_attr "conds" "set")
594726e4
JG
8512 (set_attr "length" "0")
8513 (set_attr "type" "no_insn")]
d5b7b3ae 8514)
ff9940b0
RE
8515
8516\f
8517;; Conditional branch insns
8518
f90b7a5a 8519(define_expand "cbranch_cc"
ff9940b0 8520 [(set (pc)
f90b7a5a
PB
8521 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
8522 (match_operand 2 "" "")])
8523 (label_ref (match_operand 3 "" ""))
ff9940b0 8524 (pc)))]
5b3e6663 8525 "TARGET_32BIT"
f90b7a5a 8526 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
18f0fe6b 8527 operands[1], operands[2], NULL_RTX);
f90b7a5a 8528 operands[2] = const0_rtx;"
05ed98a1
RE
8529)
8530
8531;;
8532;; Patterns to match conditional branch insns.
8533;;
8534
99aea943 8535(define_insn "arm_cond_branch"
ff9940b0 8536 [(set (pc)
05ed98a1 8537 (if_then_else (match_operator 1 "arm_comparison_operator"
f54fd62e 8538 [(match_operand 2 "cc_register" "") (const_int 0)])
ff9940b0
RE
8539 (label_ref (match_operand 0 "" ""))
8540 (pc)))]
5b3e6663 8541 "TARGET_32BIT"
6d5363fa 8542 "*
ff9940b0 8543 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
d5b7b3ae
RE
8544 {
8545 arm_ccfsm_state += 2;
8546 return \"\";
8547 }
0f447ef2 8548 return \"b%d1\\t%l0\";
d5b7b3ae 8549 "
9b66ebb1 8550 [(set_attr "conds" "use")
4925d0d5
WG
8551 (set_attr "type" "branch")
8552 (set (attr "length")
8553 (if_then_else
b75b1be2 8554 (and (match_test "TARGET_THUMB2")
4925d0d5
WG
8555 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
8556 (le (minus (match_dup 0) (pc)) (const_int 256))))
8557 (const_int 2)
8558 (const_int 4)))]
d5b7b3ae 8559)
6d5363fa 8560
d5b7b3ae 8561(define_insn "*arm_cond_branch_reversed"
ff9940b0 8562 [(set (pc)
05ed98a1 8563 (if_then_else (match_operator 1 "arm_comparison_operator"
f54fd62e 8564 [(match_operand 2 "cc_register" "") (const_int 0)])
ff9940b0
RE
8565 (pc)
8566 (label_ref (match_operand 0 "" ""))))]
5b3e6663 8567 "TARGET_32BIT"
6d5363fa 8568 "*
ff9940b0 8569 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
d5b7b3ae
RE
8570 {
8571 arm_ccfsm_state += 2;
8572 return \"\";
8573 }
0f447ef2 8574 return \"b%D1\\t%l0\";
d5b7b3ae 8575 "
9b66ebb1 8576 [(set_attr "conds" "use")
4925d0d5
WG
8577 (set_attr "type" "branch")
8578 (set (attr "length")
8579 (if_then_else
b75b1be2 8580 (and (match_test "TARGET_THUMB2")
4925d0d5
WG
8581 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
8582 (le (minus (match_dup 0) (pc)) (const_int 256))))
8583 (const_int 2)
8584 (const_int 4)))]
d5b7b3ae
RE
8585)
8586
3a33f76f 8587\f
ff9940b0
RE
8588
8589; scc insns
8590
f90b7a5a 8591(define_expand "cstore_cc"
82955615 8592 [(set (match_operand:SI 0 "s_register_operand" "")
f90b7a5a
PB
8593 (match_operator:SI 1 "" [(match_operand 2 "" "")
8594 (match_operand 3 "" "")]))]
5b3e6663 8595 "TARGET_32BIT"
f90b7a5a 8596 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
18f0fe6b 8597 operands[2], operands[3], NULL_RTX);
f90b7a5a 8598 operands[3] = const0_rtx;"
05ed98a1
RE
8599)
8600
9a946fd6 8601(define_insn_and_split "*mov_scc"
ff9940b0 8602 [(set (match_operand:SI 0 "s_register_operand" "=r")
05ed98a1 8603 (match_operator:SI 1 "arm_comparison_operator"
f54fd62e 8604 [(match_operand 2 "cc_register" "") (const_int 0)]))]
d5b7b3ae 8605 "TARGET_ARM"
9a946fd6
GY
8606 "#" ; "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
8607 "TARGET_ARM"
8608 [(set (match_dup 0)
8609 (if_then_else:SI (match_dup 1)
8610 (const_int 1)
8611 (const_int 0)))]
8612 ""
d5b7b3ae 8613 [(set_attr "conds" "use")
594726e4
JG
8614 (set_attr "length" "8")
8615 (set_attr "type" "multiple")]
d5b7b3ae 8616)
ff9940b0 8617
9a946fd6 8618(define_insn_and_split "*mov_negscc"
ff9940b0 8619 [(set (match_operand:SI 0 "s_register_operand" "=r")
05ed98a1 8620 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
f54fd62e 8621 [(match_operand 2 "cc_register" "") (const_int 0)])))]
d5b7b3ae 8622 "TARGET_ARM"
9a946fd6
GY
8623 "#" ; "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
8624 "TARGET_ARM"
8625 [(set (match_dup 0)
8626 (if_then_else:SI (match_dup 1)
8627 (match_dup 3)
8628 (const_int 0)))]
8629 {
8630 operands[3] = GEN_INT (~0);
8631 }
d5b7b3ae 8632 [(set_attr "conds" "use")
594726e4
JG
8633 (set_attr "length" "8")
8634 (set_attr "type" "multiple")]
d5b7b3ae 8635)
ff9940b0 8636
9a946fd6 8637(define_insn_and_split "*mov_notscc"
ff9940b0 8638 [(set (match_operand:SI 0 "s_register_operand" "=r")
05ed98a1 8639 (not:SI (match_operator:SI 1 "arm_comparison_operator"
f54fd62e 8640 [(match_operand 2 "cc_register" "") (const_int 0)])))]
d5b7b3ae 8641 "TARGET_ARM"
9a946fd6
GY
8642 "#" ; "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
8643 "TARGET_ARM"
8644 [(set (match_dup 0)
8645 (if_then_else:SI (match_dup 1)
8646 (match_dup 3)
8647 (match_dup 4)))]
8648 {
8649 operands[3] = GEN_INT (~1);
8650 operands[4] = GEN_INT (~0);
8651 }
d5b7b3ae 8652 [(set_attr "conds" "use")
594726e4
JG
8653 (set_attr "length" "8")
8654 (set_attr "type" "multiple")]
d5b7b3ae 8655)
ff9940b0 8656
a41a56b6
RE
8657(define_expand "cstoresi4"
8658 [(set (match_operand:SI 0 "s_register_operand" "")
aa0b3f8f 8659 (match_operator:SI 1 "expandable_comparison_operator"
a41a56b6
RE
8660 [(match_operand:SI 2 "s_register_operand" "")
8661 (match_operand:SI 3 "reg_or_int_operand" "")]))]
f90b7a5a 8662 "TARGET_32BIT || TARGET_THUMB1"
a41a56b6
RE
8663 "{
8664 rtx op3, scratch, scratch2;
8665
f90b7a5a
PB
8666 if (!TARGET_THUMB1)
8667 {
8668 if (!arm_add_operand (operands[3], SImode))
8669 operands[3] = force_reg (SImode, operands[3]);
8670 emit_insn (gen_cstore_cc (operands[0], operands[1],
8671 operands[2], operands[3]));
8672 DONE;
8673 }
8674
a41a56b6
RE
8675 if (operands[3] == const0_rtx)
8676 {
8677 switch (GET_CODE (operands[1]))
8678 {
8679 case EQ:
5b3e6663 8680 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
a41a56b6
RE
8681 break;
8682
8683 case NE:
5b3e6663 8684 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
a41a56b6
RE
8685 break;
8686
8687 case LE:
8688 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
8689 NULL_RTX, 0, OPTAB_WIDEN);
8690 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
8691 NULL_RTX, 0, OPTAB_WIDEN);
8692 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
8693 operands[0], 1, OPTAB_WIDEN);
8694 break;
8695
8696 case GE:
8697 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
8698 NULL_RTX, 1);
8699 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
8700 NULL_RTX, 1, OPTAB_WIDEN);
8701 break;
8702
8703 case GT:
8704 scratch = expand_binop (SImode, ashr_optab, operands[2],
8705 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
8706 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
8707 NULL_RTX, 0, OPTAB_WIDEN);
8708 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
8709 0, OPTAB_WIDEN);
8710 break;
8711
8712 /* LT is handled by generic code. No need for unsigned with 0. */
8713 default:
8714 FAIL;
8715 }
8716 DONE;
8717 }
8718
8719 switch (GET_CODE (operands[1]))
8720 {
8721 case EQ:
8722 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
8723 NULL_RTX, 0, OPTAB_WIDEN);
5b3e6663 8724 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
a41a56b6
RE
8725 break;
8726
8727 case NE:
8728 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
8729 NULL_RTX, 0, OPTAB_WIDEN);
5b3e6663 8730 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
a41a56b6
RE
8731 break;
8732
8733 case LE:
8734 op3 = force_reg (SImode, operands[3]);
8735
8736 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
8737 NULL_RTX, 1, OPTAB_WIDEN);
8738 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
8739 NULL_RTX, 0, OPTAB_WIDEN);
5b3e6663 8740 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
a41a56b6
RE
8741 op3, operands[2]));
8742 break;
8743
8744 case GE:
8745 op3 = operands[3];
5b3e6663 8746 if (!thumb1_cmp_operand (op3, SImode))
a41a56b6
RE
8747 op3 = force_reg (SImode, op3);
8748 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
8749 NULL_RTX, 0, OPTAB_WIDEN);
8750 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
8751 NULL_RTX, 1, OPTAB_WIDEN);
5b3e6663 8752 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
a41a56b6
RE
8753 operands[2], op3));
8754 break;
8755
8756 case LEU:
8757 op3 = force_reg (SImode, operands[3]);
8758 scratch = force_reg (SImode, const0_rtx);
5b3e6663 8759 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
a41a56b6
RE
8760 op3, operands[2]));
8761 break;
8762
8763 case GEU:
8764 op3 = operands[3];
5b3e6663 8765 if (!thumb1_cmp_operand (op3, SImode))
a41a56b6
RE
8766 op3 = force_reg (SImode, op3);
8767 scratch = force_reg (SImode, const0_rtx);
5b3e6663 8768 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
a41a56b6
RE
8769 operands[2], op3));
8770 break;
8771
8772 case LTU:
8773 op3 = operands[3];
5b3e6663 8774 if (!thumb1_cmp_operand (op3, SImode))
a41a56b6
RE
8775 op3 = force_reg (SImode, op3);
8776 scratch = gen_reg_rtx (SImode);
c4bb78e9 8777 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
a41a56b6
RE
8778 break;
8779
8780 case GTU:
8781 op3 = force_reg (SImode, operands[3]);
8782 scratch = gen_reg_rtx (SImode);
c4bb78e9 8783 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
a41a56b6
RE
8784 break;
8785
8786 /* No good sequences for GT, LT. */
8787 default:
8788 FAIL;
8789 }
8790 DONE;
8791}")
8792
f90b7a5a
PB
8793(define_expand "cstoresf4"
8794 [(set (match_operand:SI 0 "s_register_operand" "")
aa0b3f8f 8795 (match_operator:SI 1 "expandable_comparison_operator"
f90b7a5a
PB
8796 [(match_operand:SF 2 "s_register_operand" "")
8797 (match_operand:SF 3 "arm_float_compare_operand" "")]))]
8798 "TARGET_32BIT && TARGET_HARD_FLOAT"
8799 "emit_insn (gen_cstore_cc (operands[0], operands[1],
8800 operands[2], operands[3])); DONE;"
8801)
8802
8803(define_expand "cstoredf4"
8804 [(set (match_operand:SI 0 "s_register_operand" "")
aa0b3f8f 8805 (match_operator:SI 1 "expandable_comparison_operator"
f90b7a5a
PB
8806 [(match_operand:DF 2 "s_register_operand" "")
8807 (match_operand:DF 3 "arm_float_compare_operand" "")]))]
9b821a09 8808 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
f90b7a5a
PB
8809 "emit_insn (gen_cstore_cc (operands[0], operands[1],
8810 operands[2], operands[3])); DONE;"
8811)
8812
f90b7a5a
PB
8813(define_expand "cstoredi4"
8814 [(set (match_operand:SI 0 "s_register_operand" "")
aa0b3f8f 8815 (match_operator:SI 1 "expandable_comparison_operator"
a70418fc 8816 [(match_operand:DI 2 "s_register_operand" "")
73160ba9
DJ
8817 (match_operand:DI 3 "cmpdi_operand" "")]))]
8818 "TARGET_32BIT"
8819 "{
95ffee1f
RR
8820 if (!arm_validize_comparison (&operands[1],
8821 &operands[2],
8822 &operands[3]))
8823 FAIL;
8824 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
73160ba9
DJ
8825 operands[3]));
8826 DONE;
8827 }"
f90b7a5a
PB
8828)
8829
5b3e6663 8830(define_expand "cstoresi_eq0_thumb1"
a41a56b6
RE
8831 [(parallel
8832 [(set (match_operand:SI 0 "s_register_operand" "")
8833 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8834 (const_int 0)))
8835 (clobber (match_dup:SI 2))])]
5b3e6663 8836 "TARGET_THUMB1"
a41a56b6
RE
8837 "operands[2] = gen_reg_rtx (SImode);"
8838)
8839
5b3e6663 8840(define_expand "cstoresi_ne0_thumb1"
a41a56b6
RE
8841 [(parallel
8842 [(set (match_operand:SI 0 "s_register_operand" "")
8843 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8844 (const_int 0)))
8845 (clobber (match_dup:SI 2))])]
5b3e6663 8846 "TARGET_THUMB1"
a41a56b6
RE
8847 "operands[2] = gen_reg_rtx (SImode);"
8848)
8849
5b3e6663 8850(define_insn "*cstoresi_eq0_thumb1_insn"
a41a56b6
RE
8851 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
8852 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
8853 (const_int 0)))
8854 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
5b3e6663 8855 "TARGET_THUMB1"
a41a56b6
RE
8856 "@
8857 neg\\t%0, %1\;adc\\t%0, %0, %1
8858 neg\\t%2, %1\;adc\\t%0, %1, %2"
594726e4
JG
8859 [(set_attr "length" "4")
8860 (set_attr "type" "multiple")]
a41a56b6
RE
8861)
8862
5b3e6663 8863(define_insn "*cstoresi_ne0_thumb1_insn"
a41a56b6
RE
8864 [(set (match_operand:SI 0 "s_register_operand" "=l")
8865 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
8866 (const_int 0)))
8867 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
5b3e6663 8868 "TARGET_THUMB1"
a41a56b6
RE
8869 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
8870 [(set_attr "length" "4")]
8871)
8872
c4bb78e9 8873;; Used as part of the expansion of thumb ltu and gtu sequences
5b3e6663 8874(define_insn "cstoresi_nltu_thumb1"
a41a56b6 8875 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
70544f44 8876 (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
5b3e6663
PB
8877 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
8878 "TARGET_THUMB1"
a41a56b6 8879 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
594726e4
JG
8880 [(set_attr "length" "4")
8881 (set_attr "type" "multiple")]
a41a56b6
RE
8882)
8883
c4bb78e9
PB
8884(define_insn_and_split "cstoresi_ltu_thumb1"
8885 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
8886 (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
8887 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
8888 "TARGET_THUMB1"
8889 "#"
8890 "TARGET_THUMB1"
8891 [(set (match_dup 3)
8892 (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
8893 (set (match_dup 0) (neg:SI (match_dup 3)))]
8894 "operands[3] = gen_reg_rtx (SImode);"
594726e4
JG
8895 [(set_attr "length" "4")
8896 (set_attr "type" "multiple")]
c4bb78e9
PB
8897)
8898
a41a56b6 8899;; Used as part of the expansion of thumb les sequence.
5b3e6663 8900(define_insn "thumb1_addsi3_addgeu"
a41a56b6
RE
8901 [(set (match_operand:SI 0 "s_register_operand" "=l")
8902 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8903 (match_operand:SI 2 "s_register_operand" "l"))
8904 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
5b3e6663
PB
8905 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
8906 "TARGET_THUMB1"
a41a56b6 8907 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
594726e4
JG
8908 [(set_attr "length" "4")
8909 (set_attr "type" "multiple")]
a41a56b6
RE
8910)
8911
ff9940b0 8912\f
e7c3cc84
DE
8913;; Conditional move insns
8914
8915(define_expand "movsicc"
f54fd62e 8916 [(set (match_operand:SI 0 "s_register_operand" "")
aa0b3f8f 8917 (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
589fe0fc 8918 (match_operand:SI 2 "arm_not_operand" "")
f54fd62e 8919 (match_operand:SI 3 "arm_not_operand" "")))]
5b3e6663 8920 "TARGET_32BIT"
e7c3cc84 8921 "
5895f793 8922 {
95ffee1f 8923 enum rtx_code code;
3ade30ea
RE
8924 rtx ccreg;
8925
95ffee1f
RR
8926 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
8927 &XEXP (operands[1], 1)))
3ade30ea 8928 FAIL;
95ffee1f
RR
8929
8930 code = GET_CODE (operands[1]);
f90b7a5a 8931 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
18f0fe6b 8932 XEXP (operands[1], 1), NULL_RTX);
1c563bed 8933 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
5895f793
RE
8934 }"
8935)
e7c3cc84
DE
8936
8937(define_expand "movsfcc"
f54fd62e 8938 [(set (match_operand:SF 0 "s_register_operand" "")
1572e697 8939 (if_then_else:SF (match_operand 1 "arm_cond_move_operator" "")
f54fd62e 8940 (match_operand:SF 2 "s_register_operand" "")
dae840fc 8941 (match_operand:SF 3 "s_register_operand" "")))]
aad2bccb 8942 "TARGET_32BIT && TARGET_HARD_FLOAT"
e7c3cc84 8943 "
5895f793
RE
8944 {
8945 enum rtx_code code = GET_CODE (operands[1]);
8946 rtx ccreg;
7a0a1f09 8947
95ffee1f
RR
8948 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
8949 &XEXP (operands[1], 1)))
8950 FAIL;
e7c3cc84 8951
95ffee1f 8952 code = GET_CODE (operands[1]);
f90b7a5a 8953 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
18f0fe6b 8954 XEXP (operands[1], 1), NULL_RTX);
1c563bed 8955 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
5895f793
RE
8956 }"
8957)
e7c3cc84
DE
8958
8959(define_expand "movdfcc"
f54fd62e 8960 [(set (match_operand:DF 0 "s_register_operand" "")
1572e697 8961 (if_then_else:DF (match_operand 1 "arm_cond_move_operator" "")
f54fd62e 8962 (match_operand:DF 2 "s_register_operand" "")
dae840fc 8963 (match_operand:DF 3 "s_register_operand" "")))]
8fcd8c83 8964 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
e7c3cc84 8965 "
5895f793
RE
8966 {
8967 enum rtx_code code = GET_CODE (operands[1]);
3ade30ea 8968 rtx ccreg;
e7c3cc84 8969
95ffee1f
RR
8970 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
8971 &XEXP (operands[1], 1)))
8972 FAIL;
8973 code = GET_CODE (operands[1]);
f90b7a5a 8974 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
18f0fe6b 8975 XEXP (operands[1], 1), NULL_RTX);
1c563bed 8976 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
5895f793
RE
8977 }"
8978)
e7c3cc84 8979
a5a4c20a
KT
8980(define_insn "*cmov<mode>"
8981 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
8982 (if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
8983 [(match_operand 2 "cc_register" "") (const_int 0)])
8984 (match_operand:SDF 3 "s_register_operand"
8985 "<F_constraint>")
8986 (match_operand:SDF 4 "s_register_operand"
8987 "<F_constraint>")))]
8988 "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
8989 "*
8990 {
8991 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
8992 switch (code)
8993 {
8994 case ARM_GE:
8995 case ARM_GT:
8996 case ARM_EQ:
8997 case ARM_VS:
8998 return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
8999 case ARM_LT:
9000 case ARM_LE:
9001 case ARM_NE:
9002 case ARM_VC:
9003 return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
9004 default:
9005 gcc_unreachable ();
9006 }
9007 return \"\";
9008 }"
9009 [(set_attr "conds" "use")
9010 (set_attr "type" "f_sel<vfp_type>")]
9011)
9012
0480fff0 9013(define_insn_and_split "*movsicc_insn"
7a0a1f09 9014 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
f54fd62e 9015 (if_then_else:SI
05ed98a1 9016 (match_operator 3 "arm_comparison_operator"
f54fd62e 9017 [(match_operand 4 "cc_register" "") (const_int 0)])
7a0a1f09
RE
9018 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
9019 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
d5b7b3ae 9020 "TARGET_ARM"
e7c3cc84 9021 "@
f54fd62e
RE
9022 mov%D3\\t%0, %2
9023 mvn%D3\\t%0, #%B2
7a0a1f09
RE
9024 mov%d3\\t%0, %1
9025 mvn%d3\\t%0, #%B1
0480fff0
GY
9026 #
9027 #
9028 #
9029 #"
9030 ; alt4: mov%d3\\t%0, %1\;mov%D3\\t%0, %2
9031 ; alt5: mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
9032 ; alt6: mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
9033 ; alt7: mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
9034 "&& reload_completed"
9035 [(const_int 0)]
9036 {
9037 enum rtx_code rev_code;
9038 enum machine_mode mode;
9039 rtx rev_cond;
9040
9041 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9042 operands[3],
9043 gen_rtx_SET (VOIDmode,
9044 operands[0],
9045 operands[1])));
9046
9047 rev_code = GET_CODE (operands[3]);
9048 mode = GET_MODE (operands[4]);
9049 if (mode == CCFPmode || mode == CCFPEmode)
9050 rev_code = reverse_condition_maybe_unordered (rev_code);
9051 else
9052 rev_code = reverse_condition (rev_code);
9053
9054 rev_cond = gen_rtx_fmt_ee (rev_code,
9055 VOIDmode,
9056 operands[4],
9057 const0_rtx);
9058 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9059 rev_cond,
9060 gen_rtx_SET (VOIDmode,
9061 operands[0],
9062 operands[2])));
9063 DONE;
9064 }
7a0a1f09 9065 [(set_attr "length" "4,4,4,4,8,8,8,8")
f8045c41 9066 (set_attr "conds" "use")
148413a4
RR
9067 (set_attr_alternative "type"
9068 [(if_then_else (match_operand 2 "const_int_operand" "")
859abddd
SN
9069 (const_string "mov_imm")
9070 (const_string "mov_reg"))
9071 (const_string "mvn_imm")
148413a4 9072 (if_then_else (match_operand 1 "const_int_operand" "")
859abddd
SN
9073 (const_string "mov_imm")
9074 (const_string "mov_reg"))
9075 (const_string "mvn_imm")
9076 (const_string "mov_reg")
9077 (const_string "mov_reg")
9078 (const_string "mov_reg")
9079 (const_string "mov_reg")])]
5895f793 9080)
e7c3cc84 9081
e7c3cc84 9082(define_insn "*movsfcc_soft_insn"
7a0a1f09 9083 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
05ed98a1 9084 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
f54fd62e 9085 [(match_operand 4 "cc_register" "") (const_int 0)])
7a0a1f09
RE
9086 (match_operand:SF 1 "s_register_operand" "0,r")
9087 (match_operand:SF 2 "s_register_operand" "r,0")))]
d5b7b3ae 9088 "TARGET_ARM && TARGET_SOFT_FLOAT"
7a0a1f09
RE
9089 "@
9090 mov%D3\\t%0, %2
9091 mov%d3\\t%0, %1"
f8045c41 9092 [(set_attr "conds" "use")
859abddd 9093 (set_attr "type" "mov_reg")]
05ed98a1 9094)
e7c3cc84 9095
e7c3cc84 9096\f
ff9940b0
RE
9097;; Jump and linkage insns
9098
d5b7b3ae 9099(define_expand "jump"
ff9940b0
RE
9100 [(set (pc)
9101 (label_ref (match_operand 0 "" "")))]
d5b7b3ae 9102 "TARGET_EITHER"
ff9940b0 9103 ""
d5b7b3ae
RE
9104)
9105
9106(define_insn "*arm_jump"
9107 [(set (pc)
9108 (label_ref (match_operand 0 "" "")))]
5b3e6663 9109 "TARGET_32BIT"
ff9940b0 9110 "*
cca0a211
RE
9111 {
9112 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
9113 {
9114 arm_ccfsm_state += 2;
9115 return \"\";
9116 }
9117 return \"b%?\\t%l0\";
9118 }
9119 "
4925d0d5
WG
9120 [(set_attr "predicable" "yes")
9121 (set (attr "length")
9122 (if_then_else
b75b1be2 9123 (and (match_test "TARGET_THUMB2")
4925d0d5
WG
9124 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
9125 (le (minus (match_dup 0) (pc)) (const_int 2048))))
9126 (const_int 2)
594726e4
JG
9127 (const_int 4)))
9128 (set_attr "type" "branch")]
cca0a211 9129)
ff9940b0 9130
d5b7b3ae
RE
9131(define_insn "*thumb_jump"
9132 [(set (pc)
9133 (label_ref (match_operand 0 "" "")))]
5b3e6663 9134 "TARGET_THUMB1"
d5b7b3ae
RE
9135 "*
9136 if (get_attr_length (insn) == 2)
9137 return \"b\\t%l0\";
9138 return \"bl\\t%l0\\t%@ far jump\";
9139 "
9140 [(set (attr "far_jump")
9141 (if_then_else
9142 (eq_attr "length" "4")
9143 (const_string "yes")
9144 (const_string "no")))
9145 (set (attr "length")
9146 (if_then_else
a2246edc
NC
9147 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
9148 (le (minus (match_dup 0) (pc)) (const_int 2048)))
d5b7b3ae 9149 (const_int 2)
594726e4
JG
9150 (const_int 4)))
9151 (set_attr "type" "branch")]
d5b7b3ae
RE
9152)
9153
c1d5bfb9
RK
9154(define_expand "call"
9155 [(parallel [(call (match_operand 0 "memory_operand" "")
9156 (match_operand 1 "general_operand" ""))
d5b7b3ae 9157 (use (match_operand 2 "" ""))
48a08b9c 9158 (clobber (reg:SI LR_REGNUM))])]
d5b7b3ae 9159 "TARGET_EITHER"
b020fd92
NC
9160 "
9161 {
9403b7f7 9162 rtx callee, pat;
81ee8129 9163
81ee8129
SB
9164 /* In an untyped call, we can get NULL for operand 2. */
9165 if (operands[2] == NULL_RTX)
9166 operands[2] = const0_rtx;
9167
25a65198 9168 /* Decide if we should generate indirect calls by loading the
a50aa827 9169 32-bit address of the callee into a register before performing the
25a65198
RS
9170 branch and link. */
9171 callee = XEXP (operands[0], 0);
9172 if (GET_CODE (callee) == SYMBOL_REF
9173 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
9174 : !REG_P (callee))
81ee8129 9175 XEXP (operands[0], 0) = force_reg (Pmode, callee);
9403b7f7
RS
9176
9177 pat = gen_call_internal (operands[0], operands[1], operands[2]);
9178 arm_emit_call_insn (pat, XEXP (operands[0], 0));
9179 DONE;
b020fd92
NC
9180 }"
9181)
c1d5bfb9 9182
9403b7f7
RS
9183(define_expand "call_internal"
9184 [(parallel [(call (match_operand 0 "memory_operand" "")
9185 (match_operand 1 "general_operand" ""))
9186 (use (match_operand 2 "" ""))
9187 (clobber (reg:SI LR_REGNUM))])])
9188
68d560d4 9189(define_insn "*call_reg_armv5"
c1d5bfb9 9190 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
d5b7b3ae
RE
9191 (match_operand 1 "" ""))
9192 (use (match_operand 2 "" ""))
48a08b9c 9193 (clobber (reg:SI LR_REGNUM))]
9adcfa3c 9194 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
68d560d4
RE
9195 "blx%?\\t%0"
9196 [(set_attr "type" "call")]
9197)
9198
9199(define_insn "*call_reg_arm"
9200 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
9201 (match_operand 1 "" ""))
9202 (use (match_operand 2 "" ""))
9203 (clobber (reg:SI LR_REGNUM))]
9adcfa3c 9204 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
ff9940b0 9205 "*
68df59d3 9206 return output_call (operands);
d5b7b3ae
RE
9207 "
9208 ;; length is worst case, normally it is only two
9209 [(set_attr "length" "12")
9210 (set_attr "type" "call")]
9211)
ff9940b0 9212
0986ef45
JB
9213
9214;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
9215;; considered a function call by the branch predictor of some cores (PR40887).
9216;; Falls back to blx rN (*call_reg_armv5).
9217
4cdb3ed4 9218(define_insn "*call_mem"
e6add59b 9219 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
d5b7b3ae
RE
9220 (match_operand 1 "" ""))
9221 (use (match_operand 2 "" ""))
48a08b9c 9222 (clobber (reg:SI LR_REGNUM))]
9adcfa3c 9223 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
ff9940b0 9224 "*
68df59d3 9225 return output_call_mem (operands);
d5b7b3ae
RE
9226 "
9227 [(set_attr "length" "12")
9228 (set_attr "type" "call")]
9229)
9230
5b3e6663 9231(define_insn "*call_reg_thumb1_v5"
d5b7b3ae
RE
9232 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
9233 (match_operand 1 "" ""))
9234 (use (match_operand 2 "" ""))
48a08b9c 9235 (clobber (reg:SI LR_REGNUM))]
9adcfa3c 9236 "TARGET_THUMB1 && arm_arch5 && !SIBLING_CALL_P (insn)"
68d560d4
RE
9237 "blx\\t%0"
9238 [(set_attr "length" "2")
9239 (set_attr "type" "call")]
d5b7b3ae
RE
9240)
9241
5b3e6663 9242(define_insn "*call_reg_thumb1"
68d560d4
RE
9243 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
9244 (match_operand 1 "" ""))
9245 (use (match_operand 2 "" ""))
48a08b9c 9246 (clobber (reg:SI LR_REGNUM))]
9adcfa3c 9247 "TARGET_THUMB1 && !arm_arch5 && !SIBLING_CALL_P (insn)"
d5b7b3ae
RE
9248 "*
9249 {
a2503645 9250 if (!TARGET_CALLER_INTERWORKING)
b12a00f1 9251 return thumb_call_via_reg (operands[0]);
a2503645 9252 else if (operands[1] == const0_rtx)
68d560d4 9253 return \"bl\\t%__interwork_call_via_%0\";
a2503645
RS
9254 else if (frame_pointer_needed)
9255 return \"bl\\t%__interwork_r7_call_via_%0\";
d5b7b3ae 9256 else
a2503645 9257 return \"bl\\t%__interwork_r11_call_via_%0\";
d5b7b3ae
RE
9258 }"
9259 [(set_attr "type" "call")]
9260)
ff9940b0 9261
c1d5bfb9 9262(define_expand "call_value"
60dd1b7b
AH
9263 [(parallel [(set (match_operand 0 "" "")
9264 (call (match_operand 1 "memory_operand" "")
9265 (match_operand 2 "general_operand" "")))
d5b7b3ae 9266 (use (match_operand 3 "" ""))
48a08b9c 9267 (clobber (reg:SI LR_REGNUM))])]
d5b7b3ae 9268 "TARGET_EITHER"
b020fd92
NC
9269 "
9270 {
9403b7f7 9271 rtx pat, callee;
81ee8129
SB
9272
9273 /* In an untyped call, we can get NULL for operand 2. */
9274 if (operands[3] == 0)
9275 operands[3] = const0_rtx;
9276
25a65198
RS
9277 /* Decide if we should generate indirect calls by loading the
9278 32-bit address of the callee into a register before performing the
9279 branch and link. */
9280 callee = XEXP (operands[1], 0);
9281 if (GET_CODE (callee) == SYMBOL_REF
9282 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
9283 : !REG_P (callee))
c27ba912 9284 XEXP (operands[1], 0) = force_reg (Pmode, callee);
9403b7f7
RS
9285
9286 pat = gen_call_value_internal (operands[0], operands[1],
9287 operands[2], operands[3]);
9288 arm_emit_call_insn (pat, XEXP (operands[1], 0));
9289 DONE;
b020fd92
NC
9290 }"
9291)
c1d5bfb9 9292
9403b7f7
RS
9293(define_expand "call_value_internal"
9294 [(parallel [(set (match_operand 0 "" "")
9295 (call (match_operand 1 "memory_operand" "")
9296 (match_operand 2 "general_operand" "")))
9297 (use (match_operand 3 "" ""))
9298 (clobber (reg:SI LR_REGNUM))])])
9299
68d560d4 9300(define_insn "*call_value_reg_armv5"
24391720 9301 [(set (match_operand 0 "" "")
5a9335ef 9302 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
d5b7b3ae 9303 (match_operand 2 "" "")))
81ee8129 9304 (use (match_operand 3 "" ""))
48a08b9c 9305 (clobber (reg:SI LR_REGNUM))]
9adcfa3c 9306 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
68d560d4
RE
9307 "blx%?\\t%1"
9308 [(set_attr "type" "call")]
9309)
9310
9311(define_insn "*call_value_reg_arm"
9312 [(set (match_operand 0 "" "")
9313 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
9314 (match_operand 2 "" "")))
9315 (use (match_operand 3 "" ""))
9316 (clobber (reg:SI LR_REGNUM))]
9adcfa3c 9317 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
ff9940b0 9318 "*
5895f793 9319 return output_call (&operands[1]);
d5b7b3ae
RE
9320 "
9321 [(set_attr "length" "12")
9322 (set_attr "type" "call")]
9323)
ff9940b0 9324
0986ef45
JB
9325;; Note: see *call_mem
9326
4cdb3ed4 9327(define_insn "*call_value_mem"
24391720 9328 [(set (match_operand 0 "" "")
e6add59b 9329 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
d5b7b3ae 9330 (match_operand 2 "" "")))
81ee8129 9331 (use (match_operand 3 "" ""))
48a08b9c 9332 (clobber (reg:SI LR_REGNUM))]
9adcfa3c
RR
9333 "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
9334 && !SIBLING_CALL_P (insn)"
ff9940b0 9335 "*
5895f793 9336 return output_call_mem (&operands[1]);
d5b7b3ae
RE
9337 "
9338 [(set_attr "length" "12")
9339 (set_attr "type" "call")]
9340)
ff9940b0 9341
5b3e6663 9342(define_insn "*call_value_reg_thumb1_v5"
68d560d4
RE
9343 [(set (match_operand 0 "" "")
9344 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
9345 (match_operand 2 "" "")))
9346 (use (match_operand 3 "" ""))
9347 (clobber (reg:SI LR_REGNUM))]
5b3e6663 9348 "TARGET_THUMB1 && arm_arch5"
68d560d4
RE
9349 "blx\\t%1"
9350 [(set_attr "length" "2")
9351 (set_attr "type" "call")]
9352)
9353
5b3e6663 9354(define_insn "*call_value_reg_thumb1"
68d560d4
RE
9355 [(set (match_operand 0 "" "")
9356 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
9357 (match_operand 2 "" "")))
9358 (use (match_operand 3 "" ""))
9359 (clobber (reg:SI LR_REGNUM))]
5b3e6663 9360 "TARGET_THUMB1 && !arm_arch5"
68d560d4
RE
9361 "*
9362 {
a2503645 9363 if (!TARGET_CALLER_INTERWORKING)
b12a00f1 9364 return thumb_call_via_reg (operands[1]);
a2503645 9365 else if (operands[2] == const0_rtx)
68d560d4 9366 return \"bl\\t%__interwork_call_via_%1\";
a2503645
RS
9367 else if (frame_pointer_needed)
9368 return \"bl\\t%__interwork_r7_call_via_%1\";
68d560d4 9369 else
a2503645 9370 return \"bl\\t%__interwork_r11_call_via_%1\";
68d560d4
RE
9371 }"
9372 [(set_attr "type" "call")]
9373)
9374
ff9940b0
RE
9375;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
9376;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
9377
4cdb3ed4 9378(define_insn "*call_symbol"
24391720 9379 [(call (mem:SI (match_operand:SI 0 "" ""))
d5b7b3ae 9380 (match_operand 1 "" ""))
81ee8129 9381 (use (match_operand 2 "" ""))
48a08b9c 9382 (clobber (reg:SI LR_REGNUM))]
7c19c715 9383 "TARGET_32BIT
9adcfa3c 9384 && !SIBLING_CALL_P (insn)
d5b7b3ae 9385 && (GET_CODE (operands[0]) == SYMBOL_REF)
25a65198 9386 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
86efdc8e
PB
9387 "*
9388 {
ed0e6530 9389 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
86efdc8e 9390 }"
d5b7b3ae
RE
9391 [(set_attr "type" "call")]
9392)
ff9940b0 9393
4cdb3ed4 9394(define_insn "*call_value_symbol"
9f7bf991 9395 [(set (match_operand 0 "" "")
24391720 9396 (call (mem:SI (match_operand:SI 1 "" ""))
41e3f998 9397 (match_operand:SI 2 "" "")))
81ee8129 9398 (use (match_operand 3 "" ""))
48a08b9c 9399 (clobber (reg:SI LR_REGNUM))]
7c19c715 9400 "TARGET_32BIT
9adcfa3c 9401 && !SIBLING_CALL_P (insn)
d5b7b3ae 9402 && (GET_CODE (operands[1]) == SYMBOL_REF)
25a65198 9403 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
86efdc8e
PB
9404 "*
9405 {
ed0e6530 9406 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
86efdc8e 9407 }"
d5b7b3ae
RE
9408 [(set_attr "type" "call")]
9409)
9410
9411(define_insn "*call_insn"
24391720 9412 [(call (mem:SI (match_operand:SI 0 "" ""))
d5b7b3ae
RE
9413 (match_operand:SI 1 "" ""))
9414 (use (match_operand 2 "" ""))
48a08b9c 9415 (clobber (reg:SI LR_REGNUM))]
7c19c715 9416 "TARGET_THUMB1
7b8781c8 9417 && GET_CODE (operands[0]) == SYMBOL_REF
25a65198 9418 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
d5b7b3ae
RE
9419 "bl\\t%a0"
9420 [(set_attr "length" "4")
9421 (set_attr "type" "call")]
9422)
9423
9424(define_insn "*call_value_insn"
9f7bf991 9425 [(set (match_operand 0 "" "")
24391720 9426 (call (mem:SI (match_operand 1 "" ""))
d5b7b3ae
RE
9427 (match_operand 2 "" "")))
9428 (use (match_operand 3 "" ""))
48a08b9c 9429 (clobber (reg:SI LR_REGNUM))]
7c19c715 9430 "TARGET_THUMB1
7b8781c8 9431 && GET_CODE (operands[1]) == SYMBOL_REF
25a65198 9432 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
d5b7b3ae
RE
9433 "bl\\t%a1"
9434 [(set_attr "length" "4")
9435 (set_attr "type" "call")]
9436)
ff9940b0 9437
0616531f
RE
9438;; We may also be able to do sibcalls for Thumb, but it's much harder...
9439(define_expand "sibcall"
9440 [(parallel [(call (match_operand 0 "memory_operand" "")
9441 (match_operand 1 "general_operand" ""))
72b075d1
RE
9442 (return)
9443 (use (match_operand 2 "" ""))])]
7c19c715 9444 "TARGET_32BIT"
0616531f
RE
9445 "
9446 {
9adcfa3c
RR
9447 if (!REG_P (XEXP (operands[0], 0))
9448 && (GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF))
9449 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
9450
0616531f
RE
9451 if (operands[2] == NULL_RTX)
9452 operands[2] = const0_rtx;
0616531f
RE
9453 }"
9454)
9455
9456(define_expand "sibcall_value"
9f7bf991 9457 [(parallel [(set (match_operand 0 "" "")
0616531f
RE
9458 (call (match_operand 1 "memory_operand" "")
9459 (match_operand 2 "general_operand" "")))
72b075d1
RE
9460 (return)
9461 (use (match_operand 3 "" ""))])]
7c19c715 9462 "TARGET_32BIT"
0616531f
RE
9463 "
9464 {
9adcfa3c
RR
9465 if (!REG_P (XEXP (operands[1], 0)) &&
9466 (GET_CODE (XEXP (operands[1],0)) != SYMBOL_REF))
9467 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
9468
0616531f
RE
9469 if (operands[3] == NULL_RTX)
9470 operands[3] = const0_rtx;
0616531f
RE
9471 }"
9472)
9473
9474(define_insn "*sibcall_insn"
0b93d3b6 9475 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
0616531f 9476 (match_operand 1 "" ""))
72b075d1
RE
9477 (return)
9478 (use (match_operand 2 "" ""))]
9adcfa3c 9479 "TARGET_32BIT && SIBLING_CALL_P (insn)"
0616531f 9480 "*
9adcfa3c
RR
9481 if (which_alternative == 1)
9482 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
9483 else
9484 {
9485 if (arm_arch5 || arm_arch4t)
e6dcfa18 9486 return \"bx%?\\t%0\\t%@ indirect register sibling call\";
9adcfa3c
RR
9487 else
9488 return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
9489 }
0616531f
RE
9490 "
9491 [(set_attr "type" "call")]
9492)
9493
9494(define_insn "*sibcall_value_insn"
0b93d3b6
RR
9495 [(set (match_operand 0 "" "")
9496 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
0616531f 9497 (match_operand 2 "" "")))
72b075d1
RE
9498 (return)
9499 (use (match_operand 3 "" ""))]
9adcfa3c 9500 "TARGET_32BIT && SIBLING_CALL_P (insn)"
0616531f 9501 "*
9adcfa3c
RR
9502 if (which_alternative == 1)
9503 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
9504 else
9505 {
9506 if (arm_arch5 || arm_arch4t)
0b93d3b6 9507 return \"bx%?\\t%1\";
9adcfa3c
RR
9508 else
9509 return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
9510 }
0616531f
RE
9511 "
9512 [(set_attr "type" "call")]
9513)
9514
24d5b097
XG
9515(define_expand "<return_str>return"
9516 [(returns)]
482baa63
IB
9517 "(TARGET_ARM || (TARGET_THUMB2
9518 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
9519 && !IS_STACKALIGN (arm_current_func_type ())))
24d5b097 9520 <return_cond_false>"
482baa63
IB
9521 "
9522 {
9523 if (TARGET_THUMB2)
9524 {
24d5b097 9525 thumb2_expand_return (<return_simple_p>);
482baa63
IB
9526 DONE;
9527 }
9528 }
9529 "
9530)
7c19c715 9531
ff9940b0 9532;; Often the return insn will be the same as loading from memory, so set attr
7c19c715 9533(define_insn "*arm_return"
ff9940b0 9534 [(return)]
d5b7b3ae 9535 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
ff9940b0 9536 "*
ff9940b0 9537 {
d5b7b3ae
RE
9538 if (arm_ccfsm_state == 2)
9539 {
9540 arm_ccfsm_state += 2;
9541 return \"\";
9542 }
f79b86a4 9543 return output_return_instruction (const_true_rtx, true, false, false);
d5b7b3ae 9544 }"
9b66ebb1 9545 [(set_attr "type" "load1")
5a9335ef 9546 (set_attr "length" "12")
cca0a211 9547 (set_attr "predicable" "yes")]
d5b7b3ae 9548)
ff9940b0 9549
24d5b097 9550(define_insn "*cond_<return_str>return"
ff9940b0 9551 [(set (pc)
05ed98a1 9552 (if_then_else (match_operator 0 "arm_comparison_operator"
f54fd62e 9553 [(match_operand 1 "cc_register" "") (const_int 0)])
24d5b097 9554 (returns)
ff9940b0 9555 (pc)))]
24d5b097 9556 "TARGET_ARM <return_cond_true>"
ff9940b0 9557 "*
05ed98a1
RE
9558 {
9559 if (arm_ccfsm_state == 2)
9560 {
9561 arm_ccfsm_state += 2;
9562 return \"\";
9563 }
24d5b097
XG
9564 return output_return_instruction (operands[0], true, false,
9565 <return_simple_p>);
05ed98a1
RE
9566 }"
9567 [(set_attr "conds" "use")
5a9335ef 9568 (set_attr "length" "12")
9b66ebb1 9569 (set_attr "type" "load1")]
05ed98a1 9570)
ff9940b0 9571
24d5b097 9572(define_insn "*cond_<return_str>return_inverted"
ff9940b0 9573 [(set (pc)
05ed98a1 9574 (if_then_else (match_operator 0 "arm_comparison_operator"
f54fd62e 9575 [(match_operand 1 "cc_register" "") (const_int 0)])
ff9940b0 9576 (pc)
24d5b097
XG
9577 (returns)))]
9578 "TARGET_ARM <return_cond_true>"
ff9940b0 9579 "*
05ed98a1
RE
9580 {
9581 if (arm_ccfsm_state == 2)
9582 {
9583 arm_ccfsm_state += 2;
9584 return \"\";
9585 }
24d5b097
XG
9586 return output_return_instruction (operands[0], true, true,
9587 <return_simple_p>);
05ed98a1
RE
9588 }"
9589 [(set_attr "conds" "use")
3e1b8dc0 9590 (set_attr "length" "12")
9b66ebb1 9591 (set_attr "type" "load1")]
05ed98a1 9592)
ff9940b0 9593
f79b86a4
IB
9594(define_insn "*arm_simple_return"
9595 [(simple_return)]
9596 "TARGET_ARM"
9597 "*
9598 {
9599 if (arm_ccfsm_state == 2)
9600 {
9601 arm_ccfsm_state += 2;
9602 return \"\";
9603 }
9604 return output_return_instruction (const_true_rtx, true, false, true);
9605 }"
9606 [(set_attr "type" "branch")
9607 (set_attr "length" "4")
9608 (set_attr "predicable" "yes")]
9609)
9610
fcd53748
JT
9611;; Generate a sequence of instructions to determine if the processor is
9612;; in 26-bit or 32-bit mode, and return the appropriate return address
9613;; mask.
9614
9615(define_expand "return_addr_mask"
9616 [(set (match_dup 1)
9617 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
9618 (const_int 0)))
9619 (set (match_operand:SI 0 "s_register_operand" "")
9620 (if_then_else:SI (eq (match_dup 1) (const_int 0))
9621 (const_int -1)
9622 (const_int 67108860)))] ; 0x03fffffc
9623 "TARGET_ARM"
9624 "
20ae4500 9625 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
fcd53748
JT
9626 ")
9627
9628(define_insn "*check_arch2"
9629 [(set (match_operand:CC_NOOV 0 "cc_register" "")
9630 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
9631 (const_int 0)))]
9632 "TARGET_ARM"
9633 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
9634 [(set_attr "length" "8")
594726e4
JG
9635 (set_attr "conds" "set")
9636 (set_attr "type" "multiple")]
fcd53748
JT
9637)
9638
ff9940b0
RE
9639;; Call subroutine returning any type.
9640
9641(define_expand "untyped_call"
9642 [(parallel [(call (match_operand 0 "" "")
9643 (const_int 0))
9644 (match_operand 1 "" "")
9645 (match_operand 2 "" "")])]
9f7bf991 9646 "TARGET_EITHER"
ff9940b0 9647 "
5895f793
RE
9648 {
9649 int i;
9f7bf991
RE
9650 rtx par = gen_rtx_PARALLEL (VOIDmode,
9651 rtvec_alloc (XVECLEN (operands[2], 0)));
9652 rtx addr = gen_reg_rtx (Pmode);
9653 rtx mem;
9654 int size = 0;
ff9940b0 9655
9f7bf991
RE
9656 emit_move_insn (addr, XEXP (operands[1], 0));
9657 mem = change_address (operands[1], BLKmode, addr);
ff9940b0 9658
5895f793
RE
9659 for (i = 0; i < XVECLEN (operands[2], 0); i++)
9660 {
9f7bf991 9661 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
ff9940b0 9662
9f7bf991
RE
9663 /* Default code only uses r0 as a return value, but we could
9664 be using anything up to 4 registers. */
9665 if (REGNO (src) == R0_REGNUM)
9666 src = gen_rtx_REG (TImode, R0_REGNUM);
9667
9668 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
9669 GEN_INT (size));
9670 size += GET_MODE_SIZE (GET_MODE (src));
9671 }
9672
9673 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
9674 const0_rtx));
9675
9676 size = 0;
9677
9678 for (i = 0; i < XVECLEN (par, 0); i++)
9679 {
9680 HOST_WIDE_INT offset = 0;
9681 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
9682
9683 if (size != 0)
0a81f074 9684 emit_move_insn (addr, plus_constant (Pmode, addr, size));
9f7bf991
RE
9685
9686 mem = change_address (mem, GET_MODE (reg), NULL);
9687 if (REGNO (reg) == R0_REGNUM)
9688 {
9689 /* On thumb we have to use a write-back instruction. */
37119410
BS
9690 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
9691 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
9f7bf991
RE
9692 size = TARGET_ARM ? 16 : 0;
9693 }
9694 else
9695 {
9696 emit_move_insn (mem, reg);
9697 size = GET_MODE_SIZE (GET_MODE (reg));
9698 }
5895f793 9699 }
ff9940b0 9700
5895f793
RE
9701 /* The optimizer does not know that the call sets the function value
9702 registers we stored in the result block. We avoid problems by
9703 claiming that all hard registers are used and clobbered at this
9704 point. */
9705 emit_insn (gen_blockage ());
9706
9707 DONE;
9708 }"
9709)
ff9940b0 9710
9f7bf991
RE
9711(define_expand "untyped_return"
9712 [(match_operand:BLK 0 "memory_operand" "")
9713 (match_operand 1 "" "")]
9714 "TARGET_EITHER"
9715 "
9716 {
9717 int i;
9718 rtx addr = gen_reg_rtx (Pmode);
9719 rtx mem;
9720 int size = 0;
9721
9722 emit_move_insn (addr, XEXP (operands[0], 0));
9723 mem = change_address (operands[0], BLKmode, addr);
9724
9725 for (i = 0; i < XVECLEN (operands[1], 0); i++)
9726 {
9727 HOST_WIDE_INT offset = 0;
9728 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
9729
9730 if (size != 0)
0a81f074 9731 emit_move_insn (addr, plus_constant (Pmode, addr, size));
9f7bf991
RE
9732
9733 mem = change_address (mem, GET_MODE (reg), NULL);
9734 if (REGNO (reg) == R0_REGNUM)
9735 {
9736 /* On thumb we have to use a write-back instruction. */
37119410
BS
9737 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
9738 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
9f7bf991
RE
9739 size = TARGET_ARM ? 16 : 0;
9740 }
9741 else
9742 {
9743 emit_move_insn (reg, mem);
9744 size = GET_MODE_SIZE (GET_MODE (reg));
9745 }
9746 }
9747
9748 /* Emit USE insns before the return. */
9749 for (i = 0; i < XVECLEN (operands[1], 0); i++)
c41c1387 9750 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
9f7bf991
RE
9751
9752 /* Construct the return. */
9753 expand_naked_return ();
9754
9755 DONE;
9756 }"
9757)
9758
ff9940b0
RE
9759;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
9760;; all of memory. This blocks insns from being moved across this point.
9761
9762(define_insn "blockage"
b15bca31 9763 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
d5b7b3ae 9764 "TARGET_EITHER"
ff9940b0 9765 ""
d5b7b3ae
RE
9766 [(set_attr "length" "0")
9767 (set_attr "type" "block")]
9768)
ff9940b0 9769
4cdb3ed4
RE
9770(define_expand "casesi"
9771 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
589fe0fc
RE
9772 (match_operand:SI 1 "const_int_operand" "") ; lower bound
9773 (match_operand:SI 2 "const_int_operand" "") ; total range
4cdb3ed4
RE
9774 (match_operand:SI 3 "" "") ; table label
9775 (match_operand:SI 4 "" "")] ; Out of range label
907dd0c7 9776 "TARGET_32BIT || optimize_size || flag_pic"
4cdb3ed4 9777 "
5895f793 9778 {
907dd0c7 9779 enum insn_code code;
5895f793
RE
9780 if (operands[1] != const0_rtx)
9781 {
907dd0c7 9782 rtx reg = gen_reg_rtx (SImode);
4cdb3ed4 9783
5895f793 9784 emit_insn (gen_addsi3 (reg, operands[0],
4908b0bf
CLT
9785 gen_int_mode (-INTVAL (operands[1]),
9786 SImode)));
5895f793
RE
9787 operands[0] = reg;
9788 }
ff9940b0 9789
5b3e6663 9790 if (TARGET_ARM)
907dd0c7 9791 code = CODE_FOR_arm_casesi_internal;
75d28030 9792 else if (TARGET_THUMB1)
907dd0c7 9793 code = CODE_FOR_thumb1_casesi_internal_pic;
5b3e6663 9794 else if (flag_pic)
907dd0c7 9795 code = CODE_FOR_thumb2_casesi_internal_pic;
5b3e6663 9796 else
907dd0c7
RE
9797 code = CODE_FOR_thumb2_casesi_internal;
9798
9799 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
9800 operands[2] = force_reg (SImode, operands[2]);
9801
9802 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
9803 operands[3], operands[4]));
5895f793
RE
9804 DONE;
9805 }"
9806)
4cdb3ed4 9807
7a0a1f09
RE
9808;; The USE in this pattern is needed to tell flow analysis that this is
9809;; a CASESI insn. It has no other purpose.
5b3e6663 9810(define_insn "arm_casesi_internal"
7a0a1f09
RE
9811 [(parallel [(set (pc)
9812 (if_then_else
9813 (leu (match_operand:SI 0 "s_register_operand" "r")
9814 (match_operand:SI 1 "arm_rhs_operand" "rI"))
9815 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
9816 (label_ref (match_operand 2 "" ""))))
9817 (label_ref (match_operand 3 "" ""))))
48a08b9c 9818 (clobber (reg:CC CC_REGNUM))
7a0a1f09 9819 (use (label_ref (match_dup 2)))])]
d5b7b3ae 9820 "TARGET_ARM"
4cdb3ed4 9821 "*
cca0a211
RE
9822 if (flag_pic)
9823 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
9824 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
9825 "
9826 [(set_attr "conds" "clob")
594726e4
JG
9827 (set_attr "length" "12")
9828 (set_attr "type" "multiple")]
cca0a211 9829)
ff9940b0 9830
907dd0c7
RE
9831(define_expand "thumb1_casesi_internal_pic"
9832 [(match_operand:SI 0 "s_register_operand" "")
9833 (match_operand:SI 1 "thumb1_cmp_operand" "")
9834 (match_operand 2 "" "")
9835 (match_operand 3 "" "")]
75d28030 9836 "TARGET_THUMB1"
907dd0c7
RE
9837 {
9838 rtx reg0;
9839 rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
9840 emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
9841 operands[3]));
9842 reg0 = gen_rtx_REG (SImode, 0);
9843 emit_move_insn (reg0, operands[0]);
9844 emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
9845 DONE;
9846 }
9847)
9848
9849(define_insn "thumb1_casesi_dispatch"
9850 [(parallel [(set (pc) (unspec [(reg:SI 0)
9851 (label_ref (match_operand 0 "" ""))
9852;; (label_ref (match_operand 1 "" ""))
9853]
9854 UNSPEC_THUMB1_CASESI))
9855 (clobber (reg:SI IP_REGNUM))
9856 (clobber (reg:SI LR_REGNUM))])]
75d28030 9857 "TARGET_THUMB1"
907dd0c7 9858 "* return thumb1_output_casesi(operands);"
594726e4
JG
9859 [(set_attr "length" "4")
9860 (set_attr "type" "multiple")]
907dd0c7
RE
9861)
9862
d5b7b3ae 9863(define_expand "indirect_jump"
ff9940b0 9864 [(set (pc)
d5b7b3ae
RE
9865 (match_operand:SI 0 "s_register_operand" ""))]
9866 "TARGET_EITHER"
5b3e6663
PB
9867 "
9868 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
9869 address and use bx. */
9870 if (TARGET_THUMB2)
9871 {
9872 rtx tmp;
9873 tmp = gen_reg_rtx (SImode);
9874 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
9875 operands[0] = tmp;
9876 }
9877 "
d5b7b3ae
RE
9878)
9879
68d560d4 9880;; NB Never uses BX.
d5b7b3ae
RE
9881(define_insn "*arm_indirect_jump"
9882 [(set (pc)
9883 (match_operand:SI 0 "s_register_operand" "r"))]
9884 "TARGET_ARM"
9885 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
594726e4
JG
9886 [(set_attr "predicable" "yes")
9887 (set_attr "type" "branch")]
d5b7b3ae 9888)
ff9940b0 9889
4cdb3ed4 9890(define_insn "*load_indirect_jump"
ff9940b0
RE
9891 [(set (pc)
9892 (match_operand:SI 0 "memory_operand" "m"))]
d5b7b3ae
RE
9893 "TARGET_ARM"
9894 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
9b66ebb1 9895 [(set_attr "type" "load1")
859230d4
NC
9896 (set_attr "pool_range" "4096")
9897 (set_attr "neg_pool_range" "4084")
cca0a211 9898 (set_attr "predicable" "yes")]
d5b7b3ae
RE
9899)
9900
68d560d4 9901;; NB Never uses BX.
5b3e6663 9902(define_insn "*thumb1_indirect_jump"
d5b7b3ae
RE
9903 [(set (pc)
9904 (match_operand:SI 0 "register_operand" "l*r"))]
5b3e6663 9905 "TARGET_THUMB1"
d5b7b3ae
RE
9906 "mov\\tpc, %0"
9907 [(set_attr "conds" "clob")
594726e4
JG
9908 (set_attr "length" "2")
9909 (set_attr "type" "branch")]
d5b7b3ae
RE
9910)
9911
ff9940b0
RE
9912\f
9913;; Misc insns
9914
9915(define_insn "nop"
9916 [(const_int 0)]
d5b7b3ae
RE
9917 "TARGET_EITHER"
9918 "*
5b3e6663
PB
9919 if (TARGET_UNIFIED_ASM)
9920 return \"nop\";
d5b7b3ae
RE
9921 if (TARGET_ARM)
9922 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
9923 return \"mov\\tr8, r8\";
9924 "
9925 [(set (attr "length")
9926 (if_then_else (eq_attr "is_thumb" "yes")
9927 (const_int 2)
594726e4
JG
9928 (const_int 4)))
9929 (set_attr "type" "mov_reg")]
d5b7b3ae
RE
9930)
9931
60ea4be6
IB
9932(define_insn "trap"
9933 [(trap_if (const_int 1) (const_int 0))]
9934 ""
9935 "*
9936 if (TARGET_ARM)
9937 return \".inst\\t0xe7f000f0\";
9938 else
9939 return \".inst\\t0xdeff\";
9940 "
9941 [(set (attr "length")
9942 (if_then_else (eq_attr "is_thumb" "yes")
9943 (const_int 2)
9944 (const_int 4)))
9945 (set_attr "type" "trap")
9946 (set_attr "conds" "unconditional")]
9947)
9948
ff9940b0
RE
9949\f
9950;; Patterns to allow combination of arithmetic, cond code and shifts
9951
4cdb3ed4 9952(define_insn "*arith_shiftsi"
9a1ea4b9 9953 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
ff9940b0
RE
9954 (match_operator:SI 1 "shiftable_operator"
9955 [(match_operator:SI 3 "shift_operator"
9a1ea4b9
RR
9956 [(match_operand:SI 4 "s_register_operand" "r,r,r,r")
9957 (match_operand:SI 5 "shift_amount_operand" "M,M,M,r")])
9958 (match_operand:SI 2 "s_register_operand" "rk,rk,r,rk")]))]
c29e2982 9959 "TARGET_32BIT"
b020fd92 9960 "%i1%?\\t%0, %2, %4%S3"
ca68ea18 9961 [(set_attr "predicable" "yes")
d19fb8e3 9962 (set_attr "shift" "4")
9a1ea4b9
RR
9963 (set_attr "arch" "a,t2,t2,a")
9964 ;; Thumb2 doesn't allow the stack pointer to be used for
9965 ;; operand1 for all operations other than add and sub. In this case
9966 ;; the minus operation is a candidate for an rsub and hence needs
9967 ;; to be disabled.
9968 ;; We have to make sure to disable the fourth alternative if
c29e2982
BS
9969 ;; the shift_operator is MULT, since otherwise the insn will
9970 ;; also match a multiply_accumulate pattern and validate_change
9971 ;; will allow a replacement of the constant with a register
9972 ;; despite the checks done in shift_operator.
9973 (set_attr_alternative "insn_enabled"
9974 [(const_string "yes")
9a1ea4b9
RR
9975 (if_then_else
9976 (match_operand:SI 1 "add_operator" "")
9977 (const_string "yes") (const_string "no"))
9978 (const_string "yes")
c29e2982
BS
9979 (if_then_else
9980 (match_operand:SI 3 "mult_operator" "")
9981 (const_string "no") (const_string "yes"))])
6e4150e1 9982 (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_imm,alu_shift_reg")])
ff9940b0 9983
da5cafa7
RE
9984(define_split
9985 [(set (match_operand:SI 0 "s_register_operand" "")
9986 (match_operator:SI 1 "shiftable_operator"
9987 [(match_operator:SI 2 "shiftable_operator"
9988 [(match_operator:SI 3 "shift_operator"
9989 [(match_operand:SI 4 "s_register_operand" "")
9990 (match_operand:SI 5 "reg_or_int_operand" "")])
9991 (match_operand:SI 6 "s_register_operand" "")])
9992 (match_operand:SI 7 "arm_rhs_operand" "")]))
9993 (clobber (match_operand:SI 8 "s_register_operand" ""))]
c29e2982 9994 "TARGET_32BIT"
da5cafa7
RE
9995 [(set (match_dup 8)
9996 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9997 (match_dup 6)]))
9998 (set (match_dup 0)
9999 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
10000 "")
10001
4cdb3ed4 10002(define_insn "*arith_shiftsi_compare0"
48a08b9c 10003 [(set (reg:CC_NOOV CC_REGNUM)
c29e2982
BS
10004 (compare:CC_NOOV
10005 (match_operator:SI 1 "shiftable_operator"
10006 [(match_operator:SI 3 "shift_operator"
10007 [(match_operand:SI 4 "s_register_operand" "r,r")
10008 (match_operand:SI 5 "shift_amount_operand" "M,r")])
10009 (match_operand:SI 2 "s_register_operand" "r,r")])
10010 (const_int 0)))
10011 (set (match_operand:SI 0 "s_register_operand" "=r,r")
ff9940b0
RE
10012 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
10013 (match_dup 2)]))]
c29e2982 10014 "TARGET_32BIT"
5b3e6663 10015 "%i1%.\\t%0, %2, %4%S3"
ca68ea18 10016 [(set_attr "conds" "set")
d19fb8e3 10017 (set_attr "shift" "4")
c29e2982 10018 (set_attr "arch" "32,a")
6e4150e1 10019 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
ff9940b0 10020
4cdb3ed4 10021(define_insn "*arith_shiftsi_compare0_scratch"
48a08b9c 10022 [(set (reg:CC_NOOV CC_REGNUM)
c29e2982
BS
10023 (compare:CC_NOOV
10024 (match_operator:SI 1 "shiftable_operator"
10025 [(match_operator:SI 3 "shift_operator"
10026 [(match_operand:SI 4 "s_register_operand" "r,r")
10027 (match_operand:SI 5 "shift_amount_operand" "M,r")])
10028 (match_operand:SI 2 "s_register_operand" "r,r")])
10029 (const_int 0)))
10030 (clobber (match_scratch:SI 0 "=r,r"))]
10031 "TARGET_32BIT"
5b3e6663 10032 "%i1%.\\t%0, %2, %4%S3"
ca68ea18 10033 [(set_attr "conds" "set")
d19fb8e3 10034 (set_attr "shift" "4")
c29e2982 10035 (set_attr "arch" "32,a")
6e4150e1 10036 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
ff9940b0 10037
4cdb3ed4 10038(define_insn "*sub_shiftsi"
c29e2982
BS
10039 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10040 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
ff9940b0 10041 (match_operator:SI 2 "shift_operator"
c29e2982
BS
10042 [(match_operand:SI 3 "s_register_operand" "r,r")
10043 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
10044 "TARGET_32BIT"
b020fd92 10045 "sub%?\\t%0, %1, %3%S2"
ca68ea18 10046 [(set_attr "predicable" "yes")
d19fb8e3 10047 (set_attr "shift" "3")
c29e2982 10048 (set_attr "arch" "32,a")
6e4150e1 10049 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
ff9940b0 10050
4cdb3ed4 10051(define_insn "*sub_shiftsi_compare0"
48a08b9c 10052 [(set (reg:CC_NOOV CC_REGNUM)
c63165be 10053 (compare:CC_NOOV
6e4150e1 10054 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
c63165be 10055 (match_operator:SI 2 "shift_operator"
6e4150e1
JG
10056 [(match_operand:SI 3 "s_register_operand" "r,r,r")
10057 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
c63165be 10058 (const_int 0)))
6e4150e1 10059 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
c29e2982
BS
10060 (minus:SI (match_dup 1)
10061 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
10062 "TARGET_32BIT"
5b3e6663 10063 "sub%.\\t%0, %1, %3%S2"
ca68ea18 10064 [(set_attr "conds" "set")
9b66ebb1 10065 (set_attr "shift" "3")
6e4150e1
JG
10066 (set_attr "arch" "32,a,a")
10067 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
ff9940b0 10068
4cdb3ed4 10069(define_insn "*sub_shiftsi_compare0_scratch"
48a08b9c 10070 [(set (reg:CC_NOOV CC_REGNUM)
c63165be 10071 (compare:CC_NOOV
6e4150e1 10072 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
c63165be 10073 (match_operator:SI 2 "shift_operator"
6e4150e1
JG
10074 [(match_operand:SI 3 "s_register_operand" "r,r,r")
10075 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
c63165be 10076 (const_int 0)))
6e4150e1 10077 (clobber (match_scratch:SI 0 "=r,r,r"))]
c29e2982 10078 "TARGET_32BIT"
5b3e6663 10079 "sub%.\\t%0, %1, %3%S2"
ca68ea18 10080 [(set_attr "conds" "set")
9b66ebb1 10081 (set_attr "shift" "3")
6e4150e1
JG
10082 (set_attr "arch" "32,a,a")
10083 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
ff9940b0
RE
10084\f
10085
0480fff0 10086(define_insn_and_split "*and_scc"
ff9940b0 10087 [(set (match_operand:SI 0 "s_register_operand" "=r")
05ed98a1 10088 (and:SI (match_operator:SI 1 "arm_comparison_operator"
0480fff0
GY
10089 [(match_operand 2 "cc_register" "") (const_int 0)])
10090 (match_operand:SI 3 "s_register_operand" "r")))]
d5b7b3ae 10091 "TARGET_ARM"
0480fff0
GY
10092 "#" ; "mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
10093 "&& reload_completed"
10094 [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
10095 (cond_exec (match_dup 4) (set (match_dup 0)
10096 (and:SI (match_dup 3) (const_int 1))))]
10097 {
10098 enum machine_mode mode = GET_MODE (operands[2]);
10099 enum rtx_code rc = GET_CODE (operands[1]);
10100
10101 /* Note that operands[4] is the same as operands[1],
10102 but with VOIDmode as the result. */
10103 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
10104 if (mode == CCFPmode || mode == CCFPEmode)
10105 rc = reverse_condition_maybe_unordered (rc);
10106 else
10107 rc = reverse_condition (rc);
10108 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
10109 }
05ed98a1 10110 [(set_attr "conds" "use")
594726e4 10111 (set_attr "type" "multiple")
05ed98a1
RE
10112 (set_attr "length" "8")]
10113)
ff9940b0 10114
0480fff0 10115(define_insn_and_split "*ior_scc"
ff9940b0 10116 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
0480fff0
GY
10117 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
10118 [(match_operand 2 "cc_register" "") (const_int 0)])
10119 (match_operand:SI 3 "s_register_operand" "0,?r")))]
d5b7b3ae 10120 "TARGET_ARM"
0f447ef2 10121 "@
0480fff0
GY
10122 orr%d1\\t%0, %3, #1
10123 #"
10124 "&& reload_completed
10125 && REGNO (operands [0]) != REGNO (operands[3])"
10126 ;; && which_alternative == 1
10127 ; mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
10128 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
10129 (cond_exec (match_dup 4) (set (match_dup 0)
10130 (ior:SI (match_dup 3) (const_int 1))))]
10131 {
10132 enum machine_mode mode = GET_MODE (operands[2]);
10133 enum rtx_code rc = GET_CODE (operands[1]);
10134
10135 /* Note that operands[4] is the same as operands[1],
10136 but with VOIDmode as the result. */
10137 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
10138 if (mode == CCFPmode || mode == CCFPEmode)
10139 rc = reverse_condition_maybe_unordered (rc);
10140 else
10141 rc = reverse_condition (rc);
10142 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
10143 }
05ed98a1 10144 [(set_attr "conds" "use")
594726e4
JG
10145 (set_attr "length" "4,8")
10146 (set_attr "type" "logic_imm,multiple")]
05ed98a1 10147)
ff9940b0 10148
18e8200f
BS
10149; A series of splitters for the compare_scc pattern below. Note that
10150; order is important.
10151(define_split
10152 [(set (match_operand:SI 0 "s_register_operand" "")
10153 (lt:SI (match_operand:SI 1 "s_register_operand" "")
10154 (const_int 0)))
10155 (clobber (reg:CC CC_REGNUM))]
10156 "TARGET_32BIT && reload_completed"
10157 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
10158
10159(define_split
10160 [(set (match_operand:SI 0 "s_register_operand" "")
10161 (ge:SI (match_operand:SI 1 "s_register_operand" "")
10162 (const_int 0)))
10163 (clobber (reg:CC CC_REGNUM))]
10164 "TARGET_32BIT && reload_completed"
10165 [(set (match_dup 0) (not:SI (match_dup 1)))
10166 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
10167
5e7f6aaa
RE
10168(define_split
10169 [(set (match_operand:SI 0 "s_register_operand" "")
10170 (eq:SI (match_operand:SI 1 "s_register_operand" "")
10171 (const_int 0)))
10172 (clobber (reg:CC CC_REGNUM))]
10173 "arm_arch5 && TARGET_32BIT"
10174 [(set (match_dup 0) (clz:SI (match_dup 1)))
10175 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
10176)
10177
18e8200f
BS
10178(define_split
10179 [(set (match_operand:SI 0 "s_register_operand" "")
10180 (eq:SI (match_operand:SI 1 "s_register_operand" "")
10181 (const_int 0)))
10182 (clobber (reg:CC CC_REGNUM))]
10183 "TARGET_32BIT && reload_completed"
10184 [(parallel
7ec6356e
BS
10185 [(set (reg:CC CC_REGNUM)
10186 (compare:CC (const_int 1) (match_dup 1)))
18e8200f
BS
10187 (set (match_dup 0)
10188 (minus:SI (const_int 1) (match_dup 1)))])
7ec6356e 10189 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
18e8200f
BS
10190 (set (match_dup 0) (const_int 0)))])
10191
10192(define_split
10193 [(set (match_operand:SI 0 "s_register_operand" "")
10194 (ne:SI (match_operand:SI 1 "s_register_operand" "")
10195 (match_operand:SI 2 "const_int_operand" "")))
10196 (clobber (reg:CC CC_REGNUM))]
10197 "TARGET_32BIT && reload_completed"
10198 [(parallel
10199 [(set (reg:CC CC_REGNUM)
10200 (compare:CC (match_dup 1) (match_dup 2)))
10201 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
10202 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
10203 (set (match_dup 0) (const_int 1)))]
10204{
10205 operands[3] = GEN_INT (-INTVAL (operands[2]));
10206})
10207
10208(define_split
10209 [(set (match_operand:SI 0 "s_register_operand" "")
10210 (ne:SI (match_operand:SI 1 "s_register_operand" "")
10211 (match_operand:SI 2 "arm_add_operand" "")))
10212 (clobber (reg:CC CC_REGNUM))]
10213 "TARGET_32BIT && reload_completed"
10214 [(parallel
10215 [(set (reg:CC_NOOV CC_REGNUM)
10216 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
10217 (const_int 0)))
10218 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
10219 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
10220 (set (match_dup 0) (const_int 1)))])
10221
10222(define_insn_and_split "*compare_scc"
956a95a5 10223 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
05ed98a1 10224 (match_operator:SI 1 "arm_comparison_operator"
68df59d3
RE
10225 [(match_operand:SI 2 "s_register_operand" "r,r")
10226 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
48a08b9c 10227 (clobber (reg:CC CC_REGNUM))]
18e8200f
BS
10228 "TARGET_32BIT"
10229 "#"
10230 "&& reload_completed"
10231 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
10232 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
10233 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
10234{
10235 rtx tmp1;
10236 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10237 operands[2], operands[3]);
10238 enum rtx_code rc = GET_CODE (operands[1]);
0f447ef2 10239
18e8200f 10240 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
7ec6356e 10241
18e8200f
BS
10242 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
10243 if (mode == CCFPmode || mode == CCFPEmode)
10244 rc = reverse_condition_maybe_unordered (rc);
10245 else
10246 rc = reverse_condition (rc);
10247 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
594726e4
JG
10248}
10249 [(set_attr "type" "multiple")]
10250)
ff9940b0 10251
7ec6356e
BS
10252;; Attempt to improve the sequence generated by the compare_scc splitters
10253;; not to use conditional execution.
5e7f6aaa
RE
10254
10255;; Rd = (eq (reg1) (const_int0)) // ARMv5
10256;; clz Rd, reg1
10257;; lsr Rd, Rd, #5
7ec6356e
BS
10258(define_peephole2
10259 [(set (reg:CC CC_REGNUM)
10260 (compare:CC (match_operand:SI 1 "register_operand" "")
5e7f6aaa
RE
10261 (const_int 0)))
10262 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
10263 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
10264 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
10265 (set (match_dup 0) (const_int 1)))]
10266 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
10267 [(set (match_dup 0) (clz:SI (match_dup 1)))
10268 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
10269)
10270
10271;; Rd = (eq (reg1) (const_int0)) // !ARMv5
10272;; negs Rd, reg1
10273;; adc Rd, Rd, reg1
10274(define_peephole2
10275 [(set (reg:CC CC_REGNUM)
10276 (compare:CC (match_operand:SI 1 "register_operand" "")
10277 (const_int 0)))
7ec6356e
BS
10278 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
10279 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
10280 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
10281 (set (match_dup 0) (const_int 1)))
5e7f6aaa
RE
10282 (match_scratch:SI 2 "r")]
10283 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
527e82c2
WG
10284 [(parallel
10285 [(set (reg:CC CC_REGNUM)
5e7f6aaa
RE
10286 (compare:CC (const_int 0) (match_dup 1)))
10287 (set (match_dup 2) (minus:SI (const_int 0) (match_dup 1)))])
10288 (set (match_dup 0)
10289 (plus:SI (plus:SI (match_dup 1) (match_dup 2))
10290 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
10291)
10292
c743b246 10293;; Rd = (eq (reg1) (reg2/imm)) // ARMv5 and optimising for speed.
5e7f6aaa
RE
10294;; sub Rd, Reg1, reg2
10295;; clz Rd, Rd
10296;; lsr Rd, Rd, #5
10297(define_peephole2
10298 [(set (reg:CC CC_REGNUM)
10299 (compare:CC (match_operand:SI 1 "register_operand" "")
10300 (match_operand:SI 2 "arm_rhs_operand" "")))
10301 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
10302 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
10303 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
10304 (set (match_dup 0) (const_int 1)))]
c743b246
KT
10305 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)
10306 && !(TARGET_THUMB2 && optimize_insn_for_size_p ())"
5e7f6aaa
RE
10307 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
10308 (set (match_dup 0) (clz:SI (match_dup 0)))
10309 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
10310)
10311
10312
c743b246 10313;; Rd = (eq (reg1) (reg2)) // ! ARMv5 or optimising for size.
5e7f6aaa
RE
10314;; sub T1, Reg1, reg2
10315;; negs Rd, T1
10316;; adc Rd, Rd, T1
10317(define_peephole2
10318 [(set (reg:CC CC_REGNUM)
10319 (compare:CC (match_operand:SI 1 "register_operand" "")
10320 (match_operand:SI 2 "arm_rhs_operand" "")))
10321 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
10322 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
10323 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
10324 (set (match_dup 0) (const_int 1)))
10325 (match_scratch:SI 3 "r")]
10326 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
c743b246 10327 [(set (match_dup 3) (match_dup 4))
7ec6356e
BS
10328 (parallel
10329 [(set (reg:CC CC_REGNUM)
10330 (compare:CC (const_int 0) (match_dup 3)))
10331 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
5e7f6aaa
RE
10332 (set (match_dup 0)
10333 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
10334 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
c743b246
KT
10335 "
10336 if (CONST_INT_P (operands[2]))
10337 operands[4] = plus_constant (SImode, operands[1], -INTVAL (operands[2]));
10338 else
10339 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[2]);
10340 ")
7ec6356e 10341
4cdb3ed4 10342(define_insn "*cond_move"
ff9940b0 10343 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
589fe0fc 10344 (if_then_else:SI (match_operator 3 "equality_operator"
05ed98a1 10345 [(match_operator 4 "arm_comparison_operator"
f54fd62e 10346 [(match_operand 5 "cc_register" "") (const_int 0)])
589fe0fc
RE
10347 (const_int 0)])
10348 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
10349 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
d5b7b3ae 10350 "TARGET_ARM"
ff9940b0 10351 "*
05ed98a1
RE
10352 if (GET_CODE (operands[3]) == NE)
10353 {
10354 if (which_alternative != 1)
10355 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
10356 if (which_alternative != 0)
10357 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
10358 return \"\";
10359 }
10360 if (which_alternative != 0)
10361 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
10362 if (which_alternative != 1)
10363 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
10364 return \"\";
10365 "
10366 [(set_attr "conds" "use")
594726e4 10367 (set_attr "type" "mov_reg,mov_reg,multiple")
05ed98a1
RE
10368 (set_attr "length" "4,4,8")]
10369)
ff9940b0 10370
4cdb3ed4 10371(define_insn "*cond_arith"
ff9940b0
RE
10372 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10373 (match_operator:SI 5 "shiftable_operator"
05ed98a1 10374 [(match_operator:SI 4 "arm_comparison_operator"
ff9940b0
RE
10375 [(match_operand:SI 2 "s_register_operand" "r,r")
10376 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
10377 (match_operand:SI 1 "s_register_operand" "0,?r")]))
48a08b9c 10378 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 10379 "TARGET_ARM"
ff9940b0 10380 "*
05ed98a1
RE
10381 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
10382 return \"%i5\\t%0, %1, %2, lsr #31\";
c63165be 10383
05ed98a1
RE
10384 output_asm_insn (\"cmp\\t%2, %3\", operands);
10385 if (GET_CODE (operands[5]) == AND)
10386 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
10387 else if (GET_CODE (operands[5]) == MINUS)
10388 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
10389 else if (which_alternative != 0)
10390 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
10391 return \"%i5%d4\\t%0, %1, #1\";
10392 "
10393 [(set_attr "conds" "clob")
594726e4
JG
10394 (set_attr "length" "12")
10395 (set_attr "type" "multiple")]
05ed98a1 10396)
ff9940b0 10397
4cdb3ed4 10398(define_insn "*cond_sub"
ff9940b0
RE
10399 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10400 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
05ed98a1 10401 (match_operator:SI 4 "arm_comparison_operator"
ff9940b0
RE
10402 [(match_operand:SI 2 "s_register_operand" "r,r")
10403 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
48a08b9c 10404 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 10405 "TARGET_ARM"
ff9940b0 10406 "*
05ed98a1
RE
10407 output_asm_insn (\"cmp\\t%2, %3\", operands);
10408 if (which_alternative != 0)
10409 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
10410 return \"sub%d4\\t%0, %1, #1\";
10411 "
10412 [(set_attr "conds" "clob")
594726e4
JG
10413 (set_attr "length" "8,12")
10414 (set_attr "type" "multiple")]
05ed98a1 10415)
ff9940b0 10416
589fe0fc 10417(define_insn "*cmp_ite0"
d5b7b3ae 10418 [(set (match_operand 6 "dominant_cc_register" "")
589fe0fc
RE
10419 (compare
10420 (if_then_else:SI
05ed98a1 10421 (match_operator 4 "arm_comparison_operator"
990b31f7
JL
10422 [(match_operand:SI 0 "s_register_operand"
10423 "l,l,l,r,r,r,r,r,r")
10424 (match_operand:SI 1 "arm_add_operand"
10425 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
05ed98a1 10426 (match_operator:SI 5 "arm_comparison_operator"
990b31f7
JL
10427 [(match_operand:SI 2 "s_register_operand"
10428 "l,r,r,l,l,r,r,r,r")
10429 (match_operand:SI 3 "arm_add_operand"
10430 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
589fe0fc
RE
10431 (const_int 0))
10432 (const_int 0)))]
990b31f7 10433 "TARGET_32BIT"
ff9940b0 10434 "*
589fe0fc 10435 {
990b31f7
JL
10436 static const char * const cmp1[NUM_OF_COND_CMP][2] =
10437 {
10438 {\"cmp%d5\\t%0, %1\",
10439 \"cmp%d4\\t%2, %3\"},
10440 {\"cmn%d5\\t%0, #%n1\",
10441 \"cmp%d4\\t%2, %3\"},
10442 {\"cmp%d5\\t%0, %1\",
10443 \"cmn%d4\\t%2, #%n3\"},
10444 {\"cmn%d5\\t%0, #%n1\",
10445 \"cmn%d4\\t%2, #%n3\"}
10446 };
10447 static const char * const cmp2[NUM_OF_COND_CMP][2] =
10448 {
10449 {\"cmp\\t%2, %3\",
10450 \"cmp\\t%0, %1\"},
10451 {\"cmp\\t%2, %3\",
10452 \"cmn\\t%0, #%n1\"},
10453 {\"cmn\\t%2, #%n3\",
10454 \"cmp\\t%0, %1\"},
10455 {\"cmn\\t%2, #%n3\",
10456 \"cmn\\t%0, #%n1\"}
10457 };
10458 static const char * const ite[2] =
05ed98a1 10459 {
990b31f7
JL
10460 \"it\\t%d5\",
10461 \"it\\t%d4\"
05ed98a1 10462 };
990b31f7
JL
10463 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
10464 CMP_CMP, CMN_CMP, CMP_CMP,
10465 CMN_CMP, CMP_CMN, CMN_CMN};
05ed98a1
RE
10466 int swap =
10467 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
10468
990b31f7
JL
10469 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
10470 if (TARGET_THUMB2) {
10471 output_asm_insn (ite[swap], operands);
10472 }
10473 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
10474 return \"\";
05ed98a1
RE
10475 }"
10476 [(set_attr "conds" "set")
990b31f7 10477 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
594726e4 10478 (set_attr "type" "multiple")
990b31f7
JL
10479 (set_attr_alternative "length"
10480 [(const_int 6)
10481 (const_int 8)
10482 (const_int 8)
10483 (const_int 8)
10484 (const_int 8)
10485 (if_then_else (eq_attr "is_thumb" "no")
10486 (const_int 8)
10487 (const_int 10))
10488 (if_then_else (eq_attr "is_thumb" "no")
10489 (const_int 8)
10490 (const_int 10))
10491 (if_then_else (eq_attr "is_thumb" "no")
10492 (const_int 8)
10493 (const_int 10))
10494 (if_then_else (eq_attr "is_thumb" "no")
10495 (const_int 8)
10496 (const_int 10))])]
05ed98a1 10497)
ff9940b0 10498
589fe0fc 10499(define_insn "*cmp_ite1"
d5b7b3ae 10500 [(set (match_operand 6 "dominant_cc_register" "")
589fe0fc
RE
10501 (compare
10502 (if_then_else:SI
05ed98a1 10503 (match_operator 4 "arm_comparison_operator"
990b31f7
JL
10504 [(match_operand:SI 0 "s_register_operand"
10505 "l,l,l,r,r,r,r,r,r")
10506 (match_operand:SI 1 "arm_add_operand"
10507 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
05ed98a1 10508 (match_operator:SI 5 "arm_comparison_operator"
990b31f7
JL
10509 [(match_operand:SI 2 "s_register_operand"
10510 "l,r,r,l,l,r,r,r,r")
10511 (match_operand:SI 3 "arm_add_operand"
10512 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
589fe0fc
RE
10513 (const_int 1))
10514 (const_int 0)))]
990b31f7 10515 "TARGET_32BIT"
ff9940b0 10516 "*
ff9940b0 10517 {
990b31f7
JL
10518 static const char * const cmp1[NUM_OF_COND_CMP][2] =
10519 {
10520 {\"cmp\\t%0, %1\",
10521 \"cmp\\t%2, %3\"},
10522 {\"cmn\\t%0, #%n1\",
10523 \"cmp\\t%2, %3\"},
10524 {\"cmp\\t%0, %1\",
10525 \"cmn\\t%2, #%n3\"},
10526 {\"cmn\\t%0, #%n1\",
10527 \"cmn\\t%2, #%n3\"}
10528 };
10529 static const char * const cmp2[NUM_OF_COND_CMP][2] =
5895f793 10530 {
990b31f7
JL
10531 {\"cmp%d4\\t%2, %3\",
10532 \"cmp%D5\\t%0, %1\"},
10533 {\"cmp%d4\\t%2, %3\",
10534 \"cmn%D5\\t%0, #%n1\"},
10535 {\"cmn%d4\\t%2, #%n3\",
10536 \"cmp%D5\\t%0, %1\"},
10537 {\"cmn%d4\\t%2, #%n3\",
10538 \"cmn%D5\\t%0, #%n1\"}
5895f793 10539 };
990b31f7
JL
10540 static const char * const ite[2] =
10541 {
10542 \"it\\t%d4\",
10543 \"it\\t%D5\"
10544 };
10545 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
10546 CMP_CMP, CMN_CMP, CMP_CMP,
10547 CMN_CMP, CMP_CMN, CMN_CMN};
5895f793
RE
10548 int swap =
10549 comparison_dominates_p (GET_CODE (operands[5]),
10550 reverse_condition (GET_CODE (operands[4])));
10551
990b31f7
JL
10552 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
10553 if (TARGET_THUMB2) {
10554 output_asm_insn (ite[swap], operands);
10555 }
10556 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
10557 return \"\";
5895f793 10558 }"
05ed98a1 10559 [(set_attr "conds" "set")
990b31f7
JL
10560 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
10561 (set_attr_alternative "length"
10562 [(const_int 6)
10563 (const_int 8)
10564 (const_int 8)
10565 (const_int 8)
10566 (const_int 8)
10567 (if_then_else (eq_attr "is_thumb" "no")
10568 (const_int 8)
10569 (const_int 10))
10570 (if_then_else (eq_attr "is_thumb" "no")
10571 (const_int 8)
10572 (const_int 10))
10573 (if_then_else (eq_attr "is_thumb" "no")
10574 (const_int 8)
10575 (const_int 10))
10576 (if_then_else (eq_attr "is_thumb" "no")
10577 (const_int 8)
594726e4
JG
10578 (const_int 10))])
10579 (set_attr "type" "multiple")]
05ed98a1 10580)
ff9940b0 10581
1646cf41
RE
10582(define_insn "*cmp_and"
10583 [(set (match_operand 6 "dominant_cc_register" "")
10584 (compare
10585 (and:SI
10586 (match_operator 4 "arm_comparison_operator"
990b31f7
JL
10587 [(match_operand:SI 0 "s_register_operand"
10588 "l,l,l,r,r,r,r,r,r")
10589 (match_operand:SI 1 "arm_add_operand"
10590 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
1646cf41 10591 (match_operator:SI 5 "arm_comparison_operator"
990b31f7
JL
10592 [(match_operand:SI 2 "s_register_operand"
10593 "l,r,r,l,l,r,r,r,r")
10594 (match_operand:SI 3 "arm_add_operand"
10595 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
1646cf41 10596 (const_int 0)))]
990b31f7 10597 "TARGET_32BIT"
1646cf41
RE
10598 "*
10599 {
990b31f7 10600 static const char *const cmp1[NUM_OF_COND_CMP][2] =
1646cf41 10601 {
990b31f7
JL
10602 {\"cmp%d5\\t%0, %1\",
10603 \"cmp%d4\\t%2, %3\"},
10604 {\"cmn%d5\\t%0, #%n1\",
10605 \"cmp%d4\\t%2, %3\"},
10606 {\"cmp%d5\\t%0, %1\",
10607 \"cmn%d4\\t%2, #%n3\"},
10608 {\"cmn%d5\\t%0, #%n1\",
10609 \"cmn%d4\\t%2, #%n3\"}
1646cf41 10610 };
990b31f7
JL
10611 static const char *const cmp2[NUM_OF_COND_CMP][2] =
10612 {
10613 {\"cmp\\t%2, %3\",
10614 \"cmp\\t%0, %1\"},
10615 {\"cmp\\t%2, %3\",
10616 \"cmn\\t%0, #%n1\"},
10617 {\"cmn\\t%2, #%n3\",
10618 \"cmp\\t%0, %1\"},
10619 {\"cmn\\t%2, #%n3\",
10620 \"cmn\\t%0, #%n1\"}
10621 };
10622 static const char *const ite[2] =
10623 {
10624 \"it\\t%d5\",
10625 \"it\\t%d4\"
10626 };
10627 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
10628 CMP_CMP, CMN_CMP, CMP_CMP,
10629 CMN_CMP, CMP_CMN, CMN_CMN};
1646cf41
RE
10630 int swap =
10631 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
10632
990b31f7
JL
10633 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
10634 if (TARGET_THUMB2) {
10635 output_asm_insn (ite[swap], operands);
10636 }
10637 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
10638 return \"\";
1646cf41
RE
10639 }"
10640 [(set_attr "conds" "set")
10641 (set_attr "predicable" "no")
990b31f7
JL
10642 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
10643 (set_attr_alternative "length"
10644 [(const_int 6)
10645 (const_int 8)
10646 (const_int 8)
10647 (const_int 8)
10648 (const_int 8)
10649 (if_then_else (eq_attr "is_thumb" "no")
10650 (const_int 8)
10651 (const_int 10))
10652 (if_then_else (eq_attr "is_thumb" "no")
10653 (const_int 8)
10654 (const_int 10))
10655 (if_then_else (eq_attr "is_thumb" "no")
10656 (const_int 8)
10657 (const_int 10))
10658 (if_then_else (eq_attr "is_thumb" "no")
10659 (const_int 8)
594726e4
JG
10660 (const_int 10))])
10661 (set_attr "type" "multiple")]
1646cf41
RE
10662)
10663
10664(define_insn "*cmp_ior"
10665 [(set (match_operand 6 "dominant_cc_register" "")
10666 (compare
10667 (ior:SI
10668 (match_operator 4 "arm_comparison_operator"
990b31f7
JL
10669 [(match_operand:SI 0 "s_register_operand"
10670 "l,l,l,r,r,r,r,r,r")
10671 (match_operand:SI 1 "arm_add_operand"
10672 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
1646cf41 10673 (match_operator:SI 5 "arm_comparison_operator"
990b31f7
JL
10674 [(match_operand:SI 2 "s_register_operand"
10675 "l,r,r,l,l,r,r,r,r")
10676 (match_operand:SI 3 "arm_add_operand"
10677 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
1646cf41 10678 (const_int 0)))]
990b31f7 10679 "TARGET_32BIT"
1646cf41 10680 "*
1646cf41 10681 {
990b31f7
JL
10682 static const char *const cmp1[NUM_OF_COND_CMP][2] =
10683 {
10684 {\"cmp\\t%0, %1\",
10685 \"cmp\\t%2, %3\"},
10686 {\"cmn\\t%0, #%n1\",
10687 \"cmp\\t%2, %3\"},
10688 {\"cmp\\t%0, %1\",
10689 \"cmn\\t%2, #%n3\"},
10690 {\"cmn\\t%0, #%n1\",
10691 \"cmn\\t%2, #%n3\"}
10692 };
10693 static const char *const cmp2[NUM_OF_COND_CMP][2] =
10694 {
10695 {\"cmp%D4\\t%2, %3\",
10696 \"cmp%D5\\t%0, %1\"},
10697 {\"cmp%D4\\t%2, %3\",
10698 \"cmn%D5\\t%0, #%n1\"},
10699 {\"cmn%D4\\t%2, #%n3\",
10700 \"cmp%D5\\t%0, %1\"},
10701 {\"cmn%D4\\t%2, #%n3\",
10702 \"cmn%D5\\t%0, #%n1\"}
10703 };
10704 static const char *const ite[2] =
10705 {
10706 \"it\\t%D4\",
10707 \"it\\t%D5\"
10708 };
10709 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
10710 CMP_CMP, CMN_CMP, CMP_CMP,
10711 CMN_CMP, CMP_CMN, CMN_CMN};
10712 int swap =
10713 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
10714
10715 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
10716 if (TARGET_THUMB2) {
10717 output_asm_insn (ite[swap], operands);
10718 }
10719 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
10720 return \"\";
10721 }
10722 "
1646cf41 10723 [(set_attr "conds" "set")
990b31f7
JL
10724 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
10725 (set_attr_alternative "length"
10726 [(const_int 6)
10727 (const_int 8)
10728 (const_int 8)
10729 (const_int 8)
10730 (const_int 8)
10731 (if_then_else (eq_attr "is_thumb" "no")
10732 (const_int 8)
10733 (const_int 10))
10734 (if_then_else (eq_attr "is_thumb" "no")
10735 (const_int 8)
10736 (const_int 10))
10737 (if_then_else (eq_attr "is_thumb" "no")
10738 (const_int 8)
10739 (const_int 10))
10740 (if_then_else (eq_attr "is_thumb" "no")
10741 (const_int 8)
594726e4
JG
10742 (const_int 10))])
10743 (set_attr "type" "multiple")]
1646cf41
RE
10744)
10745
03f1640c 10746(define_insn_and_split "*ior_scc_scc"
956a95a5 10747 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
03f1640c
RE
10748 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
10749 [(match_operand:SI 1 "s_register_operand" "r")
10750 (match_operand:SI 2 "arm_add_operand" "rIL")])
10751 (match_operator:SI 6 "arm_comparison_operator"
10752 [(match_operand:SI 4 "s_register_operand" "r")
10753 (match_operand:SI 5 "arm_add_operand" "rIL")])))
10754 (clobber (reg:CC CC_REGNUM))]
990b31f7 10755 "TARGET_32BIT
03f1640c
RE
10756 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
10757 != CCmode)"
10758 "#"
990b31f7 10759 "TARGET_32BIT && reload_completed"
03f1640c
RE
10760 [(set (match_dup 7)
10761 (compare
10762 (ior:SI
10763 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
10764 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
10765 (const_int 0)))
10766 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
10767 "operands[7]
10768 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
10769 DOM_CC_X_OR_Y),
9af66e58
RE
10770 CC_REGNUM);"
10771 [(set_attr "conds" "clob")
594726e4
JG
10772 (set_attr "length" "16")
10773 (set_attr "type" "multiple")]
10774)
9af66e58
RE
10775
10776; If the above pattern is followed by a CMP insn, then the compare is
10777; redundant, since we can rework the conditional instruction that follows.
10778(define_insn_and_split "*ior_scc_scc_cmp"
10779 [(set (match_operand 0 "dominant_cc_register" "")
10780 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
10781 [(match_operand:SI 1 "s_register_operand" "r")
10782 (match_operand:SI 2 "arm_add_operand" "rIL")])
10783 (match_operator:SI 6 "arm_comparison_operator"
10784 [(match_operand:SI 4 "s_register_operand" "r")
10785 (match_operand:SI 5 "arm_add_operand" "rIL")]))
10786 (const_int 0)))
956a95a5 10787 (set (match_operand:SI 7 "s_register_operand" "=Ts")
9af66e58
RE
10788 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
10789 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
990b31f7 10790 "TARGET_32BIT"
9af66e58 10791 "#"
990b31f7 10792 "TARGET_32BIT && reload_completed"
9af66e58
RE
10793 [(set (match_dup 0)
10794 (compare
10795 (ior:SI
10796 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
10797 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
10798 (const_int 0)))
10799 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
10800 ""
10801 [(set_attr "conds" "set")
594726e4
JG
10802 (set_attr "length" "16")
10803 (set_attr "type" "multiple")]
10804)
03f1640c
RE
10805
10806(define_insn_and_split "*and_scc_scc"
956a95a5 10807 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
03f1640c
RE
10808 (and:SI (match_operator:SI 3 "arm_comparison_operator"
10809 [(match_operand:SI 1 "s_register_operand" "r")
10810 (match_operand:SI 2 "arm_add_operand" "rIL")])
10811 (match_operator:SI 6 "arm_comparison_operator"
10812 [(match_operand:SI 4 "s_register_operand" "r")
10813 (match_operand:SI 5 "arm_add_operand" "rIL")])))
10814 (clobber (reg:CC CC_REGNUM))]
990b31f7 10815 "TARGET_32BIT
03f1640c
RE
10816 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
10817 != CCmode)"
10818 "#"
990b31f7 10819 "TARGET_32BIT && reload_completed
9af66e58
RE
10820 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
10821 != CCmode)"
03f1640c
RE
10822 [(set (match_dup 7)
10823 (compare
10824 (and:SI
10825 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
10826 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
10827 (const_int 0)))
10828 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
10829 "operands[7]
10830 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
10831 DOM_CC_X_AND_Y),
9af66e58
RE
10832 CC_REGNUM);"
10833 [(set_attr "conds" "clob")
594726e4
JG
10834 (set_attr "length" "16")
10835 (set_attr "type" "multiple")]
10836)
9af66e58
RE
10837
10838; If the above pattern is followed by a CMP insn, then the compare is
10839; redundant, since we can rework the conditional instruction that follows.
10840(define_insn_and_split "*and_scc_scc_cmp"
10841 [(set (match_operand 0 "dominant_cc_register" "")
10842 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
10843 [(match_operand:SI 1 "s_register_operand" "r")
10844 (match_operand:SI 2 "arm_add_operand" "rIL")])
10845 (match_operator:SI 6 "arm_comparison_operator"
10846 [(match_operand:SI 4 "s_register_operand" "r")
10847 (match_operand:SI 5 "arm_add_operand" "rIL")]))
10848 (const_int 0)))
956a95a5 10849 (set (match_operand:SI 7 "s_register_operand" "=Ts")
9af66e58
RE
10850 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
10851 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
990b31f7 10852 "TARGET_32BIT"
9af66e58 10853 "#"
990b31f7 10854 "TARGET_32BIT && reload_completed"
9af66e58
RE
10855 [(set (match_dup 0)
10856 (compare
10857 (and:SI
10858 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
10859 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
10860 (const_int 0)))
10861 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
10862 ""
10863 [(set_attr "conds" "set")
594726e4
JG
10864 (set_attr "length" "16")
10865 (set_attr "type" "multiple")]
10866)
9af66e58
RE
10867
10868;; If there is no dominance in the comparison, then we can still save an
10869;; instruction in the AND case, since we can know that the second compare
10870;; need only zero the value if false (if true, then the value is already
10871;; correct).
10872(define_insn_and_split "*and_scc_scc_nodom"
956a95a5 10873 [(set (match_operand:SI 0 "s_register_operand" "=&Ts,&Ts,&Ts")
9af66e58
RE
10874 (and:SI (match_operator:SI 3 "arm_comparison_operator"
10875 [(match_operand:SI 1 "s_register_operand" "r,r,0")
10876 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
10877 (match_operator:SI 6 "arm_comparison_operator"
10878 [(match_operand:SI 4 "s_register_operand" "r,r,r")
10879 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
10880 (clobber (reg:CC CC_REGNUM))]
990b31f7 10881 "TARGET_32BIT
9af66e58
RE
10882 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
10883 == CCmode)"
10884 "#"
990b31f7 10885 "TARGET_32BIT && reload_completed"
9af66e58
RE
10886 [(parallel [(set (match_dup 0)
10887 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
10888 (clobber (reg:CC CC_REGNUM))])
10889 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
10890 (set (match_dup 0)
10891 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
10892 (match_dup 0)
10893 (const_int 0)))]
10894 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
10895 operands[4], operands[5]),
10896 CC_REGNUM);
10897 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
10898 operands[5]);"
10899 [(set_attr "conds" "clob")
594726e4
JG
10900 (set_attr "length" "20")
10901 (set_attr "type" "multiple")]
10902)
03f1640c 10903
e25c906a
RE
10904(define_split
10905 [(set (reg:CC_NOOV CC_REGNUM)
10906 (compare:CC_NOOV (ior:SI
10907 (and:SI (match_operand:SI 0 "s_register_operand" "")
10908 (const_int 1))
accbd151 10909 (match_operator:SI 1 "arm_comparison_operator"
e25c906a
RE
10910 [(match_operand:SI 2 "s_register_operand" "")
10911 (match_operand:SI 3 "arm_add_operand" "")]))
10912 (const_int 0)))
10913 (clobber (match_operand:SI 4 "s_register_operand" ""))]
10914 "TARGET_ARM"
10915 [(set (match_dup 4)
10916 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
10917 (match_dup 0)))
10918 (set (reg:CC_NOOV CC_REGNUM)
10919 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
10920 (const_int 0)))]
10921 "")
10922
10923(define_split
10924 [(set (reg:CC_NOOV CC_REGNUM)
10925 (compare:CC_NOOV (ior:SI
accbd151 10926 (match_operator:SI 1 "arm_comparison_operator"
e25c906a
RE
10927 [(match_operand:SI 2 "s_register_operand" "")
10928 (match_operand:SI 3 "arm_add_operand" "")])
10929 (and:SI (match_operand:SI 0 "s_register_operand" "")
10930 (const_int 1)))
10931 (const_int 0)))
10932 (clobber (match_operand:SI 4 "s_register_operand" ""))]
10933 "TARGET_ARM"
10934 [(set (match_dup 4)
10935 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
10936 (match_dup 0)))
10937 (set (reg:CC_NOOV CC_REGNUM)
10938 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
10939 (const_int 0)))]
10940 "")
5b3e6663 10941;; ??? The conditional patterns above need checking for Thumb-2 usefulness
e25c906a 10942
0480fff0 10943(define_insn_and_split "*negscc"
ff9940b0 10944 [(set (match_operand:SI 0 "s_register_operand" "=r")
05ed98a1 10945 (neg:SI (match_operator 3 "arm_comparison_operator"
ff9940b0
RE
10946 [(match_operand:SI 1 "s_register_operand" "r")
10947 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
48a08b9c 10948 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 10949 "TARGET_ARM"
0480fff0
GY
10950 "#"
10951 "&& reload_completed"
10952 [(const_int 0)]
10953 {
10954 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
0f447ef2 10955
0480fff0
GY
10956 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
10957 {
10958 /* Emit mov\\t%0, %1, asr #31 */
10959 emit_insn (gen_rtx_SET (VOIDmode,
10960 operands[0],
10961 gen_rtx_ASHIFTRT (SImode,
10962 operands[1],
10963 GEN_INT (31))));
10964 DONE;
10965 }
10966 else if (GET_CODE (operands[3]) == NE)
10967 {
10968 /* Emit subs\\t%0, %1, %2\;mvnne\\t%0, #0 */
10969 if (CONST_INT_P (operands[2]))
10970 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
10971 GEN_INT (- INTVAL (operands[2]))));
10972 else
10973 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
10974
10975 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
10976 gen_rtx_NE (SImode,
10977 cc_reg,
10978 const0_rtx),
10979 gen_rtx_SET (SImode,
10980 operands[0],
10981 GEN_INT (~0))));
10982 DONE;
10983 }
10984 else
10985 {
10986 /* Emit: cmp\\t%1, %2\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
10987 emit_insn (gen_rtx_SET (VOIDmode,
10988 cc_reg,
10989 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
10990 enum rtx_code rc = GET_CODE (operands[3]);
10991
10992 rc = reverse_condition (rc);
10993 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
10994 gen_rtx_fmt_ee (rc,
10995 VOIDmode,
10996 cc_reg,
10997 const0_rtx),
10998 gen_rtx_SET (VOIDmode, operands[0], const0_rtx)));
10999 rc = GET_CODE (operands[3]);
11000 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
11001 gen_rtx_fmt_ee (rc,
11002 VOIDmode,
11003 cc_reg,
11004 const0_rtx),
11005 gen_rtx_SET (VOIDmode,
11006 operands[0],
11007 GEN_INT (~0))));
11008 DONE;
11009 }
11010 FAIL;
11011 }
05ed98a1 11012 [(set_attr "conds" "clob")
594726e4
JG
11013 (set_attr "length" "12")
11014 (set_attr "type" "multiple")]
05ed98a1 11015)
ff9940b0 11016
85bd4ac6
KT
11017(define_insn_and_split "movcond_addsi"
11018 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
11019 (if_then_else:SI
11020 (match_operator 5 "comparison_operator"
11021 [(plus:SI (match_operand:SI 3 "s_register_operand" "r,r,r")
11022 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL"))
11023 (const_int 0)])
11024 (match_operand:SI 1 "arm_rhs_operand" "rI,rPy,r")
11025 (match_operand:SI 2 "arm_rhs_operand" "rI,rPy,r")))
11026 (clobber (reg:CC CC_REGNUM))]
11027 "TARGET_32BIT"
11028 "#"
11029 "&& reload_completed"
11030 [(set (reg:CC_NOOV CC_REGNUM)
11031 (compare:CC_NOOV
11032 (plus:SI (match_dup 3)
11033 (match_dup 4))
11034 (const_int 0)))
11035 (set (match_dup 0) (match_dup 1))
11036 (cond_exec (match_dup 6)
11037 (set (match_dup 0) (match_dup 2)))]
11038 "
11039 {
11040 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[5]),
11041 operands[3], operands[4]);
11042 enum rtx_code rc = GET_CODE (operands[5]);
11043
11044 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
11045 gcc_assert (!(mode == CCFPmode || mode == CCFPEmode));
11046 rc = reverse_condition (rc);
11047
11048 operands[6] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
11049 }
11050 "
11051 [(set_attr "conds" "clob")
594726e4
JG
11052 (set_attr "enabled_for_depr_it" "no,yes,yes")
11053 (set_attr "type" "multiple")]
85bd4ac6
KT
11054)
11055
ff9940b0
RE
11056(define_insn "movcond"
11057 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
68df59d3 11058 (if_then_else:SI
05ed98a1 11059 (match_operator 5 "arm_comparison_operator"
68df59d3
RE
11060 [(match_operand:SI 3 "s_register_operand" "r,r,r")
11061 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
11062 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
11063 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
48a08b9c 11064 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 11065 "TARGET_ARM"
ff9940b0
RE
11066 "*
11067 if (GET_CODE (operands[5]) == LT
11068 && (operands[4] == const0_rtx))
11069 {
d435a4be 11070 if (which_alternative != 1 && REG_P (operands[1]))
ff9940b0 11071 {
ff9940b0 11072 if (operands[2] == const0_rtx)
0f447ef2
RE
11073 return \"and\\t%0, %1, %3, asr #31\";
11074 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
ff9940b0 11075 }
d435a4be 11076 else if (which_alternative != 0 && REG_P (operands[2]))
ff9940b0 11077 {
ff9940b0 11078 if (operands[1] == const0_rtx)
0f447ef2
RE
11079 return \"bic\\t%0, %2, %3, asr #31\";
11080 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
ff9940b0
RE
11081 }
11082 /* The only case that falls through to here is when both ops 1 & 2
d6b4baa4 11083 are constants. */
ff9940b0 11084 }
0f447ef2 11085
ff9940b0
RE
11086 if (GET_CODE (operands[5]) == GE
11087 && (operands[4] == const0_rtx))
11088 {
d435a4be 11089 if (which_alternative != 1 && REG_P (operands[1]))
ff9940b0 11090 {
ff9940b0 11091 if (operands[2] == const0_rtx)
0f447ef2
RE
11092 return \"bic\\t%0, %1, %3, asr #31\";
11093 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
ff9940b0 11094 }
d435a4be 11095 else if (which_alternative != 0 && REG_P (operands[2]))
ff9940b0 11096 {
ff9940b0 11097 if (operands[1] == const0_rtx)
0f447ef2
RE
11098 return \"and\\t%0, %2, %3, asr #31\";
11099 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
ff9940b0
RE
11100 }
11101 /* The only case that falls through to here is when both ops 1 & 2
d6b4baa4 11102 are constants. */
ff9940b0 11103 }
d435a4be 11104 if (CONST_INT_P (operands[4])
ff9940b0 11105 && !const_ok_for_arm (INTVAL (operands[4])))
0f447ef2 11106 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
ff9940b0 11107 else
0f447ef2 11108 output_asm_insn (\"cmp\\t%3, %4\", operands);
ff9940b0 11109 if (which_alternative != 0)
0f447ef2 11110 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
ff9940b0 11111 if (which_alternative != 1)
0f447ef2 11112 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
ff9940b0 11113 return \"\";
5895f793 11114 "
05ed98a1 11115 [(set_attr "conds" "clob")
594726e4
JG
11116 (set_attr "length" "8,8,12")
11117 (set_attr "type" "multiple")]
05ed98a1 11118)
ff9940b0 11119
5b3e6663
PB
11120;; ??? The patterns below need checking for Thumb-2 usefulness.
11121
f54fd62e
RE
11122(define_insn "*ifcompare_plus_move"
11123 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
05ed98a1 11124 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
f54fd62e
RE
11125 [(match_operand:SI 4 "s_register_operand" "r,r")
11126 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
11127 (plus:SI
11128 (match_operand:SI 2 "s_register_operand" "r,r")
11129 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
b36ba79f 11130 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
48a08b9c 11131 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 11132 "TARGET_ARM"
f54fd62e 11133 "#"
05ed98a1 11134 [(set_attr "conds" "clob")
594726e4
JG
11135 (set_attr "length" "8,12")
11136 (set_attr "type" "multiple")]
05ed98a1 11137)
f54fd62e
RE
11138
11139(define_insn "*if_plus_move"
b36ba79f 11140 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
f54fd62e 11141 (if_then_else:SI
05ed98a1 11142 (match_operator 4 "arm_comparison_operator"
f54fd62e
RE
11143 [(match_operand 5 "cc_register" "") (const_int 0)])
11144 (plus:SI
b36ba79f
RE
11145 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
11146 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
11147 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
d5b7b3ae 11148 "TARGET_ARM"
f54fd62e
RE
11149 "@
11150 add%d4\\t%0, %2, %3
11151 sub%d4\\t%0, %2, #%n3
11152 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
b36ba79f 11153 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
05ed98a1
RE
11154 [(set_attr "conds" "use")
11155 (set_attr "length" "4,4,8,8")
148413a4
RR
11156 (set_attr_alternative "type"
11157 [(if_then_else (match_operand 3 "const_int_operand" "")
6e4150e1 11158 (const_string "alu_imm" )
594726e4 11159 (const_string "alu_reg"))
6e4150e1 11160 (const_string "alu_imm")
594726e4
JG
11161 (const_string "alu_reg")
11162 (const_string "alu_reg")])]
05ed98a1 11163)
f54fd62e
RE
11164
11165(define_insn "*ifcompare_move_plus"
68df59d3 11166 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
05ed98a1 11167 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
f54fd62e
RE
11168 [(match_operand:SI 4 "s_register_operand" "r,r")
11169 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
b36ba79f 11170 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
f54fd62e
RE
11171 (plus:SI
11172 (match_operand:SI 2 "s_register_operand" "r,r")
11173 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
48a08b9c 11174 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 11175 "TARGET_ARM"
f54fd62e 11176 "#"
05ed98a1 11177 [(set_attr "conds" "clob")
594726e4
JG
11178 (set_attr "length" "8,12")
11179 (set_attr "type" "multiple")]
05ed98a1 11180)
f54fd62e
RE
11181
11182(define_insn "*if_move_plus"
b36ba79f 11183 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
f54fd62e 11184 (if_then_else:SI
05ed98a1 11185 (match_operator 4 "arm_comparison_operator"
f54fd62e 11186 [(match_operand 5 "cc_register" "") (const_int 0)])
b36ba79f 11187 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
f54fd62e 11188 (plus:SI
b36ba79f
RE
11189 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
11190 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
d5b7b3ae 11191 "TARGET_ARM"
f54fd62e
RE
11192 "@
11193 add%D4\\t%0, %2, %3
11194 sub%D4\\t%0, %2, #%n3
11195 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
b36ba79f 11196 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
05ed98a1
RE
11197 [(set_attr "conds" "use")
11198 (set_attr "length" "4,4,8,8")
594726e4 11199 (set_attr "type" "alu_reg,alu_imm,multiple,multiple")]
05ed98a1 11200)
f54fd62e
RE
11201
11202(define_insn "*ifcompare_arith_arith"
11203 [(set (match_operand:SI 0 "s_register_operand" "=r")
05ed98a1 11204 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
f54fd62e
RE
11205 [(match_operand:SI 5 "s_register_operand" "r")
11206 (match_operand:SI 6 "arm_add_operand" "rIL")])
ff9940b0 11207 (match_operator:SI 8 "shiftable_operator"
f54fd62e
RE
11208 [(match_operand:SI 1 "s_register_operand" "r")
11209 (match_operand:SI 2 "arm_rhs_operand" "rI")])
ff9940b0 11210 (match_operator:SI 7 "shiftable_operator"
f54fd62e
RE
11211 [(match_operand:SI 3 "s_register_operand" "r")
11212 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
48a08b9c 11213 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 11214 "TARGET_ARM"
f54fd62e 11215 "#"
05ed98a1 11216 [(set_attr "conds" "clob")
594726e4
JG
11217 (set_attr "length" "12")
11218 (set_attr "type" "multiple")]
05ed98a1 11219)
ff9940b0 11220
f54fd62e
RE
11221(define_insn "*if_arith_arith"
11222 [(set (match_operand:SI 0 "s_register_operand" "=r")
05ed98a1 11223 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
11224 [(match_operand 8 "cc_register" "") (const_int 0)])
11225 (match_operator:SI 6 "shiftable_operator"
11226 [(match_operand:SI 1 "s_register_operand" "r")
11227 (match_operand:SI 2 "arm_rhs_operand" "rI")])
11228 (match_operator:SI 7 "shiftable_operator"
11229 [(match_operand:SI 3 "s_register_operand" "r")
11230 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
d5b7b3ae 11231 "TARGET_ARM"
f54fd62e 11232 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
05ed98a1 11233 [(set_attr "conds" "use")
594726e4
JG
11234 (set_attr "length" "8")
11235 (set_attr "type" "multiple")]
05ed98a1 11236)
f54fd62e 11237
4cdb3ed4 11238(define_insn "*ifcompare_arith_move"
ff9940b0 11239 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
05ed98a1 11240 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
ff9940b0 11241 [(match_operand:SI 2 "s_register_operand" "r,r")
68df59d3 11242 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
ff9940b0
RE
11243 (match_operator:SI 7 "shiftable_operator"
11244 [(match_operand:SI 4 "s_register_operand" "r,r")
11245 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
b36ba79f 11246 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
48a08b9c 11247 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 11248 "TARGET_ARM"
ff9940b0 11249 "*
ff9940b0 11250 /* If we have an operation where (op x 0) is the identity operation and
ddd5a7c1 11251 the conditional operator is LT or GE and we are comparing against zero and
d6b4baa4 11252 everything is in registers then we can do this in two instructions. */
ff9940b0
RE
11253 if (operands[3] == const0_rtx
11254 && GET_CODE (operands[7]) != AND
d435a4be
KT
11255 && REG_P (operands[5])
11256 && REG_P (operands[1])
ff9940b0
RE
11257 && REGNO (operands[1]) == REGNO (operands[4])
11258 && REGNO (operands[4]) != REGNO (operands[0]))
11259 {
11260 if (GET_CODE (operands[6]) == LT)
c63165be 11261 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
ff9940b0 11262 else if (GET_CODE (operands[6]) == GE)
c63165be 11263 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
ff9940b0 11264 }
d435a4be 11265 if (CONST_INT_P (operands[3])
ff9940b0 11266 && !const_ok_for_arm (INTVAL (operands[3])))
0f447ef2 11267 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
ff9940b0 11268 else
0f447ef2 11269 output_asm_insn (\"cmp\\t%2, %3\", operands);
c63165be 11270 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
ff9940b0 11271 if (which_alternative != 0)
b36ba79f 11272 return \"mov%D6\\t%0, %1\";
ff9940b0 11273 return \"\";
5895f793 11274 "
05ed98a1 11275 [(set_attr "conds" "clob")
594726e4
JG
11276 (set_attr "length" "8,12")
11277 (set_attr "type" "multiple")]
05ed98a1 11278)
ff9940b0 11279
f54fd62e 11280(define_insn "*if_arith_move"
b36ba79f 11281 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
05ed98a1 11282 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
f54fd62e
RE
11283 [(match_operand 6 "cc_register" "") (const_int 0)])
11284 (match_operator:SI 5 "shiftable_operator"
b36ba79f
RE
11285 [(match_operand:SI 2 "s_register_operand" "r,r")
11286 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
11287 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
d5b7b3ae 11288 "TARGET_ARM"
f54fd62e
RE
11289 "@
11290 %I5%d4\\t%0, %2, %3
b36ba79f 11291 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
05ed98a1
RE
11292 [(set_attr "conds" "use")
11293 (set_attr "length" "4,8")
594726e4 11294 (set_attr "type" "alu_shift_reg,multiple")]
05ed98a1 11295)
f54fd62e 11296
4cdb3ed4 11297(define_insn "*ifcompare_move_arith"
ff9940b0 11298 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
05ed98a1 11299 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
ff9940b0 11300 [(match_operand:SI 4 "s_register_operand" "r,r")
68df59d3 11301 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
b36ba79f 11302 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
ff9940b0
RE
11303 (match_operator:SI 7 "shiftable_operator"
11304 [(match_operand:SI 2 "s_register_operand" "r,r")
11305 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
48a08b9c 11306 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 11307 "TARGET_ARM"
ff9940b0 11308 "*
ff9940b0 11309 /* If we have an operation where (op x 0) is the identity operation and
ddd5a7c1 11310 the conditional operator is LT or GE and we are comparing against zero and
ff9940b0
RE
11311 everything is in registers then we can do this in two instructions */
11312 if (operands[5] == const0_rtx
11313 && GET_CODE (operands[7]) != AND
d435a4be
KT
11314 && REG_P (operands[3])
11315 && REG_P (operands[1])
ff9940b0
RE
11316 && REGNO (operands[1]) == REGNO (operands[2])
11317 && REGNO (operands[2]) != REGNO (operands[0]))
11318 {
11319 if (GET_CODE (operands[6]) == GE)
c63165be 11320 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
ff9940b0 11321 else if (GET_CODE (operands[6]) == LT)
c63165be 11322 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
ff9940b0 11323 }
c63165be 11324
d435a4be 11325 if (CONST_INT_P (operands[5])
ff9940b0 11326 && !const_ok_for_arm (INTVAL (operands[5])))
0f447ef2 11327 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
ff9940b0 11328 else
0f447ef2 11329 output_asm_insn (\"cmp\\t%4, %5\", operands);
c63165be 11330
ff9940b0 11331 if (which_alternative != 0)
b36ba79f 11332 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
c63165be 11333 return \"%I7%D6\\t%0, %2, %3\";
5895f793 11334 "
05ed98a1 11335 [(set_attr "conds" "clob")
594726e4
JG
11336 (set_attr "length" "8,12")
11337 (set_attr "type" "multiple")]
05ed98a1 11338)
ff9940b0 11339
f54fd62e 11340(define_insn "*if_move_arith"
b36ba79f 11341 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
f54fd62e 11342 (if_then_else:SI
05ed98a1 11343 (match_operator 4 "arm_comparison_operator"
f54fd62e 11344 [(match_operand 6 "cc_register" "") (const_int 0)])
b36ba79f 11345 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
f54fd62e 11346 (match_operator:SI 5 "shiftable_operator"
b36ba79f
RE
11347 [(match_operand:SI 2 "s_register_operand" "r,r")
11348 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
d5b7b3ae 11349 "TARGET_ARM"
f54fd62e
RE
11350 "@
11351 %I5%D4\\t%0, %2, %3
b36ba79f 11352 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
05ed98a1
RE
11353 [(set_attr "conds" "use")
11354 (set_attr "length" "4,8")
594726e4 11355 (set_attr "type" "alu_shift_reg,multiple")]
05ed98a1 11356)
f54fd62e
RE
11357
11358(define_insn "*ifcompare_move_not"
ff9940b0 11359 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
f54fd62e 11360 (if_then_else:SI
05ed98a1 11361 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
11362 [(match_operand:SI 3 "s_register_operand" "r,r")
11363 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
11364 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
11365 (not:SI
11366 (match_operand:SI 2 "s_register_operand" "r,r"))))
48a08b9c 11367 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 11368 "TARGET_ARM"
f54fd62e 11369 "#"
05ed98a1 11370 [(set_attr "conds" "clob")
594726e4
JG
11371 (set_attr "length" "8,12")
11372 (set_attr "type" "multiple")]
05ed98a1 11373)
ff9940b0 11374
f54fd62e
RE
11375(define_insn "*if_move_not"
11376 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
11377 (if_then_else:SI
05ed98a1 11378 (match_operator 4 "arm_comparison_operator"
f54fd62e
RE
11379 [(match_operand 3 "cc_register" "") (const_int 0)])
11380 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
11381 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
d5b7b3ae 11382 "TARGET_ARM"
f54fd62e
RE
11383 "@
11384 mvn%D4\\t%0, %2
11385 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
11386 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
05ed98a1 11387 [(set_attr "conds" "use")
859abddd 11388 (set_attr "type" "mvn_reg")
594726e4
JG
11389 (set_attr "length" "4,8,8")
11390 (set_attr "type" "mvn_reg,multiple,multiple")]
05ed98a1 11391)
f54fd62e
RE
11392
11393(define_insn "*ifcompare_not_move"
ff9940b0 11394 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
f54fd62e 11395 (if_then_else:SI
05ed98a1 11396 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
11397 [(match_operand:SI 3 "s_register_operand" "r,r")
11398 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
11399 (not:SI
11400 (match_operand:SI 2 "s_register_operand" "r,r"))
11401 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
48a08b9c 11402 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 11403 "TARGET_ARM"
f54fd62e 11404 "#"
05ed98a1 11405 [(set_attr "conds" "clob")
594726e4
JG
11406 (set_attr "length" "8,12")
11407 (set_attr "type" "multiple")]
05ed98a1 11408)
ff9940b0 11409
f54fd62e
RE
11410(define_insn "*if_not_move"
11411 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
11412 (if_then_else:SI
05ed98a1 11413 (match_operator 4 "arm_comparison_operator"
f54fd62e
RE
11414 [(match_operand 3 "cc_register" "") (const_int 0)])
11415 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
11416 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
d5b7b3ae 11417 "TARGET_ARM"
f54fd62e
RE
11418 "@
11419 mvn%d4\\t%0, %2
11420 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
11421 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
05ed98a1 11422 [(set_attr "conds" "use")
594726e4 11423 (set_attr "type" "mvn_reg,multiple,multiple")
05ed98a1
RE
11424 (set_attr "length" "4,8,8")]
11425)
f54fd62e
RE
11426
11427(define_insn "*ifcompare_shift_move"
ff9940b0 11428 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
f54fd62e 11429 (if_then_else:SI
05ed98a1 11430 (match_operator 6 "arm_comparison_operator"
f54fd62e
RE
11431 [(match_operand:SI 4 "s_register_operand" "r,r")
11432 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
11433 (match_operator:SI 7 "shift_operator"
11434 [(match_operand:SI 2 "s_register_operand" "r,r")
11435 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
11436 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
48a08b9c 11437 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 11438 "TARGET_ARM"
ff9940b0 11439 "#"
05ed98a1 11440 [(set_attr "conds" "clob")
594726e4
JG
11441 (set_attr "length" "8,12")
11442 (set_attr "type" "multiple")]
05ed98a1 11443)
ff9940b0 11444
f54fd62e
RE
11445(define_insn "*if_shift_move"
11446 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
11447 (if_then_else:SI
05ed98a1 11448 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
11449 [(match_operand 6 "cc_register" "") (const_int 0)])
11450 (match_operator:SI 4 "shift_operator"
11451 [(match_operand:SI 2 "s_register_operand" "r,r,r")
11452 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
11453 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
d5b7b3ae 11454 "TARGET_ARM"
68df59d3 11455 "@
f54fd62e
RE
11456 mov%d5\\t%0, %2%S4
11457 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
11458 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
05ed98a1 11459 [(set_attr "conds" "use")
d19fb8e3 11460 (set_attr "shift" "2")
9b66ebb1 11461 (set_attr "length" "4,8,8")
594726e4 11462 (set_attr "type" "mov_shift_reg,multiple,multiple")]
05ed98a1 11463)
68df59d3 11464
f54fd62e
RE
11465(define_insn "*ifcompare_move_shift"
11466 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
68df59d3 11467 (if_then_else:SI
05ed98a1 11468 (match_operator 6 "arm_comparison_operator"
f54fd62e
RE
11469 [(match_operand:SI 4 "s_register_operand" "r,r")
11470 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
11471 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
68df59d3 11472 (match_operator:SI 7 "shift_operator"
f54fd62e
RE
11473 [(match_operand:SI 2 "s_register_operand" "r,r")
11474 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
48a08b9c 11475 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 11476 "TARGET_ARM"
f54fd62e 11477 "#"
05ed98a1 11478 [(set_attr "conds" "clob")
594726e4
JG
11479 (set_attr "length" "8,12")
11480 (set_attr "type" "multiple")]
05ed98a1 11481)
68df59d3 11482
f54fd62e
RE
11483(define_insn "*if_move_shift"
11484 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
68df59d3 11485 (if_then_else:SI
05ed98a1 11486 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
11487 [(match_operand 6 "cc_register" "") (const_int 0)])
11488 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
11489 (match_operator:SI 4 "shift_operator"
11490 [(match_operand:SI 2 "s_register_operand" "r,r,r")
11491 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
d5b7b3ae 11492 "TARGET_ARM"
68df59d3 11493 "@
f54fd62e
RE
11494 mov%D5\\t%0, %2%S4
11495 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
11496 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
05ed98a1 11497 [(set_attr "conds" "use")
d19fb8e3 11498 (set_attr "shift" "2")
9b66ebb1 11499 (set_attr "length" "4,8,8")
594726e4 11500 (set_attr "type" "mov_shift_reg,multiple,multiple")]
05ed98a1 11501)
ff9940b0 11502
4cdb3ed4 11503(define_insn "*ifcompare_shift_shift"
f54fd62e 11504 [(set (match_operand:SI 0 "s_register_operand" "=r")
68df59d3 11505 (if_then_else:SI
05ed98a1 11506 (match_operator 7 "arm_comparison_operator"
f54fd62e
RE
11507 [(match_operand:SI 5 "s_register_operand" "r")
11508 (match_operand:SI 6 "arm_add_operand" "rIL")])
68df59d3 11509 (match_operator:SI 8 "shift_operator"
f54fd62e
RE
11510 [(match_operand:SI 1 "s_register_operand" "r")
11511 (match_operand:SI 2 "arm_rhs_operand" "rM")])
68df59d3 11512 (match_operator:SI 9 "shift_operator"
f54fd62e
RE
11513 [(match_operand:SI 3 "s_register_operand" "r")
11514 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
48a08b9c 11515 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 11516 "TARGET_ARM"
f54fd62e 11517 "#"
05ed98a1 11518 [(set_attr "conds" "clob")
594726e4
JG
11519 (set_attr "length" "12")
11520 (set_attr "type" "multiple")]
05ed98a1 11521)
ff9940b0 11522
f54fd62e
RE
11523(define_insn "*if_shift_shift"
11524 [(set (match_operand:SI 0 "s_register_operand" "=r")
11525 (if_then_else:SI
05ed98a1 11526 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
11527 [(match_operand 8 "cc_register" "") (const_int 0)])
11528 (match_operator:SI 6 "shift_operator"
11529 [(match_operand:SI 1 "s_register_operand" "r")
11530 (match_operand:SI 2 "arm_rhs_operand" "rM")])
11531 (match_operator:SI 7 "shift_operator"
11532 [(match_operand:SI 3 "s_register_operand" "r")
11533 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
d5b7b3ae 11534 "TARGET_ARM"
f54fd62e 11535 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
05ed98a1 11536 [(set_attr "conds" "use")
d19fb8e3 11537 (set_attr "shift" "1")
9b66ebb1
PB
11538 (set_attr "length" "8")
11539 (set (attr "type") (if_then_else
11540 (and (match_operand 2 "const_int_operand" "")
11541 (match_operand 4 "const_int_operand" ""))
859abddd
SN
11542 (const_string "mov_shift")
11543 (const_string "mov_shift_reg")))]
05ed98a1 11544)
f54fd62e 11545
4cdb3ed4 11546(define_insn "*ifcompare_not_arith"
f54fd62e 11547 [(set (match_operand:SI 0 "s_register_operand" "=r")
68df59d3 11548 (if_then_else:SI
05ed98a1 11549 (match_operator 6 "arm_comparison_operator"
f54fd62e
RE
11550 [(match_operand:SI 4 "s_register_operand" "r")
11551 (match_operand:SI 5 "arm_add_operand" "rIL")])
11552 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
68df59d3 11553 (match_operator:SI 7 "shiftable_operator"
f54fd62e
RE
11554 [(match_operand:SI 2 "s_register_operand" "r")
11555 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
48a08b9c 11556 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 11557 "TARGET_ARM"
f54fd62e 11558 "#"
05ed98a1 11559 [(set_attr "conds" "clob")
594726e4
JG
11560 (set_attr "length" "12")
11561 (set_attr "type" "multiple")]
05ed98a1 11562)
ff9940b0 11563
f54fd62e
RE
11564(define_insn "*if_not_arith"
11565 [(set (match_operand:SI 0 "s_register_operand" "=r")
11566 (if_then_else:SI
05ed98a1 11567 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
11568 [(match_operand 4 "cc_register" "") (const_int 0)])
11569 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
11570 (match_operator:SI 6 "shiftable_operator"
11571 [(match_operand:SI 2 "s_register_operand" "r")
11572 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
d5b7b3ae 11573 "TARGET_ARM"
f54fd62e 11574 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
05ed98a1 11575 [(set_attr "conds" "use")
859abddd 11576 (set_attr "type" "mvn_reg")
05ed98a1
RE
11577 (set_attr "length" "8")]
11578)
f54fd62e
RE
11579
11580(define_insn "*ifcompare_arith_not"
11581 [(set (match_operand:SI 0 "s_register_operand" "=r")
68df59d3 11582 (if_then_else:SI
05ed98a1 11583 (match_operator 6 "arm_comparison_operator"
f54fd62e
RE
11584 [(match_operand:SI 4 "s_register_operand" "r")
11585 (match_operand:SI 5 "arm_add_operand" "rIL")])
68df59d3 11586 (match_operator:SI 7 "shiftable_operator"
f54fd62e
RE
11587 [(match_operand:SI 2 "s_register_operand" "r")
11588 (match_operand:SI 3 "arm_rhs_operand" "rI")])
11589 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
48a08b9c 11590 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 11591 "TARGET_ARM"
f54fd62e 11592 "#"
05ed98a1 11593 [(set_attr "conds" "clob")
594726e4
JG
11594 (set_attr "length" "12")
11595 (set_attr "type" "multiple")]
05ed98a1 11596)
ff9940b0 11597
f54fd62e
RE
11598(define_insn "*if_arith_not"
11599 [(set (match_operand:SI 0 "s_register_operand" "=r")
11600 (if_then_else:SI
05ed98a1 11601 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
11602 [(match_operand 4 "cc_register" "") (const_int 0)])
11603 (match_operator:SI 6 "shiftable_operator"
11604 [(match_operand:SI 2 "s_register_operand" "r")
11605 (match_operand:SI 3 "arm_rhs_operand" "rI")])
11606 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
d5b7b3ae 11607 "TARGET_ARM"
f54fd62e 11608 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
05ed98a1 11609 [(set_attr "conds" "use")
594726e4 11610 (set_attr "type" "multiple")
05ed98a1
RE
11611 (set_attr "length" "8")]
11612)
f54fd62e 11613
4cdb3ed4 11614(define_insn "*ifcompare_neg_move"
f54fd62e 11615 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
68df59d3 11616 (if_then_else:SI
05ed98a1 11617 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
11618 [(match_operand:SI 3 "s_register_operand" "r,r")
11619 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
11620 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
11621 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
48a08b9c 11622 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 11623 "TARGET_ARM"
f54fd62e 11624 "#"
05ed98a1 11625 [(set_attr "conds" "clob")
594726e4
JG
11626 (set_attr "length" "8,12")
11627 (set_attr "type" "multiple")]
05ed98a1 11628)
f54fd62e
RE
11629
11630(define_insn "*if_neg_move"
11631 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
11632 (if_then_else:SI
05ed98a1 11633 (match_operator 4 "arm_comparison_operator"
f54fd62e
RE
11634 [(match_operand 3 "cc_register" "") (const_int 0)])
11635 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
11636 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
d5b7b3ae 11637 "TARGET_ARM"
f54fd62e
RE
11638 "@
11639 rsb%d4\\t%0, %2, #0
11640 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
11641 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
05ed98a1 11642 [(set_attr "conds" "use")
594726e4
JG
11643 (set_attr "length" "4,8,8")
11644 (set_attr "type" "logic_shift_imm,multiple,multiple")]
05ed98a1 11645)
ff9940b0 11646
4cdb3ed4 11647(define_insn "*ifcompare_move_neg"
f54fd62e 11648 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
68df59d3 11649 (if_then_else:SI
05ed98a1 11650 (match_operator 5 "arm_comparison_operator"
f54fd62e
RE
11651 [(match_operand:SI 3 "s_register_operand" "r,r")
11652 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
11653 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
11654 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
48a08b9c 11655 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 11656 "TARGET_ARM"
f54fd62e 11657 "#"
05ed98a1 11658 [(set_attr "conds" "clob")
594726e4
JG
11659 (set_attr "length" "8,12")
11660 (set_attr "type" "multiple")]
05ed98a1 11661)
f54fd62e
RE
11662
11663(define_insn "*if_move_neg"
11664 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
11665 (if_then_else:SI
05ed98a1 11666 (match_operator 4 "arm_comparison_operator"
f54fd62e
RE
11667 [(match_operand 3 "cc_register" "") (const_int 0)])
11668 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
11669 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
d5b7b3ae 11670 "TARGET_ARM"
f54fd62e
RE
11671 "@
11672 rsb%D4\\t%0, %2, #0
11673 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
11674 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
cca0a211 11675 [(set_attr "conds" "use")
594726e4
JG
11676 (set_attr "length" "4,8,8")
11677 (set_attr "type" "logic_shift_imm,multiple,multiple")]
cca0a211 11678)
ff9940b0 11679
4cdb3ed4 11680(define_insn "*arith_adjacentmem"
ff9940b0
RE
11681 [(set (match_operand:SI 0 "s_register_operand" "=r")
11682 (match_operator:SI 1 "shiftable_operator"
11683 [(match_operand:SI 2 "memory_operand" "m")
11684 (match_operand:SI 3 "memory_operand" "m")]))
11685 (clobber (match_scratch:SI 4 "=r"))]
d5b7b3ae 11686 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
ff9940b0 11687 "*
5895f793
RE
11688 {
11689 rtx ldm[3];
11690 rtx arith[4];
15b5c4c1
RE
11691 rtx base_reg;
11692 HOST_WIDE_INT val1 = 0, val2 = 0;
ff9940b0 11693
5895f793
RE
11694 if (REGNO (operands[0]) > REGNO (operands[4]))
11695 {
11696 ldm[1] = operands[4];
11697 ldm[2] = operands[0];
11698 }
11699 else
11700 {
11701 ldm[1] = operands[0];
11702 ldm[2] = operands[4];
11703 }
15b5c4c1
RE
11704
11705 base_reg = XEXP (operands[2], 0);
11706
11707 if (!REG_P (base_reg))
11708 {
11709 val1 = INTVAL (XEXP (base_reg, 1));
11710 base_reg = XEXP (base_reg, 0);
11711 }
11712
11713 if (!REG_P (XEXP (operands[3], 0)))
5895f793 11714 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
15b5c4c1 11715
5895f793
RE
11716 arith[0] = operands[0];
11717 arith[3] = operands[1];
15b5c4c1 11718
5895f793
RE
11719 if (val1 < val2)
11720 {
11721 arith[1] = ldm[1];
11722 arith[2] = ldm[2];
11723 }
11724 else
11725 {
11726 arith[1] = ldm[2];
11727 arith[2] = ldm[1];
11728 }
15b5c4c1
RE
11729
11730 ldm[0] = base_reg;
11731 if (val1 !=0 && val2 != 0)
5895f793 11732 {
bcf640f7
PB
11733 rtx ops[3];
11734
15b5c4c1
RE
11735 if (val1 == 4 || val2 == 4)
11736 /* Other val must be 8, since we know they are adjacent and neither
11737 is zero. */
5b3e6663 11738 output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
bcf640f7 11739 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
15b5c4c1 11740 {
15b5c4c1
RE
11741 ldm[0] = ops[0] = operands[4];
11742 ops[1] = base_reg;
11743 ops[2] = GEN_INT (val1);
11744 output_add_immediate (ops);
11745 if (val1 < val2)
5b3e6663 11746 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
15b5c4c1 11747 else
5b3e6663 11748 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
15b5c4c1 11749 }
bcf640f7
PB
11750 else
11751 {
11752 /* Offset is out of range for a single add, so use two ldr. */
11753 ops[0] = ldm[1];
11754 ops[1] = base_reg;
11755 ops[2] = GEN_INT (val1);
11756 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
11757 ops[0] = ldm[2];
11758 ops[2] = GEN_INT (val2);
11759 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
11760 }
5895f793 11761 }
15b5c4c1 11762 else if (val1 != 0)
5895f793 11763 {
5895f793 11764 if (val1 < val2)
5b3e6663 11765 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
5895f793 11766 else
5b3e6663 11767 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
5895f793
RE
11768 }
11769 else
11770 {
5895f793 11771 if (val1 < val2)
5b3e6663 11772 output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
5895f793 11773 else
5b3e6663 11774 output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
5895f793
RE
11775 }
11776 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
11777 return \"\";
11778 }"
11779 [(set_attr "length" "12")
11780 (set_attr "predicable" "yes")
9b66ebb1 11781 (set_attr "type" "load1")]
5895f793 11782)
ff9940b0 11783
ff9940b0
RE
11784; This pattern is never tried by combine, so do it as a peephole
11785
bb6ae783 11786(define_peephole2
3053b100
RE
11787 [(set (match_operand:SI 0 "arm_general_register_operand" "")
11788 (match_operand:SI 1 "arm_general_register_operand" ""))
48a08b9c 11789 (set (reg:CC CC_REGNUM)
589fe0fc 11790 (compare:CC (match_dup 1) (const_int 0)))]
3053b100 11791 "TARGET_ARM"
bb6ae783
RE
11792 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
11793 (set (match_dup 0) (match_dup 1))])]
11794 ""
cca0a211 11795)
ff9940b0 11796
ff9940b0
RE
11797(define_split
11798 [(set (match_operand:SI 0 "s_register_operand" "")
11799 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
11800 (const_int 0))
05ed98a1 11801 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
ff9940b0
RE
11802 [(match_operand:SI 3 "s_register_operand" "")
11803 (match_operand:SI 4 "arm_rhs_operand" "")]))))
11804 (clobber (match_operand:SI 5 "s_register_operand" ""))]
d5b7b3ae 11805 "TARGET_ARM"
ff9940b0
RE
11806 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
11807 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
11808 (match_dup 5)))]
5895f793
RE
11809 ""
11810)
ff9940b0 11811
589fe0fc
RE
11812;; This split can be used because CC_Z mode implies that the following
11813;; branch will be an equality, or an unsigned inequality, so the sign
11814;; extension is not needed.
ff9940b0 11815
589fe0fc 11816(define_split
48a08b9c 11817 [(set (reg:CC_Z CC_REGNUM)
589fe0fc
RE
11818 (compare:CC_Z
11819 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
ff9940b0 11820 (const_int 24))
589fe0fc
RE
11821 (match_operand 1 "const_int_operand" "")))
11822 (clobber (match_scratch:SI 2 ""))]
d5b7b3ae
RE
11823 "TARGET_ARM
11824 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
11825 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
589fe0fc 11826 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
48a08b9c 11827 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
589fe0fc 11828 "
ff9940b0 11829 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
5895f793
RE
11830 "
11831)
5b3e6663 11832;; ??? Check the patterns above for Thumb-2 usefulness
ff9940b0 11833
091426d3
RE
11834(define_expand "prologue"
11835 [(clobber (const_int 0))]
d5b7b3ae 11836 "TARGET_EITHER"
5b3e6663 11837 "if (TARGET_32BIT)
d5b7b3ae
RE
11838 arm_expand_prologue ();
11839 else
5b3e6663 11840 thumb1_expand_prologue ();
091426d3 11841 DONE;
d5b7b3ae
RE
11842 "
11843)
091426d3 11844
949d79eb 11845(define_expand "epilogue"
c9ca9b88 11846 [(clobber (const_int 0))]
d5b7b3ae 11847 "TARGET_EITHER"
949d79eb 11848 "
e3b5732b 11849 if (crtl->calls_eh_return)
42083999 11850 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
5b3e6663 11851 if (TARGET_THUMB1)
d461c88a
IB
11852 {
11853 thumb1_expand_epilogue ();
11854 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
11855 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
11856 }
11857 else if (HAVE_return)
11858 {
11859 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
11860 no need for explicit testing again. */
11861 emit_jump_insn (gen_return ());
11862 }
11863 else if (TARGET_32BIT)
11864 {
11865 arm_expand_epilogue (true);
11866 }
d5b7b3ae
RE
11867 DONE;
11868 "
11869)
949d79eb 11870
d018b46e
RH
11871(define_insn "prologue_thumb1_interwork"
11872 [(unspec_volatile [(const_int 0)] VUNSPEC_THUMB1_INTERWORK)]
11873 "TARGET_THUMB1"
11874 "* return thumb1_output_interwork ();"
594726e4
JG
11875 [(set_attr "length" "8")
11876 (set_attr "type" "multiple")]
d018b46e
RH
11877)
11878
e3289412
NC
11879;; Note - although unspec_volatile's USE all hard registers,
11880;; USEs are ignored after relaod has completed. Thus we need
11881;; to add an unspec of the link register to ensure that flow
11882;; does not think that it is unused by the sibcall branch that
11883;; will replace the standard function epilogue.
d461c88a 11884(define_expand "sibcall_epilogue"
42083999 11885 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
d461c88a
IB
11886 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
11887 "TARGET_32BIT"
11888 "
11889 arm_expand_epilogue (false);
11890 DONE;
11891 "
0616531f
RE
11892)
11893
d5b7b3ae 11894(define_insn "*epilogue_insns"
b15bca31 11895 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
c59e1214 11896 "TARGET_THUMB1"
949d79eb 11897 "*
90911ab6 11898 return thumb1_unexpanded_epilogue ();
d5b7b3ae 11899 "
5895f793 11900 ; Length is absolute worst case
d5b7b3ae 11901 [(set_attr "length" "44")
0732a089
RE
11902 (set_attr "type" "block")
11903 ;; We don't clobber the conditions, but the potential length of this
11904 ;; operation is sufficient to make conditionalizing the sequence
11905 ;; unlikely to be profitable.
11906 (set_attr "conds" "clob")]
d5b7b3ae
RE
11907)
11908
11909(define_expand "eh_epilogue"
82955615
RE
11910 [(use (match_operand:SI 0 "register_operand" ""))
11911 (use (match_operand:SI 1 "register_operand" ""))
11912 (use (match_operand:SI 2 "register_operand" ""))]
d5b7b3ae
RE
11913 "TARGET_EITHER"
11914 "
5895f793
RE
11915 {
11916 cfun->machine->eh_epilogue_sp_ofs = operands[1];
d435a4be 11917 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
5895f793
RE
11918 {
11919 rtx ra = gen_rtx_REG (Pmode, 2);
11920
11921 emit_move_insn (ra, operands[2]);
11922 operands[2] = ra;
11923 }
9b598fa0
RE
11924 /* This is a hack -- we may have crystalized the function type too
11925 early. */
11926 cfun->machine->func_type = 0;
5895f793
RE
11927 }"
11928)
949d79eb 11929
ff9940b0
RE
11930;; This split is only used during output to reduce the number of patterns
11931;; that need assembler instructions adding to them. We allowed the setting
11932;; of the conditions to be implicit during rtl generation so that
11933;; the conditional compare patterns would work. However this conflicts to
f54fd62e 11934;; some extent with the conditional data operations, so we have to split them
ff9940b0
RE
11935;; up again here.
11936
5b3e6663
PB
11937;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
11938;; conditional execution sufficient?
11939
ff9940b0
RE
11940(define_split
11941 [(set (match_operand:SI 0 "s_register_operand" "")
05ed98a1
RE
11942 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
11943 [(match_operand 2 "" "") (match_operand 3 "" "")])
11944 (match_dup 0)
11945 (match_operand 4 "" "")))
48a08b9c 11946 (clobber (reg:CC CC_REGNUM))]
4d4f9f19 11947 "TARGET_ARM && reload_completed"
05ed98a1
RE
11948 [(set (match_dup 5) (match_dup 6))
11949 (cond_exec (match_dup 7)
11950 (set (match_dup 0) (match_dup 4)))]
11951 "
11952 {
11953 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
11954 operands[2], operands[3]);
11955 enum rtx_code rc = GET_CODE (operands[1]);
11956
48a08b9c 11957 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
05ed98a1
RE
11958 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
11959 if (mode == CCFPmode || mode == CCFPEmode)
11960 rc = reverse_condition_maybe_unordered (rc);
11961 else
11962 rc = reverse_condition (rc);
11963
11964 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
11965 }"
11966)
11967
11968(define_split
11969 [(set (match_operand:SI 0 "s_register_operand" "")
11970 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
11971 [(match_operand 2 "" "") (match_operand 3 "" "")])
11972 (match_operand 4 "" "")
11973 (match_dup 0)))
48a08b9c 11974 (clobber (reg:CC CC_REGNUM))]
4d4f9f19 11975 "TARGET_ARM && reload_completed"
05ed98a1
RE
11976 [(set (match_dup 5) (match_dup 6))
11977 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
11978 (set (match_dup 0) (match_dup 4)))]
11979 "
11980 {
11981 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
11982 operands[2], operands[3]);
11983
48a08b9c 11984 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
05ed98a1
RE
11985 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
11986 }"
11987)
11988
11989(define_split
11990 [(set (match_operand:SI 0 "s_register_operand" "")
11991 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
ff9940b0
RE
11992 [(match_operand 2 "" "") (match_operand 3 "" "")])
11993 (match_operand 4 "" "")
11994 (match_operand 5 "" "")))
48a08b9c 11995 (clobber (reg:CC CC_REGNUM))]
4d4f9f19 11996 "TARGET_ARM && reload_completed"
05ed98a1
RE
11997 [(set (match_dup 6) (match_dup 7))
11998 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
11999 (set (match_dup 0) (match_dup 4)))
12000 (cond_exec (match_dup 8)
12001 (set (match_dup 0) (match_dup 5)))]
12002 "
12003 {
12004 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
12005 operands[2], operands[3]);
12006 enum rtx_code rc = GET_CODE (operands[1]);
12007
48a08b9c 12008 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
05ed98a1
RE
12009 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
12010 if (mode == CCFPmode || mode == CCFPEmode)
12011 rc = reverse_condition_maybe_unordered (rc);
12012 else
12013 rc = reverse_condition (rc);
12014
12015 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
12016 }"
12017)
12018
d5b7b3ae
RE
12019(define_split
12020 [(set (match_operand:SI 0 "s_register_operand" "")
05ed98a1 12021 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
d5b7b3ae
RE
12022 [(match_operand:SI 2 "s_register_operand" "")
12023 (match_operand:SI 3 "arm_add_operand" "")])
12024 (match_operand:SI 4 "arm_rhs_operand" "")
12025 (not:SI
12026 (match_operand:SI 5 "s_register_operand" ""))))
48a08b9c 12027 (clobber (reg:CC CC_REGNUM))]
4d4f9f19 12028 "TARGET_ARM && reload_completed"
d5b7b3ae 12029 [(set (match_dup 6) (match_dup 7))
1646cf41
RE
12030 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
12031 (set (match_dup 0) (match_dup 4)))
12032 (cond_exec (match_dup 8)
12033 (set (match_dup 0) (not:SI (match_dup 5))))]
d5b7b3ae 12034 "
5895f793
RE
12035 {
12036 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
12037 operands[2], operands[3]);
1646cf41 12038 enum rtx_code rc = GET_CODE (operands[1]);
d5b7b3ae 12039
48a08b9c 12040 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
f1c25d3b 12041 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
1646cf41
RE
12042 if (mode == CCFPmode || mode == CCFPEmode)
12043 rc = reverse_condition_maybe_unordered (rc);
12044 else
12045 rc = reverse_condition (rc);
12046
12047 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
5895f793
RE
12048 }"
12049)
d5b7b3ae
RE
12050
12051(define_insn "*cond_move_not"
12052 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
05ed98a1 12053 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
d5b7b3ae
RE
12054 [(match_operand 3 "cc_register" "") (const_int 0)])
12055 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
12056 (not:SI
12057 (match_operand:SI 2 "s_register_operand" "r,r"))))]
12058 "TARGET_ARM"
12059 "@
12060 mvn%D4\\t%0, %2
12061 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
cca0a211 12062 [(set_attr "conds" "use")
594726e4 12063 (set_attr "type" "mvn_reg,multiple")
cca0a211
RE
12064 (set_attr "length" "4,8")]
12065)
d5b7b3ae 12066
ff9940b0
RE
12067;; The next two patterns occur when an AND operation is followed by a
12068;; scc insn sequence
12069
4cdb3ed4 12070(define_insn "*sign_extract_onebit"
ff9940b0
RE
12071 [(set (match_operand:SI 0 "s_register_operand" "=r")
12072 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
12073 (const_int 1)
c1ff6200
JD
12074 (match_operand:SI 2 "const_int_operand" "n")))
12075 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 12076 "TARGET_ARM"
ff9940b0 12077 "*
cca0a211
RE
12078 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
12079 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
12080 return \"mvnne\\t%0, #0\";
12081 "
12082 [(set_attr "conds" "clob")
594726e4
JG
12083 (set_attr "length" "8")
12084 (set_attr "type" "multiple")]
cca0a211 12085)
ff9940b0 12086
4cdb3ed4 12087(define_insn "*not_signextract_onebit"
ff9940b0
RE
12088 [(set (match_operand:SI 0 "s_register_operand" "=r")
12089 (not:SI
12090 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
12091 (const_int 1)
c1ff6200
JD
12092 (match_operand:SI 2 "const_int_operand" "n"))))
12093 (clobber (reg:CC CC_REGNUM))]
d5b7b3ae 12094 "TARGET_ARM"
ff9940b0 12095 "*
cca0a211
RE
12096 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
12097 output_asm_insn (\"tst\\t%1, %2\", operands);
12098 output_asm_insn (\"mvneq\\t%0, #0\", operands);
12099 return \"movne\\t%0, #0\";
12100 "
12101 [(set_attr "conds" "clob")
594726e4
JG
12102 (set_attr "length" "12")
12103 (set_attr "type" "multiple")]
cca0a211 12104)
5b3e6663 12105;; ??? The above patterns need auditing for Thumb-2
091426d3 12106
cca0a211
RE
12107;; Push multiple registers to the stack. Registers are in parallel (use ...)
12108;; expressions. For simplicity, the first register is also in the unspec
12109;; part.
0c27e2d8
WG
12110;; To avoid the usage of GNU extension, the length attribute is computed
12111;; in a C function arm_attr_length_push_multi.
4cdb3ed4 12112(define_insn "*push_multi"
091426d3 12113 [(match_parallel 2 "multi_register_push"
d018b46e 12114 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
4e6f5666 12115 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
b15bca31 12116 UNSPEC_PUSH_MULT))])]
d018b46e 12117 ""
091426d3 12118 "*
5895f793
RE
12119 {
12120 int num_saves = XVECLEN (operands[2], 0);
3a5a4282 12121
5895f793 12122 /* For the StrongARM at least it is faster to
5b3e6663 12123 use STR to store only a single register.
7a085dce
KH
12124 In Thumb mode always use push, and the assembler will pick
12125 something appropriate. */
5b3e6663 12126 if (num_saves == 1 && TARGET_ARM)
bd2777de 12127 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
5895f793
RE
12128 else
12129 {
12130 int i;
12131 char pattern[100];
3a5a4282 12132
5b3e6663 12133 if (TARGET_ARM)
bd2777de
BS
12134 strcpy (pattern, \"stm%(fd%)\\t%m0!, {%1\");
12135 else if (TARGET_THUMB2)
12136 strcpy (pattern, \"push%?\\t{%1\");
5b3e6663
PB
12137 else
12138 strcpy (pattern, \"push\\t{%1\");
5895f793 12139
880c4dcb 12140 for (i = 1; i < num_saves; i++)
5895f793
RE
12141 {
12142 strcat (pattern, \", %|\");
12143 strcat (pattern,
12144 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
12145 }
12146
12147 strcat (pattern, \"}\");
12148 output_asm_insn (pattern, operands);
12149 }
12150
12151 return \"\";
12152 }"
4925d0d5
WG
12153 [(set_attr "type" "store4")
12154 (set (attr "length")
0c27e2d8 12155 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
5895f793 12156)
4cdb3ed4 12157
3894f59e
RE
12158(define_insn "stack_tie"
12159 [(set (mem:BLK (scratch))
f5c630c3
PB
12160 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
12161 (match_operand:SI 1 "s_register_operand" "rk")]
3894f59e
RE
12162 UNSPEC_PRLG_STK))]
12163 ""
12164 ""
594726e4
JG
12165 [(set_attr "length" "0")
12166 (set_attr "type" "block")]
3894f59e
RE
12167)
12168
3aee1982
IB
12169;; Pop (as used in epilogue RTL)
12170;;
12171(define_insn "*load_multiple_with_writeback"
12172 [(match_parallel 0 "load_multiple_operation"
12173 [(set (match_operand:SI 1 "s_register_operand" "+rk")
12174 (plus:SI (match_dup 1)
12175 (match_operand:SI 2 "const_int_operand" "I")))
12176 (set (match_operand:SI 3 "s_register_operand" "=rk")
12177 (mem:SI (match_dup 1)))
12178 ])]
12179 "TARGET_32BIT && (reload_in_progress || reload_completed)"
12180 "*
12181 {
12182 arm_output_multireg_pop (operands, /*return_pc=*/false,
12183 /*cond=*/const_true_rtx,
12184 /*reverse=*/false,
12185 /*update=*/true);
12186 return \"\";
12187 }
12188 "
12189 [(set_attr "type" "load4")
12190 (set_attr "predicable" "yes")]
12191)
12192
12193;; Pop with return (as used in epilogue RTL)
12194;;
12195;; This instruction is generated when the registers are popped at the end of
12196;; epilogue. Here, instead of popping the value into LR and then generating
12197;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
12198;; with (return).
12199(define_insn "*pop_multiple_with_writeback_and_return"
12200 [(match_parallel 0 "pop_multiple_return"
12201 [(return)
12202 (set (match_operand:SI 1 "s_register_operand" "+rk")
12203 (plus:SI (match_dup 1)
12204 (match_operand:SI 2 "const_int_operand" "I")))
12205 (set (match_operand:SI 3 "s_register_operand" "=rk")
12206 (mem:SI (match_dup 1)))
12207 ])]
12208 "TARGET_32BIT && (reload_in_progress || reload_completed)"
12209 "*
12210 {
12211 arm_output_multireg_pop (operands, /*return_pc=*/true,
12212 /*cond=*/const_true_rtx,
12213 /*reverse=*/false,
12214 /*update=*/true);
12215 return \"\";
12216 }
12217 "
12218 [(set_attr "type" "load4")
12219 (set_attr "predicable" "yes")]
12220)
12221
12222(define_insn "*pop_multiple_with_return"
12223 [(match_parallel 0 "pop_multiple_return"
12224 [(return)
12225 (set (match_operand:SI 2 "s_register_operand" "=rk")
12226 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
12227 ])]
12228 "TARGET_32BIT && (reload_in_progress || reload_completed)"
12229 "*
12230 {
12231 arm_output_multireg_pop (operands, /*return_pc=*/true,
12232 /*cond=*/const_true_rtx,
12233 /*reverse=*/false,
12234 /*update=*/false);
12235 return \"\";
12236 }
12237 "
12238 [(set_attr "type" "load4")
12239 (set_attr "predicable" "yes")]
12240)
12241
12242;; Load into PC and return
12243(define_insn "*ldr_with_return"
12244 [(return)
12245 (set (reg:SI PC_REGNUM)
12246 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
12247 "TARGET_32BIT && (reload_in_progress || reload_completed)"
12248 "ldr%?\t%|pc, [%0], #4"
12249 [(set_attr "type" "load1")
12250 (set_attr "predicable" "yes")]
12251)
4b2678f8
IB
12252;; Pop for floating point registers (as used in epilogue RTL)
12253(define_insn "*vfp_pop_multiple_with_writeback"
12254 [(match_parallel 0 "pop_multiple_fp"
12255 [(set (match_operand:SI 1 "s_register_operand" "+rk")
12256 (plus:SI (match_dup 1)
12257 (match_operand:SI 2 "const_int_operand" "I")))
315d7bd4 12258 (set (match_operand:DF 3 "vfp_hard_register_operand" "")
4b2678f8
IB
12259 (mem:DF (match_dup 1)))])]
12260 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
12261 "*
12262 {
12263 int num_regs = XVECLEN (operands[0], 0);
12264 char pattern[100];
12265 rtx op_list[2];
12266 strcpy (pattern, \"fldmfdd\\t\");
12267 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
12268 strcat (pattern, \"!, {\");
12269 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
12270 strcat (pattern, \"%P0\");
12271 if ((num_regs - 1) > 1)
12272 {
12273 strcat (pattern, \"-%P1\");
12274 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
12275 }
12276
12277 strcat (pattern, \"}\");
12278 output_asm_insn (pattern, op_list);
12279 return \"\";
12280 }
12281 "
12282 [(set_attr "type" "load4")
12283 (set_attr "conds" "unconditional")
12284 (set_attr "predicable" "no")]
12285)
12286
4cdb3ed4
RE
12287;; Special patterns for dealing with the constant pool
12288
d5b7b3ae 12289(define_insn "align_4"
b15bca31 12290 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
d5b7b3ae 12291 "TARGET_EITHER"
4cdb3ed4 12292 "*
d5b7b3ae 12293 assemble_align (32);
4cdb3ed4 12294 return \"\";
d5b7b3ae 12295 "
594726e4 12296 [(set_attr "type" "no_insn")]
d5b7b3ae 12297)
4cdb3ed4 12298
5a9335ef
NC
12299(define_insn "align_8"
12300 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
5848830f 12301 "TARGET_EITHER"
5a9335ef
NC
12302 "*
12303 assemble_align (64);
12304 return \"\";
12305 "
594726e4 12306 [(set_attr "type" "no_insn")]
5a9335ef
NC
12307)
12308
d5b7b3ae 12309(define_insn "consttable_end"
b15bca31 12310 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
d5b7b3ae 12311 "TARGET_EITHER"
4cdb3ed4 12312 "*
d5b7b3ae 12313 making_const_table = FALSE;
4cdb3ed4 12314 return \"\";
d5b7b3ae 12315 "
594726e4 12316 [(set_attr "type" "no_insn")]
d5b7b3ae 12317)
4cdb3ed4 12318
d5b7b3ae 12319(define_insn "consttable_1"
b15bca31 12320 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
5b3e6663 12321 "TARGET_THUMB1"
4cdb3ed4 12322 "*
d5b7b3ae 12323 making_const_table = TRUE;
c8af3574 12324 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
d5b7b3ae 12325 assemble_zeros (3);
4cdb3ed4 12326 return \"\";
d5b7b3ae 12327 "
594726e4
JG
12328 [(set_attr "length" "4")
12329 (set_attr "type" "no_insn")]
d5b7b3ae 12330)
4cdb3ed4 12331
d5b7b3ae 12332(define_insn "consttable_2"
b15bca31 12333 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
5b3e6663 12334 "TARGET_THUMB1"
4cdb3ed4 12335 "*
d5b7b3ae 12336 making_const_table = TRUE;
0fd8c3ad 12337 gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
c8af3574 12338 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
d5b7b3ae 12339 assemble_zeros (2);
4cdb3ed4 12340 return \"\";
d5b7b3ae 12341 "
594726e4
JG
12342 [(set_attr "length" "4")
12343 (set_attr "type" "no_insn")]
d5b7b3ae
RE
12344)
12345
12346(define_insn "consttable_4"
b15bca31 12347 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
d5b7b3ae
RE
12348 "TARGET_EITHER"
12349 "*
12350 {
0fd8c3ad 12351 rtx x = operands[0];
d5b7b3ae 12352 making_const_table = TRUE;
0fd8c3ad 12353 switch (GET_MODE_CLASS (GET_MODE (x)))
d5b7b3ae
RE
12354 {
12355 case MODE_FLOAT:
0fd8c3ad
SL
12356 if (GET_MODE (x) == HFmode)
12357 arm_emit_fp16_const (x);
12358 else
12359 {
12360 REAL_VALUE_TYPE r;
12361 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
12362 assemble_real (r, GET_MODE (x), BITS_PER_WORD);
12363 }
12364 break;
d5b7b3ae 12365 default:
5115f061
PB
12366 /* XXX: Sometimes gcc does something really dumb and ends up with
12367 a HIGH in a constant pool entry, usually because it's trying to
12368 load into a VFP register. We know this will always be used in
12369 combination with a LO_SUM which ignores the high bits, so just
12370 strip off the HIGH. */
12371 if (GET_CODE (x) == HIGH)
12372 x = XEXP (x, 0);
0fd8c3ad
SL
12373 assemble_integer (x, 4, BITS_PER_WORD, 1);
12374 mark_symbol_refs_as_used (x);
d5b7b3ae
RE
12375 break;
12376 }
12377 return \"\";
12378 }"
594726e4
JG
12379 [(set_attr "length" "4")
12380 (set_attr "type" "no_insn")]
d5b7b3ae
RE
12381)
12382
12383(define_insn "consttable_8"
b15bca31 12384 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
d5b7b3ae
RE
12385 "TARGET_EITHER"
12386 "*
12387 {
12388 making_const_table = TRUE;
12389 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
12390 {
12391 case MODE_FLOAT:
12392 {
b216cd4a
ZW
12393 REAL_VALUE_TYPE r;
12394 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
12395 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
d5b7b3ae
RE
12396 break;
12397 }
12398 default:
c8af3574 12399 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
d5b7b3ae
RE
12400 break;
12401 }
12402 return \"\";
12403 }"
594726e4
JG
12404 [(set_attr "length" "8")
12405 (set_attr "type" "no_insn")]
d5b7b3ae
RE
12406)
12407
88f77cba
JB
12408(define_insn "consttable_16"
12409 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
12410 "TARGET_EITHER"
12411 "*
12412 {
12413 making_const_table = TRUE;
12414 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
12415 {
12416 case MODE_FLOAT:
12417 {
12418 REAL_VALUE_TYPE r;
12419 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
12420 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
12421 break;
12422 }
12423 default:
12424 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
12425 break;
12426 }
12427 return \"\";
12428 }"
594726e4
JG
12429 [(set_attr "length" "16")
12430 (set_attr "type" "no_insn")]
88f77cba
JB
12431)
12432
d5b7b3ae
RE
12433;; Miscellaneous Thumb patterns
12434
657d9449 12435(define_expand "tablejump"
82955615 12436 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
657d9449 12437 (use (label_ref (match_operand 1 "" "")))])]
5b3e6663 12438 "TARGET_THUMB1"
657d9449
RE
12439 "
12440 if (flag_pic)
12441 {
12442 /* Hopefully, CSE will eliminate this copy. */
12443 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
12444 rtx reg2 = gen_reg_rtx (SImode);
12445
12446 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
12447 operands[0] = reg2;
12448 }
12449 "
12450)
12451
68d560d4 12452;; NB never uses BX.
5b3e6663 12453(define_insn "*thumb1_tablejump"
d5b7b3ae
RE
12454 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
12455 (use (label_ref (match_operand 1 "" "")))]
5b3e6663 12456 "TARGET_THUMB1"
657d9449 12457 "mov\\t%|pc, %0"
594726e4
JG
12458 [(set_attr "length" "2")
12459 (set_attr "type" "no_insn")]
d5b7b3ae 12460)
cca0a211 12461
d19fb8e3
NC
12462;; V5 Instructions,
12463
7dba8395
RH
12464(define_insn "clzsi2"
12465 [(set (match_operand:SI 0 "s_register_operand" "=r")
12466 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
5b3e6663 12467 "TARGET_32BIT && arm_arch5"
e912eadf 12468 "clz%?\\t%0, %1"
c956e102 12469 [(set_attr "predicable" "yes")
52fceb44 12470 (set_attr "type" "clz")])
d19fb8e3 12471
ca96ed43
DG
12472(define_insn "rbitsi2"
12473 [(set (match_operand:SI 0 "s_register_operand" "=r")
12474 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
12475 "TARGET_32BIT && arm_arch_thumb2"
12476 "rbit%?\\t%0, %1"
12477 [(set_attr "predicable" "yes")
52fceb44 12478 (set_attr "type" "clz")])
ca96ed43
DG
12479
12480(define_expand "ctzsi2"
12481 [(set (match_operand:SI 0 "s_register_operand" "")
12482 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
12483 "TARGET_32BIT && arm_arch_thumb2"
12484 "
8d142c15
DG
12485 {
12486 rtx tmp = gen_reg_rtx (SImode);
12487 emit_insn (gen_rbitsi2 (tmp, operands[1]));
12488 emit_insn (gen_clzsi2 (operands[0], tmp));
12489 }
ca96ed43
DG
12490 DONE;
12491 "
12492)
12493
b15bca31 12494;; V5E instructions.
d19fb8e3
NC
12495
12496(define_insn "prefetch"
fa980e6b
RE
12497 [(prefetch (match_operand:SI 0 "address_operand" "p")
12498 (match_operand:SI 1 "" "")
12499 (match_operand:SI 2 "" ""))]
5b3e6663 12500 "TARGET_32BIT && arm_arch5e"
594726e4
JG
12501 "pld\\t%a0"
12502 [(set_attr "type" "load1")]
12503)
d19fb8e3 12504
cca0a211
RE
12505;; General predication pattern
12506
12507(define_cond_exec
12508 [(match_operator 0 "arm_comparison_operator"
12509 [(match_operand 1 "cc_register" "")
12510 (const_int 0)])]
5b3e6663 12511 "TARGET_32BIT"
cca0a211 12512 ""
17a7fc37 12513[(set_attr "predicated" "yes")]
cca0a211
RE
12514)
12515
42083999
GY
12516(define_insn "force_register_use"
12517 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
6bacc7b0 12518 ""
42083999 12519 "%@ %0 needed"
594726e4
JG
12520 [(set_attr "length" "0")
12521 (set_attr "type" "no_insn")]
6bacc7b0 12522)
82955615 12523
c9ca9b88
PB
12524
12525;; Patterns for exception handling
12526
12527(define_expand "eh_return"
12528 [(use (match_operand 0 "general_operand" ""))]
12529 "TARGET_EITHER"
12530 "
12531 {
5b3e6663 12532 if (TARGET_32BIT)
c9ca9b88
PB
12533 emit_insn (gen_arm_eh_return (operands[0]));
12534 else
12535 emit_insn (gen_thumb_eh_return (operands[0]));
12536 DONE;
12537 }"
12538)
12539
12540;; We can't expand this before we know where the link register is stored.
12541(define_insn_and_split "arm_eh_return"
12542 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
12543 VUNSPEC_EH_RETURN)
12544 (clobber (match_scratch:SI 1 "=&r"))]
12545 "TARGET_ARM"
12546 "#"
12547 "&& reload_completed"
12548 [(const_int 0)]
12549 "
12550 {
12551 arm_set_return_address (operands[0], operands[1]);
12552 DONE;
12553 }"
12554)
12555
12556(define_insn_and_split "thumb_eh_return"
12557 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
12558 VUNSPEC_EH_RETURN)
12559 (clobber (match_scratch:SI 1 "=&l"))]
5b3e6663 12560 "TARGET_THUMB1"
c9ca9b88
PB
12561 "#"
12562 "&& reload_completed"
12563 [(const_int 0)]
12564 "
12565 {
12566 thumb_set_return_address (operands[0], operands[1]);
12567 DONE;
12568 }"
594726e4 12569 [(set_attr "type" "mov_reg")]
c9ca9b88
PB
12570)
12571
d3585b76
DJ
12572\f
12573;; TLS support
12574
12575(define_insn "load_tp_hard"
12576 [(set (match_operand:SI 0 "register_operand" "=r")
12577 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
12578 "TARGET_HARD_TP"
12579 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
594726e4 12580 [(set_attr "predicable" "yes")
8c48eecd 12581 (set_attr "type" "mrs")]
d3585b76
DJ
12582)
12583
12584;; Doesn't clobber R1-R3. Must use r0 for the first operand.
12585(define_insn "load_tp_soft"
12586 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
12587 (clobber (reg:SI LR_REGNUM))
12588 (clobber (reg:SI IP_REGNUM))
12589 (clobber (reg:CC CC_REGNUM))]
12590 "TARGET_SOFT_TP"
12591 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
594726e4
JG
12592 [(set_attr "conds" "clob")
12593 (set_attr "type" "branch")]
d3585b76
DJ
12594)
12595
ccdc2164
NS
12596;; tls descriptor call
12597(define_insn "tlscall"
12598 [(set (reg:SI R0_REGNUM)
12599 (unspec:SI [(reg:SI R0_REGNUM)
12600 (match_operand:SI 0 "" "X")
12601 (match_operand 1 "" "")] UNSPEC_TLS))
12602 (clobber (reg:SI R1_REGNUM))
12603 (clobber (reg:SI LR_REGNUM))
12604 (clobber (reg:SI CC_REGNUM))]
12605 "TARGET_GNU2_TLS"
12606 {
12607 targetm.asm_out.internal_label (asm_out_file, "LPIC",
12608 INTVAL (operands[1]));
12609 return "bl\\t%c0(tlscall)";
12610 }
12611 [(set_attr "conds" "clob")
594726e4
JG
12612 (set_attr "length" "4")
12613 (set_attr "type" "branch")]
ccdc2164
NS
12614)
12615
7e4dd63d
CLT
12616;; For thread pointer builtin
12617(define_expand "get_thread_pointersi"
12618 [(match_operand:SI 0 "s_register_operand" "=r")]
12619 ""
12620 "
12621 {
12622 arm_load_tp (operands[0]);
12623 DONE;
12624 }")
12625
ccdc2164
NS
12626;;
12627
80fffdef
RR
12628;; We only care about the lower 16 bits of the constant
12629;; being inserted into the upper 16 bits of the register.
a552b644
RR
12630(define_insn "*arm_movtas_ze"
12631 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
12632 (const_int 16)
12633 (const_int 16))
12634 (match_operand:SI 1 "const_int_operand" ""))]
4ce9b2b2 12635 "arm_arch_thumb2"
80fffdef 12636 "movt%?\t%0, %L1"
a552b644 12637 [(set_attr "predicable" "yes")
5e5f7673 12638 (set_attr "predicable_short_it" "no")
594726e4
JG
12639 (set_attr "length" "4")
12640 (set_attr "type" "mov_imm")]
a552b644
RR
12641)
12642
f67325e8 12643(define_insn "*arm_rev"
e619b173
CL
12644 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
12645 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
12646 "arm_arch6"
12647 "@
12648 rev\t%0, %1
12649 rev%?\t%0, %1
12650 rev%?\t%0, %1"
12651 [(set_attr "arch" "t1,t2,32")
594726e4
JG
12652 (set_attr "length" "2,2,4")
12653 (set_attr "type" "rev")]
4fc2b1aa
ST
12654)
12655
12656(define_expand "arm_legacy_rev"
12657 [(set (match_operand:SI 2 "s_register_operand" "")
12658 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
12659 (const_int 16))
12660 (match_dup 1)))
12661 (set (match_dup 2)
12662 (lshiftrt:SI (match_dup 2)
12663 (const_int 8)))
12664 (set (match_operand:SI 3 "s_register_operand" "")
12665 (rotatert:SI (match_dup 1)
12666 (const_int 8)))
12667 (set (match_dup 2)
12668 (and:SI (match_dup 2)
12669 (const_int -65281)))
12670 (set (match_operand:SI 0 "s_register_operand" "")
12671 (xor:SI (match_dup 3)
12672 (match_dup 2)))]
12673 "TARGET_32BIT"
12674 ""
12675)
12676
12677;; Reuse temporaries to keep register pressure down.
12678(define_expand "thumb_legacy_rev"
12679 [(set (match_operand:SI 2 "s_register_operand" "")
12680 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
12681 (const_int 24)))
12682 (set (match_operand:SI 3 "s_register_operand" "")
12683 (lshiftrt:SI (match_dup 1)
12684 (const_int 24)))
12685 (set (match_dup 3)
12686 (ior:SI (match_dup 3)
12687 (match_dup 2)))
12688 (set (match_operand:SI 4 "s_register_operand" "")
12689 (const_int 16))
12690 (set (match_operand:SI 5 "s_register_operand" "")
12691 (rotatert:SI (match_dup 1)
12692 (match_dup 4)))
12693 (set (match_dup 2)
12694 (ashift:SI (match_dup 5)
12695 (const_int 24)))
12696 (set (match_dup 5)
12697 (lshiftrt:SI (match_dup 5)
12698 (const_int 24)))
12699 (set (match_dup 5)
12700 (ior:SI (match_dup 5)
12701 (match_dup 2)))
12702 (set (match_dup 5)
12703 (rotatert:SI (match_dup 5)
12704 (match_dup 4)))
12705 (set (match_operand:SI 0 "s_register_operand" "")
12706 (ior:SI (match_dup 5)
12707 (match_dup 3)))]
12708 "TARGET_THUMB"
12709 ""
12710)
12711
12712(define_expand "bswapsi2"
12713 [(set (match_operand:SI 0 "s_register_operand" "=r")
12714 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
0a7822a3 12715"TARGET_EITHER && (arm_arch6 || !optimize_size)"
4fc2b1aa 12716"
0a7822a3
RR
12717 if (!arm_arch6)
12718 {
12719 rtx op2 = gen_reg_rtx (SImode);
12720 rtx op3 = gen_reg_rtx (SImode);
4fc2b1aa 12721
0a7822a3
RR
12722 if (TARGET_THUMB)
12723 {
12724 rtx op4 = gen_reg_rtx (SImode);
12725 rtx op5 = gen_reg_rtx (SImode);
4fc2b1aa 12726
0a7822a3
RR
12727 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
12728 op2, op3, op4, op5));
12729 }
12730 else
12731 {
12732 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
12733 op2, op3));
12734 }
4fc2b1aa 12735
0a7822a3
RR
12736 DONE;
12737 }
4fc2b1aa
ST
12738 "
12739)
12740
e619b173
CL
12741;; bswap16 patterns: use revsh and rev16 instructions for the signed
12742;; and unsigned variants, respectively. For rev16, expose
12743;; byte-swapping in the lower 16 bits only.
12744(define_insn "*arm_revsh"
12745 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
12746 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
12747 "arm_arch6"
12748 "@
12749 revsh\t%0, %1
12750 revsh%?\t%0, %1
12751 revsh%?\t%0, %1"
12752 [(set_attr "arch" "t1,t2,32")
594726e4
JG
12753 (set_attr "length" "2,2,4")
12754 (set_attr "type" "rev")]
e619b173
CL
12755)
12756
12757(define_insn "*arm_rev16"
12758 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
12759 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
12760 "arm_arch6"
12761 "@
12762 rev16\t%0, %1
12763 rev16%?\t%0, %1
12764 rev16%?\t%0, %1"
12765 [(set_attr "arch" "t1,t2,32")
594726e4
JG
12766 (set_attr "length" "2,2,4")
12767 (set_attr "type" "rev")]
e619b173
CL
12768)
12769
12770(define_expand "bswaphi2"
12771 [(set (match_operand:HI 0 "s_register_operand" "=r")
12772 (bswap:HI (match_operand:HI 1 "s_register_operand" "r")))]
12773"arm_arch6"
12774""
12775)
12776
56289ed2
SD
12777;; Patterns for LDRD/STRD in Thumb2 mode
12778
12779(define_insn "*thumb2_ldrd"
12780 [(set (match_operand:SI 0 "s_register_operand" "=r")
12781 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
12782 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
12783 (set (match_operand:SI 3 "s_register_operand" "=r")
12784 (mem:SI (plus:SI (match_dup 1)
12785 (match_operand:SI 4 "const_int_operand" ""))))]
12786 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
12787 && current_tune->prefer_ldrd_strd
12788 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
12789 && (operands_ok_ldrd_strd (operands[0], operands[3],
12790 operands[1], INTVAL (operands[2]),
12791 false, true))"
12792 "ldrd%?\t%0, %3, [%1, %2]"
12793 [(set_attr "type" "load2")
31dfce10
KT
12794 (set_attr "predicable" "yes")
12795 (set_attr "predicable_short_it" "no")])
56289ed2
SD
12796
12797(define_insn "*thumb2_ldrd_base"
12798 [(set (match_operand:SI 0 "s_register_operand" "=r")
12799 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
12800 (set (match_operand:SI 2 "s_register_operand" "=r")
12801 (mem:SI (plus:SI (match_dup 1)
12802 (const_int 4))))]
12803 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
12804 && current_tune->prefer_ldrd_strd
12805 && (operands_ok_ldrd_strd (operands[0], operands[2],
12806 operands[1], 0, false, true))"
12807 "ldrd%?\t%0, %2, [%1]"
12808 [(set_attr "type" "load2")
31dfce10
KT
12809 (set_attr "predicable" "yes")
12810 (set_attr "predicable_short_it" "no")])
56289ed2
SD
12811
12812(define_insn "*thumb2_ldrd_base_neg"
12813 [(set (match_operand:SI 0 "s_register_operand" "=r")
12814 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
12815 (const_int -4))))
12816 (set (match_operand:SI 2 "s_register_operand" "=r")
12817 (mem:SI (match_dup 1)))]
12818 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
12819 && current_tune->prefer_ldrd_strd
12820 && (operands_ok_ldrd_strd (operands[0], operands[2],
12821 operands[1], -4, false, true))"
12822 "ldrd%?\t%0, %2, [%1, #-4]"
12823 [(set_attr "type" "load2")
31dfce10
KT
12824 (set_attr "predicable" "yes")
12825 (set_attr "predicable_short_it" "no")])
56289ed2
SD
12826
12827(define_insn "*thumb2_strd"
12828 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
12829 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
12830 (match_operand:SI 2 "s_register_operand" "r"))
12831 (set (mem:SI (plus:SI (match_dup 0)
12832 (match_operand:SI 3 "const_int_operand" "")))
12833 (match_operand:SI 4 "s_register_operand" "r"))]
12834 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
12835 && current_tune->prefer_ldrd_strd
12836 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
12837 && (operands_ok_ldrd_strd (operands[2], operands[4],
12838 operands[0], INTVAL (operands[1]),
12839 false, false))"
12840 "strd%?\t%2, %4, [%0, %1]"
12841 [(set_attr "type" "store2")
31dfce10
KT
12842 (set_attr "predicable" "yes")
12843 (set_attr "predicable_short_it" "no")])
56289ed2
SD
12844
12845(define_insn "*thumb2_strd_base"
12846 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
12847 (match_operand:SI 1 "s_register_operand" "r"))
12848 (set (mem:SI (plus:SI (match_dup 0)
12849 (const_int 4)))
12850 (match_operand:SI 2 "s_register_operand" "r"))]
12851 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
12852 && current_tune->prefer_ldrd_strd
12853 && (operands_ok_ldrd_strd (operands[1], operands[2],
12854 operands[0], 0, false, false))"
12855 "strd%?\t%1, %2, [%0]"
12856 [(set_attr "type" "store2")
31dfce10
KT
12857 (set_attr "predicable" "yes")
12858 (set_attr "predicable_short_it" "no")])
56289ed2
SD
12859
12860(define_insn "*thumb2_strd_base_neg"
12861 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
12862 (const_int -4)))
12863 (match_operand:SI 1 "s_register_operand" "r"))
12864 (set (mem:SI (match_dup 0))
12865 (match_operand:SI 2 "s_register_operand" "r"))]
12866 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
12867 && current_tune->prefer_ldrd_strd
12868 && (operands_ok_ldrd_strd (operands[1], operands[2],
12869 operands[0], -4, false, false))"
12870 "strd%?\t%1, %2, [%0, #-4]"
12871 [(set_attr "type" "store2")
31dfce10
KT
12872 (set_attr "predicable" "yes")
12873 (set_attr "predicable_short_it" "no")])
56289ed2 12874
582e2e43
KT
12875;; ARMv8 CRC32 instructions.
12876(define_insn "<crc_variant>"
12877 [(set (match_operand:SI 0 "s_register_operand" "=r")
12878 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
12879 (match_operand:<crc_mode> 2 "s_register_operand" "r")]
12880 CRC))]
12881 "TARGET_CRC32"
12882 "<crc_variant>\\t%0, %1, %2"
12883 [(set_attr "type" "crc")
12884 (set_attr "conds" "unconditional")]
12885)
56289ed2 12886
4542a38a
GY
12887;; Load the load/store double peephole optimizations.
12888(include "ldrdstrd.md")
12889
37119410
BS
12890;; Load the load/store multiple patterns
12891(include "ldmstm.md")
3aee1982
IB
12892
12893;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
12894;; large lists without explicit writeback generated for APCS_FRAME epilogue.
12895(define_insn "*load_multiple"
12896 [(match_parallel 0 "load_multiple_operation"
12897 [(set (match_operand:SI 2 "s_register_operand" "=rk")
12898 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
12899 ])]
12900 "TARGET_32BIT"
12901 "*
12902 {
12903 arm_output_multireg_pop (operands, /*return_pc=*/false,
12904 /*cond=*/const_true_rtx,
12905 /*reverse=*/false,
12906 /*update=*/false);
12907 return \"\";
12908 }
12909 "
12910 [(set_attr "predicable" "yes")]
12911)
12912
88f77cba
JB
12913;; Vector bits common to IWMMXT and Neon
12914(include "vec-common.md")
5a9335ef
NC
12915;; Load the Intel Wireless Multimedia Extension patterns
12916(include "iwmmxt.md")
9b66ebb1
PB
12917;; Load the VFP co-processor patterns
12918(include "vfp.md")
5b3e6663
PB
12919;; Thumb-2 patterns
12920(include "thumb2.md")
88f77cba
JB
12921;; Neon patterns
12922(include "neon.md")
021b5e6b
KT
12923;; Crypto patterns
12924(include "crypto.md")
029e79eb
MS
12925;; Synchronization Primitives
12926(include "sync.md")
655b30bf
JB
12927;; Fixed-point patterns
12928(include "arm-fixed.md")